annotate main/main.cpp @ 88:51be0daa1386

Several changes related to referring to remote URLs for sessions and files: * Pull file dialog wrapper functions out from MainWindow into FileFinder * If a file referred to in a session is not found at its expected location, try a few other alternatives (same location as the session file or same location as the last audio file) before asking the user to locate it * Allow user to give a URL when locating an audio file, not just locate on the filesystem * Make wave file models remember the "original" location (e.g. URL) of the audio file, not just the actual location from which the data was loaded (e.g. local copy of that URL) -- when saving a session, use the original location so as not to refer to a temporary file * Clean up incompletely-downloaded local copies of files
author Chris Cannam
date Thu, 11 Jan 2007 13:29:58 +0000
parents 4eae5b521a34
children a4e79db79282
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Sonic Visualiser
Chris@0 5 An audio file viewer and annotation editor.
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@77 7 This file copyright 2006 Chris Cannam and QMUL.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "MainWindow.h"
Chris@0 17
Chris@1 18 #include "system/System.h"
Chris@1 19 #include "system/Init.h"
Chris@0 20 #include "base/TempDirectory.h"
Chris@0 21 #include "base/PropertyContainer.h"
Chris@0 22 #include "base/Preferences.h"
Chris@0 23
Chris@0 24 #include <QMetaType>
Chris@0 25 #include <QApplication>
Chris@0 26 #include <QDesktopWidget>
Chris@0 27 #include <QMessageBox>
Chris@0 28 #include <QTranslator>
Chris@0 29 #include <QLocale>
Chris@5 30 #include <QSettings>
Chris@7 31 #include <QIcon>
Chris@11 32 #include <QSessionManager>
Chris@0 33
Chris@0 34 #include <iostream>
Chris@0 35 #include <signal.h>
Chris@0 36
Chris@0 37 static QMutex cleanupMutex;
Chris@0 38
Chris@0 39 static void
Chris@0 40 signalHandler(int /* signal */)
Chris@0 41 {
Chris@0 42 // Avoid this happening more than once across threads
Chris@0 43
Chris@0 44 cleanupMutex.lock();
Chris@0 45 std::cerr << "signalHandler: cleaning up and exiting" << std::endl;
Chris@0 46 TempDirectory::getInstance()->cleanup();
Chris@0 47 exit(0); // without releasing mutex
Chris@0 48 }
Chris@0 49
Chris@11 50 class SVApplication : public QApplication
Chris@11 51 {
Chris@11 52 public:
Chris@11 53 SVApplication(int argc, char **argv) :
Chris@11 54 QApplication(argc, argv),
Chris@11 55 m_mainWindow(0) { }
Chris@11 56 virtual ~SVApplication() { }
Chris@11 57
Chris@11 58 void setMainWindow(MainWindow *mw) { m_mainWindow = mw; }
Chris@11 59 void releaseMainWindow() { m_mainWindow = 0; }
Chris@11 60
Chris@11 61 virtual void commitData(QSessionManager &manager) {
Chris@11 62 if (!m_mainWindow) return;
Chris@11 63 bool mayAskUser = manager.allowsInteraction();
Chris@11 64 bool success = m_mainWindow->commitData(mayAskUser);
Chris@11 65 manager.release();
Chris@11 66 if (!success) manager.cancel();
Chris@11 67 }
Chris@11 68
Chris@11 69 protected:
Chris@11 70 MainWindow *m_mainWindow;
Chris@11 71 };
Chris@11 72
Chris@0 73 int
Chris@0 74 main(int argc, char **argv)
Chris@0 75 {
Chris@11 76 SVApplication application(argc, argv);
Chris@0 77
Chris@46 78 QStringList args = application.arguments();
Chris@46 79
Chris@0 80 signal(SIGINT, signalHandler);
Chris@0 81 signal(SIGTERM, signalHandler);
Chris@0 82
Chris@0 83 #ifndef Q_WS_WIN32
Chris@0 84 signal(SIGHUP, signalHandler);
Chris@0 85 signal(SIGQUIT, signalHandler);
Chris@0 86 #endif
Chris@0 87
Chris@0 88 svSystemSpecificInitialisation();
Chris@0 89
Chris@46 90 bool audioOutput = true;
Chris@70 91 bool oscSupport = true;
Chris@70 92
Chris@70 93 if (args.contains("--help")) {
Chris@70 94 std::cerr << QApplication::tr(
Chris@70 95 "\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] [<file> ...]\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 <file>: One or more Sonic Visualiser (.sv) and audio files may be provided.\n").arg(argv[0]).toStdString() << std::endl;
Chris@70 96 exit(2);
Chris@70 97 }
Chris@70 98
Chris@46 99 if (args.contains("--no-audio")) audioOutput = false;
Chris@70 100 if (args.contains("--no-osc")) oscSupport = false;
Chris@46 101
Chris@6 102 QApplication::setOrganizationName("sonic-visualiser");
Chris@5 103 QApplication::setOrganizationDomain("sonicvisualiser.org");
Chris@6 104 QApplication::setApplicationName("sonic-visualiser");
Chris@5 105
Chris@7 106 QApplication::setWindowIcon(QIcon(":icons/waveform.png"));
Chris@7 107
Chris@0 108 QString language = QLocale::system().name();
Chris@0 109
Chris@0 110 QTranslator qtTranslator;
Chris@0 111 QString qtTrName = QString("qt_%1").arg(language);
Chris@0 112 std::cerr << "Loading " << qtTrName.toStdString() << "..." << std::endl;
Chris@0 113 qtTranslator.load(qtTrName);
Chris@0 114 application.installTranslator(&qtTranslator);
Chris@0 115
Chris@0 116 QTranslator svTranslator;
Chris@0 117 QString svTrName = QString("sonic-visualiser_%1").arg(language);
Chris@0 118 std::cerr << "Loading " << svTrName.toStdString() << "..." << std::endl;
Chris@0 119 svTranslator.load(svTrName, ":i18n");
Chris@0 120 application.installTranslator(&svTranslator);
Chris@0 121
Chris@0 122 // Permit size_t and PropertyName to be used as args in queued signal calls
Chris@0 123 qRegisterMetaType<size_t>("size_t");
Chris@0 124 qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
Chris@0 125
Chris@70 126 MainWindow gui(audioOutput, oscSupport);
Chris@11 127 application.setMainWindow(&gui);
Chris@0 128
Chris@0 129 QDesktopWidget *desktop = QApplication::desktop();
Chris@0 130 QRect available = desktop->availableGeometry();
Chris@0 131
Chris@0 132 int width = available.width() * 2 / 3;
Chris@0 133 int height = available.height() / 2;
Chris@0 134 if (height < 450) height = available.height() * 2 / 3;
Chris@0 135 if (width > height * 2) width = height * 2;
Chris@0 136
Chris@5 137 QSettings settings;
Chris@5 138 settings.beginGroup("MainWindow");
Chris@5 139 QSize size = settings.value("size", QSize(width, height)).toSize();
Chris@5 140 gui.resize(size);
Chris@5 141 if (settings.contains("position")) {
Chris@5 142 gui.move(settings.value("position").toPoint());
Chris@5 143 }
Chris@5 144 settings.endGroup();
Chris@5 145
Chris@0 146 gui.show();
Chris@64 147
Chris@54 148 bool haveSession = false;
Chris@54 149 bool haveMainModel = false;
Chris@46 150
Chris@54 151 for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
Chris@54 152
Chris@83 153 MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed;
Chris@54 154
Chris@54 155 if (i == args.begin()) continue;
Chris@54 156 if (i->startsWith('-')) continue;
Chris@54 157
Chris@85 158 if (i->startsWith("http:") || i->startsWith("ftp:")) {
Chris@85 159 status = gui.openURL(QUrl(*i));
Chris@85 160 continue;
Chris@85 161 }
Chris@85 162
Chris@54 163 QString path = *i;
Chris@54 164
Chris@54 165 if (path.endsWith("sv")) {
Chris@54 166 if (!haveSession) {
Chris@82 167 status = gui.openSessionFile(path);
Chris@82 168 if (status == MainWindow::FileOpenSucceeded) {
Chris@54 169 haveSession = true;
Chris@54 170 haveMainModel = true;
Chris@54 171 }
Chris@54 172 } else {
Chris@54 173 std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl;
Chris@82 174 status = MainWindow::FileOpenSucceeded;
Chris@54 175 }
Chris@54 176 }
Chris@82 177 if (status != MainWindow::FileOpenSucceeded) {
Chris@54 178 if (!haveMainModel) {
Chris@82 179 status = gui.openSomeFile(path, MainWindow::ReplaceMainModel);
Chris@82 180 if (status == MainWindow::FileOpenSucceeded) haveMainModel = true;
Chris@54 181 } else {
Chris@82 182 status = gui.openSomeFile(path, MainWindow::CreateAdditionalModel);
Chris@54 183 }
Chris@54 184 }
Chris@82 185 if (status == MainWindow::FileOpenFailed) {
Chris@54 186 QMessageBox::critical
Chris@54 187 (&gui, QMessageBox::tr("Failed to open file"),
Chris@54 188 QMessageBox::tr("File \"%1\" could not be opened").arg(path));
Chris@54 189 }
Chris@54 190 }
Chris@0 191
Chris@0 192 int rv = application.exec();
Chris@0 193 std::cerr << "application.exec() returned " << rv << std::endl;
Chris@0 194
Chris@0 195 cleanupMutex.lock();
Chris@0 196 TempDirectory::getInstance()->cleanup();
Chris@11 197 application.releaseMainWindow();
Chris@5 198
Chris@0 199 return rv;
Chris@0 200 }