From 3b5885dde4dd1768302d8495c5265b43416c4c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alban=20F=C3=A9ron?= Date: Sun, 8 Sep 2019 15:41:20 +0200 Subject: [PATCH] Skipping within tracks --- supysonic/api/jukebox.py | 20 ++++++++-------- supysonic/daemon/client.py | 49 +++++++++++++++++++++----------------- supysonic/jukebox.py | 27 ++++++++++++++------- 3 files changed, 56 insertions(+), 40 deletions(-) diff --git a/supysonic/api/jukebox.py b/supysonic/api/jukebox.py index 74661ce..b3e8168 100644 --- a/supysonic/api/jukebox.py +++ b/supysonic/api/jukebox.py @@ -44,36 +44,36 @@ def jukebox_control(): ): raise GenericError("Unknown action") - arg = None + args = () if action == "set": - if not id: - arg = [] - else: - arg = [uuid.UUID(i) for i in id] + if id: + args = [uuid.UUID(i) for i in id] elif action == "skip": if not index: raise MissingParameter("index") + if offset: + args = (int(index), int(offset)) else: - arg = int(index) + args = (int(index), 0) elif action == "add": if not id: raise MissingParameter("id") else: - arg = [uuid.UUID(i) for i in id] + args = [uuid.UUID(i) for i in id] elif action == "remove": if not index: raise MissingParameter("index") else: - arg = int(index) + args = (int(index),) elif action == "setGain": if not gain: raise MissingParameter("gain") else: - arg = float(gain) + args = (float(gain),) try: status = DaemonClient(current_app.config["DAEMON"]["socket"]).jukebox_control( - action, arg + action, *args ) except DaemonUnavailableError: raise GenericError("Jukebox unavaliable") diff --git a/supysonic/daemon/client.py b/supysonic/daemon/client.py index e219bf3..4688865 100644 --- a/supysonic/daemon/client.py +++ b/supysonic/daemon/client.py @@ -60,9 +60,9 @@ class ScannerStartCommand(ScannerCommand): class JukeboxCommand(DaemonCommand): - def __init__(self, action, arg): + def __init__(self, action, args): self.__action = action - self.__arg = arg + self.__args = args def apply(self, connection, daemon): if daemon.jukebox is None: @@ -74,24 +74,29 @@ class JukeboxCommand(DaemonCommand): playlist = daemon.jukebox.playlist elif self.__action == "status": pass - elif self.__action == "set": - daemon.jukebox.set(self.__arg) - elif self.__action == "start": - daemon.jukebox.start() - elif self.__action == "stop": - daemon.jukebox.stop() - elif self.__action == "skip": - daemon.jukebox.skip(self.__arg) - elif self.__action == "add": - daemon.jukebox.add(self.__arg) - elif self.__action == "clear": - daemon.jukebox.clear() - elif self.__action == "remove": - daemon.jukebox.remove(self.__arg) - elif self.__action == "shuffle": - daemon.jukebox.shuffle() - elif self.__action == "setGain": - daemon.jukebox.setgain(self.__arg) + else: + func = None + + if self.__action == "set": + func = daemon.jukebox.set + elif self.__action == "start": + func = daemon.jukebox.start + elif self.__action == "stop": + func = daemon.jukebox.stop + elif self.__action == "skip": + func = daemon.jukebox.skip + elif self.__action == "add": + func = daemon.jukebox.add + elif self.__action == "clear": + func = daemon.jukebox.clear + elif self.__action == "remove": + func = daemon.jukebox.remove + elif self.__action == "shuffle": + func = daemon.jukebox.shuffle + elif self.__action == "setGain": + func = daemon.jukebox.setgain + + func(*self.__args) rv = JukeboxResult(daemon.jukebox) rv.playlist = playlist @@ -162,9 +167,9 @@ class DaemonClient(object): with self.__get_connection() as c: c.send(ScannerStartCommand(folders, force)) - def jukebox_control(self, action, arg): + def jukebox_control(self, action, *args): if not isinstance(action, strtype): raise TypeError("Expecting string, got " + str(type(action))) with self.__get_connection() as c: - c.send(JukeboxCommand(action, arg)) + c.send(JukeboxCommand(action, args)) return c.recv() diff --git a/supysonic/jukebox.py b/supysonic/jukebox.py index 03df5b0..2360bb6 100644 --- a/supysonic/jukebox.py +++ b/supysonic/jukebox.py @@ -12,7 +12,7 @@ import os import shlex import time -from datetime import datetime +from datetime import datetime, timedelta from pony.orm import db_session, ObjectNotFound from random import shuffle from subprocess import Popen @@ -28,6 +28,7 @@ class Jukebox(object): self.__cmd = shlex.split(cmd) self.__playlist = [] self.__index = 0 + self.__offset = 0 self.__start = None self.__devnull = None @@ -62,9 +63,9 @@ class Jukebox(object): os.close(self.__devnull) self.__devnull = None - def set(self, tracks): + def set(self, *tracks): self.clear() - self.add(tracks) + self.add(*tracks) def start(self): if self.playing or not self.__playlist: @@ -72,6 +73,7 @@ class Jukebox(object): self.__skip.clear() self.__stop.clear() + self.__offset = 0 self.__thread = Thread(target=self.__play_thread) self.__thread.start() @@ -81,17 +83,20 @@ class Jukebox(object): self.__stop.set() - def skip(self, index): + def skip(self, index, offset): if index < 0 or index >= len(self.__playlist): raise IndexError() + if offset < 0: + raise ValueError() with self.__lock: self.__index = index - self.__start = None + self.__offset = offset + self.__start = datetime.utcnow() - timedelta(seconds=offset) self.__skip.set() self.start() - def add(self, tracks): + def add(self, *tracks): with self.__lock: with db_session: for t in tracks: @@ -104,6 +109,7 @@ class Jukebox(object): with self.__lock: self.__playlist.clear() self.__index = 0 + self.__offset = 0 def remove(self, index): try: @@ -156,11 +162,16 @@ class Jukebox(object): def __play_file(self): path = self.__playlist[self.__index] - args = [a.replace("%path", path) for a in self.__cmd] + args = [ + a.replace("%path", path).replace("%offset", str(self.__offset)) + for a in self.__cmd + ] + + self.__start = datetime.utcnow() - timedelta(seconds=self.__offset) + self.__offset = 0 logger.debug("Start playing with command %s", args) try: - self.__start = datetime.utcnow() return Popen( args, stdin=self._get_devnull(),