# HG changeset patch # User Dan Stowell # Date 1286803014 -3600 # Node ID a0ea7bcac15b22582af6be55da12043300e029fb # Parent 101f05420cbaf29d155f6b4c743a731badfb6c94 Now can load file when someone chooses from Mac Finder "Open with > Sonic Visualiser" - but currently *only* if the app is already running. diff -r 101f05420cba -r a0ea7bcac15b main/main.cpp --- a/main/main.cpp Fri Oct 08 13:31:00 2010 +0100 +++ b/main/main.cpp Mon Oct 11 14:16:54 2010 +0100 @@ -23,6 +23,9 @@ #include "widgets/TipDialog.h" #include "transform/TransformFactory.h" +#include +#include + #include #include #include @@ -171,6 +174,7 @@ */ static QMutex cleanupMutex; +static MainWindow *gui; static void signalHandler(int /* signal */) @@ -202,6 +206,94 @@ if (!success) manager.cancel(); } + /** Application-global handler for filepaths passed in, e.g. as command-line arguments or apple events */ + static void handleFilepathArgument(QString path, QSplashScreen *splash){ + static bool haveSession = false; + static bool haveMainModel = false; + static bool havePriorCommandLineModel = false; + + MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed; + + if (path.endsWith("sv")) { + if (!haveSession) { + status = gui->openSessionFile(path); + if (status == MainWindow::FileOpenSucceeded) { + haveSession = true; + haveMainModel = true; + } + } else { + std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl; + status = MainWindow::FileOpenSucceeded; + } + } + if (status != MainWindow::FileOpenSucceeded) { + if (!haveMainModel) { + status = gui->open(path, MainWindow::ReplaceMainModel); + if (status == MainWindow::FileOpenSucceeded) { + haveMainModel = true; + } + } else { + if (haveSession && !havePriorCommandLineModel) { + status = gui->open(path, MainWindow::AskUser); + if (status == MainWindow::FileOpenSucceeded) { + havePriorCommandLineModel = true; + } + } else { + status = gui->open(path, MainWindow::CreateAdditionalModel); + } + } + } + if (status == MainWindow::FileOpenFailed) { + if (splash) splash->hide(); + QMessageBox::critical + (gui, 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 + (gui, QMessageBox::tr("Failed to open file"), + QMessageBox::tr("Audio required

Please load at least one audio file before importing annotation data")); + } + } + +#ifdef Q_WS_MAC + static pascal OSErr HandleOpenDocAE (const AppleEvent * theAppleEvent, AppleEvent * /* reply */, SInt32 /* handlerRefcon */) { + AEDescList docList; + FSRef theFSRef; + long count = 0; + OSErr err; + + err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList); + err = AECountItems(&docList, &count); + if(count == 0){ + std::cerr << "SV warning: received apple open-documents event with no documents (count==0)" << std::endl; + AEDisposeDesc(&docList); + return noErr; + } + // NB we could be passed a list of files - however, SV on Mac currently can only open one at a time, so we simply open the first. + + err = AEGetNthPtr(&docList, 1, typeFSRef, NULL, NULL, &theFSRef, sizeof(theFSRef), NULL); + + // Call routine to open document with current reference. + if(err == noErr){ + char uPath[1024]; + FSRefMakePath(&theFSRef, (UInt8*)uPath, 1023); + std::cerr << "SV received Apple Event request to open " << uPath << std::endl; + handleFilepathArgument(uPath, NULL); + } + + AEDisposeDesc(&docList); + return noErr; + } + static OSErr InstallMacOSEventHandlers(void) + { + OSErr err; + err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(HandleOpenDocAE), 0, false); + std::cerr << "HandleOpenDocAE installed. " << err << std::endl; + return err; + } +#endif // Q_WS_MAC + protected: MainWindow *m_mainWindow; }; @@ -315,7 +407,7 @@ qRegisterMetaType("size_t"); qRegisterMetaType("PropertyContainer::PropertyName"); - MainWindow *gui = new MainWindow(audioOutput, oscSupport); + gui = new MainWindow(audioOutput, oscSupport); application.setMainWindow(gui); if (splash) { QObject::connect(gui, SIGNAL(hideSplash()), splash, SLOT(hide())); @@ -340,6 +432,10 @@ } settings.endGroup(); +#ifdef Q_WS_MAC + application.InstallMacOSEventHandlers(); +#endif // Q_WS_MAC + gui->show(); // The MainWindow class seems to have trouble dealing with this if @@ -347,59 +443,14 @@ // complete. As a lazy hack, apply it explicitly from here gui->preferenceChanged("Property Box Layout"); - bool haveSession = false; - bool haveMainModel = false; - bool havePriorCommandLineModel = false; - for (QStringList::iterator i = args.begin(); i != args.end(); ++i) { - MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed; - if (i == args.begin()) continue; if (i->startsWith('-')) continue; QString path = *i; - if (path.endsWith("sv")) { - if (!haveSession) { - status = gui->openSessionFile(path); - if (status == MainWindow::FileOpenSucceeded) { - haveSession = true; - haveMainModel = true; - } - } else { - std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl; - status = MainWindow::FileOpenSucceeded; - } - } - if (status != MainWindow::FileOpenSucceeded) { - if (!haveMainModel) { - status = gui->open(path, MainWindow::ReplaceMainModel); - if (status == MainWindow::FileOpenSucceeded) { - haveMainModel = true; - } - } else { - if (haveSession && !havePriorCommandLineModel) { - status = gui->open(path, MainWindow::AskUser); - if (status == MainWindow::FileOpenSucceeded) { - havePriorCommandLineModel = true; - } - } else { - status = gui->open(path, MainWindow::CreateAdditionalModel); - } - } - } - if (status == MainWindow::FileOpenFailed) { - if (splash) splash->hide(); - QMessageBox::critical - (gui, 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 - (gui, QMessageBox::tr("Failed to open file"), - QMessageBox::tr("Audio required

Please load at least one audio file before importing annotation data")); - } + SVApplication::handleFilepathArgument(path, splash); } #ifdef HAVE_FFTW3F