DIY Dayparting

As a Holiday Project, I am re-purposing an old macintosh as a Fake TV for my son to watch cartoons and things; it will simply be a monitor with no access to the controls, just like it’s showing a TV broadcast: turn it on, watch your program, and then it’s done; all you can do is turn off the “TV” and wait until tomorrow. Just like old times!

I have a mini2,1 (running MacOS 10.7.5) and I want to control it using iTunes (12.2.2.25) and AppleScript (2.4.3), with a schedule in iCal (5.0.3)

I want to use iTunes because of the simple organization, and playlists to manage files, plus i can just drop in movies and songs from my main computer.

I previously employed iCal as a playlist switcher, and it worked great.

However, i am making this more complicated

For example, a playlist can fade mid-song and change audio. But you can’t switch off a Bugs Bunny cartoon half-way through, that would be a rotten trick.

An easy solution to that is a Smart Playlist, “limit to 30 Minutes” and it will self-populate with the right amount of cartoons–any leftover time can be filled with a “COMING UP NEXT!” card.

Finally, just to make it totally legit, i want to throw in a Station ID before each show or cartoon–just 6-second interstitials with a fake TV Logo, like a commercial break without any actual lousy commercial. This is purely for effect.

Phew! All that! and hopefully in time for Christmas!

in Pseudocode:

The current “DIY Dayparting” script follows.

--iCal event runs this AppleScript...

--Get Current Calendar Event via iCalBuddy hasseg.org/icalBuddy
set theEvent to {first item of my text_to_list((do shell script "/usr/local/bin/icalbuddy -eed -nc -b \"\" eventsNow"), return) as string}

--Use Calendar Event as Playlist Name

EvenlyShuffleThePlaylist(theEvent)

tell application "iTunes"
	
	set full screen to true
	
	play the playlist named "Now Playing"
	
end tell

--how do I know when the playlist is all done...?

--Use Calendar Event to determine "up next" loop
set theNextThing to (theEvent & "-Next.mp4")
set unixpath to "[path-to-up-next-folder]" & theNextThing
set macfile to (POSIX file unixpath)

tell application "QuickTime Player"
	activate
	delay 1
	open file macfile
	set looping of document 1 to true
	set presenting of document 1 to true
	play document 1
end tell

--EvenlyShuffleThePlaylist based on "CK's Evenly-shuffled Playlists v0.6" by Charles Kelly http://www.manythings.org/mac/
on EvenlyShuffleThePlaylist(thePlaylist)
	set MergedPlayList to "Now Playing"
	set PlaylistInterstitials to "[Interstitials]" -- this expects a playlist of the little station IDs, however many
	set PlaylistTVShow to thePlaylist
	
	tell application "iTunes"
		-- get the playlist, creating it if necessary
		if (every playlist whose name is MergedPlayList) is {} then
			set MergedPlayList to make new user playlist with properties {name:MergedPlayList}
		else
			set MergedPlayList to user playlist MergedPlayList
		end if
		
		-- Define MergedTracks
		set MergedTracks to every track of MergedPlayList
		if (count of tracks of MergedPlayList) is 0 then
			set MergedTracks to {}
		else
			-- If MergedTracks already has tunes, put those tunes into the list.
			set MergedTracks to database ID of every track of MergedPlayList
		end if
		
		-- GET TRACKS FROM ALL LISTS
		try
			set allTracks01 to every file track of user playlist PlaylistInterstitials
			set allTracks02 to every file track of user playlist PlaylistTVShow
		on error
			-- do nothing; an error will occur when a list does not exist.
		end try
		try
			set x to (count of allTracks02)
		on error
			-- do nothing
		end try
		
		-- make the show
		repeat with i from 1 to x
			try
				set theTrack to item i of allTracks01
				set theTrackID to database ID of theTrack
				if theTrackID is not in MergedTracks then
					set enabled of (duplicate theTrack to MergedPlayList) to true
					set MergedTracks to MergedTracks & (theTrackID)
				end if
			on error
				-- do nothing
			end try
			try
				set theTrack to item i of allTracks02
				set theTrackID to database ID of theTrack
				if theTrackID is not in MergedTracks then
					set enabled of (duplicate theTrack to MergedPlayList) to true
					set MergedTracks to MergedTracks & (theTrackID)
				end if
			on error
				-- do nothing
			end try
		end repeat
	end tell
