# HG changeset patch # User Dan Stowell # Date 1287141408 -3600 # Node ID 012fdb1d19bfe21039e96f7c1cd04be9ec6e1d53 # Parent ca9f277343494184f710a6e7e7930d6c07143bd8# Parent 23f2ee395cf73bab24b607d67e2a3689192dbff9 Templating stuff pulled into macness_autotpl branch diff -r 23f2ee395cf7 -r 012fdb1d19bf main/MainWindow.cpp --- a/main/MainWindow.cpp Fri Oct 15 11:59:03 2010 +0100 +++ b/main/MainWindow.cpp Fri Oct 15 12:16:48 2010 +0100 @@ -79,6 +79,9 @@ #include "widgets/ModelDataTableDialog.h" #include "rdf/PluginRDFIndexer.h" #include "rdf/RDFExporter.h" +#ifdef Q_WS_MAC + #include "osx/svitunes.h" +#endif #include "Surveyer.h" #include "framework/VersionTester.h" @@ -442,6 +445,16 @@ m_keyReference->registerShortcut(action); menu->addAction(action); +#ifdef Q_WS_MAC + action = new QAction(tr("Import current track from iTunes"), this); + action->setShortcut(tr("Ctrl+Alt+I")); + action->setStatusTip(tr("Import currently playing/selected iTunes track")); + connect(action, SIGNAL(triggered()), this, SLOT(importITunesAudio())); + //connect(this, SIGNAL(canImportITunesAudio(bool)), action, SLOT(setEnabled(bool))); + m_keyReference->registerShortcut(action); + menu->addAction(action); +#endif + action = new QAction(tr("&Export Audio File..."), this); action->setStatusTip(tr("Export selection as an audio file")); connect(action, SIGNAL(triggered()), this, SLOT(exportAudio())); @@ -2148,6 +2161,25 @@ } } +#ifdef Q_WS_MAC +void +MainWindow::importITunesAudio() +{ + QStringList nowPlaying = iTunesNowPlaying(); + QString path = nowPlaying.at(0); + QString genre = (nowPlaying.size() > 1) ? nowPlaying.at(1) : ""; + std::cerr << "MainWindow::importITunesAudio(): genre is " << genre.toStdString() << std::endl; + + if (path != "") { + if (openAudio(path, ReplaceMainModel) == FileOpenFailed) { + emit hideSplash(); + QMessageBox::critical(this, tr("Failed to open file"), + tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); + } + } +} +#endif + void MainWindow::exportAudio() { diff -r 23f2ee395cf7 -r 012fdb1d19bf main/MainWindow.h --- a/main/MainWindow.h Fri Oct 15 11:59:03 2010 +0100 +++ b/main/MainWindow.h Fri Oct 15 12:16:48 2010 +0100 @@ -80,6 +80,9 @@ virtual void openSession(); virtual void importAudio(); virtual void importMoreAudio(); +#ifdef Q_WS_MAC + virtual void importITunesAudio(); +#endif virtual void openSomething(); virtual void openLocation(); virtual void openRecentFile(); diff -r 23f2ee395cf7 -r 012fdb1d19bf main/main.cpp --- a/main/main.cpp Fri Oct 15 11:59:03 2010 +0100 +++ b/main/main.cpp Fri Oct 15 12:16:48 2010 +0100 @@ -36,6 +36,12 @@ #include #include #include +#include +#include +#ifdef Q_WS_MAC + #include "osx/svitunes.h" + void qt_mac_set_dock_menu(QMenu *menu); // must declare it ourselves, weirdly enough +#endif #include "../version.h" @@ -188,7 +194,10 @@ public: SVApplication(int &argc, char **argv) : QApplication(argc, argv), - m_mainWindow(0) { } + m_readyForFiles(false), + m_filepathQueue(QStringList()), + m_mainWindow(0) + { } virtual ~SVApplication() { } void setMainWindow(MainWindow *mw) { m_mainWindow = mw; } @@ -202,8 +211,30 @@ if (!success) manager.cancel(); } + void handleFilepathArgument(QString path, QSplashScreen *splash); + + bool m_readyForFiles; + QStringList m_filepathQueue; + +#ifdef Q_WS_MAC + void setupDockMenu() { + std::cerr << "SV adding mac dock menu" << std::endl; + QMenu *dockMenu = new QMenu(); + QStringList nowPlaying = iTunesNowPlaying(); + QString theText = nowPlaying.at(0); + if (theText == ""){ + theText = "[[No current track in iTunes]]"; + } + dockMenu->addAction(theText); + qt_mac_set_dock_menu(dockMenu); + } +#endif + + protected: MainWindow *m_mainWindow; + bool event(QEvent *); + }; int @@ -347,59 +378,21 @@ // complete. As a lazy hack, apply it explicitly from here gui->preferenceChanged("Property Box Layout"); - bool haveSession = false; - bool haveMainModel = false; - bool havePriorCommandLineModel = false; + application.m_readyForFiles = true; // Ready to receive files from e.g. Apple Events 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")); - } + application.handleFilepathArgument(path, splash); + } + + for (QStringList::iterator i = application.m_filepathQueue.begin(); i != application.m_filepathQueue.end(); ++i) { + QString path = *i; + application.handleFilepathArgument(path, splash); } #ifdef HAVE_FFTW3F @@ -417,6 +410,10 @@ settings.endGroup(); #endif +#ifdef Q_WS_MAC + application.setupDockMenu(); +#endif + if (splash) splash->finish(gui); delete splash; @@ -457,3 +454,68 @@ return rv; } + +bool SVApplication::event(QEvent *event){ + QString thePath; + switch (event->type()) { + case QEvent::FileOpen: + thePath = static_cast(event)->file(); + if(m_readyForFiles) + handleFilepathArgument(thePath, NULL); + else + m_filepathQueue.append(thePath); + return true; + default: + return QApplication::event(event); + } +} + +/** Application-global handler for filepaths passed in, e.g. as command-line arguments or apple events */ +void SVApplication::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 = m_mainWindow->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 = m_mainWindow->open(path, MainWindow::ReplaceMainModel); + if (status == MainWindow::FileOpenSucceeded) { + haveMainModel = true; + } + } else { + if (haveSession && !havePriorCommandLineModel) { + status = m_mainWindow->open(path, MainWindow::AskUser); + if (status == MainWindow::FileOpenSucceeded) { + havePriorCommandLineModel = true; + } + } else { + status = m_mainWindow->open(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("Audio required

