Source code for i3pystatus.sonos

from i3pystatus import IntervalModule
import soco


[docs]class Sonos(IntervalModule): """ Controls and displays information from Sonos devices. A devices is found by IP, by name, or automatically if no IP or name is \ supplied. .. rubric:: Available formatters * `{player_name}` — player name * `{volume}` — volume from 0 to 100 * `{muted}` — "M" if muted, else "" * `{title}` — the title of the current song * `{artist}` — the artist of the current song * `{album}` — the album of the current song * `{duration}` — duration of the current song (%M:%S) * `{position}` — position in the current song (%M:%S) * `{state}` — Playing, Paused, Stopped Requires: soco (can be installed using pip) """ ip = None name = None format = "{state}: {artist} - {title} [{muted}{volume:.0f}%]" color = "#FFFFFF" format_no_music = "No music" color_no_music = "#888888" format_no_connection = "No connection" color_no_connection = "#888888" hide_no_connection = False interval = 1 settings = ( ("ip", "Speaker IP address."), ("name", "Speaker name (used if no IP is given)."), ("format", "Format used when playing or paused."), ("color", "Color used when playing or paused."), ("format_no_music", "Format used when stopped."), ("color_no_music", "Color used when stopped."), ("format_no_connection", "Format used if no player is connected."), ("color_no_connection", "Color used if no player is connected."), ("hide_no_connection", "Hide output if no player is connected."), ) state_text_map = { "PLAYING": "Playing", "TRANSITIONING": "Playing", "PAUSED_PLAYBACK": "Paused", "STOPPED": "Stopped", } on_leftclick = "play_pause" on_upscroll = "incr_vol" on_middleclick = "toggle_mute" on_downscroll = "decr_vol" on_doubleleftclick = "next_song" player = None def run(self): if not self.player: if self.ip: self.player = soco.SoCo(self.ip) elif self.name: self.player = soco.discovery.by_name(self.name) else: self.player = soco.discovery.any_soco() if not self.player: self.output = self.output_no_connection return try: track_info = self.group_coordinator.get_current_track_info() transp_info = self.group_coordinator.get_current_transport_info() player_name = self.player.player_name muted = self.player.mute volume = self.player.volume except: self.output = self.output_no_connection return state = transp_info["current_transport_state"] cdict = { "player_name": player_name, "volume": volume, "muted": "M" if muted else "", "title": track_info["title"], "artist": track_info["artist"], "album": track_info["album"], "duration": track_info["duration"][2:], "position": track_info["position"][2:], "state": self.state_text_map[state], } self.data = cdict if self.format_no_music is not None and state == "STOPPED": self.output = { "full_text": self.format_no_music.format(**cdict), "color": self.color_no_music } else: self.output = { "full_text": self.format.format(**cdict), "color": self.color } @property def output_no_connection(self): if self.hide_no_connection: return None else: return { "full_text": self.format_no_connection, "color": self.color_no_connection } @property def group_coordinator(self): try: return self.player.group.coordinator except: return None def play_pause(self): try: transp_info = self.group_coordinator.get_current_transport_info() state = transp_info["current_transport_state"] if state in ["PLAYING", "TRANSITIONING"]: self.group_coordinator.pause() else: self.group_coordinator.play() except: return def incr_vol(self): try: self.player.volume += 1 except: return def decr_vol(self): try: self.player.volume -= 1 except: return def toggle_mute(self): try: self.player.mute = not self.player.mute except: return def next_song(self): try: self.group_coordinator.next() except: return