# HG changeset patch # User Dan Stowell # Date 1287409468 -3600 # Node ID abb9c3dedec266005836a345ea04d9e9808ea88f # Parent fad5611ef9db2f98e91c1989c950338a37c2186a ITunesSVRemote methods to query playback position and state diff -r fad5611ef9db -r abb9c3dedec2 main/MainWindow.cpp --- a/main/MainWindow.cpp Mon Oct 18 13:59:08 2010 +0100 +++ b/main/MainWindow.cpp Mon Oct 18 14:44:28 2010 +0100 @@ -2173,6 +2173,8 @@ emit hideSplash(); QMessageBox::critical(this, tr("Failed to open file"), tr("File open failed

Audio file \"%1\" could not be opened").arg(path)); + }else{ + m_iTunes->updatePlayerState(); } } } diff -r fad5611ef9db -r abb9c3dedec2 osx/svitunes.h --- a/osx/svitunes.h Mon Oct 18 13:59:08 2010 +0100 +++ b/osx/svitunes.h Mon Oct 18 14:44:28 2010 +0100 @@ -23,7 +23,6 @@ /** * Class to handle communication with a running iTunes program on the system. * Only implemented for Mac at present, since using applescript communication. -* Pseudo-singleton - one instance expected to be owned by SVApplication. */ class ITunesSVRemote : QObject { @@ -31,15 +30,46 @@ public: - //LATER: bool iTunesRunning(); + ITunesSVRemote() : + m_playerState(STATE_UNKNOWN), + m_playerPos(0) + { } + virtual ~ITunesSVRemote() { } // Returns a list containing [posixpath, genre] QStringList getNowPlaying(); + + // Queries iTunes about player state and stores results locally + void updatePlayerState(); - //LATER: QStringList iTunesSelectedPaths(); + // Whether the app is running. Only correct if updatePlayerState() recently invoked. + bool isRunning(); + + // Whether the app is playing back. Only correct if updatePlayerState() recently invoked. + bool isPlaying(); + + // Playback position in seconds. Only correct if updatePlayerState() recently invoked. + unsigned int playerPos(); -// private: -// QString qt_mac_NSStringToQString(const NSString *nsstr); + protected: + + enum { + STATE_UNKNOWN, // before ever querying + STATE_CLOSED, // application not running + // The rest correspond to states reported by iTunes itself: + STATE_STOPPED, + STATE_PLAYING, + STATE_PAUSED, + STATE_FASTFORWARDING, + STATE_REWINDING + }; + + // itunes has a set of states: {playing, stopped, ...}. + // we also use "unknown" before checking, + // and "closed" if iTunes isn't running. + int m_playerState; + unsigned int m_playerPos; // itunes only tells us seconds + }; #endif diff -r fad5611ef9db -r abb9c3dedec2 osx/svitunes.mm --- a/osx/svitunes.mm Mon Oct 18 13:59:08 2010 +0100 +++ b/osx/svitunes.mm Mon Oct 18 14:44:28 2010 +0100 @@ -18,6 +18,10 @@ #import +#include +#include + +// private helpful function: QString qt_mac_NSStringToQString(const NSString *nsstr) { NSRange range; @@ -67,11 +71,87 @@ 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')); } + +void ITunesSVRemote::updatePlayerState(){ + 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 playing then \n\ + set playpos to 0 \n\ + else \n\ + set playpos to player position \n\ + end if \n\ + \ + return (player state as text) & \"\n\" & (playpos) \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]; + + QString resultString = qt_mac_NSStringToQString(nsResultString); + + if(resultString==""){ + m_playerState = STATE_CLOSED; + std::cerr << "ITunesSVRemote::updatePlayerState() IT IS CLOSED" << std::endl; + }else{ + QStringList results = resultString.split(QChar('\n')); + + if(results.size() != 2){ + std::cerr << "ITunesSVRemote::updatePlayerState() ERROR: results not in expected format:" + << resultString.toStdString() << std::endl; + [scriptObject release]; + return; + } + + if(results[0]=="playing") + m_playerState = STATE_PLAYING; + else if(results[0]=="paused") + m_playerState = STATE_PAUSED; + else if(results[0]=="stopped") + m_playerState = STATE_STOPPED; + else if(results[0]=="fast forwarding") + m_playerState = STATE_FASTFORWARDING; + else if(results[0]=="rewinding") + m_playerState = STATE_REWINDING; + + if(m_playerState == STATE_PLAYING){ + // store a record of the current playback position + m_playerPos = results[1].toInt(); + std::cerr << "ITunesSVRemote::updatePlayerState() got playback position as " + << m_playerPos << std::endl; + } + } + + [scriptObject release]; +} + +bool ITunesSVRemote::isRunning(){ + return (m_playerState != STATE_UNKNOWN) && (m_playerState != STATE_CLOSED); +} + +bool ITunesSVRemote::isPlaying(){ + return (m_playerState == STATE_PLAYING); +} + +unsigned int ITunesSVRemote::playerPos(){ + return m_playerPos; +}