Please load at least one audio file before importing annotation data")); + } +} diff -r 23f2ee395cf7 -r 012fdb1d19bf osx/Info.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/osx/Info.plist Fri Oct 15 12:16:48 2010 +0100 @@ -0,0 +1,67 @@ + + + + + CFBundleIconFile + sv-macicon.icns + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + SNCV + CFBundleExecutable + Sonic Visualiser + CFBundleIdentifier + org.isophonics.SonicVisualiser + CFBundleDocumentTypes + + + + CFBundleTypeExtensions + + sv + + + CFBundleTypeMIMETypes + + application/x-sonic-visualiser-project + + CFBundleTypeName + Sonic Visualiser Project + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + Editor + LSHandlerRank + Owner + LSIsAppleDefaultForType + + + + + + CFBundleTypeExtensions + + mp3 + + CFBundleTypeMIMETypes + + audio/mpeg + + CFBundleTypeName + MP3 Audio + CFBundleTypeRole + Viewer + LSIsAppleDefaultForType + + LSHandlerRank + Alternate + + + + diff -r 23f2ee395cf7 -r 012fdb1d19bf osx/svitunes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/osx/svitunes.h Fri Oct 15 12:16:48 2010 +0100 @@ -0,0 +1,24 @@ +/* + iTunes connection for + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2010 Dan Stowell 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 +#include + +//LATER: bool iTunesRunning(); + +// Returns a list containing [posixpath, genre] +QStringList iTunesNowPlaying(); + +//LATER: QStringList iTunesSelectedPaths(); + diff -r 23f2ee395cf7 -r 012fdb1d19bf osx/svitunes.mm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/osx/svitunes.mm Fri Oct 15 12:16:48 2010 +0100 @@ -0,0 +1,77 @@ +/* + iTunes connection for + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + This file copyright 2010 Dan Stowell 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 "svitunes.h" + +#include + +#import + +QString qt_mac_NSStringToQString(const NSString *nsstr) +{ + NSRange range; + range.location = 0; + range.length = [nsstr length]; + + unichar *chars = new unichar[range.length + 1]; + chars[range.length] = 0; + [nsstr getCharacters:chars range:range]; + QString result = QString::fromUtf16(chars, range.length); + delete chars; + return result; +} + +QStringList iTunesNowPlaying(){ + NSDictionary *errorDict; + NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@" \ +tell application \"System Events\" to set iTunesIsRunning to (name of processes) contains \"iTunes\" \n\ +if iTunesIsRunning is false then return \"\" \n\ +\ +tell application \"iTunes\" \n\ + if player state is not stopped then \n\ + set aTrack to current track \n\ + else \n\ + set sel to selection \n\ + if sel is not {} then --and (length of sel) is 1 then \n\ + set aTrack to item 1 of sel \n\ + else \n\ + return \"\" \n\ + end if \n\ + end if \n\ + \ + return the POSIX path of (location of aTrack as text) & \"\n\" & (genre of aTrack) \n\ +end tell \n\ +" + ]; + + NSLog([scriptObject source]); + + [scriptObject compileAndReturnError: &errorDict]; + + if(![scriptObject isCompiled]){ + NSLog(@"SV ERROR: applescript object not compiled"); + NSLog([errorDict description]); + } + + NSAppleEventDescriptor *eventDesc = [scriptObject executeAndReturnError: &errorDict]; + NSString *nsResultString = [eventDesc stringValue]; + + NSLog(@"iTunesNowPlayingPath: "); + NSLog(nsResultString); + + QString resultString = qt_mac_NSStringToQString(nsResultString); + + [scriptObject release]; + return resultString.split(QChar('\n')); +} diff -r 23f2ee395cf7 -r 012fdb1d19bf sonic-visualiser.pro --- a/sonic-visualiser.pro Fri Oct 15 11:59:03 2010 +0100 +++ b/sonic-visualiser.pro Fri Oct 15 12:16:48 2010 +0100 @@ -40,4 +40,10 @@ main/PreferencesDialog.cpp \ main/Surveyer.cpp +mac { + QMAKE_INFO_PLIST = osx/Info.plist + + OBJECTIVE_SOURCES += osx/svitunes.mm + LIBS += -framework Foundation +}