import threading import time from .client import SpotifyClient class Player: def __init__(self, client: SpotifyClient): self.client = client self._poll_thread = None self._running = False self._callbacks = [] self.current_playback = None self.current_track = None self.devices = [] def register_callback(self, cb): self._callbacks.append(cb) def _notify(self): for cb in self._callbacks: try: cb(self.current_playback, self.current_track) except Exception: pass def start_polling(self, interval=2): self._running = True self._poll_thread = threading.Thread(target=self._poll_loop, args=(interval,), daemon=True) self._poll_thread.start() def stop_polling(self): self._running = False if self._poll_thread: self._poll_thread.join(timeout=3) def _poll_loop(self, interval): while self._running: try: self.refresh() except Exception: pass time.sleep(interval) def refresh(self): try: self.current_playback = self.client.get_playback() if self.current_playback: self.devices = self.current_playback.get("devices", []) except Exception: self.current_playback = None try: self.current_track = self.client.get_current_track() except Exception: self.current_track = None self._notify() def toggle_play(self): if not self.current_playback: raise Exception("Kein Wiedergabegeraet aktiv") if self.current_playback.get("is_playing"): self.client.pause() else: self.client.play() time.sleep(0.3) self.refresh() def next(self): if not self.current_playback: raise Exception("Kein Wiedergabegeraet aktiv") self.client.next_track() time.sleep(0.5) self.refresh() def previous(self): if not self.current_playback: raise Exception("Kein Wiedergabegeraet aktiv") self.client.previous_track() time.sleep(0.5) self.refresh() def seek(self, position_ms): self.client.seek(position_ms) time.sleep(0.3) self.refresh() def set_volume(self, volume): volume = max(0, min(100, volume)) self.client.set_volume(volume) self.refresh() def volume_up(self, step=5): vol = self.get_volume() self.set_volume(vol + step) def volume_down(self, step=5): vol = self.get_volume() self.set_volume(vol - step) def get_volume(self): if self.current_playback and self.current_playback.get("device"): return self.current_playback["device"].get("volume_percent", 50) return 50 def toggle_repeat(self): if not self.current_playback: raise Exception("Kein Wiedergabegeraet aktiv") state = self.current_playback.get("repeat_state", "off") new_state = "track" if state == "off" else "off" self.client.set_repeat(new_state) self.refresh() def toggle_shuffle(self): if not self.current_playback: raise Exception("Kein Wiedergabegeraet aktiv") state = not self.current_playback.get("shuffle_state", False) self.client.set_shuffle(state) self.refresh() def play_context(self, context_uri, offset=None): self.client.play(context_uri=context_uri, offset=offset) time.sleep(0.5) self.refresh() def play_tracks(self, uris, offset=0): self.client.play(uris=uris, offset=offset) time.sleep(0.5) self.refresh() def play_track(self, uri): self.client.play(uris=[uri]) time.sleep(0.5) self.refresh() def transfer_to(self, device_id): self.client.transfer_playback(device_id) time.sleep(0.5) self.refresh() def get_track_info(self): if not self.current_track or not self.current_track.get("item"): return None track = self.current_track["item"] artists = ", ".join(a["name"] for a in track.get("artists", [])) album = track.get("album", {}).get("name", "") progress = self.current_track.get("progress_ms", 0) duration = track.get("duration_ms", 0) return { "name": track["name"], "artists": artists, "album": album, "duration_ms": duration, "progress_ms": progress, "uri": track["uri"], "is_playing": self.current_track.get("is_playing", False), "image": track.get("album", {}).get("images", [{}])[0].get("url") if track.get("album", {}).get("images") else None, } def get_playback_state(self): if not self.current_playback: return None return { "is_playing": self.current_playback.get("is_playing", False), "repeat_state": self.current_playback.get("repeat_state", "off"), "shuffle_state": self.current_playback.get("shuffle_state", False), "volume": self.current_playback.get("device", {}).get("volume_percent", 50), "device": self.current_playback.get("device", {}).get("name", "Unknown"), "device_type": self.current_playback.get("device", {}).get("type", ""), }