root/branches/0.9.5/gui/src/MainForm.cpp @ 2460

Revision 2460, 45.1 KB (checked in by mauser, 15 months ago)

[0.9.5] set version to 0.9.5.1 / disable development warning

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