diff options
Diffstat (limited to 'muse2/muse/main.cpp')
-rw-r--r-- | muse2/muse/main.cpp | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/muse2/muse/main.cpp b/muse2/muse/main.cpp new file mode 100644 index 00000000..a11b2e0b --- /dev/null +++ b/muse2/muse/main.cpp @@ -0,0 +1,531 @@ +//========================================================= +// MusE +// Linux Music Editor +// $Id: app.cpp,v 1.113.2.68 2009/12/21 14:51:51 spamatica Exp $ +// +// (C) Copyright 1999-2004 Werner Schweer (ws@seh.de) +//========================================================= + +#include <QApplication> +#include <QDir> +#include <QKeyEvent> +#include <QMessageBox> +#include <QLocale> +#include <QSplashScreen> +#include <QTimer> +#include <QTranslator> + +#include <sys/mman.h> +#include <alsa/asoundlib.h> + +#include "al/dsp.h" +#include "app.h" +#include "audio.h" +#include "audiodev.h" +#include "gconfig.h" +#include "globals.h" +#include "icons.h" +#include "sync.h" + +extern bool initDummyAudio(); +extern void initIcons(); +extern bool initJackAudio(); +extern void initMidiController(); +extern void initMetronome(); +extern void initOSC(); +extern void initVST(); +extern void initPlugins(); +extern void initShortCuts(); +extern void initDSSI(); +extern void readConfiguration(); + +static QString locale_override; + +#ifdef HAVE_LASH +#include <lash/lash.h> +extern lash_client_t * lash_client; +extern snd_seq_t * alsaSeq; +#endif + +//--------------------------------------------------------- +// getCapabilities +//--------------------------------------------------------- + +static void getCapabilities() + { +#ifdef RTCAP +#ifdef __linux__ + const char* napp = getenv("GIVERTCAP"); + if (napp == 0) + napp = "givertcap"; + int pid = fork(); + if (pid == 0) { + if (execlp(napp, napp, 0) == -1) + perror("exec givertcap failed"); + } + else if (pid == -1) { + perror("fork givertcap failed"); + } + else { + waitpid(pid, 0, 0); + } +#endif // __linux__ +#endif + } + +//--------------------------------------------------------- +// printVersion +//--------------------------------------------------------- + +static void printVersion(const char* prog) + { + fprintf(stderr, "%s: Linux Music Editor; Version %s, (svn revision %s)\n", prog, VERSION, SVNVERSION); + } + +//--------------------------------------------------------- +// MuseApplication +//--------------------------------------------------------- + +class MuseApplication : public QApplication { + MusE* muse; + + public: + MuseApplication(int& argc, char** argv) + : QApplication(argc, argv) + { + muse = 0; + } + + + void setMuse(MusE* m) { + muse = m; +#ifdef HAVE_LASH + if(useLASH) + startTimer (300); +#endif + } + + bool notify(QObject* receiver, QEvent* event) { + //if (event->type() == QEvent::KeyPress) + // printf("notify key press before app::notify accepted:%d\n", event->isAccepted()); + bool flag = QApplication::notify(receiver, event); + if (event->type() == QEvent::KeyPress) { + //printf("notify key press after app::notify accepted:%d\n", event->isAccepted()); + QKeyEvent* ke = (QKeyEvent*)event; + ///globalKeyState = ke->stateAfter(); + globalKeyState = ke->modifiers(); + bool accepted = ke->isAccepted(); + if (!accepted) { + int key = ke->key(); + ///if (ke->state() & Qt::ShiftModifier) + //if (globalKeyState & Qt::ShiftModifier) + if (((QInputEvent*)ke)->modifiers() & Qt::ShiftModifier) + key += Qt::SHIFT; + ///if (ke->state() & Qt::AltModifier) + //if (globalKeyState & Qt::AltModifier) + if (((QInputEvent*)ke)->modifiers() & Qt::AltModifier) + key += Qt::ALT; + ///if (ke->state() & Qt::ControlModifier) + //if (globalKeyState & Qt::ControlModifier) + if (((QInputEvent*)ke)->modifiers() & Qt::ControlModifier) + key+= Qt::CTRL; + muse->kbAccel(key); + return true; + } + } + if (event->type() == QEvent::KeyRelease) { + QKeyEvent* ke = (QKeyEvent*)event; + ///globalKeyState = ke->stateAfter(); + globalKeyState = ke->modifiers(); + } + + return flag; + } + +#ifdef HAVE_LASH + virtual void timerEvent (QTimerEvent * /* e */) { + if(useLASH) + muse->lash_idle_cb (); + } +#endif /* HAVE_LASH */ + + }; + +//--------------------------------------------------------- +// localeList +//--------------------------------------------------------- + +static QString localeList() + { + // Find out what translations are available: + QStringList deliveredLocaleListFiltered; + QString distLocale = QString(INSTPREFIX) + "/" + SHAREINSTPREFIX + "/" + + INSTALL_NAME + "/locale"; + QFileInfo distLocaleFi(distLocale); + if (distLocaleFi.isDir()) { + QDir dir = QDir(distLocale); + QStringList deliveredLocaleList = dir.entryList(); + for(QStringList::iterator it = deliveredLocaleList.begin(); it != deliveredLocaleList.end(); ++it) { + QString item = *it; + if (item.endsWith(".qm")) { + int inipos = item.indexOf("muse_") + 5; + int finpos = item.lastIndexOf(".qm"); + deliveredLocaleListFiltered << item.mid(inipos, finpos - inipos); + } + } + return deliveredLocaleListFiltered.join(","); + } + return QString("No translations found!"); + } + +//--------------------------------------------------------- +// usage +//--------------------------------------------------------- + +static void usage(const char* prog, const char* txt) + { + fprintf(stderr, "%s: %s\nusage: %s flags midifile\n Flags:\n", + prog, txt, prog); + fprintf(stderr, " -h this help\n"); + fprintf(stderr, " -v print version\n"); + fprintf(stderr, " -d debug mode: no threads, no RT\n"); + fprintf(stderr, " -D debug mode: enable some debug messages\n"); + fprintf(stderr, " -m debug mode: trace midi Input\n"); + fprintf(stderr, " -M debug mode: trace midi Output\n"); + fprintf(stderr, " -s debug mode: trace sync\n"); + fprintf(stderr, " -a no audio\n"); + //fprintf(stderr, " -P n set real time priority to n (default: 50)\n"); + fprintf(stderr, " -P n set audio driver real time priority to n (Dummy only, default 40. Else fixed by Jack.)\n"); + fprintf(stderr, " -Y n force midi real time priority to n (default: audio driver prio +2)\n"); + fprintf(stderr, " -p don't load LADSPA plugins\n"); +#ifdef ENABLE_PYTHON + fprintf(stderr, " -y enable Python control support\n"); +#endif +#ifdef VST_SUPPORT + fprintf(stderr, " -V don't load VST plugins\n"); +#endif +#ifdef DSSI_SUPPORT + fprintf(stderr, " -I don't load DSSI plugins\n"); +#endif +#ifdef HAVE_LASH + fprintf(stderr, " -L don't use LASH\n"); +#endif + fprintf(stderr, " -l xx force locale to the given language/country code (xx = %s)\n", localeList().toLatin1().constData()); + fprintf(stderr, "useful environment variables:\n"); + fprintf(stderr, " MUSE override library and shared directories location\n"); + fprintf(stderr, " MUSEHOME override user home directory (HOME/)\n"); + fprintf(stderr, " MUSEINSTRUMENTS override user instrument directory (MUSEHOME/muse_instruments)\n"); + } + +//--------------------------------------------------------- +// main +//--------------------------------------------------------- + +int main(int argc, char* argv[]) + { + +// error = ErrorHandler::create(argv[0]); + ruid = getuid(); + euid = geteuid(); + undoSetuid(); + getCapabilities(); + int noAudio = false; + + const char* mu = getenv("MUSEHOME"); + if(mu) + museUser = QString(mu); + if(museUser.isEmpty()) + museUser = QString(getenv("HOME")); + + QString museGlobal; + const char* p = getenv("MUSE"); + if (p) + museGlobal = p; + + if (museGlobal.isEmpty()) { + //QString museGlobal(INSTPREFIX); + //QString museGlobalLibDir(INSTLIBDIR); + //QString museGlobalLibDir(LIBINSTPREFIX); // This has no prefix. + //museGlobalLib = museGlobalLibDir + "/muse"; + //museGlobalShare = museGlobal + "/share/muse"; + + // p4.0.7 + museGlobalLib = QString(INSTPREFIX) + QString("/") + + QString(LIBINSTPREFIX) + QString("/") + + QString(INSTALL_NAME); + //museGlobalShare = museGlobal + QString("/share/") + QString(INSTALL_NAME); + museGlobalShare = QString(INSTPREFIX) + QString("/") + + QString(SHAREINSTPREFIX) + QString("/") + // This has no prefix. Default is "share", set in top cmake script. + QString(INSTALL_NAME); + } + else { + //museGlobalLib = museGlobal + "/lib"; + //museGlobalShare = museGlobal + "/share"; + museGlobalLib = museGlobal + QString("/") + QString(LIBINSTPREFIX); // p4.0.7 + museGlobalShare = museGlobal + QString("/") + QString(SHAREINSTPREFIX); + } + museProject = museProjectInitPath; //getcwd(0, 0); + configName = QString(getenv("HOME")) + QString("/.MusE"); + + museInstruments = museGlobalShare + QString("/instruments"); + + const char* ins = getenv("MUSEINSTRUMENTS"); + if(ins) + museUserInstruments = QString(ins); + if(museUserInstruments.isEmpty()) + museUserInstruments = museUser + QString("/muse_instruments"); + +#ifdef HAVE_LASH + lash_args_t * lash_args = 0; + if(useLASH) + lash_args = lash_extract_args (&argc, &argv); +#endif + + srand(time(0)); // initialize random number generator +// signal(SIGCHLD, catchSignal); // interferes with initVST() + initMidiController(); + QApplication::setColorSpec(QApplication::ManyColor); + MuseApplication app(argc, argv); + + initShortCuts(); + readConfiguration(); + + if (config.useDenormalBias) + printf("Denormal protection enabled.\n"); + // SHOW MUSE SPLASH SCREEN + if (config.showSplashScreen) { + QPixmap splsh(museGlobalShare + "/splash.png"); + + if (!splsh.isNull()) { + QSplashScreen* muse_splash = new QSplashScreen(splsh, + Qt::WindowStaysOnTopHint); + muse_splash->setAttribute(Qt::WA_DeleteOnClose); // Possibly also Qt::X11BypassWindowManagerHint + muse_splash->show(); + QTimer* stimer = new QTimer(0); + muse_splash->connect(stimer, SIGNAL(timeout()), muse_splash, SLOT(close())); + stimer->setSingleShot(true); + stimer->start(6000); + } + } + + int i; + + QString optstr("ahvdDmMsP:Y:l:py"); +#ifdef VST_SUPPORT + optstr += QString("V"); +#endif +#ifdef DSSI_SUPPORT + optstr += QString("I"); +#endif +#ifdef HAVE_LASH + optstr += QString("L"); +#endif + +//#ifdef VST_SUPPORT +// while ((i = getopt(argc, argv, "ahvdDmMsVP:py")) != EOF) { +//#else +// while ((i = getopt(argc, argv, "ahvdDmMsP:py")) != EOF) { +//#endif + + while ((i = getopt(argc, argv, optstr.toLatin1().constData())) != EOF) { + char c = (char)i; + switch (c) { + case 'v': printVersion(argv[0]); return 0; + case 'd': + debugMode = true; + realTimeScheduling = false; + break; + case 'a': + noAudio = true; + break; + case 'D': debugMsg = true; break; + case 'm': midiInputTrace = true; break; + case 'M': midiOutputTrace = true; break; + case 's': debugSync = true; break; + case 'P': realTimePriority = atoi(optarg); break; + case 'Y': midiRTPrioOverride = atoi(optarg); break; + case 'p': loadPlugins = false; break; + case 'V': loadVST = false; break; + case 'I': loadDSSI = false; break; + case 'L': useLASH = false; break; + case 'y': usePythonBridge = true; break; + case 'l': locale_override = QString(optarg); break; + case 'h': usage(argv[0], argv[1]); return -1; + default: usage(argv[0], "bad argument"); return -1; + } + } + + /* + if(!config.styleSheetFile.isEmpty()) + { + if(debugMsg) + printf("loading style sheet <%s> \n", qPrintable(config.styleSheetFile)); + QFile cf(config.styleSheetFile); + if (cf.open(QIODevice::ReadOnly)) { + QByteArray ss = cf.readAll(); + QString sheet(QString::fromUtf8(ss.data())); + app.setStyleSheet(sheet); + cf.close(); + } + else + printf("loading style sheet <%s> failed\n", qPrintable(config.styleSheetFile)); + } + */ + + AL::initDsp(); + + if (debugMsg) + printf("Start euid: %d ruid: %d, Now euid %d\n", + euid, ruid, geteuid()); + if (debugMode) { + initDummyAudio(); + realTimeScheduling = false; + } + else if (noAudio) { + initDummyAudio(); + realTimeScheduling = true; + //if (debugMode) { // ?? + // realTimeScheduling = false; + // } + } + else if (initJackAudio()) { + if (!debugMode) + { + QMessageBox::critical(NULL, "MusE fatal error", "MusE <b>failed</b> to find a <b>Jack audio server</b>.<br><br>" + "<i>MusE will continue without audio support (-a switch)!</i><br><br>" + "If this was not intended check that Jack was started. " + "If Jack <i>was</i> started check that it was\n" + "started as the same user as MusE.\n"); + + initDummyAudio(); + noAudio = true; + realTimeScheduling = true; + if (debugMode) { + realTimeScheduling = false; + } + } + else + { + fprintf(stderr, "fatal error: no JACK audio server found\n"); + fprintf(stderr, "no audio functions available\n"); + fprintf(stderr, "*** experimental mode -- no play possible ***\n"); + initDummyAudio(); + //realTimeScheduling = audioDevice->isRealtime(); + } + realTimeScheduling = true; + } + else + realTimeScheduling = audioDevice->isRealtime(); + + useJackTransport.setValue(true); + // setup the prefetch fifo length now that the segmentSize is known + // Changed by Tim. p3.3.17 + // Changed to 4 *, JUST FOR TEST!!! + fifoLength = 131072/segmentSize; + //fifoLength = (131072/segmentSize) * 4; + + + argc -= optind; + ++argc; + + if (debugMsg) { + printf("global lib: <%s>\n", museGlobalLib.toLatin1().constData()); + printf("global share: <%s>\n", museGlobalShare.toLatin1().constData()); + printf("muse home: <%s>\n", museUser.toLatin1().constData()); + printf("project dir: <%s>\n", museProject.toLatin1().constData()); + printf("user instruments: <%s>\n", museUserInstruments.toLatin1().constData()); + } + + static QTranslator translator(0); + QString locale(QApplication::keyboardInputLocale().name()); + if (locale_override.length()) + locale = locale_override; + if (locale != "C") { + QString loc("muse_"); + loc += locale; + if (translator.load(loc, QString(".")) == false) { + QString lp(museGlobalShare); + lp += QString("/locale"); + if (translator.load(loc, lp) == false) { + printf("no locale <%s>/<%s>\n", loc.toLatin1().constData(), lp.toLatin1().constData()); + } + } + app.installTranslator(&translator); + } + + if (locale == "de") { + printf("locale de\n"); + hIsB = false; + } + + if (loadPlugins) + initPlugins(); + + if (loadVST) + initVST(); + + if(loadDSSI) + initDSSI(); + + // p3.3.39 + initOSC(); + + initIcons(); + + initMetronome(); + + //QApplication::clipboard()->setSelectionMode(false); ddskrjo obsolete even in Qt3 + + QApplication::addLibraryPath(museGlobalLib + "/qtplugins"); + if (debugMsg) { + QStringList list = app.libraryPaths(); + QStringList::Iterator it = list.begin(); + printf("QtLibraryPath:\n"); + while(it != list.end()) { + printf(" <%s>\n", (*it).toLatin1().constData()); + ++it; + } + } + + muse = new MusE(argc, &argv[optind]); + app.setMuse(muse); + muse->setWindowIcon(*museIcon); + + // Added by Tim. p3.3.22 + if (!debugMode) { + if (mlockall(MCL_CURRENT | MCL_FUTURE)) + perror("WARNING: Cannot lock memory:"); + } + + muse->show(); + muse->seqStart(); + +#ifdef HAVE_LASH + { + lash_client = 0; + if(useLASH) + { + int lash_flags = LASH_Config_File; + const char *muse_name = PACKAGE_NAME; + lash_client = lash_init (lash_args, muse_name, lash_flags, LASH_PROTOCOL(2,0)); + lash_alsa_client_id (lash_client, snd_seq_client_id (alsaSeq)); + if (!noAudio) { + // p3.3.38 + //char *jack_name = ((JackAudioDevice*)audioDevice)->getJackName(); + const char *jack_name = audioDevice->clientName(); + lash_jack_client_name (lash_client, jack_name); + } + } + } +#endif /* HAVE_LASH */ + QTimer::singleShot(100, muse, SLOT(showDidYouKnowDialog())); + + int rv = app.exec(); + if(debugMsg) + printf("app.exec() returned:%d\nDeleting main MusE object\n", rv); + delete muse; + if(debugMsg) + printf("Finished! Exiting main, return value:%d\n", rv); + return rv; + + } |