Example in ASObjC with AVFoundation

Simple example showing different syntax in ASObjC. This example use AVFoundation to play a mp3 song from URL on internet. As you could see its use tell block with properties from AVAudioPlayer class. But we could also do the same part in different way. The second script show that. And we could also do it without setValue:forKey and valueForKey: The third script show that. You could also see that we add set with capital letter for the first character and end and before its value a colon.
And with a Boolean value we add () at the end. The syntax is kind of flexible in ASObjC and some approaches are more Objective-C look a like when others it more AppleScript.

use framework "Foundation"
use framework "AVFoundation"
use scripting additions

set theString to "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3"

set theURL to current application's |NSURL|'s URLWithString:theString
set theData to current application's NSData's dataWithContentsOfURL:theURL
set {audioPlayer, theError} to current application's AVAudioPlayer's alloc()'s initWithData:theData |error|:(reference)
if audioPlayer is missing value then error (theError's localizedDescription() as text)

tell audioPlayer
    -- The number of times the audio repeats playback.
    numberOfLoops to 0
    -- The audio player’s volume relative to other audio output.
    volume to 1.0
    -- Prepares the player for audio playback.
    prepareToPlay()
    -- Plays audio asynchronously.
    play()
end tell

if (audioPlayer's playing) as boolean is true then
    display dialog "Audio is playing..." buttons {"OK"} default button "OK"
end if
if (result's button returned) is "OK" then return audioPlayer's |stop|()

Script ex2

audioPlayer's setValue:0 forKey:"numberOfLoops"
audioPlayer's setValue:1.0 forKey:"volume"
audioPlayer's valueForKey:"prepareToPlay"
audioPlayer's valueForKey:"play"

Script ex3

audioPlayer's setNumberOfLoops:0
audioPlayer's setVolume:1.0
audioPlayer's prepareToPlay()
audioPlayer's play()

Here is simple example in Xcode to use play button and stop button with textfield as input URL
I’m not 100% if I need the use statement it was working without it.

You need to create play & stop button and textfield in Interface Builder and delegate → textField
and buttons → delegate and that’s it.

In Xcode handlers look like
on propertyName_(params)
– some code
end propertyName_

-- use framework "Foundation"
-- use framework "AVFoundation"
-- use scripting additions

script AppDelegate
    property parent : class "NSObject"

    property urlString : missing value
    property audioPlayer : missing value
    
    -- IBOutlets
    property theWindow : missing value
    
    on applicationWillFinishLaunching_(aNotification)
        -- Insert code here to initialize your application before any files are opened 
    end applicationWillFinishLaunching_
    
    on applicationShouldTerminate_(sender)
        -- Insert code here to do any housekeeping before your application quits 
        return current application's NSTerminateNow
    end applicationShouldTerminate_
    
    on buttonPlay_(sender)
        set theString to urlString's stringValue()
        set theURL to current application's |NSURL|'s URLWithString:theString
        set theData to current application's NSData's dataWithContentsOfURL:theURL
        set {audioPlayer, theError} to current application's AVAudioPlayer's alloc()'s initWithData:theData |error|:(reference)
if audioPlayer is missing value then error (theError's localizedDescription() as text)

        audioPlayer's setValue:0 forKey:"numberOfLoops"
        audioPlayer's setValue:1.0 forKey:"volume"
        audioPlayer's valueForKey:"prepareToPlay"
        audioPlayer's valueForKey:"play"
    end buttonPlay_

    on buttonStop_(sender)
        tell audioPlayer to |stop|()
    end buttonStop_
end script

Here we hardcode it and by using handlers its 10 minutes extra time compare to Xcode version.
So not only is Xcode Interface Builder useful it make the process faster.

use framework "Foundation"
use framework "AppKit"
use scripting additions

property arguments : missing value
property audioPlayer : missing value
property textFieldWithURLString : missing value

on run
	if current application's NSThread's isMainThread() as boolean then
		my performDialog:arguments
	else
		my performSelectorOnMainThread:"performDialog:" withObject:arguments waitUntilDone:true
	end if
end run

on performDialog:arguments
	set buttonPlay to createButtonWithTitle("Play", 490, 75, 64, 21, "buttonPlay:")
	set buttonStop to createButtonWithTitle("Stop", 490, 50, 64, 21, "buttonStop:")
	
	set textFieldWithURLString to createTextfieldWithPlaceholder("Type the url to play", 20, 50, 462, 21)
	
	set subviewItems to {buttonPlay, buttonStop, textFieldWithURLString}
	
	set {theWidth, theHeight} to {564, 114}
	set theWindow to createWindowWithRect(subviewItems, 0, 0, theWidth, theHeight)
	theWindow's setTitle:"Examples with AVAudioPlayer..."
	theWindow's |center|()
	theWindow's makeKeyAndOrderFront:me
end performDialog:

on buttonPlay:sender
	set theString to textFieldWithURLString's stringValue()
	set theURL to current application's |NSURL|'s URLWithString:theString
	set theData to current application's NSData's dataWithContentsOfURL:theURL
	set {audioPlayer, theError} to current application's AVAudioPlayer's alloc()'s initWithData:theData |error|:(reference)
	if audioPlayer is missing value then error (theError's localizedDescription() as text)
	
	audioPlayer's setValue:0 forKey:"numberOfLoops"
	audioPlayer's setValue:1.0 forKey:"volume"
	audioPlayer's valueForKey:"prepareToPlay"
	audioPlayer's valueForKey:"play"
end buttonPlay:

on buttonStop:sender
	tell audioPlayer to |stop|()
end buttonStop:

on createButtonWithTitle(title, x, y, width, height, selector)
	set theButtonTitle to current application's NSButton's buttonWithTitle:title target:me action:selector
	theButtonTitle's setFrameSize:{width, height}
	theButtonTitle's setFrameOrigin:{x, y}
	return theButtonTitle
end createButtonWithTitle

on createTextfieldWithPlaceholder(placeholder, x, y, width, height)
	set textFieldSSize to current application's NSMakeRect(x, y, width, height)
	set theTextField to current application's NSTextField's alloc()'s initWithFrame:textFieldSSize
	theTextField's setPlaceholderString:placeholder
	return theTextField
end createTextfieldWithPlaceholder

on createWindowWithRect(subviewItems, x, y, width, height)
	set windowSize to current application's NSMakeRect(x, y, width, height)
	set winStyle to (current application's NSWindowStyleMaskTitled as integer) + (current application's NSWindowStyleMaskClosable as integer)
	set theWindow to current application's NSWindow's alloc()'s initWithContentRect:windowSize styleMask:winStyle backing:2 defer:true
	
	repeat with anSubview in subviewItems
		(theWindow's contentView()'s addSubview:anSubview)
	end repeat
	return theWindow
end createWindowWithRect
1 Like