def speak(room):
    global sonosPlayerList, _myIp

    for place, player in sonosPlayerList.iteritems():
        if (room.lower() == 'default' and place
                == _CORE_PLACEMENT.lower()) or room.lower() == place.lower():

            # Taking a snapshot of the current state allows use to easily pause the currently playing track on the device before speaking on it and restore the music later
            snapshot = Snapshot(player)
            snapshot.snapshot()

            if isPlaying(player):
                player.pause()
                time.sleep(0.5)

            player.volume = 50
            player.play_uri(
                'x-file-cifs://{}/share/snipsTalk.wav'.format(_myIp),
                title='Snips')

            # Sonos can be sleeping. We have to loop until detecting a playing state or sometimes it might fail speaking, ending before it even started
            while player.get_current_transport_info(
            )['current_transport_state'] != 'PLAYING':
                time.sleep(0.1)

            # Once we started playing the sound, loop until it's finished
            while player.get_current_transport_info(
            )['current_transport_state'] == 'PLAYING':
                time.sleep(0.1)

            # Restore the state we were before speaking on the player
            snapshot.restore()
示例#2
0
    def __init__(self, hass, player):
        """Initialize the Sonos device."""
        from soco.snapshot import Snapshot

        self.hass = hass
        self.volume_increment = 5
        self._unique_id = player.uid
        self._player = player
        self._player_volume = None
        self._player_volume_muted = None
        self._speaker_info = None
        self._name = None
        self._status = None
        self._coordinator = None
        self._media_content_id = None
        self._media_duration = None
        self._media_image_url = None
        self._media_artist = None
        self._media_album_name = None
        self._media_title = None
        self._media_radio_show = None
        self._media_next_title = None
        self._support_previous_track = False
        self._support_next_track = False
        self._support_pause = False
        self._current_track_uri = None
        self._current_track_is_radio_stream = False
        self._queue = None
        self._last_avtransport_event = None
        self._is_playing_line_in = None
        self._is_playing_tv = None
        self.soco_snapshot = Snapshot(self._player)
def play_alert(zones, alert_uri, alert_volume=60, alert_duration=0, fade_back=True):
    # Use soco.snapshot to capture current state of each zone to allow restore
    for zone in zones:
        zone.snap = Snapshot(zone)
        zone.snap.snapshot()
        print('snapshot of zone: {}'.format(zone.player_name))

    # prepare all zones for playing the alert
    for zone in zones:
        # Each Sonos group has one coordinator only these can play, pause, etc.
        if zone.is_coordinator:
            if not zone.is_playing_tv:  # can't pause TV - so don't try!
                # pause music for each coordinators if playing
                trans_state = zone.get_current_transport_info()
                if trans_state['current_transport_state'] == 'PLAYING':
                    zone.pause()

        # For every Sonos player set volume and mute for every zone
        zone.volume = alert_volume
        zone.mute = False

    # play the sound (uri) on each sonos coordinator
    print('will play: {} on all coordinators'.format(alert_uri))
    for zone in zones:
        if zone.is_coordinator:
            zone.play_uri(uri=alert_uri, title='Sonos Alert')

    # wait for alert_duration
    time.sleep(alert_duration)

    # restore each zone to previous state
    for zone in zones:
        print('restoring {}'.format(zone.player_name))
        zone.snap.restore(fade=fade_back)
示例#4
0
    def save_snapshot(self, speaker: Speaker):
        """Saves the current playback state of the passed speaker

        :param models.speaker.Speaker speaker: Speaker which playback state should be saved
        """
        soco_instance = self.get_coordinator_instance(speaker)
        soco_instance.snapshot = Snapshot(soco_instance)
        soco_instance.snapshot.snapshot()
示例#5
0
 def __init__(self, hass, player):
     """Initialize the Sonos device."""
     self.hass = hass
     self.volume_increment = 5
     super(SonosDevice, self).__init__()
     self._player = player
     self.update()
     from soco.snapshot import Snapshot
     self.soco_snapshot = Snapshot(self._player)
