Chris@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@0: Chris@0: /* Chris@0: Sonic Visualiser Chris@0: An audio file viewer and annotation editor. Chris@0: Centre for Digital Music, Queen Mary, University of London. Chris@77: This file copyright 2006 Chris Cannam and QMUL. Chris@0: Chris@0: This program is free software; you can redistribute it and/or Chris@0: modify it under the terms of the GNU General Public License as Chris@0: published by the Free Software Foundation; either version 2 of the Chris@0: License, or (at your option) any later version. See the file Chris@0: COPYING included with this distribution for more information. Chris@0: */ Chris@0: Chris@0: #include "MainWindow.h" Chris@0: Chris@1: #include "system/System.h" Chris@1: #include "system/Init.h" Chris@0: #include "base/TempDirectory.h" Chris@0: #include "base/PropertyContainer.h" Chris@0: #include "base/Preferences.h" Chris@120: #include "widgets/TipDialog.h" Chris@0: Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@0: #include Chris@5: #include Chris@7: #include Chris@11: #include Chris@0: Chris@0: #include Chris@0: #include Chris@0: Chris@0: static QMutex cleanupMutex; Chris@0: Chris@0: static void Chris@0: signalHandler(int /* signal */) Chris@0: { Chris@0: // Avoid this happening more than once across threads Chris@0: Chris@0: cleanupMutex.lock(); Chris@0: std::cerr << "signalHandler: cleaning up and exiting" << std::endl; Chris@0: TempDirectory::getInstance()->cleanup(); Chris@0: exit(0); // without releasing mutex Chris@0: } Chris@0: Chris@11: class SVApplication : public QApplication Chris@11: { Chris@11: public: Chris@11: SVApplication(int argc, char **argv) : Chris@11: QApplication(argc, argv), Chris@11: m_mainWindow(0) { } Chris@11: virtual ~SVApplication() { } Chris@11: Chris@11: void setMainWindow(MainWindow *mw) { m_mainWindow = mw; } Chris@11: void releaseMainWindow() { m_mainWindow = 0; } Chris@11: Chris@11: virtual void commitData(QSessionManager &manager) { Chris@11: if (!m_mainWindow) return; Chris@11: bool mayAskUser = manager.allowsInteraction(); Chris@11: bool success = m_mainWindow->commitData(mayAskUser); Chris@11: manager.release(); Chris@11: if (!success) manager.cancel(); Chris@11: } Chris@11: Chris@11: protected: Chris@11: MainWindow *m_mainWindow; Chris@11: }; Chris@11: Chris@0: int Chris@0: main(int argc, char **argv) Chris@0: { Chris@11: SVApplication application(argc, argv); Chris@0: Chris@46: QStringList args = application.arguments(); Chris@46: Chris@0: signal(SIGINT, signalHandler); Chris@0: signal(SIGTERM, signalHandler); Chris@0: Chris@0: #ifndef Q_WS_WIN32 Chris@0: signal(SIGHUP, signalHandler); Chris@0: signal(SIGQUIT, signalHandler); Chris@0: #endif Chris@0: Chris@0: svSystemSpecificInitialisation(); Chris@0: Chris@46: bool audioOutput = true; Chris@70: bool oscSupport = true; Chris@70: Chris@70: if (args.contains("--help")) { Chris@70: std::cerr << QApplication::tr( Chris@70: "\nSonic Visualiser is a program for viewing and exploring audio data\nfor semantic music analysis and annotation.\n\nUsage:\n\n %1 [--no-audio] [--no-osc] [ ...]\n\n --no-audio: Do not attempt to open an audio output device\n --no-osc: Do not provide an Open Sound Control port for remote control\n : One or more Sonic Visualiser (.sv) and audio files may be provided.\n").arg(argv[0]).toStdString() << std::endl; Chris@70: exit(2); Chris@70: } Chris@70: Chris@46: if (args.contains("--no-audio")) audioOutput = false; Chris@70: if (args.contains("--no-osc")) oscSupport = false; Chris@46: Chris@6: QApplication::setOrganizationName("sonic-visualiser"); Chris@5: QApplication::setOrganizationDomain("sonicvisualiser.org"); Chris@6: QApplication::setApplicationName("sonic-visualiser"); Chris@5: Chris@89: QApplication::setWindowIcon(QIcon(":icons/svicon16.png")); Chris@7: Chris@0: QString language = QLocale::system().name(); Chris@0: Chris@0: QTranslator qtTranslator; Chris@0: QString qtTrName = QString("qt_%1").arg(language); Chris@0: std::cerr << "Loading " << qtTrName.toStdString() << "..." << std::endl; Chris@0: qtTranslator.load(qtTrName); Chris@0: application.installTranslator(&qtTranslator); Chris@0: Chris@0: QTranslator svTranslator; Chris@0: QString svTrName = QString("sonic-visualiser_%1").arg(language); Chris@0: std::cerr << "Loading " << svTrName.toStdString() << "..." << std::endl; Chris@0: svTranslator.load(svTrName, ":i18n"); Chris@0: application.installTranslator(&svTranslator); Chris@0: Chris@0: // Permit size_t and PropertyName to be used as args in queued signal calls Chris@0: qRegisterMetaType("size_t"); Chris@0: qRegisterMetaType("PropertyContainer::PropertyName"); Chris@0: Chris@70: MainWindow gui(audioOutput, oscSupport); Chris@11: application.setMainWindow(&gui); Chris@0: Chris@0: QDesktopWidget *desktop = QApplication::desktop(); Chris@0: QRect available = desktop->availableGeometry(); Chris@0: Chris@0: int width = available.width() * 2 / 3; Chris@0: int height = available.height() / 2; Chris@0: if (height < 450) height = available.height() * 2 / 3; Chris@0: if (width > height * 2) width = height * 2; Chris@0: Chris@5: QSettings settings; Chris@5: settings.beginGroup("MainWindow"); Chris@5: QSize size = settings.value("size", QSize(width, height)).toSize(); Chris@5: gui.resize(size); Chris@5: if (settings.contains("position")) { Chris@5: gui.move(settings.value("position").toPoint()); Chris@5: } Chris@5: settings.endGroup(); Chris@5: Chris@0: gui.show(); Chris@64: Chris@118: // The MainWindow class seems to have trouble dealing with this if Chris@118: // it tries to adapt to this preference before the constructor is Chris@118: // complete. As a lazy hack, apply it explicitly from here Chris@118: gui.preferenceChanged("Property Box Layout"); Chris@118: Chris@54: bool haveSession = false; Chris@54: bool haveMainModel = false; Chris@46: Chris@54: for (QStringList::iterator i = args.begin(); i != args.end(); ++i) { Chris@54: Chris@83: MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed; Chris@54: Chris@54: if (i == args.begin()) continue; Chris@54: if (i->startsWith('-')) continue; Chris@54: Chris@85: if (i->startsWith("http:") || i->startsWith("ftp:")) { Chris@85: status = gui.openURL(QUrl(*i)); Chris@85: continue; Chris@85: } Chris@85: Chris@54: QString path = *i; Chris@54: Chris@54: if (path.endsWith("sv")) { Chris@54: if (!haveSession) { Chris@82: status = gui.openSessionFile(path); Chris@82: if (status == MainWindow::FileOpenSucceeded) { Chris@54: haveSession = true; Chris@54: haveMainModel = true; Chris@54: } Chris@54: } else { Chris@54: std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl; Chris@82: status = MainWindow::FileOpenSucceeded; Chris@54: } Chris@54: } Chris@82: if (status != MainWindow::FileOpenSucceeded) { Chris@54: if (!haveMainModel) { Chris@82: status = gui.openSomeFile(path, MainWindow::ReplaceMainModel); Chris@82: if (status == MainWindow::FileOpenSucceeded) haveMainModel = true; Chris@54: } else { Chris@82: status = gui.openSomeFile(path, MainWindow::CreateAdditionalModel); Chris@54: } Chris@54: } Chris@82: if (status == MainWindow::FileOpenFailed) { Chris@54: QMessageBox::critical Chris@54: (&gui, QMessageBox::tr("Failed to open file"), Chris@54: QMessageBox::tr("File \"%1\" could not be opened").arg(path)); Chris@54: } Chris@54: } Chris@0: Chris@120: TipDialog tipDialog; Chris@120: if (tipDialog.isOK()) { Chris@120: tipDialog.exec(); Chris@120: } Chris@120: Chris@0: int rv = application.exec(); Chris@0: std::cerr << "application.exec() returned " << rv << std::endl; Chris@0: Chris@0: cleanupMutex.lock(); Chris@0: TempDirectory::getInstance()->cleanup(); Chris@11: application.releaseMainWindow(); Chris@5: Chris@0: return rv; Chris@0: }