-
Notifications
You must be signed in to change notification settings - Fork 15
/
connector-osx-kn6.scpt
311 lines (297 loc) · 9.62 KB
/
connector-osx-kn6.scpt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
--
-- slideshow -- Observe and Control Slideshow Applications
-- Copyright (c) 2014-2023 Dr. Ralf S. Engelschall <http://engelschall.com>
--
-- This Source Code Form is subject to the terms of the Mozilla Public
-- License (MPL), version 2.0. If a copy of the MPL was not distributed
-- with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
--
-- File: connector-osx-kn6.scpt
-- Purpose: connector engine for Apple Keynote 6 under Mac OS X
-- Language: AppleScript
--
-- utility function
on filterText(this_text, allowed_chars)
set new_text to ""
repeat with this_char in this_text
set x to the offset of this_char in allowed_chars
if x is not 0 then
set new_text to (new_text & this_char) as string
end if
end repeat
return new_text
end filterText
-- utility function
on replaceText(this_text, search_string, replacement_string)
set AppleScript's text item delimiters to the search_string
set the item_list to every text item of this_text
set AppleScript's text item delimiters to the replacement_string
set this_text to the item_list as string
set AppleScript's text item delimiters to ""
return this_text
end replace_chars
-- utility function
on asciiCharset()
set charset to " \"'!#$%()*+,-./:;<=>?@[\\]^_{|}~"
set charset to (charset & "0123456789")
set charset to (charset & "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
set charset to (charset & "abcdefghijklmnopqrstuvwxyz")
return charset
end asciiCharset
-- get application state
on knGetState()
set state to "closed"
tell application "System Events"
set is_running to (exists (some process whose name is "Keynote"))
end tell
if is_running then
try
set state to "running"
tell application "Keynote"
if false then -- FIXME: how to detect play mode?
set state to "viewing"
else if (get count of slides of front document) > 0 then
set state to "editing"
end if
end tell
on error errMsg
end try
end if
return state
end knGetState
-- get Apple Keynote current slide
on knGetCurSlide()
try
tell application "Keynote"
if false then -- FIXME: how to detect play mode?
return (get slide number of current slide of front document) -- FIXME: wrong!
else
return (get slide number of current slide of front document)
end if
end tell
on error errMsg
return 0
end try
end knGetCurSlide
-- get Apple Keynote maximum slide
on knGetMaxSlide()
try
tell application "Keynote"
return (get count of slides of front document)
end tell
on error errMsg
return 0
end try
end knGetMaxSlide
-- the STATE command
on cmdSTATE()
set state to knGetState()
if state is "closed" then
set position to 0
set slides to 0
else
set position to knGetCurSlide()
set slides to knGetMaxSlide()
end if
return ("{ \"response\": { " & ¬
"\"state\": \"" & state & "\", " & ¬
"\"position\": " & position & ", " & ¬
"\"slides\": " & slides & " " & ¬
"} }")
end cmdSTATE
-- the INFO command
on cmdINFO()
set output to ""
if knGetMaxSlide() is 0 then
error "still no active presentation"
end if
tell application "Keynote"
set thePresentation to front document
set theTitles to ""
set theNotes to ""
set slideCount to (get count of slides of thePresentation)
repeat with slideNum from 1 to slideCount
set theSlide to slide slideNum of thePresentation
set theTitle to (get object text of default title item of theSlide) as string
if theTitles is not "" then
set theTitles to (theTitles & ", ")
end if
set theTitles to (theTitles & "\"" & (my replaceText(theTitle, "\"", "\\\"")) & "\"")
set theNote to (presenter notes of theSlide) as string
set theNote to (my filterText(theNote, my asciiCharset()))
if theNotes is not "" then
set theNotes to (theNotes & ", ")
end if
set theNotes to (theNotes & "\"" & (my replaceText(theNote, "\"", "\\\"")) & "\"")
end repeat
set theTitles to ("[ " & theTitles & " ]")
set theNotes to ("[ " & theNotes & " ]")
set output to ("{ \"response\": { \"titles\": " & theTitles & ", \"notes\": " & theNotes & " } }")
end tell
return output
end cmdINFO
-- the control commands
on cmdCTRL(command, arg)
set state to knGetState()
if command is "BOOT" then
if state is not "closed" then
error "application already running"
end if
tell application "Keynote"
activate
end tell
else if command is "QUIT" then
if state is "closed" then
error "application already closed"
end if
tell application "Keynote"
quit
end tell
else if command is "OPEN" then
if state is "editing" or state is "viewing" then
error "active presentation already existing"
end if
tell application "Keynote"
tell application "Finder" to set thePath to ¬
POSIX file (POSIX path of (container of (path to me) as string) & (arg)) as alias
open thePath
end tell
else if command is "CLOSE" then
if state is "closed" or state is "running" then
error "still no active presentation"
end if
tell application "Keynote"
close front document
end tell
else if command is "START" then
if state is "closed" or state is "running" then
error "still no active presentation"
end if
if state is "viewing" then
error "active presentation already viewing"
end if
tell application "Keynote"
start front document from (slide 1 of front document)
end tell
else if command is "STOP" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
stop front document
end tell
else if command is "PAUSE" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
activate
tell application "System Events" to keystroke "b"
end tell
else if command is "RESUME" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
activate
tell application "System Events" to keystroke "b"
end tell
else if command is "FIRST" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
repeat with i from 1 to (my knGetMaxSlide())
try
show previous
on error errMsg
exit repeat
end try
delay 0.02
end repeat
end tell
else if command is "LAST" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
repeat with i from 1 to ((my knGetMaxSlide()) - 1)
try
show next
on error errMsg
exit repeat
end try
delay 0.02
end repeat
end tell
else if command is "GOTO" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
repeat with i from 1 to (my knGetMaxSlide())
try
show previous
on error errMsg
exit repeat
end try
delay 0.02
end repeat
repeat with i from 1 to ((arg as integer) - 1)
try
show next
end try
delay 0.02
end repeat
end tell
else if command is "PREV" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
show previous
end tell
else if command is "NEXT" then
if state is not "viewing" then
error "no active slideshow"
end if
tell application "Keynote"
show next
end tell
end if
return "{ \"response\": \"OK\" }"
end cmdCTRL
-- main procedure
on run argv
set cmd to item 1 of argv
set arg to ""
if count of argv is 2 then
set arg to item 2 of argv
end if
try
if cmd is "STAT" then
set output to cmdSTATE()
else if cmd is "INFO" then
set output to cmdINFO()
else if cmd is "BOOT" ¬
or cmd is "QUIT" ¬
or cmd is "OPEN" ¬
or cmd is "CLOSE" ¬
or cmd is "START" ¬
or cmd is "STOP" ¬
or cmd is "PAUSE" ¬
or cmd is "RESUME" ¬
or cmd is "FIRST" ¬
or cmd is "LAST" ¬
or cmd is "GOTO" ¬
or cmd is "PREV" ¬
or cmd is "NEXT" then
set output to cmdCTRL(cmd, arg)
else
set output to "{ \"error\": \"invalid command\" }"
end if
on error errMsg
set output to ("{ \"error\": \"" & errMsg & "\" }")
end try
copy output to stdout
end run