root/branches/0.9.4/gui/src/MainForm.cpp @ 1562

Revision 1562, 45.5 KB (checked in by mauser, 3 years ago)

Bugfix: generate a valid id for new instruments

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