end EvenlyShuffleThePlaylist

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list

I’d welcome any suggestions or contributions, and I will post my progress here as I try to figure this out.

Your email address doesn’t work.

please excuse me! i did not allow for how long it has been since I created my MacScripter.net account. I have changed it to a current & functioning address. Thank you!

hoooooooooo boy, well…

           set allTracks01 to every file track of user playlist PlaylistInterstitials

…consistently results in “iTunes got an error: descriptor type mismatch occurred.

I’ve spent a few hours trying every imaginable combination of descriptors, and I am stumped. I’m going to go drink cheap wine and try again tomorrow.

Ӯ

i have streamlined and moved blocks around, but it’s little better than pseudocode;

each and every attempt to “set blahBlah to tracks of playlist” results in "iTunes got an error: descriptor type mismatch occurred."

I’m stymied, and the Google is no help. Presented here for perusal; I will continue after today’s location scout.

--Get Current Calendar Event via iCalBuddy hasseg.org/icalBuddy
set PlaylistTVShow to {first item of my text_to_list((do shell script "/usr/local/bin/icalbuddy -eed -nc -b \"\" eventsNow"), return) as string}

tell application "iTunes"
	--Shuffle based on "CK's Evenly-shuffled Playlists v0.6" by Charles Kelly http://www.manythings.org/mac/
	set MergedPlayList to "Now Playing"
	set PlaylistInterstitials to "[ID-D]" -- Intersitials for the [D]aytime broadcast
	
	if (every playlist whose name is MergedPlayList) is {} then
		set MergedPlayList to make new user playlist with properties {name:MergedPlayList} -- if no playlist, make it
	else
		set MergedPlayList to user playlist MergedPlayList -- if playlist, clean it out
		repeat
			set tr to tracks of playlist MergedPlayList
			if tr is {} then exit repeat
			repeat with t in tr
				delete t
			end repeat
		end repeat
	end if
	
	set x to (count of tracks of user playlist PlaylistTVShow) -- length based on requested TV Show
	repeat with i from 1 to x
		set theTrack to some item of playlist PlaylistInterstitials
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to MergedPlayList) to true
		set MergedTracks to MergedTracks & (theTrackID)
		set theTrack to item i of playlist PlaylistTVShow
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to MergedPlayList) to true
		set MergedTracks to MergedTracks & (theTrackID)
	end repeat
	
	set full screen to true
	play the playlist named "Now Playing"
	
end tell

set nextUp to (POSIX file "/Users/chadwick/Movies/TV Up Next Loop (City).mp4")

--wait for playlist to finish

on idle
	tell application "iTunes"
		try
			if player state is not stopped then return 5
		on error
			return 5
		end try
	end tell
	tell application "QuickTime Player"
		activate
		delay 1
		open file nextUp
		set looping of document 1 to true
		set presenting of document 1 to true
		play document 1
	end tell
	return 5
end idle

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list

I am suspicious that my problem derives from using a variable as a Playlist name.? I will investigate this.

Ӯ

As far as I know, the instruction :

set theTrack to some item of playlist PlaylistInterstitials

is wrong.

Try :

set theTrack to some track of playlist PlaylistInterstitials # or some file track if you want to be more selective

To test this instruction I used :

tell application "iTunes"
	activate
	set playlistNames to name of every user playlist
	set playlistName to choose from list playlistNames # returns false or  a list of one name
	if playlistName is false then error number -128
	set playlistName to item 1 of playlistName # If I miss this one I get mismatch error
	name of every track of user playlist playlistName
	set aPlaylist to user playlist playlistName
	name of every track of aPlaylist
	set theTrack to some file track of playlist playlistName
	name of theTrack
end tell

