How to make iTunes stop after current track?

I’m trying to figure out how to make iTunes (12.8) stop playback after the current track.

I know Doug has a script called This Is The Last Song, but I need the function within a bigger script, and Doug saves his scripts as read-only so you can’t study how they achieve what they do.

I found an old blog post with

tell application "iTunes" to play selection with once

but while it compiles, it doesn’t seem to do anything.

Should I be clearing the “Up Next” list somehow, or what’s the approach?

ITunes also posts distributed Notifications very time the player state changes.
IE play / pause / new track.

You can register using the distributedNotification center and get
The userInfo dict from the notification. It will contain info on the track.
You can store this info and every time a new track plays.
You can compare the new info to the info you stored to see if it’s
When you wanna stop.

It’s quite a bit extra code compared to the above.
But if your wanting to stop after a particular song.
Then this may be helpful.

This is a really helpful app for finding out about NSDistributedNotifications
https://github.com/lilyball/NotificationWatcher

iTunes posts them whenever the player state changes.
Play, Pause, New Track

You can see from the info above that you can grab from the Notification’s userInfo()

Unfortunately there’s bug where the elapsedStr does not update if you play and pause in the middle.
So you have to repeal iTunes for it’s player position and then get the duration of the current track.
You can then properly calculated the remaing time.

When the next track plays. You’ll get a new notification.
In your case you can just stop.
Or if you need to check name etc. You can check and choose whether to stop.

See next post for code I put together that creates a NSDictionary and Record initially from the notification, then it gets the current time of the player position and the total length of the track and then calculates the time remaining. Then adds those new values to the Dictionary.

Save as an Application with Stay Open Option.
Run and check console

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Cocoa"
use framework "Foundation"
use framework "AppKit"

use scripting additions

-- classes, constants, and enums used
property NSDistributedNotificationCenter : a reference to current application's NSDistributedNotificationCenter
property NSThread : a reference to current application's NSThread

property NSString : a reference to current application's NSString
property NSMutableString : a reference to current application's NSMutableString
property NSArray : a reference to current application's NSArray
property NSMutableArray : a reference to current application's NSMutableArray
property NSDictionary : a reference to current application's NSDictionary
property NSMutableDictionary : a reference to current application's NSMutableDictionary
property NSNumber : a reference to current application's NSNumber

global notifCenter, contRun

property curTrack : missing value
property curTrackDict : missing value
property curTrackRec : missing value
property curTime : 0
property curLength : 0
property curRemain : 0


on run
	-- set up variables
	log {"run called"}
	current application's NSLog("run called")
	--display dialog "I'm running!"
	my setUpDefaults()
	log {"contRun is:", contRun}
	
	continue idle
end run

on idle
	-- do something
	--log {"idle called"}
	return 60
end idle

on quit
	-- do some cleanup
	log {"quit called"}
	current application's NSLog("quit called")
	my removeObservers()
	continue quit
end quit


on setUpDefaults()
	log {"setUpDefaults called"}
	current application's NSLog("setUpDefaults called")
	set contRun to true
	my setUpObservers()
	my addObservers()
end setUpDefaults

on setUpObservers()
	log {"setUpObservers called"}
	current application's NSLog("setUpObservers called")
end setUpObservers


on addObservers()
	log {"addObservers called"}
	current application's NSLog("addObservers called")
	NSDistributedNotificationCenter's defaultCenter's addObserver:me selector:"iTunesPlayerStateChanged:" |name|:"com.apple.iTunes.playerInfo" object:(missing value)
	log {"addObservers end"}
	current application's NSLog("addObservers end")
end addObservers

on removeObservers()
	log {"removeObservers called"}
	current application's NSLog("removeObservers called")
	
	NSDistributedNotificationCenter's defaultCenter's removeObserver:me
end removeObservers

#pragma mark ITUNES PLAYER STATE CHANGED TRACK WAS REFRESHED NOTIFICATION

on iTunesPlayerStateChanged:aNotification
	log {"iTunesPlayerStateChange called"}
	current application's NSLog("iTunesPlayerStateChange called")
	set aDict to aNotification's userInfo()
	set aStateString to (aDict's valueForKey:"Player State")
	current application's NSLog("aStateString IS:%@", aStateString)
	current application's NSLog("aNotification userInfo IS:%@", aDict)
	set curTrackDict to NSMutableDictionary's new()
	(curTrackDict's setValuesForKeysWithDictionary:aDict)
	current application's NSLog("curTrackDict IS:%@", curTrackDict)
	
	set isPlaying to (aStateString's isEqualToString:"Playing") as boolean
	set aStateText to aStateString as text
	log {"aStateText is:", aStateText}
	log {"isPlaying is:", isPlaying}
	
	
	if isPlaying then
		my refreshITunesTrack()
	end if
	
end iTunesPlayerStateChanged:

on refreshITunesTrack()
	log {"refreshITunesTrack called"}
	current application's NSLog("iTunesPlayerStateChange called")
	
	tell application id "com.apple.iTunes"
		try
			set curTrack to get current track
			set curTime to player position
			set curLength to duration of curTrack
			set curRemain to curLength - curTime
		end try
	end tell
	(curTrackDict's setValue:curTime forKey:"currentTime")
	(curTrackDict's setValue:curLength forKey:"currentLength")
	(curTrackDict's setValue:curRemain forKey:"currentRemain")
	current application's NSLog("update times curTrackDict IS:%@", curTrackDict)
	set curTrackRec to curTrackDict as record
	current application's NSLog("curTrackRec IS:%@", curTrackRec)
end refreshITunesTrack