Page 1 of 1

Control AirPlay with AppleScript and Domoticz

Posted: Monday 30 November 2015 20:55
by kvanhoorn
Hi,

Here's a project I'm working on for a while now.
I have a couple of airplay locations in house (for example: bathroom, kitchen, garage).
At 6:30 radio starts playing in the bathroom, at 7:00 in the kitchen etcetera.
But I also wanted to control it manually on location with a hardware button.
The KlikaanKlikuit AWST-8802 switches trigger a switch in Domoticz (on Raspberry Pi) which does a webcall to my Mac which triggers the AppleScript.

The on-button has three functions:
(if music is not playing) start playing a specific radio station from specific playlist or
(if music is playing but not on this speaker) add this airport to itunes selected devices or
(if music is playing on this speaker) play next song.

The off-button has two functions:
(if music is playing on this speaker) remove this airport from selected itunes devices or
(if music is not playing on this speaker) let itunes stop playing over all speakers and remove all speakers as selected device.

The On-Action of the device looks like this:

Code: Select all

http://admin:[email protected]/radio_control.php?state=on&speaker=AE_Kitchen&volume=50
The Off-Action of the device looks like this:

Code: Select all

http://admin:[email protected]/radio_control.php?state=off&speaker=AE_Kitchen
The webcall is a simple php script (with basic authentication) that looks like this:

Code: Select all