示例#6
0
    def __init__(self, hass, player):
        """Initialize the Sonos device."""
        from soco.snapshot import Snapshot

        self.hass = hass
        self.volume_increment = 5
        self._player = player
        self._name = None
        self.update()
        self.soco_snapshot = Snapshot(self._player)
    def snapshot(self, with_group=True):
        """Snapshot the player."""
        from soco.snapshot import Snapshot

        self._soco_snapshot = Snapshot(self.soco)
        self._soco_snapshot.snapshot()

        if with_group:
            self._snapshot_group = self.soco.group
            if self._coordinator:
                self._coordinator.snapshot(False)
        else:
            self._snapshot_group = None
示例#8
0
    def play_snippet(self, uri, volume=-1, group_command=False, fade_in=False):
        """
        Plays a audio snippet. This will pause the current audio track , plays the snippet and after that, the previous
        track will be continued.
        :param uri: uri to be played
        :param volume: Snippet volume [-1-100]. After the snippet was played, the previous/original volume is set. If
        volume is '-1', the current volume is used. Default: -1
        :param group_command: Only affects the volume. If True, the snippet volume is set to all zone members. Default:
        False
        :raise err:
        """

        self._fade_in = fade_in

        if not self.is_coordinator:
            logger.debug(
                "forwarding play_snippet command to coordinator with uid {uid}"
                .format(uid=self.zone_coordinator.uid))
            self._zone_coordinator.play_snippet(uri, volume)
        else:
            with self._snippet_queue_lock:
                try:
                    was_empty = False
                    ''' Check if event queue is empty.
                    if yes, then add the currently played track to the end of the queue
                    '''
                    if self._snippet_queue.empty():

                        # if there is now music item in the current playlist, an exception is thrown
                        # uncritical
                        try:

                            self._saved_music_item = Snapshot(
                                device=self.soco, snapshot_queue=True)
                            self._saved_music_item.snapshot()

                            was_empty = True
                        except:
                            pass

                    # snippet is priority 1, save_music_track is 2
                    self._snippet_queue.put((1, uri, volume))
                    if was_empty:
                        self._snippet_queue.put((2, self._saved_music_item))

                except KeyError as err:  # The key have been deleted in another thread
                    del self._snippet_queue.queue[:]
                    raise err
                except Exception as err:
                    del self._snippet_queue.queue[:]
                    raise err
示例#9
0
def play():
    file = 'http://192.168.1.52/sounds/' + random.choice(sounds)
    try:
        sonos = by_name("Lekrum")
        if sonos.group:
            sonos = sonos.group.coordinator

        snap = Snapshot(sonos)
        snap.snapshot()
        sonos.play_uri(file)
        time.sleep(5)
        snap.restore(fade=True)
    except:
        print("Failed to play on " + str(sonos))
示例#10
0
def play_alert(zones,
               alert_uri,
               alert_volume=20,
               alert_duration=0,
               fade_back=False):
    """
    Demo function using soco.snapshot across multiple Sonos players.

    Args:
        zones (set): a set of SoCo objects
        alert_uri (str): uri that Sonos can play as an alert
        alert_volume (int): volume level for playing alert (0 tp 100)
        alert_duration (int): length of alert (if zero then length of track)
        fade_back (bool): on reinstating the zones fade up the sound?
    """

    # Use soco.snapshot to capture current state of each zone to allow restore
    for zone in zones:
        zone.snap = Snapshot(zone)
        zone.snap.snapshot()
        print('snapshot of zone: {}'.format(zone.player_name))

    # prepare all zones for playing the alert
    for zone in zones:
        # Each Sonos group has one coordinator only these can play, pause, etc.
        if zone.is_coordinator:
            if not zone.is_playing_tv:  # can't pause TV - so don't try!
                # pause music for each coordinators if playing
                trans_state = zone.get_current_transport_info()
                if trans_state['current_transport_state'] == 'PLAYING':
                    zone.pause()

        # For every Sonos player set volume and mute for every zone
        zone.volume = alert_volume
        zone.mute = False

    # play the sound (uri) on each sonos coordinator
    print('will play: {} on all coordinators'.format(alert_uri))
    for zone in zones:
        if zone.is_coordinator:
            zone.play_uri(uri=alert_uri, title='Sonos Alert')

    # wait for alert_duration
    time.sleep(alert_duration)

    # restore each zone to previous state
    for zone in zones:
        print('restoring {}'.format(zone.player_name))
        zone.snap.restore(fade=fade_back)
