Sunday, October 17, 2021

#1 2021-09-25 10:15:39 am

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

ASObjC with scriptable application (ScriptingBridge)

The code itself is properly not so useful... The code is more to show
how the framework ScriptingBridge works if you like to script ASObjC with scriptable application.
In this example I use Finder to get information from files in trash.

The code is only for research and for my curiosity.

Applescript:

use framework "Foundation"
use framework "ScriptingBridge"
use scripting additions

set bundleID to id of application "Finder"
set finder to current application's SBApplication's applicationWithBundleIdentifier:bundleID

tell finder to tell |trash|() to tell |items|()
   log (its valueForKey:"URL") as list
end tell

tell finder to set theURL to (its valueForKey:"URL") of |items|() of |trash|() as list
log theURL

set theURL to ((its valueForKey:"URL") of |items|() of |trash|() of finder) as list
log theURL

tell finder to tell |trash|()
   log (its |properties|()) as record
   tell |items|()
       log (its valueForKey:"name") as list
       log (its valueForKey:"URL") as list
       log (its valueForKey:"comment") as list
       log (its valueForKey:"kind") as list
       log (its valueForKey:"nameExtension") as list
       log (its valueForKey:"modificationDate") as list
       log (its valueForKey:"creationDate") as list
       log (its valueForKey:"owner") as list
   end tell
end tell

Applescript:

use framework "Foundation"
use framework "ScriptingBridge"
use scripting additions

tell application "System Events" to set thePID to unix id of application process "Finder"
set finder to current application's SBApplication's applicationWithProcessIdentifier:thePID

tell finder to tell |trash|() to tell |items|()
   log (its valueForKey:"name") as list
end tell

set thePath to POSIX path of (path to applications folder) & "TextEdit.app"
set theURL to current application's |NSURL|'s fileURLWithPath:thePath
set textedit to current application's SBApplication's applicationWithURL:theURL

