root/branches/undo/src/gui/src/main.cpp @ 2236

Revision 2236, 14.1 KB (checked in by wolke, 2 years ago)

add first step of jack session implementation

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
23#include <QtGui>
24#include <QLibraryInfo>
25#include <hydrogen/config.h>
26#include <hydrogen/version.h>
27#include <getopt.h>
28
29#include "SplashScreen.h"
30#include "HydrogenApp.h"
31#include "MainForm.h"
32#include "PlaylistEditor/PlaylistDialog.h"
33
34#ifdef H2CORE_HAVE_LASH
35#include <hydrogen/LashClient.h>
36#endif
37#ifdef H2CORE_HAVE_JACKSESSION
38#include <jack/session.h>
39#endif
40
41#include <hydrogen/midiMap.h>
42#include <hydrogen/audio_engine.h>
43#include <hydrogen/hydrogen.h>
44#include <hydrogen/globals.h>
45#include <hydrogen/event_queue.h>
46#include <hydrogen/Preferences.h>
47#include <hydrogen/h2_exception.h>
48#include <hydrogen/playlist.h>
49#include <hydrogen/helpers/filesystem.h>
50
51#include <signal.h>
52#include <iostream>
53using namespace std;
54
55void showInfo();
56void showUsage();
57
58
59#define HAS_ARG 1
60static struct option long_opts[] = {
61        {"driver", required_argument, NULL, 'd'},
62        {"song", required_argument, NULL, 's'},
63#ifdef H2CORE_HAVE_JACKSESSION
64        {"session-id", required_argument, NULL, 'S'},
65#endif
66        {"playlist", required_argument, NULL, 'p'},
67        {"version", 0, NULL, 'v'},
68        {"nosplash", 0, NULL, 'n'},
69        {"verbose", optional_argument, NULL, 'V'},
70        {"help", 0, NULL, 'h'},
71        {"install", required_argument, NULL, 'i'},
72        {"drumkit", required_argument, NULL, 'k'},
73        {0, 0, 0, 0},
74};
75
76#define NELEM(a) ( sizeof(a)/sizeof((a)[0]) )
77
78
79//
80// Set the palette used in the application
81//
82void setPalette( QApplication *pQApp )
83{
84        // create the default palette
85        QPalette defaultPalette;
86
87        // A general background color.
88        defaultPalette.setColor( QPalette::Background, QColor( 58, 62, 72 ) );
89
90        // A general foreground color.
91        defaultPalette.setColor( QPalette::Foreground, QColor( 255, 255, 255 ) );
92
93        // Used as the background color for text entry widgets; usually white or another light color.
94        defaultPalette.setColor( QPalette::Base, QColor( 88, 94, 112 ) );
95
96        // Used as the alternate background color in views with alternating row colors
97        defaultPalette.setColor( QPalette::AlternateBase, QColor( 138, 144, 162 ) );
98
99        // The foreground color used with Base. This is usually the same as the Foreground, in which case it must provide good contrast with Background and Base.
100        defaultPalette.setColor( QPalette::Text, QColor( 255, 255, 255 ) );
101
102        // The general button background color. This background can be different from Background as some styles require a different background color for buttons.
103        defaultPalette.setColor( QPalette::Button, QColor( 88, 94, 112 ) );
104
105        // A foreground color used with the Button color.
106        defaultPalette.setColor( QPalette::ButtonText, QColor( 255, 255, 255 ) );
107
108
109        // Lighter than Button color.
110        defaultPalette.setColor( QPalette::Light, QColor( 138, 144, 162 ) );
111
112        // Between Button and Light.
113        defaultPalette.setColor( QPalette::Midlight, QColor( 128, 134, 152 ) );
114
115        // Darker than Button.
116        defaultPalette.setColor( QPalette::Dark, QColor( 58, 62, 72 ) );
117
118        // Between Button and Dark.
119        defaultPalette.setColor( QPalette::Mid, QColor( 81, 86, 99 ) );
120
121        // A very dark color. By default, the shadow color is Qt::black.
122        defaultPalette.setColor( QPalette::Shadow, QColor( 255, 255, 255 ) );
123
124
125        // A color to indicate a selected item or the current item.
126        defaultPalette.setColor( QPalette::Highlight, QColor( 116, 124, 149 ) );
127
128        // A text color that contrasts with Highlight.
129        defaultPalette.setColor( QPalette::HighlightedText, QColor( 255, 255, 255 ) );
130
131        pQApp->setPalette( defaultPalette );
132}
133
134
135static int setup_unix_signal_handlers()
136{
137#ifndef WIN32
138    struct sigaction usr1;
139
140    usr1.sa_handler = MainForm::usr1SignalHandler;
141    sigemptyset(&usr1.sa_mask);
142    usr1.sa_flags = 0;
143    usr1.sa_flags |= SA_RESTART;
144
145    if (sigaction(SIGUSR1, &usr1, 0) > 0)
146       return 1;
147
148    return 0;
149#endif
150}
151
152int main(int argc, char *argv[])
153{
154        try {
155                // Options...
156                char *cp;
157                struct option *op;
158                char opts[NELEM(long_opts) * 3 + 1];
159
160                // Build up the short option QString
161                cp = opts;
162                for (op = long_opts; op < &long_opts[NELEM(long_opts)]; op++) {
163                        *cp++ = op->val;
164                        if (op->has_arg)
165                                *cp++ = ':';
166                        if (op->has_arg == optional_argument )
167                                *cp++ = ':';  // gets another one
168                }
169
170                QApplication* pQApp = new QApplication(argc, argv);
171
172                // Deal with the options
173                QString songFilename;
174#ifdef H2CORE_HAVE_JACKSESSION
175                QString sessionId;
176#endif
177                QString playlistFilename;
178                bool bNoSplash = false;
179                QString sSelectedDriver;
180                bool showVersionOpt = false;
181                unsigned logLevelOpt = H2Core::Logger::Error;
182                QString drumkitName;
183                QString drumkitToLoad;
184                bool showHelpOpt = false;
185
186                int c;
187                for (;;) {
188                        c = getopt_long(argc, argv, opts, long_opts, NULL);
189                        if (c == -1)
190                                break;
191
192                        switch(c) {
193                                case 'd':
194                                        sSelectedDriver = QString::fromLocal8Bit(optarg);
195                                        break;
196
197                                case 's':
198                                        songFilename = QString::fromLocal8Bit(optarg);
199                                        break;
200#ifdef H2CORE_HAVE_JACKSESSION
201                                case 'S':
202                                        sessionId = QString::fromLocal8Bit(optarg);
203                                        break;
204#endif
205
206                                case 'p':
207                                        playlistFilename = QString::fromLocal8Bit(optarg);
208                                        break;
209
210                                case 'k':
211                                        //load Drumkit
212                                        drumkitToLoad = QString::fromLocal8Bit(optarg);
213                                        break;
214
215                                case 'v':
216                                        showVersionOpt = true;
217                                        break;
218
219                                case 'i':
220                                        //install h2drumkit
221                                        drumkitName = QString::fromLocal8Bit( optarg );
222                                        break;
223
224                                case 'V':
225                                        if( optarg ) {
226                                                logLevelOpt = H2Core::Logger::parse_log_level( optarg );
227                                        } else {
228                                                logLevelOpt = H2Core::Logger::Error|H2Core::Logger::Warning;
229                                        }
230                                        break;
231                                case 'n':
232                                        bNoSplash = true;
233                                        break;
234
235                                case 'h':
236                                case '?':
237                                        showHelpOpt = true;
238                                        break;
239                        }
240                }
241
242                setup_unix_signal_handlers();
243
244                if( showVersionOpt ) {
245                        std::cout << H2Core::get_version() << std::endl;
246                        exit(0);
247                }
248                showInfo();
249                if( showHelpOpt ) {
250                        showUsage();
251                        exit(0);
252                }
253
254                // Man your battle stations... this is not a drill.
255        H2Core::Logger::create_instance();
256        H2Core::Logger::set_bit_mask( logLevelOpt );
257        H2Core::Logger* logger = H2Core::Logger::get_instance();
258        H2Core::Object::bootstrap( logger, logger->should_log(H2Core::Logger::Debug) );
259        H2Core::Filesystem::bootstrap( logger );
260                MidiMap::create_instance();
261                H2Core::Preferences::create_instance();
262                // See below for H2Core::Hydrogen.
263
264
265                ___INFOLOG( QString("Using QT version ") + QString( qVersion() ) );
266                ___INFOLOG( "Using data path: " + H2Core::Filesystem::sys_data_path() );
267
268                H2Core::Preferences *pPref = H2Core::Preferences::get_instance();
269
270#ifdef H2CORE_HAVE_LASH
271
272                LashClient::create_instance("hydrogen", "Hydrogen", &argc, &argv);
273                LashClient* lashClient = LashClient::get_instance();
274
275#endif
276                if( ! drumkitName.isEmpty() ){
277                    H2Core::Drumkit::install( drumkitName );
278                    exit(0);
279                }
280               
281                if (sSelectedDriver == "auto") {
282                        pPref->m_sAudioDriver = "Auto";
283                }
284                else if (sSelectedDriver == "jack") {
285                        pPref->m_sAudioDriver = "Jack";
286                }
287                else if ( sSelectedDriver == "oss" ) {
288                        pPref->m_sAudioDriver = "Oss";
289                }
290                else if ( sSelectedDriver == "alsa" ) {
291                        pPref->m_sAudioDriver = "Alsa";
292                }
293
294                QString family = pPref->getApplicationFontFamily();
295                pQApp->setFont( QFont( family, pPref->getApplicationFontPointSize() ) );
296
297                QTranslator qttor( 0 );
298                QTranslator tor( 0 );
299                QString sTranslationFile = QString("hydrogen.") + QLocale::system().name();
300                QString sLocale = QLocale::system().name();
301                if ( sLocale != "C") {
302                        if (qttor.load( QString( "qt_" ) + sLocale,
303                                QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
304                                pQApp->installTranslator( &qttor );
305                        else
306                                ___INFOLOG( QString("Warning: No Qt translation for locale %1 found.").arg(QLocale::system().name()));
307
308
309                        QString sTranslationPath = "data/i18n";
310                        QString total = sTranslationPath + "/" + sTranslationFile + ".qm";
311
312                        bool bTransOk = tor.load( total, "." );
313                        if ( bTransOk ) {
314                                ___INFOLOG( QString( "Using locale: %1/%2" ).arg( sTranslationPath ).arg( sTranslationFile ) );
315                        }
316                        else {
317                                sTranslationPath = H2Core::Filesystem::i18n_dir();
318                                total = sTranslationPath + "/" + sTranslationFile + ".qm";
319                                bTransOk = tor.load( total, "." );
320                                if (bTransOk) {
321                                        ___INFOLOG( "Using locale: " + sTranslationPath + "/" + sTranslationFile );
322                                }
323                                else {
324                                        ___INFOLOG( "Warning: no locale found: " + sTranslationPath + "/" + sTranslationFile );
325                                }
326                        }
327                        if (tor.isEmpty()) {
328                                ___INFOLOG( "Warning: error loading locale: " +  total );
329                        }
330                }
331                pQApp->installTranslator( &tor );
332
333                QString sStyle = pPref->getQTStyle();
334                if ( !sStyle.isEmpty() ) {
335                        pQApp->setStyle( sStyle );
336                }
337
338                setPalette( pQApp );
339
340                SplashScreen *pSplash = new SplashScreen();
341
342                if (bNoSplash) {
343                        pSplash->hide();
344                }
345                else {
346                        pSplash->show();
347                }
348
349#ifdef H2CORE_HAVE_LASH
350        if ( H2Core::Preferences::get_instance()->useLash() ){ 
351                if (lashClient->isConnected())
352                {
353                        lash_event_t* lash_event = lashClient->getNextEvent();
354                        if (lash_event && lash_event_get_type(lash_event) == LASH_Restore_File)
355                        {
356                                // notify client that this project was not a new one
357                                lashClient->setNewProject(false);
358                               
359                                songFilename = "";
360                                songFilename.append( QString::fromLocal8Bit(lash_event_get_string(lash_event)) );
361                                songFilename.append("/hydrogen.h2song");
362                               
363//                              H2Core::Logger::get_instance()->log("[LASH] Restore file: " + songFilename);
364       
365                                lash_event_destroy(lash_event);
366                        }
367                        else if (lash_event)
368                        {
369//                              H2Core::Logger::get_instance()->log("[LASH] ERROR: Instead of restore file got event: " + lash_event_get_type(lash_event));
370                                lash_event_destroy(lash_event);
371                        }
372                }
373        }       
374#endif
375
376                // Hydrogen here to honor all preferences.
377                H2Core::Hydrogen::create_instance();
378                MainForm *pMainForm = new MainForm( pQApp, songFilename );
379                pMainForm->show();
380                pSplash->finish( pMainForm );
381                bool loadlist = HydrogenApp::get_instance()->getPlayListDialog()->loadListByFileName( playlistFilename );
382                if( loadlist ){
383                        Playlist::get_instance()->setNextSongByNumber( 0 );
384                }else
385                {
386                        ___ERRORLOG ( "Error loading the playlist" );
387                }
388
389                if( ! playlistFilename.isEmpty() ){
390                    bool loadlist = HydrogenApp::get_instance()->getPlayListDialog()->loadListByFileName( playlistFilename );
391                    if( loadlist ){
392                            Playlist::get_instance()->setNextSongByNumber( 0 );
393                    } else {
394                            ___ERRORLOG ( "Error loading the playlist" );
395                    }
396                }
397
398
399                if( ! drumkitToLoad.isEmpty() ){
400                        H2Core::Drumkit* drumkitInfo = H2Core::Drumkit::load( drumkitToLoad );
401                        H2Core::Hydrogen::get_instance()->loadDrumkit( drumkitInfo );
402                }
403                               
404
405                pQApp->exec();
406
407                delete pSplash;
408                delete pMainForm;
409                delete pQApp;
410                delete pPref;
411                delete H2Core::EventQueue::get_instance();
412                delete H2Core::AudioEngine::get_instance();
413
414                delete MidiMap::get_instance();
415                delete ActionManager::get_instance();
416
417                ___INFOLOG( "Quitting..." );
418                cout << "\nBye..." << endl;
419                delete H2Core::Logger::get_instance();
420
421                if (H2Core::Object::count_active()) {
422            H2Core::Object::write_objects_map_to_cerr();
423                }
424
425                //      pQApp->dumpObjectTree();
426
427        }
428        catch ( const H2Core::H2Exception& ex ) {
429                std::cerr << "[main] Exception: " << ex.what() << std::endl;
430        }
431        catch (...) {
432                std::cerr << "[main] Unknown exception X-(" << std::endl;
433        }
434
435        return 0;
436}
437
438
439
440/**
441 * Show some information
442 */
443void showInfo()
444{
445        cout << "\nHydrogen " + H2Core::get_version() + " [" + __DATE__ + "]  [http://www.hydrogen-music.org]" << endl;
446        cout << "Copyright 2002-2008 Alessandro Cominu" << endl;
447//      ___INFOLOG( "Compiled modules: " + QString(COMPILED_FEATURES) << endl;
448
449        if ( H2Core::Object::count_active() ) {
450                cout << "\nObject counting = active" << endl;
451        }
452
453        cout << "\nHydrogen comes with ABSOLUTELY NO WARRANTY" << endl;
454        cout << "This is free software, and you are welcome to redistribute it" << endl;
455        cout << "under certain conditions. See the file COPYING for details\n" << endl;
456}
457
458
459
460/**
461 * Show the correct usage
462 */
463void showUsage()
464{
465        std::cout << "Usage: hydrogen [-v] [-h] -s file" << std::endl;
466        std::cout << "   -d, --driver AUDIODRIVER - Use the selected audio driver (jack, alsa, oss)" << std::endl;
467        std::cout << "   -s, --song FILE - Load a song (*.h2song) at startup" << std::endl;
468
469#ifdef H2CORE_HAVE_JACKSESSION
470        std::cout << "   -S, --session-id ID - Start a JackSessionHandler session" << std::endl;
471#endif
472
473        std::cout << "   -p, --playlist FILE - Load a playlist (*.h2playlist) at startup" << std::endl;
474        std::cout << "   -k, --kit drumkit_name - Load a drumkit at startup" << std::endl;
475        std::cout << "   -i, --install FILE - install a drumkit (*.h2drumkit)" << std::endl;
476#ifdef H2CORE_HAVE_LASH
477        std::cout << "   --lash-no-start-server - If LASH server not running, don't start" << endl
478                  << "                            it (LASH 0.5.3 and later)." << std::endl;
479        std::cout << "   --lash-no-autoresume - Tell LASH server not to assume I'm returning" << std::endl
480                  << "                          from a crash." << std::endl;
481#endif
482        std::cout << "   -n, --nosplash - Hide splash screen" << std::endl;
483        std::cout << "   -V[Level], --verbose[=Level] - Print a lot of debugging info" << std::endl;
484        std::cout << "                 Level, if present, may be None, Error, Warning, Info, Debug or 0xHHHH" << std::endl;
485        std::cout << "   -v, --version - Show version info" << std::endl;
486        std::cout << "   -h, --help - Show this help message" << std::endl;
487}
488
Note: See TracBrowser for help on using the browser.