changeset 372:012fdb1d19bf macness_autotpl

Templating stuff pulled into macness_autotpl branch
author Dan Stowell <dan.stowell@eecs.qmul.ac.uk>
date Fri, 15 Oct 2010 12:16:48 +0100
parents ca9f27734349 (diff) 23f2ee395cf7 (current diff)
children 80d91b72ae7d
files
diffstat 7 files changed, 317 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- 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("<b>File open failed</b><p>Audio file \"%1\" could not be opened").arg(path));
+    }
+    }
+}
+#endif
+
 void
 MainWindow::exportAudio()
 {
--- 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();
--- 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 <QSplashScreen>
 #include <QTimer>
 #include <QPainter>
+#include <QFileOpenEvent>
+#include <QMenu>
+#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("<b>Audio required</b><p>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<QFileOpenEvent *>(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("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
+    }
+}
--- /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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+	<key>CFBundleIconFile</key>
+	<string>sv-macicon.icns</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+    <key>CFBundleGetInfoString</key>
+	<string>Created by Qt/QMake</string>
+	<key>CFBundleSignature</key>
+	<string>SNCV</string>
+	<key>CFBundleExecutable</key>
+	<string>Sonic Visualiser</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.isophonics.SonicVisualiser</string>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<!-- we are an 'editor' of SV files -->
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>sv</string>
+			</array>
+			<!-- TODO
+			<key>CFBundleTypeIconFile</key>
+			<string>SVProject.icns</string> -->
+			<key>CFBundleTypeMIMETypes</key>
+			<array>
+				<string>application/x-sonic-visualiser-project</string>
+			</array>
+			<key>CFBundleTypeName</key>
+			<string>Sonic Visualiser Project</string>
+			<key>CFBundleTypeOSTypes</key>
+			<array>
+				<string>****</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>LSHandlerRank</key>
+			<string>Owner</string>
+			<key>LSIsAppleDefaultForType</key>
+			<true/>
+		</dict>
+		
+		<!-- we are a 'viewer' of general audio files -->
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>mp3</string>
+			</array>
+			<key>CFBundleTypeMIMETypes</key>
+			<array>
+				<string>audio/mpeg</string>
+			</array>
+			<key>CFBundleTypeName</key>
+			<string>MP3 Audio</string>
+			<key>CFBundleTypeRole</key>
+			<string>Viewer</string>
+			<key>LSIsAppleDefaultForType</key>
+			<false/>
+			<key>LSHandlerRank</key>
+			<string>Alternate</string>
+		</dict>
+	</array>
+  </dict>
+</plist>
--- /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 <QString>
+#include <QStringList>
+
+//LATER: bool iTunesRunning();
+
+// Returns a list containing [posixpath, genre]
+QStringList iTunesNowPlaying();
+
+//LATER: QStringList iTunesSelectedPaths();
+
--- /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 <Foundation/NSAppleScript.h>
+
+#import <Foundation/Foundation.h>
+
+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'));
+}
--- 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
+}