I am trying to figure out how to write code for one script to stop another script.
Here is the situation: I have created two scripts - one for recording and one for playback in Sound Studio - to simulate a radio room at a children’s museum. I have two push buttons running into iKeys into a macmini. One runs a script to open, save any file currently open with a time stamp, close it, open a new file and begin recording for 4 minutes. Another button is for playback only. (Other buttons on the desk play audio from a flash audio player-intro, outro, commercials, etc.) The problem occurs when/if the kids don’t record the entire 4 minute program and push playback. The record script continues on during playback. Then they hit record again and start a new 4 minute recording (meanwhile the first 4 min recording is still going). Eventually, after about a dozen or so of these “pile ups” we get an error message.
So how can I insert code in the playback script to stop the record script?
I’m not really familiar with Sound Studio (actually, I’ve never heard of it), and I don’t understand your scenario, but I do understand your final question. In any script, i’m pretty sure that there is no true way to stop it without using ‘return’ (or ‘quit’ if it is an application). However, a script can only call return for itself. I am not at my Mac so I the code I may give you might not be 100% accurate but it shouldn’t be difficult at all to understand where I am getting at.
Your Script that is stopping the other one (I’m thinking the playback script)
--Code to stop the other script.
set thePath to (path to desktop as Unicode text) & "log.txt"
set theFile to (open for access file thePath)
set eof theFile to 0
write "stop" to theFile
close access theFile
Code to be put into the script to be stopped (i.e. recording script)
set shouldStop to "nothing"
try --just in case the file wasn't made yet
set theFile to (open for access file ((path to desktop as Unicode text) & "log.txt"))
set shouldStop to read theFile
close access theFile
end try
if shouldStop is "stop" then return
While the first code snippet should be used only when you want to quit the other script, the second code snippet should be used rather frequently so as to check whether it has been asked to stop. Depending on function, this may go inot an ‘on idle’ handler instead. I suppose that if you are running this script as an applictaion then you may be able to put this entire function into a custom handler (eg. shouldStop()) and then call the custom handler. In this case, you would want to replace the last line of snippet #2 to ‘then quit’ instead of ‘then return’. You could try doing that with a normal script but (as I am not at my Mac I can’t check) it might try to quit Script Editor. While my code is somewhat cumbersome in size and use, I hope it is at least a temporary answer to your problem!
P.S. If it is an application, one script may call ‘quit’ for the other (eg. tell application “Recording Script” to quit) but I am afraid that if it is doing something, it may wait until it is done (in this case recording) before quitting. Try it out though!
I’ve decided to just include the two scripts I’m using to start/stop the recording and playback the recording. I’ve pieced this together from a few different scripts and it works well but I’m trying to figure out how to make it so if you wanted to playback the audio before the 4 minutes was up, you could do so. This is not possible for now because I can’t figure out how to interrupt the shell script.
Recording Script for Sound Studio:
tell application "Sound Studio"
activate
end tell
tell application "System Events"
tell process "Sound Studio"
end tell
--stop and save the audio file with a time stamp
keystroke "." using {command down}
keystroke "s" using {command down}
delay 1
tell window "Save"
set theDate to (current date)
keystroke ((year of theDate) as string)
keystroke "-"
keystroke ((month of theDate) as string)
keystroke "-"
keystroke ((day of theDate) as string)
keystroke "-"
keystroke ((time of theDate) as string)
keystroke "--LICM"
keystroke "s" using {command down}
end tell
delay 5
--open a new file and begin recording
keystroke "w" using {command down}
keystroke "n" using {command down}
keystroke "r" using {command down}
end tell
--record for 4 minutes then stop
do shell script "sleep 240"
tell application "System Events"
tell process "Sound Studio"
end tell
keystroke "." using {command down}
end tell
And here is the simple…
Playback Script for Sound Studio:
--stop and playback the audio
tell application "Sound Studio"
activate
end tell
tell application "System Events"
tell process "Sound Studio"
end tell
keystroke "." using {command down}
delay 1
keystroke "p" using {command down}
end tell
I realize not everyone will have Sound Studio handy, but if you do and you want to help me with a few things, thanks in advance. For anyone else interested in creating this type of thing for yourself or your kids, here you go:
This is a Radio Room exhibit for children. I’m using a Tascam US144 usb interface with a Mac Mini. I have five microphones feeding into a 12 channel mixer with the stereo xlr main outs feeding into the Tascam. Then from the Tascam I have it feed into a receiver/amp that sends the audio to two speakers. I have six pushbuttons. The Record and Playback buttons feed into an iKeys usb device that I programmed for keystrokes (in this case, to activate my scripts). The four other buttons activate commercials and show intros and outros from an Akman SR4 flash player feeding into the 12 channel mixer.
My first problem is allowing the playback script to run if the they don’t want to wait the 4 minutes. As I stated, the shell script won’t allow interrupt once it’s in progress. Another feature I’m working on is a way to mute the microphones until recording begins because the kids like to sit down and immediately start screaming. This is difficult because the Tascam doesn’t give you control over the input settings. My only workable idea is to figure out a way to open preferences in Sound Studio and click the “Play-through in to out” checkbox. This would mean the audio signal going to the amp is coming from the Mac Mini and not the Tascam. And if that wasn’t enough, my third feature to work on is a way to activate an “On Air” sign when it begins recording! I have a MIDI relay that I’m hoping will work by scripting a midi signal to turn the relay on.
Are you wedded to Sound Studio?
Did you know that most of the QuickTime Player’s “Pro” features are scriptable without buying “QuickTime Pro” even though they are not directly accessible from the UI?
Well, even if you want to stick with Sound Studio you should be able to adapt the interruption method I used here. It is an elaboration on the same do shell script+sleep method.
on run
set sleeperName to "SleepingWhileRecordingForRadioStation"
"/tmp" -- Wherever, or put your own alias in the next var
set finalSaveDir to alias POSIX file result
set {origFile, savedFile} to saveCurrentIn(getTimeStampFileIn(finalSaveDir))
-- Maybe delete the origFile?
set newFile to startNewRecording(sleeperName, 240)
{origFile, savedFile, newFile}
end run
to saveCurrentIn(filePath)
--stop and save the audio file with a time stamp
set origAlias to missing value
set savedAlias to missing value
tell application "QuickTime Player"
try
stop first document
set origAlias to my alias (my POSIX file (path of first document)) -- Use lots of my because otherwise the tell block breaks the expression.
save self contained first document in filePath
set savedAlias to my alias (my POSIX file (path of first document))
end try
try -- Try to close even if the above stuff failed.
close first document without saving
end try
end tell
return {origAlias, savedAlias}
end saveCurrentIn
to startNewRecording(sleeperName, sleepLength)
--open a new file and begin recording
tell application "QuickTime Player" to ¬
new audio recording -- The resulting reference is not usable («class » id 12; the code is four NULs; gives an error if you try to use it), but we can refer to is as "first document"
-- Turn up the monitor volume (plays the sound while it is recording). This does not seem to be directly scriptable. Oh well, at least it is very simple.
tell application "System Events" to ¬
set value of slider 1 of first window of application process "QuickTime Player" to 1.0
tell application "QuickTime Player" to ¬
start first document
--record for 4 minutes then stop
try
-- This "exec -a" syntax lets us set a special name for the process that we can easily distinguish in the output of "ps" or single out with killall.
-- The parentheses create a sub-shell which lets the shell sense whether the sleep was killed, or just exited normally.
set sleepEndedNormally to true
do shell script "(exec -a " & quoted form of sleeperName & " sleep " & quoted form of (sleepLength as text) & ")"
on error m number n
if n is greater than 0 then
set sleepEndedNormally to false
else
error m number n
end if
end try
set docAlias to missing value
tell application "QuickTime Player"
-- Only stop the document if sleep was not killed. Presumaly whoever interrupted the sleep by killing it will have already stopped (and probably started playing) the document. We do not want to interrupt that possible playback.
if sleepEndedNormally then ¬
stop first document -- This changes it from a "recording" to a normal "document" it has already been saved, probably on the desktop.
try
set docAlias to my alias (my POSIX file (path of first document))
end try
end tell
return docAlias
end startNewRecording
to getTimeStampFileIn(dir)
tell (current date)
((its year) as string) & "-" & ¬
((its month) as string) & "-" & ¬
((its day) as string) & "-" & ¬
((its time) as string) & "--LICM"
end tell
POSIX file ((POSIX path of dir) & result)
end getTimeStampFileIn
on run
set sleeperName to "SleepingWhileRecordingForRadioStation"
interruptRecordingScript(sleeperName)
stopCurrentAndPlay()
end run
to stopCurrentAndPlay()
tell application "QuickTime Player"
tell first document
stop -- If recording, converts from "recording" to normal "document".
set current time to 0 -- Restart at beginning (if it was already playing); or take this out if you want to keep playing where it left off and are OK with a slight stutter between the stop and start
start
end tell
end tell
end stopCurrentAndPlay
to interruptRecordingScript(sleeperName)
try -- Swallow the error if there is no matching process.
do shell script "killall " & quoted form of sleeperName
end try
end interruptRecordingScript
on run
set sleeperName to "SleepingWhileRecordingForRadioStation"
isRecording(sleeperName)
end run
to isRecording(sleeperName)
sleeperName is in (paragraphs of (do shell script "ps Aco command"))
end isRecording
QuickTime Player Version 7.6.2 (518)
QuickTimeâ„¢ Version 7.6.2 (1327)
Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 4 Public Beta (4528.17)
Operating System: Mac OS X (10.4)
We are not married to Sound Studio, but I forgot to mention that we have the monitor visible so the kids can see the waveform while they are recording and SS has a really great modifiable waveform screen that you can set to any color scheme you want. When we toured a local radio station they had a similar program that their djs used to record commercials and sound bites.