Everything behaved flawlessly.

Yvan KOENIG running Sierra 10.12.1 in French (VALLAURIS, France) vendredi 9 décembre 2016 17:28:48

thank you, Mr Koenig! perfect!

I had just workarounded that with

set theTrack to track (random number from 1 to (count of PlaylistInterstitials)) of playlist PlaylistInterstitials

but your insight with the much lovelier syntax some track worked perfectly

at this point, this block successfully builds a perfectly shuffled playlist, inserting randomly selected Station IDs into the Smart Playlist’s cartoon selections…

  set x to (count of tracks of playlist (PlaylistTVShow as string)) -- length based on requested TV Show
   repeat with i from 1 to x
       set theTrack to some track of playlist PlaylistInterstitials
       set theTrackID to database ID of theTrack
       set enabled of (duplicate theTrack to MergedPlayList) to true
       set MergedTracks to MergedTracks & (theTrackID)
       set theTrack to track i of playlist "Bugs Bunny"
       set theTrackID to database ID of theTrack
       set enabled of (duplicate theTrack to MergedPlayList) to true
       set MergedTracks to MergedTracks & (theTrackID)
   end repeat

However, it only works as set theTrack to track i of playlist “Bugs Bunny” (playlist specifically named instead of variable derived from event name)

using set theTrack to track i of playlist PlaylistTVShow fails with the descriptor type mismatch error.

I expect I need to coerce the PlaylistTVShow into some format that is eluding me. I will think on it while I drive to the Old Abandoned Prison set.

Ӯ

Comments embedded in the script.

tell application "iTunes"
log (get class of PlaylistTVShow)
--> What is returned here
	set PlaylistTVShow to PlaylistTVShow as text
	log PlaylistTVShow --> Is it "Bugs Bunny" ?
	set x to count tracks of playlist PlaylistTVShow -- length based on requested TV Show
	repeat with i from 1 to x
		set theTrack to some track of playlist PlaylistInterstitials
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to MergedPlayList) to true
		set MergedTracks to MergedTracks & (theTrackID)
		# Which was the failing instruction ?
		# Was it : set theTrack to track i of playlist PlaylistTVShow ?
		# If it was I'm not surprised that it failed
		# because here you weren't coercing it as text.
		# It's why I coerced it on entry so there is no need to repeat the job
		set theTrack to track i of playlist "Bugs Bunny"
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to MergedPlayList) to true
		set MergedTracks to MergedTracks & (theTrackID)
	end repeat
end tell

You wrote :
but your insight with the much lovelier syntax some track worked perfectly

but the truth is that I reproduced your own syntax.
I just replaced your erroneous item by the correct track.:wink:

Yvan KOENIG running Sierra 10.12.1 in French (VALLAURIS, France) vendredi 9 décembre 2016 18:12:18

okay 'Scripter Hepcats.

the current iteration by grace of AppleScript and Mssr. Koenig…

This script combines a smart playlist (in order) and the interstitials playlist (randomly selected) to make a perfectly shuffled playlist all ready to go.

However, THAT is where it stops.

The command play playlist results in a “parameter error.” (Also, there are a couple notes imbedded in the script, re: failures in “use of playlistMerged”…)

progress is good, but the speed bumps are infuriating.

More tomorrow.

--Get Current Calendar Event via iCalBuddy hasseg.org/icalBuddy
set PlaylistTVShow to {first item of my text_to_list((do shell script "/usr/local/bin/icalbuddy -eed -nc -b \"\" eventsNow"), return) as text}

