Friday, January 28, 2022

#1 2021-10-30 03:12:01 pm

Fredrik71
Member
Registered: 2019-10-23
Posts: 929

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.

Applescript:

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

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

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

Applescript:

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

Script ex3

Applescript:

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_

Applescript:

-- 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.

Applescript:

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

Last edited by Fredrik71 (2021-10-31 09:37:47 am)


if you are the expert, who will you call if its not your imagination.


Filed under: AVFoundation

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)