Hi Rene,
Thats pretty nice. I added a stream method to play streaming media and changed it to use google tts. I am trying to add the possibility to restore the previous media and position after it finishes the last interruption. My issue is that would work for one interuption but because I am sending it 5 one after another, the last previous state is either stopped or the last tts command (if that makes sense) .
import appdaemon.plugins.hass.hassapi as hass
from queue import Queue
import sys
from threading import Thread
from threading import Event
import time
#import globals
#
# App to manage announcements via TTS and stream sound files to Sonos
#
# Provides methods to enqueue TTS and Media file requests and make sure that only one is executed at a time
# Volume of the media player is set to a specified level and then restored afterwards
#
# Args:
#
# player - media player to use for announcements
# base = base directory for media - this will be a subdirectory under <home assistant config dir>/www
# ip = IP address of machine running this app
# port = HASS port
#
# To use from another APP:
# TTS:
# sound = self.get_app("Sound")
# sound.tts(text, volume, duration)
# duration should be set to longer than the expected duration of the speech
#
# e.g.:
#
# sound = self.get_app("Sound")
# sound.tts("Warning: Intuder alert", 0.5, 10)#
#
# SOUND:
# sound = self.get_app("Sound")
# sound.play(file, volume, content_type, duration)
# file is the path of the file to play relative to "base"
# Content type is the mime type of the media e.g. "audio/mp3" or "audio/wav"
# duration should be set to longer than the expected duration of the media file
#
# e.g.:
# sound = self.get_app("Sound")
# sound.play("warning.wav", "audio/wav", 0.5, 10)
#
# Release Notes
#
# Version 1.0:
# Initial Version
class Sound(hass.Hass):
def initialize(self):
# Create Queue
self.queue = Queue(maxsize=0)
# Create worker thread
t = Thread(target=self.worker)
t.daemon = True
t.start()
self.event = Event()
def worker(self):
active = True
while active:
try:
# Get data from queue
data = self.queue.get()
if data["type"] == "terminate":
active = False
else:
# Save current volume
mediaplayer_state = self.get_state(self.args["player"])
self.log('media player state before insteruption was:{}'.format(mediaplayer_state))
volume = self.get_state(self.args["player"], attribute="volume_level")
media_position = self.get_state(self.args["player"], attribute="media_position")
media_playing = self.get_state(self.args["player"], attribute="media_content_id")
# Set to the desired volume
self.call_service("media_player/volume_set", entity_id = self.args["player"], volume_level = data["volume"])
if data["type"] == "tts":
# Call TTS service
self.call_service("tts/google_say", entity_id = self.args["player"], message = data["text"])
if data["type"] == "play":
netpath = netpath = 'http://{}:{}/local/{}/{}'.format(self.args["ip"], self.args["port"], self.args["base"], data["path"])
self.call_service("media_player/play_media", entity_id = self.args["player"], media_content_id = netpath, media_content_type = data["content"])
if data["type"] == "stream":
self.call_service("media_player/play_media", entity_id = self.args["player"], media_content_id = data["path"], media_content_type = data["content"])
# Sleep to allow message to complete before restoring volume
self.log('Sleeping for:{} seconds'.format(data["length"]))
time.sleep(int(data["length"]))
# Restore volume
self.call_service("media_player/volume_set", entity_id = self.args["player"], volume_level = volume)
# Restore previous media if it was playing
# if mediaplayer_state == 'playing':
# self.log('Restoring previous media player state')
# self.call_service("media_player/play_media", entity_id = self.args["player"], media_content_id = media_playing, media_content_type = "music")
#self.call_service("media_player/media_seek", entity_id = self.args["player"], seek_position = media_position)
# Set state locally as well to avoid race condition
self.set_state(self.args["player"], attributes = {"volume_level": volume})
except:
self.log("Error")
self.log(sys.exc_info())
# Rinse and repeat
self.queue.task_done()
self.log("Worker thread exiting")
self.event.set()
def tts(self, text, volume, length):
self.queue.put({"type": "tts", "text": text, "volume": volume, "length": length})
def play(self, path, content, volume, length):
self.queue.put({"type": "play", "path": path, "content": content, "volume": volume, "length": length})
def stream(self, path, content, volume, length):
self.queue.put({"type": "stream", "path": path, "content": content, "volume": volume, "length": length})
def terminate(self):
self.event.clear()
self.queue.put({"type": "terminate"})
self.event.wait()