dan@367
|
1 /*
|
dan@367
|
2 iTunes connection for
|
dan@367
|
3 Sonic Visualiser
|
dan@367
|
4 An audio file viewer and annotation editor.
|
dan@367
|
5 Centre for Digital Music, Queen Mary, University of London.
|
dan@367
|
6 This file copyright 2010 Dan Stowell and QMUL.
|
dan@367
|
7
|
dan@367
|
8 This program is free software; you can redistribute it and/or
|
dan@367
|
9 modify it under the terms of the GNU General Public License as
|
dan@367
|
10 published by the Free Software Foundation; either version 2 of the
|
dan@367
|
11 License, or (at your option) any later version. See the file
|
dan@367
|
12 COPYING included with this distribution for more information.
|
dan@367
|
13 */
|
dan@367
|
14
|
dan@367
|
15 #include "svitunes.h"
|
dan@367
|
16
|
dan@367
|
17 #include <Foundation/NSAppleScript.h>
|
dan@367
|
18
|
dan@367
|
19 #import <Foundation/Foundation.h>
|
dan@367
|
20
|
dan@383
|
21 #include <iostream>
|
dan@383
|
22 #include <cstdio>
|
dan@383
|
23
|
dan@383
|
24 // private helpful function:
|
dan@367
|
25 QString qt_mac_NSStringToQString(const NSString *nsstr)
|
dan@367
|
26 {
|
dan@367
|
27 NSRange range;
|
dan@367
|
28 range.location = 0;
|
dan@367
|
29 range.length = [nsstr length];
|
dan@367
|
30
|
dan@367
|
31 unichar *chars = new unichar[range.length + 1];
|
dan@367
|
32 chars[range.length] = 0;
|
dan@367
|
33 [nsstr getCharacters:chars range:range];
|
dan@367
|
34 QString result = QString::fromUtf16(chars, range.length);
|
dan@367
|
35 delete chars;
|
dan@367
|
36 return result;
|
dan@367
|
37 }
|
dan@367
|
38
|
dan@381
|
39 QStringList ITunesSVRemote::getNowPlaying(){
|
dan@367
|
40 NSDictionary *errorDict;
|
dan@367
|
41 NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@" \
|
dan@367
|
42 tell application \"System Events\" to set iTunesIsRunning to (name of processes) contains \"iTunes\" \n\
|
dan@367
|
43 if iTunesIsRunning is false then return \"\" \n\
|
dan@368
|
44 \
|
dan@368
|
45 tell application \"iTunes\" \n\
|
dan@368
|
46 if player state is not stopped then \n\
|
dan@368
|
47 set aTrack to current track \n\
|
dan@368
|
48 else \n\
|
dan@368
|
49 set sel to selection \n\
|
dan@368
|
50 if sel is not {} then --and (length of sel) is 1 then \n\
|
dan@368
|
51 set aTrack to item 1 of sel \n\
|
dan@368
|
52 else \n\
|
dan@368
|
53 return \"\" \n\
|
dan@368
|
54 end if \n\
|
dan@368
|
55 end if \n\
|
dan@368
|
56 \
|
dan@370
|
57 return the POSIX path of (location of aTrack as text) & \"\n\" & (genre of aTrack) \n\
|
dan@368
|
58 end tell \n\
|
dan@368
|
59 "
|
dan@367
|
60 ];
|
dan@367
|
61
|
dan@367
|
62 NSLog([scriptObject source]);
|
dan@367
|
63
|
dan@367
|
64 [scriptObject compileAndReturnError: &errorDict];
|
dan@367
|
65
|
dan@367
|
66 if(![scriptObject isCompiled]){
|
dan@367
|
67 NSLog(@"SV ERROR: applescript object not compiled");
|
dan@367
|
68 NSLog([errorDict description]);
|
dan@367
|
69 }
|
dan@367
|
70
|
dan@367
|
71 NSAppleEventDescriptor *eventDesc = [scriptObject executeAndReturnError: &errorDict];
|
dan@367
|
72 NSString *nsResultString = [eventDesc stringValue];
|
dan@367
|
73
|
dan@367
|
74 QString resultString = qt_mac_NSStringToQString(nsResultString);
|
dan@367
|
75
|
dan@367
|
76 [scriptObject release];
|
dan@370
|
77 return resultString.split(QChar('\n'));
|
dan@367
|
78 }
|
dan@383
|
79
|
dan@383
|
80 void ITunesSVRemote::updatePlayerState(){
|
dan@383
|
81 NSDictionary *errorDict;
|
dan@383
|
82 NSAppleScript *scriptObject = [[NSAppleScript alloc] initWithSource:@" \
|
dan@383
|
83 tell application \"System Events\" to set iTunesIsRunning to (name of processes) contains \"iTunes\" \n\
|
dan@383
|
84 if iTunesIsRunning is false then return \"\" \n\
|
dan@383
|
85 \
|
dan@383
|
86 tell application \"iTunes\" \n\
|
dan@383
|
87 if player state is not playing then \n\
|
dan@383
|
88 set playpos to 0 \n\
|
dan@383
|
89 else \n\
|
dan@383
|
90 set playpos to player position \n\
|
dan@383
|
91 end if \n\
|
dan@383
|
92 \
|
dan@383
|
93 return (player state as text) & \"\n\" & (playpos) \n\
|
dan@383
|
94 end tell \n\
|
dan@383
|
95 "
|
dan@383
|
96 ];
|
dan@383
|
97
|
dan@383
|
98 NSLog([scriptObject source]);
|
dan@383
|
99
|
dan@383
|
100 [scriptObject compileAndReturnError: &errorDict];
|
dan@383
|
101
|
dan@383
|
102 if(![scriptObject isCompiled]){
|
dan@383
|
103 NSLog(@"SV ERROR: applescript object not compiled");
|
dan@383
|
104 NSLog([errorDict description]);
|
dan@383
|
105 }
|
dan@383
|
106
|
dan@383
|
107 NSAppleEventDescriptor *eventDesc = [scriptObject executeAndReturnError: &errorDict];
|
dan@383
|
108 NSString *nsResultString = [eventDesc stringValue];
|
dan@383
|
109
|
dan@383
|
110 QString resultString = qt_mac_NSStringToQString(nsResultString);
|
dan@383
|
111
|
dan@383
|
112 if(resultString==""){
|
dan@383
|
113 m_playerState = STATE_CLOSED;
|
dan@383
|
114 std::cerr << "ITunesSVRemote::updatePlayerState() IT IS CLOSED" << std::endl;
|
dan@383
|
115 }else{
|
dan@383
|
116 QStringList results = resultString.split(QChar('\n'));
|
dan@383
|
117
|
dan@383
|
118 if(results.size() != 2){
|
dan@383
|
119 std::cerr << "ITunesSVRemote::updatePlayerState() ERROR: results not in expected format:"
|
dan@383
|
120 << resultString.toStdString() << std::endl;
|
dan@383
|
121 [scriptObject release];
|
dan@383
|
122 return;
|
dan@383
|
123 }
|
dan@383
|
124
|
dan@383
|
125 if(results[0]=="playing")
|
dan@383
|
126 m_playerState = STATE_PLAYING;
|
dan@383
|
127 else if(results[0]=="paused")
|
dan@383
|
128 m_playerState = STATE_PAUSED;
|
dan@383
|
129 else if(results[0]=="stopped")
|
dan@383
|
130 m_playerState = STATE_STOPPED;
|
dan@383
|
131 else if(results[0]=="fast forwarding")
|
dan@383
|
132 m_playerState = STATE_FASTFORWARDING;
|
dan@383
|
133 else if(results[0]=="rewinding")
|
dan@383
|
134 m_playerState = STATE_REWINDING;
|
dan@383
|
135
|
dan@383
|
136 if(m_playerState == STATE_PLAYING){
|
dan@383
|
137 // store a record of the current playback position
|
dan@383
|
138 m_playerPos = results[1].toInt();
|
dan@383
|
139 std::cerr << "ITunesSVRemote::updatePlayerState() got playback position as "
|
dan@383
|
140 << m_playerPos << std::endl;
|
dan@383
|
141 }
|
dan@383
|
142 }
|
dan@383
|
143
|
dan@383
|
144 [scriptObject release];
|
dan@383
|
145 }
|
dan@383
|
146
|
dan@383
|
147 bool ITunesSVRemote::isRunning(){
|
dan@383
|
148 return (m_playerState != STATE_UNKNOWN) && (m_playerState != STATE_CLOSED);
|
dan@383
|
149 }
|
dan@383
|
150
|
dan@383
|
151 bool ITunesSVRemote::isPlaying(){
|
dan@383
|
152 return (m_playerState == STATE_PLAYING);
|
dan@383
|
153 }
|
dan@383
|
154
|
dan@383
|
155 unsigned int ITunesSVRemote::playerPos(){
|
dan@383
|
156 return m_playerPos;
|
dan@383
|
157 }
|
dan@384
|
158
|
dan@384
|
159 void ITunesSVRemote::resetPlayerState(){
|
dan@384
|
160 m_playerPos = 0;
|
dan@384
|
161 }
|