示例#11
0
    def get_playlist(self):
        try:
            snapshot = Snapshot(device=self.soco, snapshot_queue=True)
            snapshot.snapshot()
            f = io.BytesIO()
            pickle.dump(snapshot.queue, f, pickle.HIGHEST_PROTOCOL)
            f.seek(0)
            return definitions.MB_PLAYLIST + base64.b64encode(
                f.read()).decode('ascii')

        except Exception as err:
            raise Exception(
                "Unable to get playlist! Error: {err}".format(err=err))
        finally:
            f.close()
示例#12
0
    def test_sonos_restore(self, restoreMock, *args):
        """Ensuring soco methods called for sonos_restor service."""
        from soco.snapshot import Snapshot

        sonos.setup_platform(self.hass, {}, fake_add_device, '192.0.2.1')
        device = self.hass.data[sonos.DATA_SONOS][-1]
        device.hass = self.hass

        restoreMock.return_value = True
        device._snapshot_coordinator = mock.MagicMock()
        device._snapshot_coordinator.soco_device = SoCoMock('192.0.2.17')
        device._soco_snapshot = Snapshot(device._player)
        device.restore()
        self.assertEqual(restoreMock.call_count, 1)
        self.assertEqual(restoreMock.call_args, mock.call(False))
示例#13
0
    def doorbell(self):
        for zone in self.zones:
            zone.snap = Snapshot(zone)
            zone.snap.snapshot()


#            print('found zone')
#            print(zone.snap.volume, zone.is_coordinator, zone.is_playing_tv,  zone.player_name.encode('latin-1'))

        coordinators = [
            zone for zone in self.zones
            if zone.is_coordinator and not zone.is_playing_tv
        ]

        #        print (coordinators)

        for zone_c in coordinators:
            trans_state = zone_c.get_current_transport_info()
            #print(zone_c.player_name.encode('latin-1'), trans_state)
            if trans_state['current_transport_state'] == 'PLAYING':
                zone_c.pause()

        for zone in self.zones:
            if zone.is_playing_tv:
                zone.volume = 0
            else:
                zone.volume = 1

        waitTime = 0
        for zone_c in coordinators:
            #            print('Play doorbell', zone_c.player_name.encode('latin-1'))
            zone_c.play_uri(
                'x-file-cifs://raspberrypi/PiShare/Sounds/doorbell.mp3')
            if (waitTime == 0):
                waitTime = int(
                    zone_c.get_current_track_info()['duration'][-2:])

        time.sleep(waitTime)
        for zone in self.zones:
            if zone.is_playing_tv:
                pass
            else:
                print('restoring {}'.format(
                    zone.player_name.encode('latin-1')))
                zone.snap.restore(fade=True)
示例#14
0
    def __init__(self, name, init, messager):
        self.name = name
        self.pref_zone = init['children']['1']
        sonos_list = soco.discover()
        zones = {}
        self.prev_snapshot = {}
        while (len(sonos_list) > 0):
            player = sonos_list.pop()
            zones[player.player_name] = player
            snap = Snapshot(player)
            self.prev_snapshot[player.player_name] = snap
            self.prev_snapshot[player.player_name].snapshot()
            if (player.player_name == self.pref_zone):
                self.sonos = player
        self.zones = zones

        self.state = {}

        #self.children = init['children']
        self.messager = messager
        self.polling = 60
        self.last_check = time.time()
示例#15
0
    def set_playlist(self, playlist, play_on_insert):
        try:
            snapshot = Snapshot(device=self.soco, snapshot_queue=False)
            snapshot.device.stop()
            snapshot.snapshot()

            # check magic bytes
            if not playlist.startswith("#so_pl#"):
                raise Exception("This is not a valid playlist file.")

            # remove magic bytes
            playlist = playlist.lstrip(definitions.MB_PLAYLIST)

            with tempfile.TemporaryFile() as f:
                f.write(base64.b64decode(playlist))
                f.seek(0)
                snapshot.queue = pickle.load(f)
                snapshot.restore()
            if play_on_insert:
                self.set_play(1, True)
        except Exception as err:
            print(err)
            pass
