Mercurial > hg > tony
view main/main.cpp @ 587:2090dd9bfbc1
Windows build updates
author | Chris Cannam |
---|---|
date | Wed, 04 Sep 2019 17:34:28 +0100 |
parents | f52766aa747b |
children | 164fa1ee2642 |
line wrap: on
line source
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Tony An intonation analysis and annotation tool Centre for Digital Music, Queen Mary, University of London. This file copyright 2006-2012 Chris Cannam and QMUL. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "MainWindow.h" #include "system/System.h" #include "system/Init.h" #include "base/TempDirectory.h" #include "base/PropertyContainer.h" #include "base/Preferences.h" #include "widgets/TipDialog.h" #include "widgets/InteractiveFileFinder.h" #include "transform/TransformFactory.h" #include "svcore/plugin/PluginScan.h" #include <QMetaType> #include <QApplication> #include <QScreen> #include <QMessageBox> #include <QTranslator> #include <QLocale> #include <QSettings> #include <QIcon> #include <QSessionManager> #include <QSplashScreen> #include <QFileOpenEvent> #include <QDir> #include <iostream> #include <signal.h> #include <cstdlib> #include "../version.h" #include <vamp-hostsdk/PluginHostAdapter.h> static QMutex cleanupMutex; static bool cleanedUp = false; static void signalHandler(int /* signal */) { // Avoid this happening more than once across threads cerr << "signalHandler: cleaning up and exiting" << endl; cleanupMutex.lock(); if (!cleanedUp) { TempDirectory::getInstance()->cleanup(); cleanedUp = true; } cleanupMutex.unlock(); exit(0); } class TonyApplication : public QApplication { public: TonyApplication(int &argc, char **argv) : QApplication(argc, argv), m_mainWindow(0), m_readyForFiles(false) { // tidier without, I reckon setAttribute(Qt::AA_DontShowIconsInMenus); } virtual ~TonyApplication() { } void setMainWindow(MainWindow *mw) { m_mainWindow = mw; } void releaseMainWindow() { m_mainWindow = 0; } virtual void commitData(QSessionManager &manager) { if (!m_mainWindow) return; bool mayAskUser = manager.allowsInteraction(); bool success = m_mainWindow->commitData(mayAskUser); manager.release(); if (!success) manager.cancel(); } void readyForFiles() { m_readyForFiles = true; } void handleFilepathArgument(QString path, QSplashScreen *splash); void handleQueuedPaths(QSplashScreen *splash) { foreach (QString f, m_filepathQueue) { handleFilepathArgument(f, splash); } } protected: MainWindow *m_mainWindow; bool m_readyForFiles; QStringList m_filepathQueue; virtual bool event(QEvent *event) { if (event->type() == QEvent::FileOpen) { QString path = static_cast<QFileOpenEvent *>(event)->file(); if (m_readyForFiles) { handleFilepathArgument(path, NULL); } else { m_filepathQueue.append(path); } return true; } else { return QApplication::event(event); } } }; static QString getEnvQStr(QString variable) { #ifdef Q_OS_WIN32 std::wstring wvar = variable.toStdWString(); wchar_t *value = _wgetenv(wvar.c_str()); if (!value) return QString(); else return QString::fromStdWString(std::wstring(value)); #else std::string var = variable.toStdString(); return QString::fromUtf8(qgetenv(var.c_str())); #endif } static void putEnvQStr(QString assignment) { #ifdef Q_OS_WIN32 std::wstring wassignment = assignment.toStdWString(); _wputenv(_wcsdup(wassignment.c_str())); #else putenv(strdup(assignment.toUtf8().data())); #endif } static void setupTonyVampPath() { QString tonyVampPath = getEnvQStr("TONY_VAMP_PATH"); #ifdef Q_OS_WIN32 QChar sep(';'); #else QChar sep(':'); #endif if (tonyVampPath == "") { tonyVampPath = QApplication::applicationDirPath(); #ifdef Q_OS_WIN32 QString programFiles = getEnvQStr("ProgramFiles"); if (programFiles == "") programFiles = "C:\\Program Files"; QString defaultTonyPath(programFiles + "\\Tony"); tonyVampPath = tonyVampPath + sep + defaultTonyPath; #else #ifdef Q_OS_MAC tonyVampPath = tonyVampPath + "/../Resources:" + tonyVampPath; #else QString defaultTonyPath("/usr/local/lib/tony:/usr/lib/tony"); tonyVampPath = tonyVampPath + sep + defaultTonyPath; #endif #endif } std::vector<std::string> vampPathList = Vamp::PluginHostAdapter::getPluginPath(); for (auto p: vampPathList) { tonyVampPath = tonyVampPath + sep + QString::fromUtf8(p.c_str()); } SVCERR << "Setting VAMP_PATH to " << tonyVampPath << " for Tony plugins" << endl; QString env = "VAMP_PATH=" + tonyVampPath; // Windows lacks setenv, must use putenv (different arg convention) putEnvQStr(env); } int main(int argc, char **argv) { if (argc == 2 && (QString(argv[1]) == "--version" || QString(argv[1]) == "-v")) { cerr << TONY_VERSION << endl; exit(0); } svSystemSpecificInitialisation(); #ifdef Q_OS_MAC if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) { // Fix for OS/X 10.9 font problem QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande"); } #endif TonyApplication application(argc, argv); QApplication::setOrganizationName("sonic-visualiser"); QApplication::setOrganizationDomain("sonicvisualiser.org"); QApplication::setApplicationName("Tony"); setupTonyVampPath(); QStringList args = application.arguments(); signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); #ifndef Q_OS_WIN32 signal(SIGHUP, signalHandler); signal(SIGQUIT, signalHandler); #endif bool audioOutput = true; bool sonification = true; bool spectrogram = true; if (args.contains("--help") || args.contains("-h") || args.contains("-?")) { std::cerr << QApplication::tr( "\nTony is a program for interactive note and pitch analysis and annotation.\n\nUsage:\n\n %1 [--no-audio] [--no-sonification] [--no-spectrogram] [<file> ...]\n\n --no-audio: Do not attempt to open an audio output device\n --no-sonification: Disable sonification of pitch tracks and notes and hide their toggles.\n --no-spectrogram: Disable spectrogram.\n <file>: One or more Tony (.ton) and audio files may be provided.").arg(argv[0]).toStdString() << std::endl; exit(2); } if (args.contains("--no-audio")) audioOutput = false; if (args.contains("--no-sonification")) sonification = false; if (args.contains("--no-spectrogram")) spectrogram = false; InteractiveFileFinder::getInstance()->setApplicationSessionExtension("ton"); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QSplashScreen *splash = 0; // If we had a splash screen, we would show it here QIcon icon; int sizes[] = { 16, 22, 24, 32, 48, 64, 128 }; for (size_t i = 0; i < sizeof(sizes)/sizeof(sizes[0]); ++i) { icon.addFile(QString(":icons/tony-%1x%2.png").arg(sizes[i]).arg(sizes[i])); } QApplication::setWindowIcon(icon); QString language = QLocale::system().name(); QTranslator qtTranslator; QString qtTrName = QString("qt_%1").arg(language); std::cerr << "Loading " << qtTrName.toStdString() << "..." << std::endl; bool success = false; if (!(success = qtTranslator.load(qtTrName))) { QString qtDir = getenv("QTDIR"); if (qtDir != "") { success = qtTranslator.load (qtTrName, QDir(qtDir).filePath("translations")); } } if (!success) { std::cerr << "Failed to load Qt translation for locale" << std::endl; } application.installTranslator(&qtTranslator); StoreStartupLocale(); // Permit size_t and PropertyName to be used as args in queued signal calls qRegisterMetaType<size_t>("size_t"); qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName"); MainWindow::SoundOptions options = MainWindow::WithEverything; if (!audioOutput) options = 0; MainWindow *gui = new MainWindow(options, sonification, spectrogram); application.setMainWindow(gui); if (splash) { QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide())); } QScreen *screen = QApplication::primaryScreen(); QRect available = screen->availableGeometry(); int width = (available.width() * 2) / 3; int height = available.height() / 2; if (height < 450) height = (available.height() * 2) / 3; if (width > height * 2) width = height * 2; QSettings settings; settings.beginGroup("MainWindow"); QSize size = settings.value("size", QSize(width, height)).toSize(); gui->resizeConstrained(size); if (settings.contains("position")) { QRect prevrect(settings.value("position").toPoint(), size); if (!(available & prevrect).isEmpty()) { gui->move(prevrect.topLeft()); } } settings.endGroup(); gui->show(); application.readyForFiles(); for (QStringList::iterator i = args.begin(); i != args.end(); ++i) { if (i == args.begin()) continue; if (i->startsWith('-')) continue; QString path = *i; application.handleFilepathArgument(path, splash); } application.handleQueuedPaths(splash); if (splash) splash->finish(gui); delete splash; int rv = application.exec(); gui->hide(); cleanupMutex.lock(); if (!cleanedUp) { TransformFactory::deleteInstance(); TempDirectory::getInstance()->cleanup(); cleanedUp = true; } application.releaseMainWindow(); delete gui; cleanupMutex.unlock(); return rv; } /** Application-global handler for filepaths passed in, e.g. as * command-line arguments or apple events */ void TonyApplication::handleFilepathArgument(QString path, QSplashScreen *splash) { static bool haveSession = false; static bool haveMainModel = false; static bool havePriorCommandLineModel = false; if (!m_mainWindow) return; MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed; #ifdef Q_OS_WIN32 path.replace("\\", "/"); #endif if (path.endsWith("ton")) { if (!haveSession) { status = m_mainWindow->openSessionPath(path); if (status == MainWindow::FileOpenSucceeded) { haveSession = true; haveMainModel = true; } } else { std::cerr << "WARNING: Ignoring additional session file argument \"" << path << "\"" << std::endl; status = MainWindow::FileOpenSucceeded; } } if (status != MainWindow::FileOpenSucceeded) { if (!haveMainModel) { status = m_mainWindow->openPath(path, MainWindow::ReplaceSession); if (status == MainWindow::FileOpenSucceeded) { haveMainModel = true; } } else { if (haveSession && !havePriorCommandLineModel) { status = m_mainWindow->openPath(path, MainWindow::AskUser); if (status == MainWindow::FileOpenSucceeded) { havePriorCommandLineModel = true; } } else { status = m_mainWindow->openPath(path, MainWindow::CreateAdditionalModel); } } } if (status == MainWindow::FileOpenFailed) { if (splash) splash->hide(); QMessageBox::critical (m_mainWindow, QMessageBox::tr("Failed to open file"), QMessageBox::tr("File or URL \"%1\" could not be opened").arg(path)); } else if (status == MainWindow::FileOpenWrongMode) { if (splash) splash->hide(); QMessageBox::critical (m_mainWindow, QMessageBox::tr("Failed to open file"), QMessageBox::tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data")); } }