dan@367: /* dan@367: iTunes connection for dan@367: Sonic Visualiser dan@367: An audio file viewer and annotation editor. dan@367: Centre for Digital Music, Queen Mary, University of London. dan@367: This file copyright 2010 Dan Stowell and QMUL. dan@367: dan@367: This program is free software; you can redistribute it and/or dan@367: modify it under the terms of the GNU General Public License as dan@367: published by the Free Software Foundation; either version 2 of the dan@367: License, or (at your option) any later version. See the file dan@367: COPYING included with this distribution for more information. dan@367: */ dan@367: dan@367: #include "svitunes.h" dan@367: dan@367: #include dan@367: dan@367: #import dan@367: dan@383: #include dan@383: #include dan@383: dan@383: // private helpful function: dan@367: QString qt_mac_NSStringToQString(const NSString *nsstr) dan@367: { dan@367: NSRange range; dan@367: range.location = 0; dan@367: range.length = [nsstr length]; dan@367: dan@367: unichar *chars = new unichar[range.length + 1]; dan@367: chars[range.length] = 0; dan@367: [nsstr getCharacters:chars range:range]; dan@367: QString result = QString::fromUtf16(chars, range.length); dan@367: delete chars; dan@367: return result; dan@367: } dan@367: dan@381: QStringList ITunesSVRemote::getNowPlaying(){ dan@367: NSDictionary *errorDict; dan@367: NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@" \ dan@367: tell application \"System Events\" to set iTunesIsRunning to (name of processes) contains \"iTunes\" \n\ dan@367: if iTunesIsRunning is false then return \"\" \n\ dan@368: \ dan@368: tell application \"iTunes\" \n\ dan@368: if player state is not stopped then \n\ dan@368: set aTrack to current track \n\ dan@368: else \n\ dan@368: set sel to selection \n\ dan@368: if sel is not {} then --and (length of sel) is 1 then \n\ dan@368: set aTrack to item 1 of sel \n\ dan@368: else \n\ dan@368: return \"\" \n\ dan@368: end if \n\ dan@368: end if \n\ dan@368: \ dan@370: return the POSIX path of (location of aTrack as text) & \"\n\" & (genre of aTrack) \n\ dan@368: end tell \n\ dan@368: " dan@367: ]; dan@367: dan@367: NSLog([scriptObject source]); dan@367: dan@367: [scriptObject compileAndReturnError: &errorDict]; dan@367: dan@367: if(![scriptObject isCompiled]){ dan@367: NSLog(@"SV ERROR: applescript object not compiled"); dan@367: NSLog([errorDict description]); dan@367: } dan@367: dan@367: NSAppleEventDescriptor *eventDesc = [scriptObject executeAndReturnError: &errorDict]; dan@367: NSString *nsResultString = [eventDesc stringValue]; dan@367: dan@367: QString resultString = qt_mac_NSStringToQString(nsResultString); dan@367: dan@367: [scriptObject release]; dan@370: return resultString.split(QChar('\n')); dan@367: } dan@383: dan@383: void ITunesSVRemote::updatePlayerState(){ dan@383: NSDictionary *errorDict; dan@383: NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@" \ dan@383: tell application \"System Events\" to set iTunesIsRunning to (name of processes) contains \"iTunes\" \n\ dan@383: if iTunesIsRunning is false then return \"\" \n\ dan@383: \ dan@383: tell application \"iTunes\" \n\ dan@383: if player state is not playing then \n\ dan@383: set playpos to 0 \n\ dan@383: else \n\ dan@383: set playpos to player position \n\ dan@383: end if \n\ dan@383: \ dan@383: return (player state as text) & \"\n\" & (playpos) \n\ dan@383: end tell \n\ dan@383: " dan@383: ]; dan@383: dan@383: NSLog([scriptObject source]); dan@383: dan@383: [scriptObject compileAndReturnError: &errorDict]; dan@383: dan@383: if(![scriptObject isCompiled]){ dan@383: NSLog(@"SV ERROR: applescript object not compiled"); dan@383: NSLog([errorDict description]); dan@383: } dan@383: dan@383: NSAppleEventDescriptor *eventDesc = [scriptObject executeAndReturnError: &errorDict]; dan@383: NSString *nsResultString = [eventDesc stringValue]; dan@383: dan@383: QString resultString = qt_mac_NSStringToQString(nsResultString); dan@383: dan@383: if(resultString==""){ dan@383: m_playerState = STATE_CLOSED; dan@383: std::cerr << "ITunesSVRemote::updatePlayerState() IT IS CLOSED" << std::endl; dan@383: }else{ dan@383: QStringList results = resultString.split(QChar('\n')); dan@383: dan@383: if(results.size() != 2){ dan@383: std::cerr << "ITunesSVRemote::updatePlayerState() ERROR: results not in expected format:" dan@383: << resultString.toStdString() << std::endl; dan@383: [scriptObject release]; dan@383: return; dan@383: } dan@383: dan@383: if(results[0]=="playing") dan@383: m_playerState = STATE_PLAYING; dan@383: else if(results[0]=="paused") dan@383: m_playerState = STATE_PAUSED; dan@383: else if(results[0]=="stopped") dan@383: m_playerState = STATE_STOPPED; dan@383: else if(results[0]=="fast forwarding") dan@383: m_playerState = STATE_FASTFORWARDING; dan@383: else if(results[0]=="rewinding") dan@383: m_playerState = STATE_REWINDING; dan@383: dan@383: if(m_playerState == STATE_PLAYING){ dan@383: // store a record of the current playback position dan@383: m_playerPos = results[1].toInt(); dan@383: std::cerr << "ITunesSVRemote::updatePlayerState() got playback position as " dan@383: << m_playerPos << std::endl; dan@383: } dan@383: } dan@383: dan@383: [scriptObject release]; dan@383: } dan@383: dan@383: bool ITunesSVRemote::isRunning(){ dan@383: return (m_playerState != STATE_UNKNOWN) && (m_playerState != STATE_CLOSED); dan@383: } dan@383: dan@383: bool ITunesSVRemote::isPlaying(){ dan@383: return (m_playerState == STATE_PLAYING); dan@383: } dan@383: dan@383: unsigned int ITunesSVRemote::playerPos(){ dan@383: return m_playerPos; dan@383: }