def __init__(self): super().__init__() settings = get_settings() quoted = {k: shlex.quote(v) for (k, v) in settings.items()} command = LIBRESPOT if settings['autoplay'] == 'true': command += LIBRESPOT_AUTOPLAY if (settings['discovery'] == 'false' and settings['password'] != '' and settings['username'] != ''): command += LIBRESPOT_AUTHENTICATE self.command = shlex.split(command.format(**quoted)) log(shlex.split(command.format(**dict(quoted, password='******')))) self.is_aborted = False self.is_dead = False self.pulseaudio = Pulseaudio(settings) self.listitem = xbmcgui.ListItem() self.listitem.addStreamInfo('audio', {'codec': CODEC}) self.listitem.setPath(path=self.pulseaudio.url)
class Librespot(xbmc.Player): def __init__(self): super().__init__() settings = get_settings() quoted = {k: shlex.quote(v) for (k, v) in settings.items()} command = LIBRESPOT if settings['autoplay'] == 'true': command += LIBRESPOT_AUTOPLAY if (settings['discovery'] == 'false' and settings['password'] != '' and settings['username'] != ''): command += LIBRESPOT_AUTHENTICATE self.command = shlex.split(command.format(**quoted)) log(shlex.split(command.format(**dict(quoted, password='******')))) self.is_aborted = False self.is_dead = False self.pulseaudio = Pulseaudio(settings) self.listitem = xbmcgui.ListItem() self.listitem.addStreamInfo('audio', {'codec': CODEC}) self.listitem.setPath(path=self.pulseaudio.url) def __enter__(self): self.pulseaudio.load_modules() self.panics = 0 self.librespot = None self.is_playing_librespot = False if not self.isPlaying(): self.start_librespot() def __exit__(self, *args): self.stop_librespot() self.pulseaudio.unload_modules() def on_event_panic(self): self.pulseaudio.suspend_sink(1) self.panics += 1 log('event panic {}/{}'.format(self.panics, MAX_PANICS)) self.is_dead = self.panics >= MAX_PANICS self.stop_librespot(True) def on_event_playing(self, type, id): log('event playing') SPOTIFY.update_listitem(self.listitem, type, id, self.country) if not self.isPlaying(): log('starting librespot playback') self.pulseaudio.suspend_sink(0) self.play(self.pulseaudio.url, self.listitem) elif self.is_playing_librespot: log('updating librespot playback') self.updateInfoTag(self.listitem) def on_event_stopped(self): self.pulseaudio.suspend_sink(1) log('event stopped') self.panics = 0 self.stop() def onPlayBackEnded(self): self.onPlayBackStopped() def onPlayBackError(self): self.onPlayBackStopped() def onPlayBackStarted(self): log('Kodi playback started') self.is_playing_librespot = self.getPlayingFile() == self.pulseaudio.url if not self.is_playing_librespot: self.stop_librespot() def onPlayBackStopped(self): if self.is_playing_librespot: log('librespot playback stopped') self.is_playing_librespot = False self.stop_librespot(True) else: log('Kodi playback stopped') self.start_librespot() def run_librespot(self): log('librespot thread started') self.restart = True while self.restart and not self.is_dead: self.librespot = subprocess.Popen( self.command, cwd=ADDON_HOME, env=ADDON_ENVT, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, text=True) log('librespot started') with self.librespot.stdout: for line in self.librespot.stdout: words = line.split() if words[0] == '@Playing': self.on_event_playing(words[1], words[2]) elif words[0] == '@Stopped': self.on_event_stopped() elif words[0] == 'stack': self.on_event_panic() else: log(line.rstrip()) if 'Country:' in line: self.country = words[-1].strip('"') log('country={}'.format(self.country)) self.pulseaudio.suspend_sink(1) self.stop() self.librespot.wait() log('librespot stopped') self.librespot = None log('librespot thread stopped') def start_librespot(self): if self.librespot is None: self.thread = threading.Thread(target=self.run_librespot) self.thread.start() def stop(self): if self.is_playing_librespot and not self.is_aborted: log('stopping librespot playback') self.is_playing_librespot = False super().stop() def stop_librespot(self, restart=False): self.restart = restart if self.librespot is not None: self.librespot.terminate() if not restart: self.thread.join()