tell application "iTunes"
	--Shuffle based on "CK's Evenly-shuffled Playlists v0.6" by Charles Kelly http://www.manythings.org/mac/
	set playlistMerged to "Now Playing"
	set PlaylistInterstitials to "[ID-D]" -- Intersitials for the [D]aytime broadcast
	set PlaylistTVShow to PlaylistTVShow as text
	set playlistUpNext to "[some filler playlist TBD]"
	
	if (playlist playlistMerged) is {} then
		set playlistMerged to make new user playlist with properties {name:playlistMerged} -- if no playlist, make it
	else
		set playlistMerged to playlistMerged as text
		set playlistMerged to user playlist playlistMerged -- if playlist, clean it out
		repeat
			set tr to get tracks of playlist "Now Playing" -- use of playlistMerged got "descriptor type mismatch"
			if tr is {} then exit repeat
			repeat with t in tr
				delete t
			end repeat
		end repeat
	end if
	
	set x to count of tracks of playlist PlaylistTVShow -- length based on requested TV Show
	set MergedTracks to {}
	repeat with i from 1 to x
		set theTrack to some track of playlist PlaylistInterstitials
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to playlistMerged) to true
		set MergedTracks to MergedTracks & (theTrackID)
		set theTrack to track i of playlist PlaylistTVShow
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to playlistMerged) to true
		set MergedTracks to MergedTracks & (theTrackID)
	end repeat
	
	play playlist "Now Playing" -- use of playlistMerged gets "descriptor type mismatch" / current syntax results in "iTunes got an error: Parameter error." I DON'T KNOW WHAT TO BELIEVE ANYMORE.
	set full screen to true
	
end tell

--wait for playlist to finish

on idle
	tell application "iTunes"
		try
			if player state is not stopped then return 5
		on error
			return 5
		end try
		play playlist playlistUpNext
	end tell
	return 5
end idle

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	set AppleScript's text item delimiters to saveD
	return (theList)
end text_to_list

Ӯ

Hi.

I haven’t been following this thread and haven’t tried your script. But looking through it quickly:

The descriptor problem is because you’ve changed the value of playlistMerged from the playlist’s name to the playlist itself, so putting ‘playlist’ in front of it again is wrong. Either keep the name and put ‘playlist’ in front of it or use the playlist and leave out the word ‘playlist’ in subsequent references to it:

-- set playlistMerged to user playlist playlistMerged -- leave this out
repeat
	set tr to get tracks of playlist playlistMerged -- 'playlist' + the name in the variable

. or .

set playlistMerged to user playlist playlistMerged -- set the variable to the playlist object
repeat
	set tr to get tracks of playlistMerged -- the playlist object in the variable

The other problem you mentioned:

The variable playlistUpNext needs to be declared global at the top of the script so that it can be seen in both the run and idle handlers.

good heavens, thank you NG!

The descriptor problem is because you’ve changed the value of playlistMerged from the playlist’s name to the playlist itself” seems stupidly obvious in retrospect, guess i was just staring too long, thank you.

Ӯ

i cannot get past the mysterious “parameter error.”

In fact, under analysis, i cannot get iTunes to play anything via AppleScript.

I tried several different ways to get any playlist at all playing; no results.

Eventually, i just tried to get anything to play…

tell application "iTunes"
	activate
	play
end tell

Nothing. iTunes just sits there.

I engaged in a little code cleanup, basically fiddling while Rome burns.

Here is the latest version of the script, which does everything except actually play

set PlaylistTVShow to ({first item of my text_to_list((do shell script "/usr/local/bin/icalbuddy -eed -nc -b \"\" eventsNow"), return)} as text) --Get Current Calendar Event via iCalBuddy hasseg.org/icalBuddy

global playlistUpNext
set playlistUpNext to "[some filler playlist TBD]"

tell application "iTunes"
	--Shuffle based on "CK's Evenly-shuffled Playlists v0.6" by Charles Kelly http://www.manythings.org/mac/
	set playlistMerged to "Now Playing"
	set PlaylistInterstitials to "[ID-D]" -- Intersitials for the [D]aytime broadcast
	
	if (not (exists playlist playlistMerged)) then
		set playlistMerged to make new user playlist with properties {name:playlistMerged} -- if no playlist, make it
	else
		set playlistMerged to user playlist playlistMerged -- if playlist, clean it out
		delete tracks of playlistMerged
	end if
	
	set x to count of tracks of playlist PlaylistTVShow -- length based on requested TV Show
	set MergedTracks to {}
	repeat with i from 1 to x
		set theTrack to some track of playlist PlaylistInterstitials
		set enabled of (duplicate theTrack to playlistMerged) to true
		set MergedTracks to MergedTracks & (database ID of theTrack)
		set theTrack to track i of playlist PlaylistTVShow
		set enabled of (duplicate theTrack to playlistMerged) to true
		set MergedTracks to MergedTracks & (database ID of theTrack)
	end repeat
	
	play playlistMerged
	