示例#16
0
def on_doorbell(root_path, audio_file, volume, zone):
    global doorbell_playing

    http_path = root_path + "/" + audio_file.url
    print('on_doorbell {} {} {}'.format(audio_file.name, volume, zone))
    if is_doorbell_busy():
        print('Doorbell already playing...suppressing')
        return
    doorbell_playing = True

    snap = Snapshot(zone)
    snap.snapshot()

    # Zone does not support snapshort restore properly for soundbar
    should_ring = zone.is_coordinator and not zone.is_playing_tv

    if should_ring:
        trans_state = zone.get_current_transport_info()
        if trans_state['current_transport_state'] == 'PLAYING':
            zone.pause()
        zone.volume = volume

        print('Play doorbell on ', zone.player_name)
        zone.play_uri(uri=http_path, title="Doorbell")

        time.sleep(audio_file.length)
        print('Restoring {}'.format(zone.player_name))

        if snap.is_playing_cloud_queue:
            print(
                "Unlikely to resume playback. Cloud restore doesn't really work"
            )
        snap.restore(fade=False)
    else:
        print('Cannot play doorbell on the provided zone')
    doorbell_playing = False
示例#17
0
# -*- coding: utf-8 -*-
"""
Test for #224
"""

import time
import soco
from soco.snapshot import Snapshot

# alert = "x-file-cifs://DoorPi/DoorPiPublic/doorbell/sounds/Tinkle5sec.mp3"
alert = 'http://archive.org/download/TenD2005-07-16.flac16/TenD2005-07-16t10Wonderboy_64kb.mp3'

device = soco.SoCo('192.168.1.73')

#take snapshot of current state
snap = Snapshot(device)
is_coord = snap.snapshot

# print 'playlist_pos:', snap.playlist_position
# print 'track_pos:', snap.track_position
# #print 'stream_uri:', snap.stream_uri
# #print 'meta:', snap.metadata
# print 'media uri:', snap.media_uri
# #print 'media meta:', snap.media_metadata
# print 'Transport state:', snap.transport_state

# Do something here that changes what's playing etc.
device.volume = 20
if is_coord:
    device.play_uri(uri=alert)
time.sleep(4)
示例#18
0
def take_snapshot():
    print("Taking snapshot for backup purposes...")
    snap = Snapshot(speaker)
    return snap.snapshot()
示例#19
0
    def say(self, message):
        # Need to subscribe to transport events, this is so that we know
        # when a given track has finished, and so we can stop it, if
        # we do not stop it, then it will repeat the text for a second time
        sub = self.device.avTransport.subscribe()

        # fade out
        #prefade_volume = self.device.volume
        #for v in range(prefade_volume):
        #    self.device.volume -= 1
        #    time.sleep(0.25)

        # Take a snapshot of the current sonos device state, we will want
        # to roll back to this when we are done
        snap = Snapshot(self.device)
        snap.snapshot()

        msg = cgi.escape(message)
        payload = {
            'ie': 'UTF-8',
            'q': message,
            'tl': 'en',
            'total': 1,
            'idx': 0,
            'client': 't',
            'textlen': len(message),
            'tk': Token().calculate_token(message)
        }
        #trans_URL = "x-rincon-mp3radio://translate.google.com/translate_tts?tl=en&q=%s" % msg
        trans_URL = "x-rincon-mp3radio://translate.google.com/translate_tts?" + urlencode(
            payload)
        print trans_URL
        #from IPython import embed
        #embed()
        self.device.play_uri(trans_URL, title="Speech")

        #self.device.volume = prefade_volume

        impatience = time.time()
        patience = time.time() + 20
        while patience > impatience:
            try:
                event = sub.events.get(timeout=0.5)
                print event.variables
                if 'restart_pending' not in event.variables:
                    continue
                restart_pending = event.variables['restart_pending']
                # About to try and restart, so stop looping and stop the
                # track before it starts again
                if restart_pending == '1':
                    break
            except Empty:
                pass
            # Wait another second for the speech to stop playing
            time.sleep(1)
            impatience = time.time()

        time.sleep(0)
        # Stop the stream playing
        self.device.stop()
        # Restore the sonos device back to it's previous state
        snap.restore()

        # fade back in
        #for v in range(prefade_volume):
        #    self.device.volume += 1
        #    time.sleep(0.25)

        # We no longer want to  receive messages
        sub.unsubscribe()
        event_listener.stop()
