root/branches/jackMidi/gui/src/MainForm.cpp @ 822

Revision 822, 44.2 KB (checked in by gabriel@…, 4 years ago)

Merge rev 560:571 from trunk.

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22#include "version.h"
23
24#include <hydrogen/hydrogen.h>
25#include <hydrogen/playlist.h>
26#include <hydrogen/audio_engine.h>
27#include <hydrogen/smf/SMF.h>
28#include <hydrogen/Preferences.h>
29#include <hydrogen/LocalFileMng.h>
30#include <hydrogen/Pattern.h>
31#include <hydrogen/event_queue.h>
32using namespace H2Core;
33
34#include "AboutDialog.h"
35#include "AudioEngineInfoForm.h"
36#include "ExportSongDialog.h"
37#include "HydrogenApp.h"
38#include "InstrumentRack.h"
39#include "Skin.h"
40#include "MainForm.h"
41#include "PlayerControl.h"
42#include "HelpBrowser.h"
43#include "LadspaFXProperties.h"
44#include "SongPropertiesDialog.h"
45
46#include "Mixer/Mixer.h"
47#include "InstrumentEditor/InstrumentEditorPanel.h"
48#include "PatternEditor/PatternEditorPanel.h"
49#include "SongEditor/SongEditor.h"
50#include "SongEditor/SongEditorPanel.h"
51#include "SoundLibrary/SoundLibraryPanel.h"
52#include "SoundLibrary/SoundLibraryImportDialog.h"
53#include "SoundLibrary/SoundLibrarySaveDialog.h"
54#include "SoundLibrary/SoundLibraryExportDialog.h"
55
56#include <QtGui>
57
58#ifndef WIN32
59        #include <sys/time.h>
60#endif
61
62#ifdef LASH_SUPPORT
63#include <lash-1.0/lash/lash.h>
64#include <hydrogen/LashClient.h>
65#endif
66
67#include <cassert>
68
69using namespace std;
70using namespace H2Core;
71
72MainForm::MainForm( QApplication *app, const QString& songFilename )
73 : QMainWindow( 0, 0 )
74 , Object( "MainForm" )
75{
76        setMinimumSize( QSize( 1000, 600 ) );
77        setWindowIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
78
79        m_pQApp = app;
80
81        m_pQApp->processEvents();
82
83        // Load default song
84        Song *song = NULL;
85        if (songFilename != "") {
86                song = Song::load( songFilename );
87                if (song == NULL) {
88                        //QMessageBox::warning( this, "Hydrogen", trUtf8("Error loading song.") );
89                        song = Song::get_empty_song();
90                        song->set_filename( "" );
91                }
92        }
93        else {
94                Preferences *pref = Preferences::getInstance();
95                bool restoreLastSong = pref->isRestoreLastSongEnabled();
96                QString filename = pref->getLastSongFilename();
97                if ( restoreLastSong && (filename != "" )) {
98                        song = Song::load( filename );
99                        if (song == NULL) {
100                                //QMessageBox::warning( this, "Hydrogen", trUtf8("Error restoring last song.") );
101                                song = Song::get_empty_song();
102                                song->set_filename( "" );
103                        }
104                }
105                else {
106                        song = Song::get_empty_song();
107                        song->set_filename( "" );
108                }
109        }
110
111        h2app = new HydrogenApp( this, song );
112        h2app->addEventListener( this );
113
114        createMenuBar();
115
116        h2app->setStatusBarMessage( trUtf8("Hydrogen Ready."), 10000 );
117
118        initKeyInstMap();
119
120        // we need to do all this to support the keyboard playing
121        // for all the window modes
122        h2app->getMixer()->installEventFilter (this);
123        h2app->getPatternEditorPanel()->installEventFilter (this);
124        h2app->getSongEditorPanel()->installEventFilter (this);
125        h2app->getPlayerControl()->installEventFilter(this);
126        InstrumentEditorPanel::getInstance()->installEventFilter(this);
127        h2app->getAudioEngineInfoForm()->installEventFilter(this);
128
129        installEventFilter( this );
130
131        connect(&m_http, SIGNAL(done(bool)), this, SLOT(latestVersionDone(bool)));
132        getLatestVersion();
133
134
135        connect( &m_autosaveTimer, SIGNAL(timeout()), this, SLOT(onAutoSaveTimer()));
136        m_autosaveTimer.start( 60 * 1000 );
137
138
139#ifdef LASH_SUPPORT
140
141        if ( Preferences::getInstance()->useLash() ){
142                LashClient* lashClient = LashClient::getInstance();
143                if (lashClient->isConnected())
144                {
145                        // send alsa client id now since it can only be sent
146                        // after the audio engine has been started.
147                        Preferences *pref = Preferences::getInstance();
148                        if ( pref->m_sMidiDriver == "ALSA" ) {
149        //                      infoLog("[LASH] Sending alsa seq id to LASH server");
150                                lashClient->sendAlsaClientId();
151                        }
152                        // start timer for polling lash events
153                        lashPollTimer = new QTimer(this);
154                        connect( lashPollTimer, SIGNAL( timeout() ), this, SLOT( onLashPollTimer() ) );
155                        lashPollTimer->start(500);
156                }
157        }
158#endif
159
160       
161//playlist display timer
162        QTimer *playlistDisplayTimer = new QTimer(this);
163        connect( playlistDisplayTimer, SIGNAL( timeout() ), this, SLOT( onPlaylistDisplayTimer() ) );
164        playlistDisplayTimer->start(30000);     // update player control at
165// ~ playlist display timer
166       
167//beatcouter
168        Hydrogen::get_instance()->setBcOffsetAdjust();
169
170}
171
172
173
174MainForm::~MainForm()
175{
176        // remove the autosave file
177        QFile file( getAutoSaveFilename() );
178        file.remove();
179
180        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
181                Hydrogen::get_instance()->sequencer_stop();
182        }
183
184        // remove the autosave file
185        m_autosaveTimer.stop();
186        QFile autosaveFile( "hydrogen_autosave.h2song" );
187        autosaveFile.remove();
188
189        hide();
190
191        if (h2app != NULL) {
192                delete Playlist::get_instance();
193                delete h2app;
194                h2app = NULL;
195        }
196
197}
198
199
200
201///
202/// Create the menubar
203///
204void MainForm::createMenuBar()
205{
206        // menubar
207        QMenuBar *m_pMenubar = new QMenuBar( this );
208        setMenuBar( m_pMenubar );
209
210        // FILE menu
211        QMenu *m_pFileMenu = m_pMenubar->addMenu( trUtf8( "&Project" ) );
212
213        m_pFileMenu->addAction( trUtf8( "&New" ), this, SLOT( action_file_new() ), QKeySequence( "Ctrl+N" ) );
214        m_pFileMenu->addAction( trUtf8( "Show &info" ), this, SLOT( action_file_songProperties() ), QKeySequence( "" ) );
215
216        m_pFileMenu->addSeparator();                            // -----
217
218        m_pFileMenu->addAction( trUtf8( "&Open" ), this, SLOT( action_file_open() ), QKeySequence( "Ctrl+O" ) );
219        m_pFileMenu->addAction( trUtf8( "Open &Demo" ), this, SLOT( action_file_openDemo() ), QKeySequence( "Ctrl+D" ) );
220
221        m_pRecentFilesMenu = m_pFileMenu->addMenu( trUtf8( "Open &recent" ) );
222
223        m_pFileMenu->addSeparator();                            // -----
224
225        m_pFileMenu->addAction( trUtf8( "&Save" ), this, SLOT( action_file_save() ), QKeySequence( "Ctrl+S" ) );
226        m_pFileMenu->addAction( trUtf8( "Save &as..." ), this, SLOT( action_file_save_as() ), QKeySequence( "Ctrl+Shift+S" ) );
227
228        m_pFileMenu->addSeparator();                            // -----
229
230        m_pFileMenu->addAction ( trUtf8 ( "Open &Pattern" ), this, SLOT ( action_file_openPattern() ), QKeySequence ( "" ) );
231        m_pFileMenu->addAction( trUtf8( "Expor&t pattern as..." ), this, SLOT( action_file_export_pattern_as() ), QKeySequence( "Ctrl+P" ) );
232
233        m_pFileMenu->addSeparator();                            // -----
234
235        m_pFileMenu->addAction( trUtf8( "Export &MIDI file" ), this, SLOT( action_file_export_midi() ), QKeySequence( "Ctrl+M" ) );
236        m_pFileMenu->addAction( trUtf8( "&Export song" ), this, SLOT( action_file_export() ), QKeySequence( "Ctrl+E" ) );
237
238
239#ifndef Q_OS_MACX
240        m_pFileMenu->addSeparator();                            // -----
241
242        m_pFileMenu->addAction( trUtf8("&Quit"), this, SLOT( action_file_exit() ), QKeySequence( "Ctrl+Q" ) );
243#endif
244
245        updateRecentUsedSongList();
246        connect( m_pRecentFilesMenu, SIGNAL( triggered(QAction*) ), this, SLOT( action_file_open_recent(QAction*) ) );
247        //~ FILE menu
248
249
250        // INSTRUMENTS MENU
251        QMenu *m_pInstrumentsMenu = m_pMenubar->addMenu( trUtf8( "I&nstruments" ) );
252        m_pInstrumentsMenu->addAction( trUtf8( "&Add instrument" ), this, SLOT( action_instruments_addInstrument() ), QKeySequence( "" ) );
253        m_pInstrumentsMenu->addAction( trUtf8( "&Clear all" ), this, SLOT( action_instruments_clearAll() ), QKeySequence( "" ) );
254        m_pInstrumentsMenu->addAction( trUtf8( "&Save library" ), this, SLOT( action_instruments_saveLibrary() ), QKeySequence( "" ) );
255        m_pInstrumentsMenu->addAction( trUtf8( "&Export library" ), this, SLOT( action_instruments_exportLibrary() ), QKeySequence( "" ) );
256        m_pInstrumentsMenu->addAction( trUtf8( "&Import library" ), this, SLOT( action_instruments_importLibrary() ), QKeySequence( "" ) );
257
258
259
260
261        // Tools menu
262        QMenu *m_pToolsMenu = m_pMenubar->addMenu( trUtf8( "&Tools" ));
263
264//      if ( Preferences::getInstance()->getInterfaceMode() == Preferences::SINGLE_PANED ) {
265//              m_pWindowMenu->addAction( trUtf8("Show song editor"), this, SLOT( action_window_showSongEditor() ), QKeySequence( "" ) );
266//      }
267        m_pToolsMenu->addAction( trUtf8("Playlist &editor"), this, SLOT( action_window_showPlaylistDialog() ), QKeySequence( "" ) );
268
269        m_pToolsMenu->addAction( trUtf8("&Mixer"), this, SLOT( action_window_showMixer() ), QKeySequence( "Alt+M" ) );
270
271        m_pToolsMenu->addAction( trUtf8("&Instrument Rack"), this, SLOT( action_window_showDrumkitManagerPanel() ), QKeySequence( "Alt+I" ) );
272        m_pToolsMenu->addAction( trUtf8("&Preferences"), this, SLOT( showPreferencesDialog() ), QKeySequence( "Alt+P" ) );
273
274        //~ Tools menu
275
276
277        if ( Object::is_using_verbose_log() ) {
278                // DEBUG menu
279                QMenu *m_pDebugMenu = m_pMenubar->addMenu( trUtf8("De&bug") );
280                m_pDebugMenu->addAction( trUtf8( "Show &audio engine info" ), this, SLOT( action_debug_showAudioEngineInfo() ) );
281                m_pDebugMenu->addAction( trUtf8( "Print Objects" ), this, SLOT( action_debug_printObjects() ) );
282                //~ DEBUG menu
283        }
284
285        // INFO menu
286        QMenu *m_pInfoMenu = m_pMenubar->addMenu( trUtf8( "&Info" ) );
287        m_pInfoMenu->addAction( trUtf8("&User manual"), this, SLOT( showUserManual() ), QKeySequence( "Ctrl+?" ) );
288        m_pInfoMenu->addSeparator();
289        m_pInfoMenu->addAction( trUtf8("&About"), this, SLOT( action_help_about() ), QKeySequence( trUtf8("", "Info|About") ) );
290        //~ INFO menu
291}
292
293
294
295
296void MainForm::onLashPollTimer()
297{
298#ifdef LASH_SUPPORT     
299if ( Preferences::getInstance()->useLash() ){
300        LashClient* client = LashClient::getInstance();
301       
302        if (!client->isConnected())
303        {
304                WARNINGLOG("[LASH] Not connected to server!");
305                return;
306        }
307       
308        bool keep_running = true;
309
310        lash_event_t* event;
311
312        string songFilename = "";
313        QString filenameSong = "";
314        Song *song = Hydrogen::get_instance()->getSong();
315        while (event = client->getNextEvent()) {
316               
317                switch (lash_event_get_type(event)) {
318                       
319                        case LASH_Save_File:
320               
321                                INFOLOG("[LASH] Save file");
322                       
323                                songFilename.append(lash_event_get_string(event));
324                                songFilename.append("/hydrogen.h2song");
325                               
326                                filenameSong = songFilename.c_str();
327                                song->set_filename( filenameSong );
328                                action_file_save();
329                         
330                                client->sendEvent(LASH_Save_File);
331                         
332                                break;
333               
334                        case LASH_Restore_File:
335               
336                                songFilename.append(lash_event_get_string(event));
337                                songFilename.append("/hydrogen.h2song");
338                               
339                                INFOLOG("[LASH] Restore file: " + to_string( songFilename ));
340
341                                filenameSong = songFilename.c_str();
342                                                         
343                                openSongFile( filenameSong );
344                         
345                                client->sendEvent(LASH_Restore_File);
346                         
347                                break;
348
349                        case LASH_Quit:
350               
351//                              infoLog("[LASH] Quit!");
352                                keep_running = false;
353                               
354                                break;
355               
356                        default:
357                                ;
358//                              infoLog("[LASH] Got unknown event!");
359
360                }
361
362                lash_event_destroy(event);
363
364        }
365
366   if (!keep_running)
367   {
368           lashPollTimer->stop();
369           action_file_exit();
370   }
371}
372#endif
373}
374
375
376/// return true if the app needs to be closed.
377bool MainForm::action_file_exit()
378{
379        if ( Hydrogen::get_instance()->getSong()->__is_modified ) {
380                int res = QMessageBox::information(
381                                this,
382                                "Hydrogen",
383                                trUtf8("\nThe song has unsaved changes\n Do you want to save the changes before exiting?\n"),
384                                trUtf8("&Save"),
385                                trUtf8("&Discard"),
386                                trUtf8("&Cancel"),
387                                0,      // Enter == button 0
388                                2       // Escape == button 2
389                );
390                switch( res ) {
391                        case 0:
392                                // Save clicked or Alt+S pressed or Enter pressed.
393                                if ( Hydrogen::get_instance()->getSong()->get_filename() != "") {
394                                        action_file_save();
395                                } else {
396                                        action_file_save_as();
397                                }
398                                // save
399                                break;
400                        case 1:
401                                // Discard clicked or Alt+D pressed
402                                // don't save but exit
403                                break;
404                        case 2:
405                                // Cancel clicked or Alt+C pressed or Escape pressed
406                                // don't exit
407                                return false;
408                                break;
409                        default:
410                                ERRORLOG( "Unknown return code: " + to_string( res ) );
411                }
412        }
413        closeAll();
414        return true;
415}
416
417
418
419void MainForm::action_file_new()
420{
421        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
422                Hydrogen::get_instance()->sequencer_stop();
423        }
424
425        if ( Hydrogen::get_instance()->getSong()->__is_modified ) {
426                switch(
427                                QMessageBox::information( this, "Hydrogen",
428                                                trUtf8("\nThe document contains unsaved changes\n"
429                                                "Do you want to save the changes before exiting?\n"),
430                                                trUtf8("&Save"), trUtf8("&Discard"), trUtf8("&Cancel"),
431                                                0,      // Enter == button 0
432                                                2 ) ) { // Escape == button 2
433                        case 0: // Save clicked or Alt+S pressed or Enter pressed.
434                                if ( Hydrogen::get_instance()->getSong()->get_filename() != "") {
435                                        action_file_save();
436                                } else {
437                                        // never been saved
438                                        action_file_save_as();
439                                }
440                                // save
441                                break;
442                        case 1: // Discard clicked or Alt+D pressed
443                                // don't save but exit
444                                break;
445                        case 2: // Cancel clicked or Alt+C pressed or Escape pressed
446                                // don't exit
447                                return;
448                                break;
449                }
450        }
451
452        Song * song = Song::get_empty_song();
453        song->set_filename( "" );
454        h2app->setSong(song);
455        Hydrogen::get_instance()->setSelectedPatternNumber( 0 );
456        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->update_background_color();
457}
458
459
460
461void MainForm::action_file_save_as()
462{
463        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
464                Hydrogen::get_instance()->sequencer_stop();
465        }
466
467        QFileDialog *fd = new QFileDialog(this);
468        fd->setFileMode( QFileDialog::AnyFile );
469        fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
470        fd->setAcceptMode( QFileDialog::AcceptSave );
471        fd->setWindowTitle( trUtf8( "Save song" ) );
472
473        Song *song = Hydrogen::get_instance()->getSong();
474        QString defaultFilename;
475        QString lastFilename = song->get_filename();
476
477        if (lastFilename == "") {
478                defaultFilename = Hydrogen::get_instance()->getSong()->__name;
479                defaultFilename += ".h2song";
480        }
481        else {
482                defaultFilename = lastFilename;
483        }
484
485        fd->selectFile( defaultFilename );
486
487        QString filename = "";
488        if (fd->exec() == QDialog::Accepted) {
489                filename = fd->selectedFiles().first();
490        }
491
492        if (filename != "") {
493                QString sNewFilename = filename;
494                if ( sNewFilename.endsWith(".h2song") == false ) {
495                        filename += ".h2song";
496                }
497
498                song->set_filename(filename);
499                action_file_save();
500        }
501        h2app->setScrollStatusBarMessage( trUtf8("Song saved as.") + QString(" Into: ") + defaultFilename, 2000 );
502        //update SoundlibraryPanel
503        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
504        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
505}
506
507
508
509void MainForm::action_file_save()
510{
511//      if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
512//              (Hydrogen::get_instance())->stop();
513//      }
514
515        Song *song = Hydrogen::get_instance()->getSong();
516        QString filename = song->get_filename();
517
518        if (filename == "") {
519                // just in case!
520                return action_file_save_as();
521        }
522
523        LocalFileMng mng;
524        bool saved = false;
525        saved = song->save( filename );
526       
527
528        if(! saved) {
529                QMessageBox::warning( this, "Hydrogen", trUtf8("Could not save song.") );
530        } else {
531                Preferences::getInstance()->setLastSongFilename( song->get_filename() );
532
533                // add the new loaded song in the "last used song" vector
534                Preferences *pPref = Preferences::getInstance();
535                vector<QString> recentFiles = pPref->getRecentFiles();
536                recentFiles.insert( recentFiles.begin(), filename );
537                pPref->setRecentFiles( recentFiles );
538
539                updateRecentUsedSongList();
540
541                h2app->setScrollStatusBarMessage( trUtf8("Song saved.") + QString(" Into: ") + filename, 2000 );
542        }
543        //update SoundlibraryPanel
544        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
545        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
546}
547
548
549
550
551void MainForm::action_help_about() {
552        //QWidget *parent = this;
553//      if (workspace) {
554//              parent = workspace;
555//      }
556
557        // show modal dialog
558        AboutDialog *dialog = new AboutDialog( NULL );
559        dialog->exec();
560}
561
562
563
564
565void MainForm::showUserManual()
566{
567        h2app->getHelpBrowser()->hide();
568        h2app->getHelpBrowser()->show();
569}
570
571
572void MainForm::action_file_export_pattern_as()
573{
574        if ( ( Hydrogen::get_instance()->getState() == STATE_PLAYING ) )
575        {
576                Hydrogen::get_instance()->sequencer_stop();
577        }
578
579        Hydrogen *engine = Hydrogen::get_instance();
580        int selectedpattern = engine->getSelectedPatternNumber();
581        Song *song = engine->getSong();
582        Pattern *pat = song->get_pattern_list()->get ( selectedpattern );
583
584        Instrument *instr = song->get_instrument_list()->get ( 0 );
585        assert ( instr );
586
587        QString sDataDir = Preferences::getInstance()->getDataDirectory();
588
589
590        QDir dir ( sDataDir + "patterns" );
591
592
593        QFileDialog *fd = new QFileDialog ( this );
594        fd->setFileMode ( QFileDialog::AnyFile );
595        fd->setFilter ( trUtf8 ( "Hydrogen Pattern (*.h2pattern)" ) );
596        fd->setAcceptMode ( QFileDialog::AcceptSave );
597        fd->setWindowTitle ( trUtf8 ( "Save Pattern as ..." ) );
598        fd->setDirectory ( dir );
599
600
601
602        QString defaultPatternname = QString ( pat->get_name() );
603
604        fd->selectFile ( defaultPatternname );
605
606        LocalFileMng fileMng;
607        QString filename = "";
608        if ( fd->exec() == QDialog::Accepted )
609        {
610                filename = fd->selectedFiles().first();
611        }
612
613        if ( filename != "" )
614        {
615                QString sNewFilename = filename;
616                sNewFilename += ".h2pattern";
617                QString patternname = sNewFilename;
618                QString realpatternname = filename;
619                QString realname = realpatternname.mid( realpatternname.lastIndexOf( "/" ) + 1 );
620                pat->set_name(realname);
621                HydrogenApp::getInstance()->getSongEditorPanel()->updateAll();
622                int err = fileMng.savePattern ( song , selectedpattern, patternname, realname, 2 );
623                if ( err != 0 )
624                {
625                        _ERRORLOG ( "Error saving the pattern" );
626                }
627        }
628        h2app->setStatusBarMessage ( trUtf8 ( "Pattern saved." ), 10000 );
629       
630        //update SoundlibraryPanel
631        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
632        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
633}
634
635
636
637void MainForm::action_file_open() {
638        if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
639                Hydrogen::get_instance()->sequencer_stop();
640        }
641
642        if ( Hydrogen::get_instance()->getSong()->__is_modified ) {
643                switch(
644                        QMessageBox::information( this, "Hydrogen",
645                                        trUtf8("\nThe document contains unsaved changes\n"
646                                        "Do you want to save the changes before exiting?\n"),
647                                        trUtf8("&Save"), trUtf8("&Discard"), trUtf8("&Cancel"),
648                                        0,      // Enter == button 0
649                                        2 ) ) { // Escape == button 2
650                        case 0: // Save clicked or Alt+S pressed or Enter pressed.
651                                if ( Hydrogen::get_instance()->getSong()->get_filename() != "") {
652                                        action_file_save();
653                                }
654                                else {
655                                        action_file_save_as();
656                                }
657                                // save
658                                break;
659                        case 1: // Discard clicked or Alt+D pressed
660                                // don't save but exit
661                                break;
662                        case 2: // Cancel clicked or Alt+C pressed or Escape pressed
663                                // don't exit
664                                return;
665                                break;
666                }
667        }
668
669       
670         
671
672       
673
674        static QString lastUsedDir = Preferences::getInstance()->getDataDirectory() + "/songs";
675       
676        QFileDialog *fd = new QFileDialog(this);
677        fd->setFileMode(QFileDialog::ExistingFile);
678        fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
679        fd->setDirectory( lastUsedDir );
680
681        fd->setWindowTitle( trUtf8( "Open song" ) );
682
683        /// \todo impostare il preview
684        /*
685        fd->setContentsPreviewEnabled( TRUE );
686        fd->setContentsPreview( "uno", "due" );
687        fd->setPreviewMode( QFileDialog::Contents );
688        */
689
690        QString filename = "";
691        if (fd->exec() == QDialog::Accepted) {
692                filename = fd->selectedFiles().first();
693                lastUsedDir = fd->directory().absolutePath();
694        }
695
696
697        if (filename != "") {
698                openSongFile( filename );
699        }
700
701        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->update_background_color();
702}
703
704
705void MainForm::action_file_openPattern()
706{
707
708        Hydrogen *engine = Hydrogen::get_instance();
709        Song *song = engine->getSong();
710        PatternList *pPatternList = song->get_pattern_list();
711
712        Instrument *instr = song->get_instrument_list()->get ( 0 );
713        assert ( instr );
714
715        QDir dirPattern( Preferences::getInstance()->getDataDirectory() + "/patterns" );
716        QFileDialog *fd = new QFileDialog ( this );
717        fd->setFileMode ( QFileDialog::ExistingFile );
718        fd->setFilter ( trUtf8 ( "Hydrogen Pattern (*.h2pattern)" ) );
719        fd->setDirectory ( dirPattern );
720
721        fd->setWindowTitle ( trUtf8 ( "Open Pattern" ) );
722
723
724        QString filename = "";
725        if ( fd->exec() == QDialog::Accepted )
726        {
727                filename = fd->selectedFiles().first();
728        }
729        QString patternname = filename;
730
731
732        LocalFileMng mng;
733        LocalFileMng fileMng;
734        Pattern* err = fileMng.loadPattern ( patternname );
735        if ( err == 0 )
736        {
737                _ERRORLOG( "Error loading the pattern" );
738                _ERRORLOG( patternname );
739        }
740        else
741        {
742                H2Core::Pattern *pNewPattern = err;
743                pPatternList->add ( pNewPattern );
744                song->__is_modified = true;
745        }
746
747        HydrogenApp::getInstance()->getSongEditorPanel()->updateAll();
748}
749
750/// \todo parametrizzare il metodo action_file_open ed eliminare il seguente...
751void MainForm::action_file_openDemo()
752{
753        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
754                Hydrogen::get_instance()->sequencer_stop();
755        }
756
757        if ( ( Hydrogen::get_instance()->getSong())->__is_modified ) {
758                switch(
759                        QMessageBox::information( this, "Hydrogen",
760                                        trUtf8("\nThe document contains unsaved changes\n"
761                                        "Do you want to save the changes before exiting?\n"),
762                                        trUtf8("&Save"), trUtf8("&Discard"), trUtf8("&Cancel"),
763                                        0,      // Enter == button 0
764                                        2 ) ) { // Escape == button 2
765                        case 0: // Save clicked or Alt+S pressed or Enter pressed.
766                                if ( Hydrogen::get_instance()->getSong()->get_filename() != "") {
767                                        action_file_save_as();
768                                }
769                                else {
770                                        action_file_save_as();
771                                }
772                                // save
773                                break;
774                        case 1: // Discard clicked or Alt+D pressed
775                                // don't save but exit
776                                break;
777                        case 2: // Cancel clicked or Alt+C pressed or Escape pressed
778                                // don't exit
779                                return;
780                                break;
781                }
782        }
783
784
785        QFileDialog *fd = new QFileDialog(this);
786        fd->setFileMode(QFileDialog::ExistingFile);
787        fd->setFilter( trUtf8("Hydrogen Song (*.h2song)") );
788
789        fd->setWindowTitle( trUtf8( "Open song" ) );
790//      fd->setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
791
792        /// \todo impostare il preview
793        /*
794        fd->setContentsPreviewEnabled( TRUE );
795        fd->setContentsPreview( "uno", "due" );
796        fd->setPreviewMode( QFileDialog::Contents );
797        */
798        fd->setDirectory( QString( Preferences::getInstance()->getDemoPath() ) );
799
800
801        QString filename = "";
802        if (fd->exec() == QDialog::Accepted) {
803                filename = fd->selectedFiles().first();
804        }
805
806
807        if (filename != "") {
808                openSongFile( filename );
809                Hydrogen::get_instance()->getSong()->set_filename( "" );
810        }
811}
812
813
814
815void MainForm::showPreferencesDialog()
816{
817        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
818                Hydrogen::get_instance()->sequencer_stop();
819        }
820
821        h2app->showPreferencesDialog();
822}
823
824
825
826void MainForm::action_window_showPlaylistDialog()
827{
828        h2app->showPlaylistDialog();   
829}
830
831
832
833void MainForm::action_window_showMixer()
834{
835        bool isVisible = HydrogenApp::getInstance()->getMixer()->isVisible();
836        h2app->showMixer( !isVisible );
837}
838
839
840
841void MainForm::action_debug_showAudioEngineInfo()
842{
843        h2app->showAudioEngineInfoForm();
844}
845
846
847
848///
849/// Shows the song editor
850///
851void MainForm::action_window_showSongEditor()
852{
853        bool isVisible = h2app->getSongEditorPanel()->isVisible();
854        h2app->getSongEditorPanel()->setHidden( isVisible );
855}
856
857
858
859void MainForm::action_instruments_addInstrument()
860{
861        AudioEngine::get_instance()->lock("MainForm::action_instruments_addInstrument");
862        InstrumentList* pList = Hydrogen::get_instance()->getSong()->get_instrument_list();
863
864        // create a new valid ID for this instrument
865        int nID = -1;
866        for ( uint i = 0; i < pList->get_size(); ++i ) {
867                Instrument* pInstr = pList->get( i );
868                if ( pInstr->get_id().toInt() > nID ) {
869                        nID = pInstr->get_id().toInt();
870                }
871        }
872        ++nID;
873
874        Instrument *pNewInstr = new Instrument(to_string( nID ), "New instrument", new ADSR());
875        pList->add( pNewInstr );
876        Hydrogen::get_instance()->renameJackPorts();
877        AudioEngine::get_instance()->unlock();
878
879        Hydrogen::get_instance()->setSelectedInstrumentNumber( pList->get_size() - 1 );
880
881        // Force an update
882        //EventQueue::getInstance()->pushEvent( EVENT_SELECTED_PATTERN_CHANGED, -1 );
883}
884
885
886
887void MainForm::action_instruments_clearAll()
888{
889        switch(
890               QMessageBox::information( this,
891                                         "Hydrogen",
892                                         trUtf8("Clear all instruments?"),
893                                         trUtf8("Ok"),
894                                         trUtf8("Cancel"),
895                                         0,      // Enter == button 0
896                                         1 )) { // Escape == button 2
897        case 0:
898          // ok btn pressed
899          break;
900        case 1:
901          // cancel btn pressed
902          return;
903        }
904
905        // Remove all layers
906        AudioEngine::get_instance()->lock("MainForm::action_instruments_clearAll");
907        Song *pSong = Hydrogen::get_instance()->getSong();
908        InstrumentList* pList = pSong->get_instrument_list();
909        for (uint i = 0; i < pList->get_size(); i++) {
910                Instrument* pInstr = pList->get( i );
911                pInstr->set_name( (QString( trUtf8( "Instrument %1" ) ).arg( i + 1 )) );
912                // remove all layers
913                for ( int nLayer = 0; nLayer < MAX_LAYERS; nLayer++ ) {
914                        InstrumentLayer* pLayer = pInstr->get_layer( nLayer );
915                        delete pLayer;
916                        pInstr->set_layer( NULL, nLayer );
917                }
918        }
919        AudioEngine::get_instance()->unlock();
920        EventQueue::get_instance()->push_event( EVENT_SELECTED_INSTRUMENT_CHANGED, -1 );
921}
922
923
924
925void MainForm::action_instruments_exportLibrary()
926{
927        SoundLibraryExportDialog exportDialog( this );
928        exportDialog.exec();
929}
930
931
932
933
934void MainForm::action_instruments_importLibrary()
935{
936        SoundLibraryImportDialog dialog( this );
937        dialog.exec();
938}
939
940
941
942void MainForm::action_instruments_saveLibrary()
943{
944        SoundLibrarySaveDialog dialog( this );
945        dialog.exec();
946        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->test_expandedItems();
947        HydrogenApp::getInstance()->getInstrumentRack()->getSoundLibraryPanel()->updateDrumkitList();
948}
949
950
951
952
953
954
955
956///
957/// Window close event
958///
959void MainForm::closeEvent( QCloseEvent* ev )
960{
961        if ( action_file_exit() == false ) {
962                // don't close!!!
963                ev->ignore();
964                return;
965        }
966
967        ev->accept();
968}
969
970
971
972void MainForm::action_file_export() {
973        if ( (Hydrogen::get_instance()->getState() == STATE_PLAYING) ) {
974                Hydrogen::get_instance()->sequencer_stop();
975        }
976
977        ExportSongDialog *dialog = new ExportSongDialog(this);
978        dialog->exec();
979        delete dialog;
980}
981
982
983
984void MainForm::action_window_showDrumkitManagerPanel()
985{
986        InstrumentRack *pPanel = HydrogenApp::getInstance()->getInstrumentRack();
987        pPanel->setHidden( pPanel->isVisible() );
988}
989
990
991
992
993void MainForm::closeAll() {
994        // save window properties in the preferences files
995        Preferences *pref = Preferences::getInstance();
996
997        // mainform
998        WindowProperties mainFormProp;
999        mainFormProp.x = x();
1000        mainFormProp.y = y();
1001        mainFormProp.height = height();
1002        mainFormProp.width = width();
1003        pref->setMainFormProperties( mainFormProp );
1004
1005        // Save mixer properties
1006        WindowProperties mixerProp;
1007        mixerProp.x = h2app->getMixer()->x();
1008        mixerProp.y = h2app->getMixer()->y();
1009        mixerProp.width = h2app->getMixer()->width();
1010        mixerProp.height = h2app->getMixer()->height();
1011        mixerProp.visible = h2app->getMixer()->isVisible();
1012        pref->setMixerProperties( mixerProp );
1013
1014        // save pattern editor properties
1015        WindowProperties patternEditorProp;
1016        patternEditorProp.x = h2app->getPatternEditorPanel()->x();
1017        patternEditorProp.y = h2app->getPatternEditorPanel()->y();
1018        patternEditorProp.width = h2app->getPatternEditorPanel()->width();
1019        patternEditorProp.height = h2app->getPatternEditorPanel()->height();
1020        patternEditorProp.visible = h2app->getPatternEditorPanel()->isVisible();
1021        pref->setPatternEditorProperties( patternEditorProp );
1022
1023        // save song editor properties
1024        WindowProperties songEditorProp;
1025        songEditorProp.x = h2app->getSongEditorPanel()->x();
1026        songEditorProp.y = h2app->getSongEditorPanel()->y();
1027        songEditorProp.width = h2app->getSongEditorPanel()->width();
1028        songEditorProp.height = h2app->getSongEditorPanel()->height();
1029
1030        QSize size = h2app->getSongEditorPanel()->frameSize();
1031        songEditorProp.visible = h2app->getSongEditorPanel()->isVisible();
1032        pref->setSongEditorProperties( songEditorProp );
1033
1034
1035        // save audio engine info properties
1036        WindowProperties audioEngineInfoProp;
1037        audioEngineInfoProp.x = h2app->getAudioEngineInfoForm()->x();
1038        audioEngineInfoProp.y = h2app->getAudioEngineInfoForm()->y();
1039        audioEngineInfoProp.visible = h2app->getAudioEngineInfoForm()->isVisible();
1040        pref->setAudioEngineInfoProperties( audioEngineInfoProp );
1041
1042
1043#ifdef LADSPA_SUPPORT
1044        // save LADSPA FX window properties
1045        for (uint nFX = 0; nFX < MAX_FX; nFX++) {
1046                WindowProperties prop;
1047                prop.x = h2app->getLadspaFXProperties(nFX)->x();
1048                prop.y = h2app->getLadspaFXProperties(nFX)->y();
1049                prop.visible= h2app->getLadspaFXProperties(nFX)->isVisible();
1050                pref->setLadspaProperties(nFX, prop);
1051        }
1052#endif
1053
1054        m_pQApp->quit();
1055}
1056
1057
1058
1059// keybindings..
1060
1061void MainForm::onPlayStopAccelEvent()
1062{
1063        int nState = Hydrogen::get_instance()->getState();
1064        switch (nState) {
1065                case STATE_READY:
1066                        Hydrogen::get_instance()->sequencer_play();
1067                        break;
1068
1069                case STATE_PLAYING:
1070                        Hydrogen::get_instance()->sequencer_stop();
1071                        break;
1072
1073                default:
1074                        ERRORLOG( "[MainForm::onPlayStopAccelEvent()] Unhandled case." );
1075        }
1076}
1077
1078
1079
1080void MainForm::onRestartAccelEvent()
1081{
1082        Hydrogen* pEngine = Hydrogen::get_instance();
1083        pEngine->setPatternPos( 0 );
1084}
1085
1086
1087
1088void MainForm::onBPMPlusAccelEvent()
1089{
1090        Hydrogen* pEngine = Hydrogen::get_instance();
1091        AudioEngine::get_instance()->lock( "MainForm::onBPMPlusAccelEvent" );
1092
1093        Song* pSong = pEngine->getSong();
1094        if (pSong->__bpm  < 300) {
1095                pEngine->setBPM( pSong->__bpm + 0.1 );
1096        }
1097        AudioEngine::get_instance()->unlock();
1098}
1099
1100
1101
1102void MainForm::onBPMMinusAccelEvent()
1103{
1104        Hydrogen* pEngine = Hydrogen::get_instance();
1105        AudioEngine::get_instance()->lock( "MainForm::onBPMMinusAccelEvent" );
1106
1107        Song* pSong = pEngine->getSong();
1108        if (pSong->__bpm > 40 ) {
1109                pEngine->setBPM( pSong->__bpm - 0.1 );
1110        }
1111        AudioEngine::get_instance()->unlock();
1112}
1113
1114
1115
1116void MainForm::onSaveAsAccelEvent()
1117{
1118        action_file_save_as();
1119}
1120
1121
1122
1123void MainForm::onSaveAccelEvent()
1124{
1125        action_file_save();
1126}
1127
1128
1129
1130void MainForm::onOpenAccelEvent()
1131{
1132        action_file_open();
1133}
1134
1135
1136
1137void MainForm::updateRecentUsedSongList()
1138{
1139        m_pRecentFilesMenu->clear();
1140
1141        Preferences *pPref = Preferences::getInstance();
1142        vector<QString> recentUsedSongs = pPref->getRecentFiles();
1143
1144        QString sFilename = "";
1145
1146        for ( uint i = 0; i < recentUsedSongs.size(); ++i ) {
1147                sFilename = recentUsedSongs[ i ];
1148
1149                if ( sFilename != "" ) {
1150                        QAction *pAction = new QAction( this  );
1151                        pAction->setText( sFilename );
1152                        m_pRecentFilesMenu->addAction( pAction );
1153                }
1154        }
1155}
1156
1157
1158
1159void MainForm::action_file_open_recent(QAction *pAction)
1160{
1161//      INFOLOG( pAction->text() );
1162        openSongFile( pAction->text() );
1163}
1164
1165
1166
1167void MainForm::openSongFile( const QString& sFilename )
1168{
1169        Hydrogen *engine = Hydrogen::get_instance();
1170        if ( engine->getState() == STATE_PLAYING ) {
1171                engine->sequencer_stop();
1172        }
1173
1174        h2app->closeFXProperties();
1175        LocalFileMng mng;
1176        Song *pSong = Song::load( sFilename );
1177        if ( pSong == NULL ) {
1178                QMessageBox::information( this, "Hydrogen", trUtf8("Error loading song.") );
1179                return;
1180        }
1181
1182        // add the new loaded song in the "last used song" vector
1183        Preferences *pPref = Preferences::getInstance();
1184        vector<QString> recentFiles = pPref->getRecentFiles();
1185        recentFiles.insert( recentFiles.begin(), sFilename );
1186        pPref->setRecentFiles( recentFiles );
1187
1188        h2app->setSong( pSong );
1189
1190        updateRecentUsedSongList();
1191        engine->setSelectedPatternNumber( 0 );
1192}
1193
1194
1195
1196void MainForm::initKeyInstMap()
1197{
1198        int instr = 0;
1199        keycodeInstrumentMap[Qt::Key_Z] = instr++;
1200        keycodeInstrumentMap[Qt::Key_S] = instr++;
1201        keycodeInstrumentMap[Qt::Key_X] = instr++;
1202        keycodeInstrumentMap[Qt::Key_D] = instr++;
1203        keycodeInstrumentMap[Qt::Key_C] = instr++;
1204        keycodeInstrumentMap[Qt::Key_V] = instr++;
1205        keycodeInstrumentMap[Qt::Key_G] = instr++;
1206        keycodeInstrumentMap[Qt::Key_B] = instr++;
1207        keycodeInstrumentMap[Qt::Key_H] = instr++;
1208        keycodeInstrumentMap[Qt::Key_N] = instr++;
1209        keycodeInstrumentMap[Qt::Key_J] = instr++;
1210        keycodeInstrumentMap[Qt::Key_M] = instr++;
1211
1212        keycodeInstrumentMap[Qt::Key_Q] = instr++;
1213        keycodeInstrumentMap[Qt::Key_2] = instr++;
1214        keycodeInstrumentMap[Qt::Key_W] = instr++;
1215        keycodeInstrumentMap[Qt::Key_3] = instr++;
1216        keycodeInstrumentMap[Qt::Key_E] = instr++;
1217        keycodeInstrumentMap[Qt::Key_R] = instr++;
1218        keycodeInstrumentMap[Qt::Key_5] = instr++;
1219        keycodeInstrumentMap[Qt::Key_T] = instr++;
1220        keycodeInstrumentMap[Qt::Key_6] = instr++;
1221        keycodeInstrumentMap[Qt::Key_Y] = instr++;
1222        keycodeInstrumentMap[Qt::Key_7] = instr++;
1223        keycodeInstrumentMap[Qt::Key_U] = instr++;
1224
1225
1226        /*
1227        // QWERTY etc.... rows of the keyboard
1228        keycodeInstrumentMap[Qt::Key_Q] = instr++;
1229        keycodeInstrumentMap[Qt::Key_W] = instr++;
1230        keycodeInstrumentMap[Qt::Key_E] = instr++;
1231        keycodeInstrumentMap[Qt::Key_R] = instr++;
1232        keycodeInstrumentMap[Qt::Key_T] = instr++;
1233        keycodeInstrumentMap[Qt::Key_Y] = instr++;
1234        keycodeInstrumentMap[Qt::Key_U] = instr++;
1235        keycodeInstrumentMap[Qt::Key_I] = instr++;
1236        keycodeInstrumentMap[Qt::Key_O] = instr++;
1237        keycodeInstrumentMap[Qt::Key_P] = instr++;
1238        keycodeInstrumentMap[Qt::Key_BracketLeft] = instr++;
1239        keycodeInstrumentMap[Qt::Key_BracketRight] = instr++;
1240        keycodeInstrumentMap[Qt::Key_A] = instr++;
1241        keycodeInstrumentMap[Qt::Key_S] = instr++;
1242        keycodeInstrumentMap[Qt::Key_D] = instr++;
1243        keycodeInstrumentMap[Qt::Key_F] = instr++;
1244        keycodeInstrumentMap[Qt::Key_G] = instr++;
1245        keycodeInstrumentMap[Qt::Key_H] = instr++;
1246        keycodeInstrumentMap[Qt::Key_J] = instr++;
1247        keycodeInstrumentMap[Qt::Key_K] = instr++;
1248        keycodeInstrumentMap[Qt::Key_L] = instr++;
1249        keycodeInstrumentMap[Qt::Key_Semicolon] = instr++;
1250        keycodeInstrumentMap[Qt::Key_Apostrophe] = instr++;
1251        keycodeInstrumentMap[Qt::Key_Z] = instr++;
1252        keycodeInstrumentMap[Qt::Key_X] = instr++;
1253        keycodeInstrumentMap[Qt::Key_C] = instr++;
1254        keycodeInstrumentMap[Qt::Key_V] = instr++;
1255        keycodeInstrumentMap[Qt::Key_B] = instr++;
1256        keycodeInstrumentMap[Qt::Key_N] = instr++;
1257        keycodeInstrumentMap[Qt::Key_M] = instr++;
1258        keycodeInstrumentMap[Qt::Key_Comma] = instr++;
1259        keycodeInstrumentMap[Qt::Key_Period] = instr++;
1260*/
1261}
1262
1263
1264
1265bool MainForm::eventFilter( QObject *o, QEvent *e )
1266{
1267        UNUSED( o );
1268
1269        if ( e->type() == QEvent::KeyPress) {
1270                // special processing for key press
1271                QKeyEvent *k = (QKeyEvent *)e;
1272
1273                // qDebug( "Got key press for instrument '%c'", k->ascii() );
1274                int songnumber = 0;
1275
1276                switch (k->key()) {
1277                        case Qt::Key_Space:
1278                                onPlayStopAccelEvent();
1279                                return TRUE; // eat event
1280
1281
1282                        case Qt::Key_Comma:
1283                                Hydrogen::get_instance()->handleBeatCounter();
1284                                return TRUE; // eat even
1285                                break;
1286
1287                        case Qt::Key_Backspace:
1288                                onRestartAccelEvent();
1289                                return TRUE; // eat event
1290                                break;
1291
1292                        case Qt::Key_Plus:
1293                                onBPMPlusAccelEvent();
1294                                return TRUE; // eat event
1295                                break;
1296
1297                        case Qt::Key_Minus:
1298                                onBPMMinusAccelEvent();
1299                                return TRUE; // eat event
1300                                break;
1301
1302                        case Qt::Key_Backslash:
1303                                Hydrogen::get_instance()->onTapTempoAccelEvent();
1304                                return TRUE; // eat event
1305                                break;
1306
1307                        case  Qt::Key_S | Qt::CTRL:
1308                                onSaveAccelEvent();
1309                                return TRUE;
1310                                break;
1311                       
1312                        case  Qt::Key_F5 :
1313                                if( Hydrogen::get_instance()->m_PlayList.size() == 0)
1314                                        break;
1315                                Playlist::get_instance()->setPrevSongPlaylist();
1316                                songnumber = Playlist::get_instance()->getActiveSongNumber();
1317                                HydrogenApp::getInstance()->setScrollStatusBarMessage( trUtf8( "Playlist: Set song No. %1" ).arg( songnumber +1 ), 5000 );
1318                                return TRUE;
1319                                break;
1320
1321                        case  Qt::Key_F6 :
1322                                if( Hydrogen::get_instance()->m_PlayList.size() == 0)
1323                                        break;
1324                                Playlist::get_instance()->setNextSongPlaylist();
1325                                songnumber = Playlist::get_instance()->getActiveSongNumber();
1326                                HydrogenApp::getInstance()->setScrollStatusBarMessage( trUtf8( "Playlist: Set song No. %1" ).arg( songnumber +1 ), 5000 );
1327                                return TRUE;
1328                                break;
1329
1330                        case  Qt::Key_F12 : //panic button stop all playing notes
1331                                Hydrogen::get_instance()->__panic();
1332//                              QMessageBox::information( this, "Hydrogen", trUtf8( "Panic" ) );
1333                                return TRUE;
1334                                break;
1335
1336                        case  Qt::Key_F9 : // Qt::Key_Left do not work. Some ideas ?
1337                                Hydrogen::get_instance()->setPatternPos( Hydrogen::get_instance()->getPatternPos() - 1 );
1338                                return TRUE;
1339                                break;
1340
1341                        case  Qt::Key_F10 : // Qt::Key_Right do not work. Some ideas ?
1342                                Hydrogen::get_instance()->setPatternPos( Hydrogen::get_instance()->getPatternPos() + 1 );
1343                                return TRUE;
1344                                break;
1345                       
1346                        case Qt::Key_L :
1347                                Hydrogen::get_instance()->togglePlaysSelected();
1348                                QString msg = Preferences::getInstance()->patternModePlaysSelected() ? "Single pattern mode" : "Stacked pattern mode";
1349                                HydrogenApp::getInstance()->setStatusBarMessage( msg, 5000 );
1350                                HydrogenApp::getInstance()->getSongEditorPanel()->setModeActionBtn( Preferences::getInstance()->patternModePlaysSelected() );
1351                                HydrogenApp::getInstance()->getSongEditorPanel()->updateAll();
1352                               
1353                                return TRUE;
1354                       
1355                //      QAccel *a = new QAccel( this );
1356//      a->connectItem( a->insertItem(Key_S + CTRL), this, SLOT( onSaveAccelEvent() ) );
1357//      a->connectItem( a->insertItem(Key_O + CTRL), this, SLOT( onOpenAccelEvent() ) );
1358
1359                }
1360
1361                // virtual keyboard handling
1362                map<int,int>::iterator found = keycodeInstrumentMap.find ( k->key() );
1363                if (found != keycodeInstrumentMap.end()) {
1364//                      INFOLOG( "[eventFilter] virtual keyboard event" );
1365                        // insert note at the current column in time
1366                        // if event recording enabled
1367                        int row = (*found).second;
1368                        Hydrogen* engine = Hydrogen::get_instance();
1369
1370                        float velocity = 0.8;
1371                        float pan_L = 1.0;
1372                        float pan_R = 1.0;
1373
1374                        engine->addRealtimeNote (row, velocity, pan_L, pan_R);
1375
1376                        return TRUE; // eat event
1377                }
1378                else {
1379                        return FALSE; // let it go
1380                }
1381        }
1382        else {
1383                return FALSE; // standard event processing
1384        }
1385}
1386
1387
1388
1389
1390
1391/// print the object map
1392void MainForm::action_debug_printObjects()
1393{
1394        INFOLOG( "[action_debug_printObjects]" );
1395        Object::print_object_map();
1396}
1397
1398
1399
1400
1401
1402
1403void MainForm::action_file_export_midi()
1404{
1405        if ( ((Hydrogen::get_instance())->getState() == STATE_PLAYING) ) {
1406                Hydrogen::get_instance()->sequencer_stop();
1407        }
1408
1409        QFileDialog *fd = new QFileDialog(this);
1410        fd->setFileMode(QFileDialog::AnyFile);
1411        fd->setFilter( trUtf8("Midi file (*.mid)") );
1412        fd->setDirectory( QDir::homePath() );
1413        fd->setWindowTitle( trUtf8( "Export MIDI file" ) );
1414        fd->setAcceptMode( QFileDialog::AcceptSave );
1415//      fd->setIcon( QPixmap( Skin::getImagePath() + "/icon16.png" ) );
1416
1417        QString sFilename = "";
1418        if ( fd->exec() == QDialog::Accepted ) {
1419                sFilename = fd->selectedFiles().first();
1420        }
1421
1422        if ( sFilename != "" ) {
1423                if ( sFilename.endsWith(".mid") == false ) {
1424                        sFilename += ".mid";
1425                }
1426
1427                Song *pSong = Hydrogen::get_instance()->getSong();
1428
1429                // create the Standard Midi File object
1430                SMFWriter *pSmfWriter = new SMFWriter();
1431                pSmfWriter->save( sFilename, pSong );
1432
1433                delete pSmfWriter;
1434        }
1435}
1436
1437
1438
1439void MainForm::errorEvent( int nErrorCode )
1440{
1441        //ERRORLOG( "[errorEvent]" );
1442
1443        QString msg;
1444        switch (nErrorCode) {
1445                case Hydrogen::UNKNOWN_DRIVER:
1446                        msg = trUtf8( "Unknown audio driver" );
1447                        break;
1448
1449                case Hydrogen::ERROR_STARTING_DRIVER:
1450                        msg = trUtf8( "Error starting audio driver" );
1451                        break;
1452
1453                case Hydrogen::JACK_SERVER_SHUTDOWN:
1454                        msg = trUtf8( "Jack driver: server shutdown" );
1455                        break;
1456
1457                case Hydrogen::JACK_CANNOT_ACTIVATE_CLIENT:
1458                        msg = trUtf8( "Jack driver: cannot activate client" );
1459                        break;
1460
1461                case Hydrogen::JACK_CANNOT_CONNECT_OUTPUT_PORT:
1462                        msg = trUtf8( "Jack driver: cannot connect output port" );
1463                        break;
1464
1465                case Hydrogen::JACK_ERROR_IN_PORT_REGISTER:
1466                        msg = trUtf8( "Jack driver: error in port register" );
1467                        break;
1468
1469                default:
1470                        msg = QString( trUtf8( "Unknown error %1" ) ).arg( nErrorCode );
1471        }
1472        QMessageBox::information( this, "Hydrogen", msg );
1473}
1474
1475
1476void MainForm::action_file_songProperties()
1477{
1478        SongPropertiesDialog *pDialog = new SongPropertiesDialog( this );
1479        if ( pDialog->exec() == QDialog::Accepted ) {
1480                Hydrogen::get_instance()->getSong()->__is_modified = true;
1481        }
1482        delete pDialog;
1483}
1484
1485
1486void MainForm::action_window_showPatternEditor()
1487{
1488        bool isVisible = HydrogenApp::getInstance()->getPatternEditorPanel()->isVisible();
1489        HydrogenApp::getInstance()->getPatternEditorPanel()->setHidden( isVisible );
1490}
1491
1492
1493///
1494/// Retrieve from the website the latest version available.
1495///
1496/// Warning: Hydrogen is not a spyware!!
1497/// Hydrogen sends only the current version and the OS used in order to let possible
1498/// to use an auto-updater in the future (this feature is not ready yet).
1499///
1500/// *** No user data will be stored in the server ***
1501///
1502void MainForm::getLatestVersion()
1503{
1504        #if defined( Q_OS_MACX )
1505        QString os = "Mac";
1506        #elif defined( Q_OS_WIN32 )
1507        QString os = "Windows";
1508        #elif defined( Q_OS_WIN64 )
1509        QString os = "Windows64";
1510        #elif defined( Q_OS_LINUX )
1511        QString os = "Linux";
1512        #elif defined( Q_OS_FREEBSD )
1513        QString os = "FreeBSD";
1514        #elif defined( Q_OS_UNIX )
1515        QString os = "Unix";
1516        #else
1517        QString os = "Unknown";
1518        #endif
1519
1520
1521        QString sRequest = QString("/getLatestVersion.php?UsingVersion=%1").arg( get_version().c_str() );
1522        sRequest += QString( "&OS=%1" ).arg( os );
1523
1524        //INFOLOG( sRequest );
1525
1526        QHttpRequestHeader header( "GET", sRequest );
1527        header.setValue( "Host", "www.hydrogen-music.org" );
1528
1529        m_http.setHost( "www.hydrogen-music.org" );
1530        m_http.request( header );
1531}
1532
1533
1534
1535void MainForm::latestVersionDone(bool bError)
1536{
1537        if ( bError ) {
1538                INFOLOG( "[MainForm::latestVersionDone] Error." );
1539                return;
1540        }
1541
1542        QString sLatestVersion( m_http.readAll() );
1543        sLatestVersion = sLatestVersion.simplified();
1544        QString sLatest_major = sLatestVersion.section( '.', 0, 0 );
1545        QString sLatest_minor = sLatestVersion.section( '.', 1, 1 );
1546        QString sLatest_micro = sLatestVersion.section( '.', 2, 2 );
1547//      INFOLOG( "Latest available version is: " + QString( sLatestVersion.ascii() ) );
1548
1549        QString sCurrentVersion = get_version().c_str();
1550        QString sCurrent_major = sCurrentVersion.section( '.', 0, 0 );
1551        QString sCurrent_minor = sCurrentVersion.section( '.', 1, 1 );
1552        QString sCurrent_micro = sCurrentVersion.section( '.', 2, 2 );
1553        if ( sCurrent_micro.section( '-', 0, 0 ) != "" ) {
1554                sCurrent_micro = sCurrent_micro.section( '-', 0, 0 );
1555        }
1556
1557        bool bExistsNewVersion = false;
1558        if ( sLatest_major > sCurrent_major ) {
1559                bExistsNewVersion = true;
1560        }
1561        else if ( sLatest_minor > sCurrent_minor ) {
1562                        bExistsNewVersion = true;
1563        }
1564        else if ( sLatest_micro > sCurrent_micro ) {
1565                bExistsNewVersion = true;
1566        }
1567
1568        bool bUsingDevelVersion = false;
1569        if ( sLatest_major < sCurrent_major ) {
1570                bUsingDevelVersion = true;
1571        }
1572        else if ( sLatest_major == sCurrent_major && sLatest_minor < sCurrent_minor ) {
1573                bUsingDevelVersion = true;
1574        }
1575        else if ( sLatest_major == sCurrent_major && sLatest_minor == sCurrent_minor && sLatest_micro < sCurrent_micro ) {
1576                bUsingDevelVersion = true;
1577        }
1578
1579        if ( bExistsNewVersion ) {
1580                QString sLatest = QString(sLatest_major) + "." +  QString(sLatest_minor) + "." + QString(sLatest_micro);
1581                WARNINGLOG( "\n\n*** A newer version (v" + sLatest + ") of Hydrogen is available at http://www.hydrogen-music.org\n" );
1582        }
1583
1584        if ( bUsingDevelVersion ) {
1585                Preferences *pref = Preferences::getInstance();
1586                bool isDevelWarningEnabled = pref->getShowDevelWarning();
1587                if(isDevelWarningEnabled) {
1588
1589                        QString msg = trUtf8( "You're using a development version of Hydrogen, please help us reporting bugs or suggestions in the hydrogen-devel mailing list.<br><br>Thank you!" );
1590                        QMessageBox develMessageBox( this );
1591                        develMessageBox.setText( msg );
1592                        develMessageBox.addButton( QMessageBox::Ok );
1593                        develMessageBox.addButton( trUtf8( "Don't show this message anymore" ) , QMessageBox::AcceptRole );
1594
1595                        if( develMessageBox.exec() == 0 ){
1596                                //don't show warning again
1597                                pref->setShowDevelWarning( false );
1598                        }
1599          }
1600
1601
1602        }
1603}
1604
1605
1606
1607QString MainForm::getAutoSaveFilename()
1608{
1609        Song *pSong = Hydrogen::get_instance()->getSong();
1610        assert( pSong );
1611        QString sOldFilename = pSong->get_filename();
1612        QString newName = "autosave.h2song";
1613
1614        if ( sOldFilename != "" ) {
1615                newName = sOldFilename.left( sOldFilename.length() - 7 ) + ".autosave.h2song";
1616        }
1617
1618        return newName;
1619}
1620
1621
1622
1623void MainForm::onAutoSaveTimer()
1624{
1625        //INFOLOG( "[onAutoSaveTimer]" );
1626        Song *pSong = Hydrogen::get_instance()->getSong();
1627        assert( pSong );
1628        QString sOldFilename = pSong->get_filename();
1629
1630        pSong->save( getAutoSaveFilename() );
1631
1632        pSong->set_filename(sOldFilename);
1633
1634/*
1635        Song *pSong = h2app->getSong();
1636        if (pSong->getFilename() == "") {
1637                pSong->save( "autosave.h2song" );
1638                return;
1639        }
1640
1641        action_file_save();
1642*/
1643}
1644
1645
1646void MainForm::onPlaylistDisplayTimer()
1647{
1648        if( Hydrogen::get_instance()->m_PlayList.size() == 0)
1649                return;
1650        int songnumber = Playlist::get_instance()->getActiveSongNumber();
1651        QString songname = "";
1652        if ( songnumber == -1 )
1653                        return;
1654
1655        if ( Hydrogen::get_instance()->getSong()->__name == "Untitled Song" ){
1656                songname = Hydrogen::get_instance()->getSong()->get_filename();
1657        }else
1658        {
1659                songname = Hydrogen::get_instance()->getSong()->__name;
1660        }
1661        QString message = (trUtf8("Playlist: Song No. %1").arg( songnumber + 1)) + QString("  ---  Songname: ") + songname + QString("  ---  Author: ") + Hydrogen::get_instance()->getSong()->__author;
1662        HydrogenApp::getInstance()->setScrollStatusBarMessage( message, 2000 );
1663}
Note: See TracBrowser for help on using the browser.