end tell

on idle --wait for playlist to finish
	tell application "iTunes"
		try
			if player state is not stopped then return 5
		on error
			return 5
		end try
		play playlist playlistUpNext
	end tell
	return 5
end idle

on text_to_list(txt, delim)
	set saveD to text item delimiters
	try
		set text item delimiters to {delim}
		set theList to every text item of txt
	on error
		set text item delimiters to saveD
	end try
	set text item delimiters to saveD
	return (theList)
end text_to_list

under further analysis, basically NOTHING I DO will get iTunes to play.

press space bar in active window, click the play triangle, select “Play” from the Controls menu, NOTHING.

Double-clicking will result in the selected item playing once then returning to the playlist window”iTunes will NOT play any playlist in sequence.

this is weird and infuriating.

I’m going to get coffee.

Ӯ

PS. another script attempt; failed, but just checking all variables

tell application "iTunes"
	activate
	set view of browser window 1 to playlist "Now Playing"
	tell application "System Events" to keystroke "a" using command down
	play playlist "Now Playing"
end tell

Hello

I renamed several variables to make your script more understandable.

When it IS a string (the name of a playlist) I use : somethingName
When it IS a list (a playlist) I use : somethingList
With these changes, I’m quite sure that you will understand better what is at work.

global playlistUpNextName

--Get Current Calendar Event via iCalBuddy hasseg.org/icalBuddy
set PlaylistTVShowName to first item of my text_to_list((do shell script "/usr/local/bin/icalbuddy -eed -nc -b \"\" eventsNow"), return) as text # Here, it is a string, no need to coerce it later

# Moved here and renamed to make clear that they are names (string) not playlist (list)
# As they are strings they aren't iTunes objects

set playlistMergedName to "Now Playing"
set PlaylistInterstitialsName to "[ID-D]" -- Intersitials for the [D]aytime broadcast.
set playlistUpNextName to "[some filler playlist TBD]"

tell application "iTunes"
	--Shuffle based on "CK's Evenly-shuffled Playlists v0.6" by Charles Kelly http://www.manythings.org/mac/
	if (playlist playlistMergedName) is {} then
		set playlistMergedList to make new user playlist with properties {name:playlistMergedName} -- if no playlist, make it
	else
		set playlistMergedList to user playlist playlistMergedName -- if playlist, clean it out
		--repeat # My understanding is that this instruction (and its end one) is useless
		set tr to get tracks of playlistMergedList
		--if tr is {} then exit repeat # Thanks to Nigel who pointed that it must be disabled!
		repeat with t in tr
			delete t
		end repeat
		--end repeat
	end if
	
	set x to count tracks of playlist PlaylistTVShowName -- length based on requested TV Show
	set MergedTracks to {}
	repeat with i from 1 to x
		set theTrack to some track of playlist PlaylistInterstitialsName
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to playlistMergedList) to true
		set end of MergedTracks to theTrackID # do the same thing but I think that it's more clear
		set theTrack to track i of playlist PlaylistTVShowName
		set theTrackID to database ID of theTrack
		set enabled of (duplicate theTrack to playlistMergedList) to true
		set end of MergedTracks to theTrackID # do the same thing but I think that it's more clear
	end repeat
	
	--play playlist "Now Playing" -- use of playlistMerged gets "descriptor type mismatch" / current syntax results in "iTunes got an error: Parameter error." I DON'T KNOW WHAT TO BELIEVE ANYMORE.
	play playlist playlistMergedName
	set full screen to true
	
end tell

--wait for playlist to finish