tell textedit to tell |documents|()
   log (its valueForKey:"path") as list
   log (its valueForKey:"name") as list
   log ((its valueForKey:"text")'s objectAtIndex:1) as list
   log (its valueForKey:"properties") as list
end tell

Here is a example using PyObjC

from Foundation import *
from ScriptingBridge import SBApplication

iTunesEPlSPaused = 1800426352

## Controls -> Repeat
off = 0x6b52704f
one = 0x6b527031
all = 0x6b416c6c

## Controls -> Shuffle
songs = 0x6b536853
albums = 0x6b536841
groupings = 0x6b536847

## Check the iTunes.h

iTunes = SBApplication.applicationWithBundleIdentifier_('com.apple.iTunes')
if iTunes:
    print iTunes.currentTrack().name()
    print iTunes.currentTrack().album()
    print iTunes.currentTrack().artist()
    print iTunes.currentTrack().genre()
    print iTunes.currentTrack().kind()

## Is Airplay enabled   
    print iTunes.valueForKey_("AirPlayEnabled")

## Print the stream name and url (ex. Internet Radio)   
    print iTunes.currentStreamTitle()
    print iTunes.currentStreamURL()

## We could also do
    print iTunes.currentTrack().valueForKey_("time")

    print iTunes.valueForKey_("name")

## Set the sound volume to 85
if iTunes:     
    iTunes.setValue_forKey_("85","soundVolume")
   
"""   
## Set the mute to true
if iTunes:
    iTunes.setValue_forKey_("true","mute")
"""

## Set the shuffled to true
"""
if iTunes:
    iTunes.setValue_forKey_("true","shuffleEnabled")
"""
## set the frontmost of application to true
if iTunes:
    iTunes.setValue_forKey_("true","frontmost")

## Set the shuffled mode to songs
if iTunes:
    iTunes.setValue_forKey_(songs,"shuffleMode")

## Set the song repeat (off, one, all)
if iTunes:
    iTunes.setValue_forKey_(off,"songRepeat")

## Pause the current playing track
"""
if iTunes:
    iTunes.pause()
    print iTunes.playerState() ## 1800426352
if iTunesEPlSPaused:
    print "Track have been paused"
"""

## Next track
"""
if iTunes:
    iTunes.nextTrack()
"""

## Toggle the playing/paused state
"""
if iTunes:
    iTunes.playpause()
"""



## SBElementArray Class

iTunesPlaylists = iTunes.playlists()
if iTunesPlaylists:
    print iTunesPlaylists.valueForKey_("properties")
   
iTunesSource = iTunes.sources()
if iTunesSource:
    print iTunesSource.valueForKey_("properties")
   
iTunesTracks = iTunes.tracks()
if iTunesTracks:
    print iTunesTracks.valueForKey_("properties")

iTunesBrowserWindows = iTunes.browserWindows()
if iTunesBrowserWindows:
    print iTunesBrowserWindows.valueForKey_("properties")

iTunesEncoders = iTunes.encoders()
if iTunesEncoders:
    print iTunesEncoders.valueForKey_("properties")
   
iTunesEQPresets = iTunes.EQPresets()
if iTunesEQPresets:
    print iTunesEQPresets.valueForKey_("properties")

iTunesWindows = iTunes.windows()
if iTunesWindows:
    print iTunesWindows.valueForKey_("properties")

## Set the window to fullcreen
"""
    iTunesWindows.setValue_forKey_("true","fullScreen")
"""

Last edited by Fredrik71 (2021-10-10 05:43:05 pm)


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

Offline

 

#2 2021-09-29 07:16:21 pm

technomorph
Member
Registered: 2017-12-14
Posts: 201

Re: ASObjC with scriptable application (ScriptingBridge)

Why would you ever do this?
Makes no sense.

The number of Apple Events that will get sent back and forth will make
All of this extremely slow

Last edited by technomorph (2021-09-29 07:22:04 pm)

Offline

 

#3 2021-09-30 08:32:09 am

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

Re: ASObjC with scriptable application (ScriptingBridge)

technomorph wrote:

Why would you ever do this?


The purpose of the script was only to understand the framework... (Scripting Bridge)

AS already knows how to talk to the terminology of scriptable application so in that sense you are
right but that was never the purpose of the example.

Sorry if I was not clear enough.


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

Offline

 

#4 2021-09-30 06:04:40 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6705

Re: ASObjC with scriptable application (ScriptingBridge)

Fredrik71 wrote:

The purpose of the script was only to understand the framework... (Scripting Bridge).



It's worth understanding the purpose of the framework. Initially, the only way for an app written in Objective-C to call send and receive Apple events was to create a script, call that, and do the necessary value conversions. ScriptingBridge was created as a way for Objective-C code to call Apple events directly, without AppleScript.

So calling it from AppleScript is, well, somewhat circular.


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#5 2021-10-07 11:40:10 pm

technomorph
Member
Registered: 2017-12-14
Posts: 201

Re: ASObjC with scriptable application (ScriptingBridge)

Yeah I think it would be more helpful to post the Objective-C code.

I started with AppleScript the user more AsObjC,
The moved into using XCode and started in Objective-C.
I mainly use Objective-C but much of my programming is based around DJing and music so
I interact a great deal with Spotify and iTunes.   I’ve used the ITLibrary framework and
It’s great, but it doesn’t allow you to manipulate anything.  Also I’ve found that the searching is
Still not up to what I like (I’m just starting to learn how use RegEx’s in my predicates).  And that
The iTunes scripting search give me better results.

So over time I’ve been trying to use more scripting bridge than AppleScripts
But it’s defintely not as easy to use and the results are not always what expected.
Also definitely some time issues with sending Apple Events.

Offline

 

#6 2021-10-10 07:30:06 am

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

Re: ASObjC with scriptable application (ScriptingBridge)

@technomorph
Check this PyObjC script you could see its almost the same as my ASObjC code in my first post.

To run below code use the Python that was included with your Mac ex. /usr/bin/python
If you use Python3 you need to change the print line to be: print(iTunes.currentTrack().name())
And install the package PyObjC

I'm not saying this approach is fast but it does work.

from Foundation import *
from ScriptingBridge import SBApplication

iTunes = SBApplication.applicationWithBundleIdentifier_('com.apple.iTunes')
if iTunes:
    print iTunes.currentTrack().name()
    print iTunes.currentTrack().album()
    print iTunes.currentTrack().artist()
    print iTunes.currentTrack().genre()
    print iTunes.currentTrack().kind()

## We could also do
    print iTunes.currentTrack().valueForKey_("time")

## Pause the current playing track
"""
    iTunes.pause()
    print iTunes.playerState()
if 1800426352:
    print "Track have been paused"
"""

## Next track
if iTunes:
    iTunes.nextTrack()

## Toggle the playing/paused state
    iTunes.playpause()


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

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)