示例#20
0
    def say(self, message):
        log("Speech: Message to say is: %s" % message)
        # Start by checking to see if the message is valid
        if not self.checkIfValidMessage(message):
            return

        xbmc.executebuiltin("ActivateWindow(busydialog)")
        try:
            # Need to subscribe to transport events, this is so that we know
            # when a given track has finished, and so we can stop it, if
            # we do not stop it, then it will repeat the text for a second time
            sub = self.device.avTransport.subscribe()

            # Take a snapshot of the current sonos device state, we will want
            # to roll back to this when we are done
            log("Speech: Taking snapshot")
            snap = Snapshot(self.device)
            snap.snapshot()

            # Get the URI and play it
            trans_URI = self._get_uri(message)
            log("Speech: Playing URI %s" % trans_URI)
            self.device.play_uri(trans_URI,
                                 title=ADDON.getLocalizedString(32105))

            # The maximum number of seconds that we will wait for the message to
            # complete playing
            duration = 200
            while duration > 0:
                # Check to see if the system is shutting down
                if xbmc.abortRequested:
                    break
                try:
                    eventItem = sub.events.get(timeout=0.1)

                    # Now get the details of an event if there is one there
                    if eventItem is not None:
                        # Check to see if there is a message saying that it is waiting
                        # to restart the audio stream.  This happens because it is
                        # being treated like a radio stream, so Sonos things when the
                        # end of the mp3 file playing is reached that there has been
                        # a connection error and needs to reconnect. If left to itself
                        # it would play the mp3 file again
                        if hasattr(eventItem, 'restart_pending') and (
                                eventItem.restart_pending is not None):
                            # About to try and restart, so stop looping and stop the
                            # track before it starts again
                            if eventItem.restart_pending == '1':
                                log("Speech: Detected restart attempt")
                                break
                except Empty:
                    pass
                # Wait another 10th of a second for the speech to stop playing
                duration = duration - 1
                xbmc.sleep(100)

            log("Speech: Stopping speech")
            # Stop the stream playing
            self.device.stop()

            log("Speech: Restoring snapshot")
            try:
                # We no longer want to  receive messages
                sub.unsubscribe()
            except:
                log(
                    "Sonos: Failed to unsubscribe: %s" %
                    traceback.format_exc(), xbmc.LOGERROR)
            try:
                # Make sure the thread is stopped even if unsubscribe failed
                event_listener.stop()
            except:
                log(
                    "Sonos: Failed to stop event listener: %s" %
                    traceback.format_exc(), xbmc.LOGERROR)
            del sub
            # Restore the sonos device back to it's previous state
            snap.restore()
            del snap
        except:
            log("Speech: %s" % traceback.format_exc(), xbmc.LOGERROR)
            xbmc.executebuiltin("Dialog.Close(busydialog)")
            raise

        xbmc.executebuiltin("Dialog.Close(busydialog)")
示例#21
0
 def _snap(self):
     for zone in self.zones:
         zone.snap = Snapshot(zone)
         zone.snap.snapshot()
示例#22
0
文件: basic_snap.py 项目: pwt/SoCo
import soco
from soco.snapshot import Snapshot

# something to play on a Sonos player to start (a radio station)
start_uri = "x-sonosapi-stream:s2846?sid=254&flags=32"

# alert sound to interrupt the above (a poem) - use amy file Sonos can play
alert_uri = "https://ia800504.us.archive.org/21/items/PoemsInEnglish/tygerblake.mp3"

# choose device
device = soco.SoCo("192.168.1.68")  # <--change IP to one of your Sonos devices

# start playing something on this device(a radio station)
print("playing a radio station")
device.play_uri(start_uri, title="test radio station")
time.sleep(10)  # pause to ensure radio station playing

# take snapshot of current state
snap = Snapshot(device)  # 1) create a Snapshot class for this device
snap.snapshot()  # 2) take a snapshot of this device's status

# Do something that changes what's playing on this device
print("playing alert")
device.volume += 10  # increase volume
device.play_uri(alert_uri, title="my alert")  # play an alert sound
time.sleep(10)  # wait for a bit !

# Restore previous state of Sonos (with slow fade up)
print("reinstating how it was before....")
snap.restore(fade=True)