on idle
	tell application "iTunes"
		try
			if player state is not stopped then return 5
		on error
			return 5
		end try
		play playlist playlistUpNextName # defined as a global value
	end tell
	return 5
end idle

on text_to_list(txt, delim)
	set saveD to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to {delim}
		set theList to every text item of txt
		set AppleScript's text item delimiters to saveD
	on error errStr number errNum
		set AppleScript's text item delimiters to saveD
		error errStr number errNum
	end try
	return theList
end text_to_list

Yvan KOENIG running Sierra 10.12.1 in French (VALLAURIS, France) samedi 10 décembre 2016 17:23:32

According to iTunes’s scripting dictionary, ‘play’ plays tracks or files. There’s no mention of it playing playlists. Maybe you have to repeat through the tracks in a playlist and play them individually.

Hello Nigel

A I was not accustomed to scripting iTunes I ran a short test script before posting.

tell application "iTunes"
	set theNames to name of playlists
	play playlist (item 5 of theNames)
end tell

It behaved flawlessly.

Yvan KOENIG running Sierra 10.12.1 in French (VALLAURIS, France) samedi 10 décembre 2016 18:03:49

Mr Koenig, Mr Garvey, thank you so much for your attention and suggestions! I really appreciate it.

Mr Koenig, re: “play playlist (item 5 of theNames),” i know right??? but check it out…

Mr Garvey, heavens it has me stumped. The google produces examples of people using “play playlist” like http://alvinalexander.com/apple/itunes-applescript-examples-scripts-mac-reference

and i have tried a bunch of variations, including things like

 	 play playlist playlistMerged
	
	play track 1 of playlist playlistMerged
	
	activate
	set view of browser window 1 to playlist "Now Playing"
	play 

and I just can’t get a play!

my next theory when i’m back to the mini is: maybe iTunes treats playlists of “TV Shows” differently? I will try changing the video type to “Music Video” and see what happens…! [Edit: nothing happened!]

Thanks again, you are all fantastic!

Ӯ

When I write that a script behaved flawlessly, it’s because it did.
I ran it again and the history was :

[format]tell application “iTunes”
get name of every playlist
→ {“Bibliothèque”, “Musique”, “Vidéos”, “Films”, “Vidéos personnelles”, “Séries TV”, “Podcasts”, “iTunes U”, “Livres”, “Livres audio”, “PDF”, “Livres audio”, “Achats”, “Ajouté récemment”, “Ajouts récents”, “Années 90”, “Clips vidéo musicaux”, “Les 25 plus écoutés”, “Meilleur classement”, “Morceaux récents”, “Musique classique”, “Chansons - youtube”, “compilation #3”, “Compilation #4”, “Compilation #5”, “Danielle Messia”, “Économiseur d’écran des illustrations iTunes”, “Ipod Michèle”, “Jazz”, “Jean Ferrat”, “Ma Liste”, “Playlist sans titre”, “pour maman”, “pour maman 2”, “Purchased by koenigyvan@mac.com”, “Serge Reggiani”, “Stromae Racine carrée”, “Vidéos offertes par Apple”}
play playlist “Vidéos personnelles”
end tell[/format]

I must add an important feature:
[format]play playlist (item 5 of theNames)[/format]
is equivalent to
[format]play track 1 of playlist (item 5 of theNames)[/format]

Yvan KOENIG running Sierra 10.12.1 in French (VALLAURIS, France) samedi 10 décembre 2016 20:48:53

I apologize if there is a misunderstanding, Mr Koenig”i was not arguing.

“I know right” was merely to emphasize that the clear and simple script you offered should behave flawlessly; my screen shot was merely to demonstrate that for some obscure reason the script fails on my test machine. (To be clear, I only called out that particular line because AppleScript editor highlighted it as the offending code.)

I assure you, I appreciate everyone’s help and I am certainly not here to pick a fight with anyone!

(further, that example code works fine & instantly on my MacBookPro11,5 with macOS 10.12.1, but fails on the test machine… a mini2,1 with Mac OS X 10.7.5…)

Ӯ