To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / main / main.cpp @ 312:6394462e0c12
History | View | Annotate | Download (9.21 KB)
| 1 |
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|---|---|
| 2 |
|
| 3 |
/*
|
| 4 |
Vect
|
| 5 |
An experimental audio player for plural recordings of a work
|
| 6 |
Centre for Digital Music, Queen Mary, University of London.
|
| 7 |
This file copyright 2006-2012 Chris Cannam and QMUL.
|
| 8 |
|
| 9 |
This program is free software; you can redistribute it and/or
|
| 10 |
modify it under the terms of the GNU General Public License as
|
| 11 |
published by the Free Software Foundation; either version 2 of the
|
| 12 |
License, or (at your option) any later version. See the file
|
| 13 |
COPYING included with this distribution for more information.
|
| 14 |
*/
|
| 15 |
|
| 16 |
#include "MainWindow.h" |
| 17 |
|
| 18 |
#include "system/System.h" |
| 19 |
#include "system/Init.h" |
| 20 |
#include "base/TempDirectory.h" |
| 21 |
#include "base/PropertyContainer.h" |
| 22 |
#include "base/Preferences.h" |
| 23 |
#include "widgets/TipDialog.h" |
| 24 |
#include "svcore/plugin/PluginScan.h" |
| 25 |
|
| 26 |
#include <QMetaType> |
| 27 |
#include <QApplication> |
| 28 |
#include <QScreen> |
| 29 |
#include <QMessageBox> |
| 30 |
#include <QTranslator> |
| 31 |
#include <QLocale> |
| 32 |
#include <QSettings> |
| 33 |
#include <QIcon> |
| 34 |
#include <QSessionManager> |
| 35 |
#include <QDir> |
| 36 |
|
| 37 |
#include <iostream> |
| 38 |
#include <signal.h> |
| 39 |
|
| 40 |
#include "../version.h" |
| 41 |
|
| 42 |
#include <vamp-hostsdk/PluginHostAdapter.h> |
| 43 |
|
| 44 |
static QMutex cleanupMutex;
|
| 45 |
static bool cleanedUp = false; |
| 46 |
|
| 47 |
static void |
| 48 |
signalHandler(int /* signal */) |
| 49 |
{
|
| 50 |
// Avoid this happening more than once across threads
|
| 51 |
|
| 52 |
std::cerr << "signalHandler: cleaning up and exiting" << std::endl;
|
| 53 |
cleanupMutex.lock(); |
| 54 |
if (!cleanedUp) {
|
| 55 |
TempDirectory::getInstance()->cleanup(); |
| 56 |
cleanedUp = true;
|
| 57 |
} |
| 58 |
cleanupMutex.unlock(); |
| 59 |
exit(0);
|
| 60 |
} |
| 61 |
|
| 62 |
class VectApplication : public QApplication |
| 63 |
{
|
| 64 |
public:
|
| 65 |
VectApplication(int &argc, char **argv) : |
| 66 |
QApplication(argc, argv), |
| 67 |
m_mainWindow(0) { }
|
| 68 |
virtual ~VectApplication() { }
|
| 69 |
|
| 70 |
void setMainWindow(MainWindow *mw) { m_mainWindow = mw; }
|
| 71 |
void releaseMainWindow() { m_mainWindow = 0; } |
| 72 |
|
| 73 |
virtual void commitData(QSessionManager &manager) { |
| 74 |
if (!m_mainWindow) return; |
| 75 |
bool mayAskUser = manager.allowsInteraction();
|
| 76 |
bool success = m_mainWindow->commitData(mayAskUser);
|
| 77 |
manager.release(); |
| 78 |
if (!success) manager.cancel();
|
| 79 |
} |
| 80 |
|
| 81 |
protected:
|
| 82 |
MainWindow *m_mainWindow; |
| 83 |
}; |
| 84 |
|
| 85 |
static QString
|
| 86 |
getEnvQStr(QString variable) |
| 87 |
{
|
| 88 |
#ifdef Q_OS_WIN32
|
| 89 |
std::wstring wvar = variable.toStdWString(); |
| 90 |
wchar_t *value = _wgetenv(wvar.c_str());
|
| 91 |
if (!value) return QString(); |
| 92 |
else return QString::fromStdWString(std::wstring(value)); |
| 93 |
#else
|
| 94 |
std::string var = variable.toStdString();
|
| 95 |
return QString::fromUtf8(qgetenv(var.c_str()));
|
| 96 |
#endif
|
| 97 |
} |
| 98 |
|
| 99 |
static void |
| 100 |
putEnvQStr(QString assignment) |
| 101 |
{
|
| 102 |
#ifdef Q_OS_WIN32
|
| 103 |
std::wstring wassignment = assignment.toStdWString(); |
| 104 |
_wputenv(_wcsdup(wassignment.c_str())); |
| 105 |
#else
|
| 106 |
putenv(strdup(assignment.toUtf8().data())); |
| 107 |
#endif
|
| 108 |
} |
| 109 |
|
| 110 |
static void |
| 111 |
setupMyVampPath() |
| 112 |
{
|
| 113 |
// This based on similar logic from the Tony application
|
| 114 |
|
| 115 |
QString myVampPath = getEnvQStr("SONIC_LINEUP_VAMP_PATH");
|
| 116 |
|
| 117 |
#ifdef Q_OS_WIN32
|
| 118 |
QChar sep(';');
|
| 119 |
#else
|
| 120 |
QChar sep(':');
|
| 121 |
#endif
|
| 122 |
|
| 123 |
if (myVampPath == "") { |
| 124 |
|
| 125 |
QString appName = QApplication::applicationName(); |
| 126 |
QString myDir = QApplication::applicationDirPath(); |
| 127 |
QString binaryName = QFileInfo(QCoreApplication::arguments().at(0))
|
| 128 |
.fileName(); |
| 129 |
|
| 130 |
#ifdef Q_OS_WIN32
|
| 131 |
QString programFiles = getEnvQStr("ProgramFiles");
|
| 132 |
if (programFiles == "") programFiles = "C:\\Program Files"; |
| 133 |
QString pfPath(programFiles + "\\" + appName);
|
| 134 |
myVampPath = myDir + sep + pfPath; |
| 135 |
#else
|
| 136 |
#ifdef Q_OS_MAC
|
| 137 |
myVampPath = myDir + "/../Resources";
|
| 138 |
#else
|
| 139 |
if (binaryName != "") { |
| 140 |
myVampPath = |
| 141 |
myDir + "/../lib/" + binaryName + sep;
|
| 142 |
} |
| 143 |
myVampPath = myVampPath + |
| 144 |
myDir + "/../lib/" + appName + sep +
|
| 145 |
myDir; |
| 146 |
#endif
|
| 147 |
#endif
|
| 148 |
} |
| 149 |
|
| 150 |
SVCERR << "Setting VAMP_PATH to " << myVampPath
|
| 151 |
<< " for Sonic Lineup plugins" << endl;
|
| 152 |
|
| 153 |
QString env = "VAMP_PATH=" + myVampPath;
|
| 154 |
|
| 155 |
// Windows lacks setenv, must use putenv (different arg convention)
|
| 156 |
putEnvQStr(env); |
| 157 |
} |
| 158 |
|
| 159 |
int
|
| 160 |
main(int argc, char **argv) |
| 161 |
{
|
| 162 |
if (argc == 2 && (QString(argv[1]) == "--version" || |
| 163 |
QString(argv[1]) == "-v")) { |
| 164 |
cerr << VECT_VERSION << endl; |
| 165 |
exit(0);
|
| 166 |
} |
| 167 |
|
| 168 |
svSystemSpecificInitialisation(); |
| 169 |
|
| 170 |
VectApplication application(argc, argv); |
| 171 |
|
| 172 |
QApplication::setOrganizationName("sonic-visualiser");
|
| 173 |
QApplication::setOrganizationDomain("sonicvisualiser.org");
|
| 174 |
QApplication::setApplicationName("Sonic Lineup");
|
| 175 |
|
| 176 |
setupMyVampPath(); |
| 177 |
|
| 178 |
QStringList args = application.arguments(); |
| 179 |
|
| 180 |
signal(SIGINT, signalHandler); |
| 181 |
signal(SIGTERM, signalHandler); |
| 182 |
|
| 183 |
#ifndef Q_OS_WIN32
|
| 184 |
signal(SIGHUP, signalHandler); |
| 185 |
signal(SIGQUIT, signalHandler); |
| 186 |
#endif
|
| 187 |
|
| 188 |
svSystemSpecificInitialisation(); |
| 189 |
|
| 190 |
bool audioOutput = true; |
| 191 |
|
| 192 |
if (args.contains("--help") || args.contains("-h") || args.contains("-?")) { |
| 193 |
std::cerr << QApplication::tr( |
| 194 |
"\nSonic Lineup is a comparative viewer for sets of related audio recordings.\n\nUsage:\n\n %1 [--no-audio] [<file1>, <file2>...]\n\n --no-audio: Do not attempt to open an audio output device\n <file1>, <file2>...: Audio files; Sonic Lineup is designed for comparative\nviewing of multiple recordings of the same music or other related material.\n").arg(argv[0]).toStdString() << std::endl; |
| 195 |
exit(2);
|
| 196 |
} |
| 197 |
|
| 198 |
if (args.contains("--no-audio")) { |
| 199 |
audioOutput = false;
|
| 200 |
} |
| 201 |
|
| 202 |
if (args.contains("--first-run")) { |
| 203 |
QSettings settings; |
| 204 |
settings.clear(); |
| 205 |
} |
| 206 |
|
| 207 |
InteractiveFileFinder::getInstance()->setApplicationSessionExtension("vect");
|
| 208 |
|
| 209 |
QSettings settings; |
| 210 |
settings.beginGroup("Preferences");
|
| 211 |
// Running plugins in-process allows us to use the serialise
|
| 212 |
// option in the MATCH plugin, which cuts down on memory pressure
|
| 213 |
// and makes things go more smoothly
|
| 214 |
settings.setValue("run-vamp-plugins-in-process", true); |
| 215 |
settings.endGroup(); |
| 216 |
|
| 217 |
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); |
| 218 |
QApplication::setAttribute(Qt::AA_DontShowIconsInMenus); |
| 219 |
|
| 220 |
QIcon icon; |
| 221 |
int sizes[] = { 16, 22, 24, 32, 48, 64, 128 }; |
| 222 |
for (int i = 0; i < (int)(sizeof(sizes)/sizeof(sizes[0])); ++i) { |
| 223 |
icon.addFile(QString(":icons/sv-%1x%2.png").arg(sizes[i]).arg(sizes[i]));
|
| 224 |
} |
| 225 |
QApplication::setWindowIcon(icon); |
| 226 |
|
| 227 |
QString language = QLocale::system().name(); |
| 228 |
|
| 229 |
QTranslator qtTranslator; |
| 230 |
QString qtTrName = QString("qt_%1").arg(language);
|
| 231 |
SVCERR << "Loading " << qtTrName.toStdString() << "..." << endl; |
| 232 |
bool success = false; |
| 233 |
if (!(success = qtTranslator.load(QLocale(), qtTrName))) {
|
| 234 |
QString qtDir = getenv("QTDIR");
|
| 235 |
if (qtDir != "") { |
| 236 |
success = qtTranslator.load |
| 237 |
(QLocale(), qtTrName, QDir(qtDir).filePath("translations"));
|
| 238 |
} |
| 239 |
} |
| 240 |
if (!success) {
|
| 241 |
SVCERR << "Failed to load Qt translation for locale" << endl;
|
| 242 |
} |
| 243 |
application.installTranslator(&qtTranslator); |
| 244 |
|
| 245 |
QTranslator svecTranslator; |
| 246 |
QString svecTrName = QString("vect_%1").arg(language);
|
| 247 |
SVCERR << "Loading " << svecTrName << "..." << endl; |
| 248 |
if (svecTranslator.load(svecTrName, ":i18n")) { |
| 249 |
application.installTranslator(&svecTranslator); |
| 250 |
} else {
|
| 251 |
SVCERR << "Failed to load translation" << endl;
|
| 252 |
} |
| 253 |
|
| 254 |
StoreStartupLocale(); |
| 255 |
|
| 256 |
// Make known-plugins query as early as possible
|
| 257 |
PluginScan::getInstance()->scan(); |
| 258 |
|
| 259 |
// Permit size_t and PropertyName to be used as args in queued signal calls
|
| 260 |
qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
|
| 261 |
|
| 262 |
MainWindow::SoundOptions options = |
| 263 |
MainWindow::WithAudioInput | MainWindow::WithAudioOutput; |
| 264 |
if (!audioOutput) options = 0; |
| 265 |
|
| 266 |
MainWindow *gui = new MainWindow(options);
|
| 267 |
application.setMainWindow(gui); |
| 268 |
|
| 269 |
QScreen *screen = QApplication::primaryScreen(); |
| 270 |
QRect available = screen->availableGeometry(); |
| 271 |
|
| 272 |
int width = available.width() * 2 / 3; |
| 273 |
int height = available.height() / 2; |
| 274 |
if (height < 450) height = available.height() * 2 / 3; |
| 275 |
if (width > height * 2) width = height * 2; |
| 276 |
|
| 277 |
settings.beginGroup("MainWindow");
|
| 278 |
|
| 279 |
QSize size = settings.value("size", QSize(width, height)).toSize();
|
| 280 |
gui->resizeConstrained(size); |
| 281 |
|
| 282 |
if (settings.contains("position")) { |
| 283 |
QRect prevrect(settings.value("position").toPoint(), size);
|
| 284 |
if (!(available & prevrect).isEmpty()) {
|
| 285 |
gui->move(prevrect.topLeft()); |
| 286 |
} |
| 287 |
} |
| 288 |
|
| 289 |
if (settings.value("maximised", false).toBool()) { |
| 290 |
gui->setWindowState(Qt::WindowMaximized); |
| 291 |
} |
| 292 |
|
| 293 |
settings.endGroup(); |
| 294 |
|
| 295 |
gui->show(); |
| 296 |
|
| 297 |
SmallSession session; |
| 298 |
bool haveSession = false; |
| 299 |
|
| 300 |
for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
|
| 301 |
|
| 302 |
if (i == args.begin()) continue; |
| 303 |
if (i->startsWith('-')) continue; |
| 304 |
|
| 305 |
if (session.mainFile == "") { |
| 306 |
session.mainFile = *i; |
| 307 |
} else {
|
| 308 |
session.additionalFiles.push_back(*i); |
| 309 |
} |
| 310 |
|
| 311 |
haveSession = true;
|
| 312 |
} |
| 313 |
|
| 314 |
if (haveSession) {
|
| 315 |
gui->openSmallSession(session); |
| 316 |
} |
| 317 |
|
| 318 |
int rv = application.exec();
|
| 319 |
|
| 320 |
cleanupMutex.lock(); |
| 321 |
TempDirectory::getInstance()->cleanup(); |
| 322 |
application.releaseMainWindow(); |
| 323 |
|
| 324 |
delete gui;
|
| 325 |
|
| 326 |
cleanupMutex.unlock(); |
| 327 |
|
| 328 |
return rv;
|
| 329 |
} |