-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAVMIDIPlayer.lcb
More file actions
331 lines (278 loc) · 15.6 KB
/
AVMIDIPlayer.lcb
File metadata and controls
331 lines (278 loc) · 15.6 KB
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/**
This Library is a wrapper for macOS & iOS AVIMIDIPlayer, useful for playing MIDI musical performance data.
Description:
This Library is a wrapper for macOS & iOS AVIMIDIPlayer.
>*Note:* This library is provided as-is under GPL3 license.
> Please share and share a like.
*/
library org.openxtalk.avmidiplay.paulmcclernan
use com.livecode.engine
use com.livecode.foreign
use com.livecode.objc
use com.livecode.array
use com.livecode.list
use com.livecode.byte
use com.livecode.binary
use com.livecode.assert
metadata version is "1.0.0"
metadata author is "Paul McClernan"
metadata title is "OpenXTalk.org AVMIDIPlayer"
metadata svgicon is "M66.43,52.07c-0.71,0.32-1.48,0.56-2.31,0.78c-2.35,0.65-5.44,0.04-5.44,0.04l-8.52,9.56c0,0,11.03,11.58,13.36,13.92 s4.02,6.19,4.02,6.19l8.77-19.76C76.31,62.8,67.18,58.92,66.43,52.07z M56.35,86.86c-2.83-2.4-16.4-15.09-16.4-15.09L21.22,90.12c0,0,3.25,1.93,5.41,1.86c5.6-0.17,10.48-3.77,15.46-3.77 c4.58,0,8.99,3.52,15.56,3.77c1.55,0.06,2.88-0.35,4.41-1.24c0.7-0.41,2.02-1.54,2.02-1.54S59.18,89.26,56.35,86.86z M52.45,18.42c5.85-5.85,5.42-15.63,5.42-15.63s-8.65,0.97-13.34,6.82c-5.22,6.51-5.07,13.39-4.94,14.51 C44.49,24.13,48.71,22.16,52.45,18.42z M18.38,48.03c-3.59,0.27-3.23,4.28-3.21,4.45l0.03,0.32l-0.23,0.23l-5.54,5.89l-5.85-5.95l8.91,24.95l18.58-18.16l-8.8-9.83 C22.28,49.93,19.79,47.92,18.38,48.03z M9.98,39.65c0,0,1.4-2.6,5.19-5.27c2.15-1.51,4.69-2.88,7.45-3.52c1.75-0.41,3.72-0.62,5.86-0.62 c3.63,0,9.12,1.35,9.12,1.35l-10.85,4.24c-1.77,0.8-2.58,2.62-2.85,3.38l14.4,13.75c3.71-3.62,6.78-6.15,9.99-9.57 c-0.51-4.23,0.89-8.11,3.22-10.81c4.73-5.48,13.47-2.78,13.47-2.78l-3.55,3.05c0,0-4.13,3.16-3.01,6.79 c0.27,0.87,0.84,2.34,2.44,3.17c0.93,0.48,4.09,0.37,5.6-0.95C68.48,40.1,70.45,38,70.45,38s0.88-1.54,1.8-2.43 c1.11-1.08,3.56-2.91,3.56-2.91s-4.82-5.38-8.14-6.83c-2.91-1.27-6.15-1.89-9.71-1.91c-7.4-0.03-12.83,4.65-16.7,4.35 c-3.19-0.25-9.47-4.38-14.6-4.35c-7.22,0.05-13.04,2.44-17.47,7.33C5.44,35.37,4,45.11,4,45.11l1.89-1.93c0,0,2.98-0.11,3.34-0.41 c1.48-1.24,1.31-2.33,1.31-2.33L9.98,39.65z M18.15,46.11c1.68-0.19,4.88,2.09,4.88,2.09l9.22,10.03l4.11-3.86L21.75,39.42l0.13-0.52c0.03-0.14,0.88-3.49,3.9-4.84 l5.18-2.02c-1.95-0.07-5.6-0.11-7.97,0.42c-3.26,0.74-8.73,4.32-10.78,7.04c0.06,0.17,0.09,0.34,0.1,0.53 c0.08,1.49-1.41,3.45-2.02,3.98c-0.73,0.63-2.55,1.03-3.63,1.21l-3.94,3.94l6.59,6.6l3.85-3.86c-0.04-1.6,0.45-3.4,1.78-4.57 C15.67,46.71,16.48,46.3,18.15,46.11z M70.95,39.93c-0.62,0.44-4.18,6.07-9.58,4.98c-2.9-0.58-4.65-3.5-4.92-5.3c-0.6-4.07,1.8-6.16,3.56-7.69 c0.59-0.52,1.6-1.31,1.6-1.31s-6.16-0.73-9.16,3.5c-3.98,5.61-1.98,9.83-1.98,9.83S13.22,80.66,12.03,81.82 c-0.09,0.56-0.5,3.71,0.93,5.31c1.56,1.74,3.06,2.79,5.34,2.24c1.3-0.32,39.44-38.44,39.44-38.44s3.65,0.56,5.67,0.07 C68.3,49.8,70.71,46.32,70.95,39.93z M65.52,84.81c-0.14,0.85-0.52,1.48-1.2,1.99c-0.5,0.41-1.12,0.62-1.88,0.62c-2.8,0-6.23-3.51-6.24-3.52L41.82,70.25 l6.44-6.55c0,0,13.44,13.7,14.11,14.36C63.03,78.73,65.79,83.22,65.52,84.81z"
private foreign handler objC_NSURLURLWithString(in pURLString as ObjcId) returns ObjcId binds to "objc:NSURL.+URLWithString:"
private foreign handler objC_NSURLfileOrDirURLWithPath(in pPathString as ObjcId, in pIsDir as CBool) returns ObjcId binds to "objc:.NSURL.+fileURLWithPath:isDirectory:"
private foreign handler objC_NSURLfileURLWithPath(in pPathString as ObjcId) returns ObjcId binds to "objc:NSURL.+fileURLWithPath:"
private foreign handler objC_NSErrorAlloc() returns ObjcRetainedId binds to "objc:NSError.+alloc"
private foreign handler objC_AVMIDIPlayerAlloc() returns ObjcRetainedId binds to "objc:AVMIDIPlayer.+alloc"
private foreign handler objC_AVMIDIPlayer(in pAVMIDIPlayerInstance as ObjcRetainedId, in pFileNSURL as ObjcId, in pSoundFontNSURL as ObjcId, out pNSError as ObjcId) returns ObjcId binds to "objc:AVMIDIPlayer.-initWithContentsOfURL:soundBankURL:error:"
private foreign handler objC_AVMIDIPlayerPrepare(in pAVPlayerRef as ObjcId) returns nothing binds to "objc:AVMIDIPlayer.-prepareToPlay"
private foreign handler objC_AVMIDIPlayerPlay(in pAVPlayerRef as ObjcId, in pAVPlayDone as optional pointer) returns nothing binds to "objc:AVMIDIPlayer.-play:"
private foreign handler objC_AVMIDIPlayerStop(in pAVPlayerRef as ObjcId) returns nothing binds to "objc:AVMIDIPlayer.-stop"
private foreign handler objC_AVMIDIPlayerPlaying(in pAVPlayerRef as ObjcId) returns CBool binds to "objc:AVMIDIPlayer.isPlaying"
private foreign handler objC_AVMIDIPlayerRate(in pAVPlayerRef as ObjcId, in pRate as ObjcId) returns nothing binds to "objc:AVMIDIPlayer.rate"
private foreign handler objC_AVMIDIPlayerDuration(in pAVPlayerRef as ObjcId) returns NaturalFloat binds to "objc:AVMIDIPlayer.duration"
private foreign handler objC_AVMIDIPlayerCurrentPosition(in pAVPlayerRef as ObjcId) returns NaturalFloat binds to "objc:AVMIDIPlayer.currentPosition"
private foreign handler objC_AVMIDIPlayerSet(in pAVPlayerRef as ObjcId, in pValue as ObjcId, in pSelector as ObjcId) returns nothing binds to "objc:AVMIDIPlayer.-setValue:forKey:"
--------------------- Public handler:
private variable mAVMIDIPlayerInstance as ObjcId
private variable sAVMIDIPlayerStopCallbackHandlerPtr as optional ObjcBlockPointer
private variable sTarget as ScriptObject
public handler AVMIDIPlayerStopCallback(in pBlock as ObjcBlockPointer)
-- foreign handler MCEngineAddRunloopAction(in pCallback as Pointer, in pContext as optional Pointer, out rAction as Pointer) returns CBool
-- foreign handler MCEngineRemoveRunloopAction(in pAction as Pointer) returns nothing
-- foreign handler MCEngineRunloopWait() returns CBool
-- foreign handler MCEngineRunloopBreakWait() returns nothing
-- variable tObject as ScriptObject
-- resolve script object "this stack"
-- put the result into tObject
-- send command "AVMIDIPlayerDone" to tObject -- with [1,2,3]
-- variable tCurrentPosition as NaturalFloat
-- variable tCurrentPosition as Number
-- variable rString as String
-- unsafe
-- put objC_AVMIDIPlayerCurrentPosition(mAVMIDIPlayerInstance) into tCurrentPosition
-- put objC_AVMIDIPlayerCurrentPosition(mAVMIDIPlayerInstance,tNewPosition) into tCurrentPosition
-- end unsafe
-- put tCurrentPosition formatted as string into rString
-- log sTarget
--send "AVMIDIPlayerStopped" to sTarget with tCurrentPosition
-- if the message was not handled then
-- log sTarget
--put tCurrentPosition formatted as string into rString
-- post "AVMIDIPlayerStopped" to sTarget with [tCurrentPosition]
-- post "AVMIDIPlayerStopped" to sTarget with [rString]
post "AVMIDIPlayerStopped" to sTarget
-- MCEngineRunloopWait() -- true
-- MCEngineRunloopBreakWait()
-- log "The message was not handled"
end handler
public handler AVMIDIPlayerInitCallback()
if sAVMIDIPlayerStopCallbackHandlerPtr is nothing then
if not CreateObjcBlockPointerFromHandler(AVMIDIPlayerStopCallback, sAVMIDIPlayerStopCallbackHandlerPtr) then
put nothing into sAVMIDIPlayerStopCallbackHandlerPtr
end if
-- put the caller into sTarget
resolve script object "this stack"
put the result into sTarget
end if
end handler
public handler AVMIDIPlayerRemoveCallback()
if sAVMIDIPlayerStopCallbackHandlerPtr is not nothing then
DeleteObjcBlockPointer(sAVMIDIPlayerStopCallbackHandlerPtr)
put nothing into sAVMIDIPlayerStopCallbackHandlerPtr
end if
end handler
/**
Loads a MIDI file from and a Soundbank file from file paths and prepares for playback.
Example:
AVMIDIPlayerLoad "/Users/Me/MIDIMusic.mid","/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls"
Parameters:
MIDIfilePath (string): the file path to a MIDI file
SoundFontPath (string): the file path to a SoundBank SF2 or DLS file
Description:
Loads a MIDI file from and a Soundbank file in either SoundFont2 or
Downloadable Sound DLS format from absolute file paths passed in and
"prerolls" the data, preparing it for playback.
*/
public handler AVMIDIPlayerLoad(in MIDIfilePath as String, in SoundFontPath as String) returns nothing
if (the operating system is "mac") or (the operating system is "ios") then
--- need NSURL objects to pass to AVMIDIplayer
variable tFileNSURL as ObjcObject
variable tSoundFontNSURL as ObjcObject
--- need NSError object to pass to AVMIDIplayer
variable tNSError as optional ObjcObject
-- variable tIsDir as optional CBool
-- put false into tIsDir
unsafe
put objC_NSURLfileURLWithPath(StringToNSString(MIDIfilePath)) into tFileNSURL
-- put objC_NSURLfileURLWithPath(StringToNSString(pFilePath),tIsDir) into tFileNSURL
put objC_NSURLfileURLWithPath(StringToNSString(SoundFontPath)) into tSoundFontNSURL
-- put objC_NSURLfileURLWithPath(StringToNSString(pSoundFontPath),tIsDir) into tSoundFontNSURL
-- NEED to Add Checking for validity of URLs or the LC Engine will crash when it passes an invalid URL to AVMIDIPlayer!!!
-- put objC_NSErrorAlloc() into tNSError
put objC_AVMIDIPlayerAlloc() into mAVMIDIPlayerInstance
put objC_AVMIDIPlayer(mAVMIDIPlayerInstance, tFileNSURL ,tSoundFontNSURL, tNSError) into mAVMIDIPlayerInstance
objC_AVMIDIPlayerPrepare(mAVMIDIPlayerInstance)
end unsafe
end if
end handler
/**
Loads a MIDI file from and a Soundbank file from URLs and prepares for playback.
Example:
AVMIDIPlayerLoad "file:///Users/Me/MIDIMusic.mid","file:///System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls"
Parameters:
MIDIFileURL (string): A local file URL that points to a MIDI file
SoundFontURL (string): A local file URL that points to SoundBank SF2 or DLS file
Description:
Loads a MIDI file from and a Soundbank file in either SoundFont2 or
Downloadable Sound DLS format from local file URLs passed in and
"prerolls" the data, preparing it for playback.
*/
public handler AVMIDIPlayerLoadURLs(in MIDIFileURL as String, in SoundFontURL as String) returns nothing
if (the operating system is "mac") or (the operating system is "ios") then
--- need NSURL objects to pass to AVMIDIplayer
variable tFileNSURL as ObjcObject
variable tSoundFontNSURL as ObjcObject
--- need NSError object to pass to AVMIDIplayer
variable tNSError as optional ObjcObject
unsafe
put objC_NSURLURLwithString(StringToNSString(MIDIFileURL)) into tFileNSURL
put objC_NSURLURLwithString(StringToNSString(SoundFontURL)) into tSoundFontNSURL
-- NEED to Add Checking for validity of URLs or the LC Engine will crash when it passes an invalid URL to AVMIDIPlayer!!!
-- put objC_NSErrorAlloc() into tNSError
put objC_AVMIDIPlayerAlloc() into mAVMIDIPlayerInstance
put objC_AVMIDIPlayer(mAVMIDIPlayerInstance, tFileNSURL ,tSoundFontNSURL, tNSError) into mAVMIDIPlayerInstance
objC_AVMIDIPlayerPrepare(mAVMIDIPlayerInstance)
end unsafe
end if
end handler
/**
Plays the data that was loaded with either AVMIDIPlayerLoad or AVMIDIPlayerLoadURLs
Example:
AVMIDIPlayerPlay
Description:
Plays the data that was loaded with either AVMIDIPlayerLoad or AVMIDIPlayerLoadURLs
*/
public handler AVMIDIPlayerPlay()
-- variable tAVMIDIPlayerCompletionHandler as optional pointer
unsafe
objC_AVMIDIPlayerPlay(mAVMIDIPlayerInstance, sAVMIDIPlayerStopCallbackHandlerPtr)
end unsafe
end handler
/**
Stops playback
Example:
AVMIDIPlayerStop
Description:
Stops playback of data playback stated with AVMIDIPlayerPlay.
*/
public handler AVMIDIPlayerStop() returns optional NaturalFloat
unsafe
objC_AVMIDIPlayerStop(mAVMIDIPlayerInstance)
return objC_AVMIDIPlayerCurrentPosition(mAVMIDIPlayerInstance)
end unsafe
end handler
/**
Checks to see if MIDI Data is currently being played back
Example:
if AVMIDIPlayerIsPlaying() then AVMIDIPlayerStop
Description:
A boolean that indicates if MIDI Data is currently being played back.
*/
public handler AVMIDIPlayerIsPlaying() returns Boolean
unsafe
return objC_AVMIDIPlayerPlaying(mAVMIDIPlayerInstance)
end unsafe
end handler
/**
Sets the decimal rate of playback; 1.0 being original, 0.5 half, and 2.0 double speed.
Example:
AVMIDIPlayerSetRate 0.75 -- 3/4 the speed of original MIDI file tempo.
Parameters:
playbackRate (Number): a decimal number to set the playback rate to.
Description:
Sets the decimal rate of playback; 1.0 being the original tempo of the MIDI File.
Set playbackRate to 0.5 for half the speed or the original tempo or 2.0 to double the speed.
*/
public handler AVMIDIPlayerSetRate(in playbackRate as Real) returns nothing
unsafe
objC_AVMIDIPlayerSet(mAVMIDIPlayerInstance,NumberToNSNumber(playbackRate),StringToNSString("rate"))
end unsafe
end handler
/**
Returns the length of a loaded sequence in seconds and microseconds.
Example:
function SecsToHrsMinSecs pSecs -- in seconds.millisecs
lock screen
split pSecs by "."
put trunc(pSecs[1]) into deltaTime
put trunc(deltaTime div 3600) into h -- hours
put trunc((deltaTime - (h * 3600)) / 60) into m -- minutes
put deltaTime - (h * 3600) - (m * 60) into s -- seconds
put format( "%01i:%02i:%02i", h, m, s ) &":"& pSecs[2] into displayTime
return displayTime
end SecsToHrsMinSecs
put "The MIDI Sequence is " & SecsToHrsMinSecs(AVMIDIPlayerDuration()) & " long"
Example:
set the endValue of scrollbar "PlayBackProgress" to AVMIDIPlayerDuration()
Description:
Returns the length of a sequence in seconds and microseconds. A sequence
must first be loaded into memory using AVMIDIPlayerLoad or AVMIDIPlayetLoadURLs.
*/
public handler AVMIDIPlayerDuration() returns String
variable tDuration as optional NaturalFloat
unsafe
-- put objC_AVMIDIPlayerInfo(mAVMIDIPlayerInstance,StringToNSString("duration")) into tDuration
put objC_AVMIDIPlayerDuration(mAVMIDIPlayerInstance) into tDuration
return tDuration formatted as string
end unsafe
end handler
/**
Returns the current position of playing sequence in seconds and microseconds.
Example:
function SecsToHrsMinSecs pSecs -- in seconds.millisecs
lock screen
split pSecs by "."
put trunc(pSecs[1]) into deltaTime
put trunc(deltaTime div 3600) into h -- hours
put trunc((deltaTime - (h * 3600)) / 60) into m -- minutes
put deltaTime - (h * 3600) - (m * 60) into s -- seconds
put format( "%01i:%02i:%02i", h, m, s ) &":"& pSecs[2] into displayTime
return displayTime
end SecsToHrsMinSecs
put SecsToHrsMinSecs(AVMIDIPlayerSetCurrentPosition())
Example:
set the thumbPosition of scrollBar "PlayBackProgress" to AVMIDIPlayerSetCurrentPosition()
Description:
Returns the current position of playback in seconds and microseconds.
Use for displaying the current playback progress or current time within a sequence.
Note that current position will continue to increment past the sequence duration
until a stop command is issued.
*/
public handler AVMIDIPlayerGetCurrentPosition() returns String
variable tCurrentPosition as NaturalFloat
-- variable tNewPosition as NaturalFloat
unsafe
put objC_AVMIDIPlayerCurrentPosition(mAVMIDIPlayerInstance) into tCurrentPosition
-- put objC_AVMIDIPlayerCurrentPosition(mAVMIDIPlayerInstance,tNewPosition) into tCurrentPosition
return tCurrentPosition formatted as string
end unsafe
end handler
/**
Sets the current position in seconds.microseconds for a sequence to play from.
Example:
AVMIDIPlayerSetCurrentPosition(the thumbPosition of scrollBar "PlayBackProgress")
Example:
AVMIDIPlayerSetCurrentPosition 10.1 -- sets the position to 10 and 1/10th of a second.
Description:
Sets the current position in seconds.microseconds for a sequence to play from.
A sequence must first be loaded into memory using AVMIDIPlayerLoad or AVMIDIPlayetLoadURLs
before the current position can be set.
Use for "scrubbing" to different points within a sequence or for pause-resume functionality.
*/
public handler AVMIDIPlayerSetCurrentPosition(in pNewPosition as Real) returns nothing
-- variable tNewPosition as NaturalFloat
unsafe
objC_AVMIDIPlayerSet(mAVMIDIPlayerInstance,NumberToNSNumber(pNewPosition),StringToNSString("currentPosition"))
end unsafe
end handler
end library