<?php
if (count($_GET) >= 2) {
    
    $speaker = str_replace('_', ' ', $_GET['speaker']);

    $cmd = 'sudo su "kevin" -c "/usr/bin/osascript /path/to/script/radio_airplay.scpt ' . 
        $_GET['state'] . ' ' .
        '\'' . $speaker . '\' ' . 
        (@$_GET['volume'] ?: '') . '"';

    $result = exec($cmd);

    var_dump($cmd);
    var_dump($result);
}
?>
The AppleScript looks like this: (I couldn't upload a scpt-extension file, edit with Script Editor app)

Code: Select all

on run argv
	
	try
		set onOff to item 1 of argv
		set inpDevicename to item 2 of argv
		set inpVolume to 0
		if (onOff is "on") then
			set inpVolume to item 3 of argv
		end if
	on error
		error number -128
		return
	end try
	
	if onOff is "on" then
		
		speakerOn(inpDevicename, inpVolume)
		
	else if onOff is "off" then
		
		speakerOff(inpDevicename)
		
	end if
	
end run

on stopItunes()
	
	tell application "iTunes"
		
		pause
		
	end tell
	
end stopItunes

on speakerOn(speakername, vol)
	
	tell application "iTunes"
		
		# check if speaker exists in home network
		if not my is_speaker(speakername) then
			
			log ("Airplay device '" & speakername & "' not found")
			error number -128
			return
			
		end if
		
		# check if speaker is already active
		if not my is_current_speaker(speakername) then
			
			log ("setting device " & speakername)
			my set_speaker(speakername, vol)
			
			# else play next track (speaker is active)
		else if player state is playing then
			
			next track
			
		end if
		
		# if itunes is not playing yet, start with 3FM
		if player state is not playing then
			play playlist "Stream (radio)"
			play track "3FM" of playlist "Stream (radio)"
		end if
		
	end tell
	
end speakerOn

on speakerOff(speakername)
	
	tell application "iTunes"
		
		# check if speaker exists in home network
		if not my is_speaker(speakername) then
			
			log ("Airplay device '" & speakername & "' not found")
			error number -128
			return
			
		end if
		
		# check if speaker is already active
		if my is_current_speaker(speakername) then
			
			log ("unsetting device " & speakername)
			my unset_speaker(speakername)
			
		else
			
			my unset_all_speakers()
			
		end if
		
	end tell
	
end speakerOff

on set_speaker(speakername, vol)
	
	tell application "iTunes"
		
		set apDevices to (get AirPlay devices where selected is true)
		
		set speaker to (first AirPlay device whose name = speakername)
		set sound volume of speaker to vol
		
		# add speaker to speakerlist
		copy speaker to the end of apDevices
		set current AirPlay devices to apDevices
		
	end tell
	
end set_speaker

on unset_speaker(speakername)
	
	tell application "iTunes"
		
		set apDevices to (get AirPlay devices where selected is true)
		
		set speaker to (first AirPlay device whose name = speakername)
		
		# remove speaker from speakerlist
		set apDevicesNew to {}
		repeat with aDevice in apDevices
			if (aDevice's name as string is not speakername) then
				copy aDevice to the end of apDevicesNew
			end if
		end repeat
		
		set current AirPlay devices to apDevicesNew
		
		if (count apDevicesNew) is 1 then
			my stopItunes()
		end if
		
	end tell
	
end unset_speaker

on unset_all_speakers()
	
	tell application "iTunes"
		
		set speaker to (first AirPlay device whose name = "Computer")
		set current AirPlay devices to speaker
		
		my stopItunes()
		
	end tell
	
end unset_all_speakers

on is_speaker(speakername)
	
	tell application "iTunes"
		
		set apDevices to (get name of every AirPlay device)
		set deviceFound to false
		
		repeat with aDevice in apDevices
			if (aDevice as string is speakername) then
				set deviceFound to true
			end if
		end repeat
		
		return deviceFound
		
	end tell
	
end is_speaker

on is_current_speaker(speakername)
	
	tell application "iTunes"
		
		set apDevices to (get name of AirPlay devices where selected is true)
		set deviceFound to false
		
		repeat with aDevice in apDevices
			if (aDevice as string is speakername) then
				set deviceFound to true
			end if
		end repeat
		
		return deviceFound
		
	end tell
	
end is_current_speaker
Please feel free to modify the code, it's absolutely not optimal. This is the first time I'm coding AppleScript.

Re: Control AirPlay with AppleScript and Domoticz

Posted: Saturday 19 December 2015 22:04
by cristou
Hello, im a french guy (sory for my bad english...)

Can you explain how you processes ?
I have a mac itunes and airport express.
I 'd like domoticz sending sound to my airport express ?
I do not really know apple script ...
Can you explain me in private ? send me the file by email can be ?
Thank you for your help.

Re: Control AirPlay with AppleScript and Domoticz

Posted: Tuesday 22 December 2015 23:56
by thebeetleuk
I would like to understand this a bit more as well. When you say you have a few airplay locations. What are these devices? Also how are you streaming the audio to the device?

Re: Control AirPlay with AppleScript and Domoticz

Posted: Saturday 26 December 2015 22:16
by thebeetleuk
Looking at the script it looks like you are connecting to itunes and playing through that?

Re: Control AirPlay with AppleScript and Domoticz

Posted: Sunday 27 December 2015 20:42
by thebeetleuk

Re: Control AirPlay with AppleScript and Domoticz

Posted: Sunday 03 January 2016 12:36
by kvanhoorn
cristou wrote:Hello, im a french guy (sory for my bad english...)

Can you explain how you processes ?
I have a mac itunes and airport express.
I 'd like domoticz sending sound to my airport express ?
I do not really know apple script ...
Can you explain me in private ? send me the file by email can be ?
Thank you for your help.
Dear Cristou, this is al the code I use.
I have a couple of Airport Expresses, and my Mac Pro controls those speakers from its iTunes installation.
Please try to set it up, if you come by any trouble, contact me.

I have an installation of OS X Server for the php-file, but you can also use the free application MAMP.

Re: Control AirPlay with AppleScript and Domoticz

Posted: Sunday 03 January 2016 12:38
by kvanhoorn
thebeetleuk wrote:I would like to understand this a bit more as well. When you say you have a few airplay locations. What are these devices? Also how are you streaming the audio to the device?
Dear thebeetleuk, I use Airport Expresses with speakers connected to them.
iTunes on my Mac Pro connects to these devices.

Domoticz calls the applescript on the iTunes computer via the PHP-script on a webserver.
From the arguments domoticz sends and the current state of a speaker, it decides which action it should take.