19 #include "system/System.h" 20 #include "system/Init.h" 21 #include "base/TempDirectory.h" 22 #include "base/PropertyContainer.h" 23 #include "base/Preferences.h" 24 #include "data/fileio/FileSource.h" 25 #include "widgets/TipDialog.h" 26 #include "widgets/InteractiveFileFinder.h" 27 #include "framework/TransformUserConfigurator.h" 28 #include "transform/TransformFactory.h" 29 #include "plugin/PluginScan.h" 30 #include "plugin/PluginPathSetter.h" 33 #include <QApplication> 35 #include <QMessageBox> 36 #include <QTranslator> 40 #include <QSessionManager> 44 #include <QFileOpenEvent> 45 #include <QCommandLineParser> 53 #include "../version.h" 193 cerr <<
"signalHandler: cleaning up and exiting" << endl;
197 TempDirectory::getInstance()->cleanup();
210 QApplication(argc, argv),
223 bool mayAskUser = manager.allowsInteraction();
226 if (!success) manager.cancel();
236 bool event(QEvent *)
override;
242 if (argc == 2 && (QString(argv[1]) ==
"--version" ||
243 QString(argv[1]) ==
"-v")) {
244 cerr << SV_VERSION << endl;
248 svSystemSpecificInitialisation();
252 QApplication::setOrganizationName(
"sonic-visualiser");
253 QApplication::setOrganizationDomain(
"sonicvisualiser.org");
254 QApplication::setApplicationName(QApplication::tr(
"Sonic Visualiser"));
255 QApplication::setApplicationVersion(SV_VERSION);
258 QCommandLineParser parser;
259 parser.setApplicationDescription(QApplication::tr(
"\nSonic Visualiser is a program for viewing and exploring audio data\nfor semantic music analysis and annotation."));
260 parser.addHelpOption();
261 parser.addVersionOption();
263 parser.addOption(QCommandLineOption
264 (
"no-audio", QApplication::tr
265 (
"Do not attempt to open an audio output device.")));
266 parser.addOption(QCommandLineOption
267 (
"no-osc", QApplication::tr
268 (
"Do not provide an Open Sound Control port for remote control.")));
269 parser.addOption(QCommandLineOption
270 (
"no-splash", QApplication::tr
271 (
"Do not show a splash screen.")));
272 parser.addOption(QCommandLineOption
273 (
"osc-script", QApplication::tr
274 (
"Batch run the Open Sound Control script found in the given file. Supply \"-\" as file to read from stdin. Scripts consist of /command arg1 arg2 ... OSC control lines, optionally interleaved with numbers to specify pauses in seconds."),
276 parser.addOption(QCommandLineOption
277 (
"first-run", QApplication::tr
278 (
"Clear any saved settings and reset to first-run behaviour.")));
280 parser.addPositionalArgument
281 (
"[<file> ...]", QApplication::tr(
"One or more Sonic Visualiser (.sv) and audio files may be provided."));
283 QStringList args = application.arguments();
284 if (!parser.parse(args)) {
285 if (parser.unknownOptionNames().contains(
"?")) {
293 parser.process(args);
295 if (parser.isSet(
"first-run")) {
300 bool audioOutput = !(parser.isSet(
"no-audio"));
301 bool oscSupport = !(parser.isSet(
"no-osc"));
302 bool showSplash = !(parser.isSet(
"no-splash"));
305 SVDEBUG <<
"Note: --no-audio flag set, will not use audio device" << endl;
308 SVDEBUG <<
"Note: --no-osc flag set, will not open OSC port" << endl;
311 args = parser.positionalArguments();
313 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
327 QString language = QLocale::system().name();
328 SVDEBUG <<
"System language is: " << language << endl;
330 settings.beginGroup(
"Preferences");
331 QString prefLanguage = settings.value(
"locale", language).toString();
332 if (prefLanguage != QString()) language = prefLanguage;
335 settings.beginGroup(
"Preferences");
336 if (!(settings.value(
"always-use-default-font",
false).toBool())) {
338 if (!language.startsWith(
"ru_")) {
339 QFont font(QApplication::font());
340 QString preferredFamily =
"Segoe UI";
341 font.setFamily(preferredFamily);
342 if (QFontInfo(font).family() == preferredFamily) {
343 font.setPointSize(9);
344 QApplication::setFont(font);
351 settings.beginGroup(
"Preferences");
353 if (!settings.contains(
"run-vamp-plugins-in-process")) {
354 settings.setValue(
"run-vamp-plugins-in-process",
false);
358 settings.beginGroup(
"Preferences");
360 if (!settings.value(
"show-splash",
true).toBool()) {
369 QTimer::singleShot(5000, splash, SLOT(hide()));
370 application.processEvents();
373 settings.beginGroup(
"RDF");
375 bool absent = !(settings.contains(
"rdf-indices"));
376 QString plugIndex(
"http://www.vamp-plugins.org/rdf/plugins/index.txt");
377 QString packsIndex(
"http://www.vamp-plugins.org/rdf/packs/index.txt");
382 list = settings.value(
"rdf-indices").toStringList();
383 if (!settings.contains(
"rdf-indices-refreshed-for-4.1")) {
385 if (!list.contains(packsIndex)) {
388 settings.setValue(
"rdf-indices-refreshed-for-4.1",
true);
391 settings.setValue(
"rdf-indices", list);
394 PluginPathSetter::initialiseEnvironmentVariables();
397 int sizes[] = { 16, 22, 24, 32, 48, 64, 128 };
398 for (
int i = 0; i < int(
sizeof(sizes)/
sizeof(sizes[0])); ++i) {
399 icon.addFile(QString(
":icons/sv-%1x%2.png").arg(sizes[i]).arg(sizes[i]));
401 QApplication::setWindowIcon(icon);
404 application.processEvents();
407 QTranslator qtTranslator;
408 QString qtTrName = QString(
"qt_%1").arg(language);
409 SVDEBUG <<
"Loading " << qtTrName <<
"... ";
410 bool success =
false;
411 if (!(success = qtTranslator.load(qtTrName))) {
412 QString qtDir = getenv(
"QTDIR");
414 success = qtTranslator.load
415 (qtTrName, QDir(qtDir).filePath(
"translations"));
419 SVDEBUG <<
"Failed\nFailed to load Qt translation for locale" << endl;
421 cerr <<
"Done" << endl;
423 application.installTranslator(&qtTranslator);
425 QTranslator svTranslator;
426 QString svTrName = QString(
"sonic-visualiser_%1").arg(language);
427 SVDEBUG <<
"Loading " << svTrName <<
"... ";
428 svTranslator.load(svTrName,
":i18n");
429 SVDEBUG <<
"Done" << endl;
430 application.installTranslator(&svTranslator);
432 StoreStartupLocale();
434 #if (QT_VERSION >= 0x050400) 435 SVDEBUG <<
"Note: SSL library build version is: " 436 << QSslSocket::sslLibraryBuildVersionString()
441 application.processEvents();
445 qRegisterMetaType<PropertyContainer::PropertyName>(
"PropertyContainer::PropertyName");
446 qRegisterMetaType<ZoomLevel>(
"ZoomLevel");
448 MainWindow::AudioMode audioMode =
449 MainWindow::AUDIO_PLAYBACK_NOW_RECORD_LATER;
450 MainWindow::MIDIMode midiMode =
451 MainWindow::MIDI_LISTEN;
454 audioMode = MainWindow::AUDIO_NONE;
455 midiMode = MainWindow::MIDI_NONE;
461 InteractiveFileFinder::setParentWidget(gui);
462 TransformUserConfigurator::setParentWidget(gui);
464 QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide()));
465 QObject::connect(gui, SIGNAL(hideSplash(QWidget *)),
466 splash, SLOT(finishSplash(QWidget *)));
469 QScreen *screen = QApplication::primaryScreen();
470 QRect available = screen->availableGeometry();
472 int width = (available.width() * 2) / 3;
473 int height = available.height() / 2;
474 if (height < 450) height = (available.height() * 2) / 3;
475 if (width > height * 2) width = height * 2;
477 settings.beginGroup(
"MainWindow");
479 QSize size = settings.value(
"size", QSize(width, height)).toSize();
480 gui->resizeConstrained(size);
482 if (settings.contains(
"position")) {
483 QRect prevrect(settings.value(
"position").toPoint(), size);
484 if (!(available & prevrect).isEmpty()) {
485 gui->move(prevrect.topLeft());
489 if (settings.value(
"maximised",
false).toBool()) {
490 gui->setWindowState(Qt::WindowMaximized);
504 for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
511 if (i->startsWith(
'-'))
continue;
525 settings.beginGroup(
"FFTWisdom");
526 QString wisdom = settings.value(
"wisdom").toString();
528 fftwf_import_wisdom_from_string(wisdom.toLocal8Bit().data());
531 wisdom = settings.value(
"wisdom_d").toString();
533 fftw_import_wisdom_from_string(wisdom.toLocal8Bit().data());
539 QString scriptFile = parser.value(
"osc-script");
540 if (scriptFile !=
"") {
541 SVDEBUG <<
"Note: Cueing OSC script from filename \"" << scriptFile
543 gui->cueOSCScript(scriptFile);
546 SVDEBUG <<
"Entering main event loop" << endl;
548 int rv = application.exec();
555 TransformFactory::deleteInstance();
556 TempDirectory::getInstance()->cleanup();
563 settings.beginGroup(
"FFTWisdom");
564 char *cwisdom = fftwf_export_wisdom_to_string();
566 settings.setValue(
"wisdom", cwisdom);
570 cwisdom = fftw_export_wisdom_to_string();
572 settings.setValue(
"wisdom_d", cwisdom);
579 FileSource::debugReport();
593 #pragma GCC diagnostic ignored "-Wswitch-enum" 597 switch (event->type()) {
598 case QEvent::FileOpen:
599 thePath =
static_cast<QFileOpenEvent *
>(
event)->file();
606 return QApplication::event(event);
612 static bool haveSession =
false;
613 static bool haveMainModel =
false;
614 static bool havePriorCommandLineModel =
false;
616 MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed;
619 path.replace(
"\\",
"/");
622 if (path.endsWith(
"sv")) {
625 if (status == MainWindow::FileOpenSucceeded) {
627 haveMainModel =
true;
630 cerr <<
"WARNING: Ignoring additional session file argument \"" << path <<
"\"" << endl;
631 status = MainWindow::FileOpenSucceeded;
634 if (status != MainWindow::FileOpenSucceeded) {
635 if (!haveMainModel) {
636 status =
m_mainWindow->openPath(path, MainWindow::ReplaceSession);
637 if (status == MainWindow::FileOpenSucceeded) {
638 haveMainModel =
true;
641 if (haveSession && !havePriorCommandLineModel) {
642 status =
m_mainWindow->openPath(path, MainWindow::AskUser);
643 if (status == MainWindow::FileOpenSucceeded) {
644 havePriorCommandLineModel =
true;
647 status =
m_mainWindow->openPath(path, MainWindow::CreateAdditionalModel);
651 if (status == MainWindow::FileOpenFailed) {
652 if (splash) splash->hide();
653 QMessageBox::critical
655 QMessageBox::tr(
"File or URL \"%1\" could not be opened").arg(path));
656 }
else if (status == MainWindow::FileOpenWrongMode) {
657 if (splash) splash->hide();
658 QMessageBox::critical
660 QMessageBox::tr(
"<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
void handleFilepathArgument(QString path, SVSplash *splash)
Application-global handler for filepaths passed in, e.g.
virtual void commitData(QSessionManager &manager)
int main(int argc, char **argv)
static void signalHandler(int)
static QMutex cleanupMutex
SVApplication(int &argc, char **argv)
QStringList m_filepathQueue
void setMainWindow(MainWindow *mw)
bool event(QEvent *) override
void preferenceChanged(PropertyContainer::PropertyName) override
~SVApplication() override
MainWindow * m_mainWindow
virtual bool commitData(bool mayAskUser)