1
0
mirror of https://github.com/spl0k/supysonic.git synced 2024-12-22 17:06:17 +00:00

Jukebox endpoint + some fixes

This commit is contained in:
Alban Féron 2019-09-01 17:07:35 +02:00
parent 75b89e5f45
commit 0d40ede256
No known key found for this signature in database
GPG Key ID: 8CE0313646D16165
5 changed files with 109 additions and 10 deletions

View File

@ -98,4 +98,5 @@ from .annotation import *
from .chat import *
from .search import *
from .playlists import *
from .jukebox import *
from .unsupported import *

94
supysonic/api/jukebox.py Normal file
View File

@ -0,0 +1,94 @@
# coding: utf-8
#
# This file is part of Supysonic.
# Supysonic is a Python implementation of the Subsonic server API.
#
# Copyright (C) 2019 Alban 'spl0k' Féron
#
# Distributed under terms of the GNU AGPLv3 license.
import uuid
from flask import current_app, request
from pony.orm import ObjectNotFound
from ..daemon import DaemonClient
from ..daemon.exceptions import DaemonUnavailableError
from ..db import Track
from . import api
from .exceptions import GenericError, MissingParameter
@api.route("/jukeboxControl.view", methods=["GET", "POST"])
def jukebox_control():
action = request.values["action"]
index = request.values.get("index")
offset = request.values.get("offset")
id = request.values.getlist("id")
gain = request.values.get("gain")
if action not in (
"get",
"status",
"set",
"start",
"stop",
"skip",
"add",
"clear",
"remove",
"shuffle",
"setGain",
):
raise GenericError("Unknown action")
arg = None
if action == "set":
if not id:
arg = []
else:
arg = [uuid.UUID(i) for i in id]
elif action == "skip":
if not index:
raise MissingParameter("index")
else:
arg = int(index)
elif action == "add":
if not id:
raise MissingParameter("id")
else:
arg = [uuid.UUID(i) for i in id]
elif action == "remove":
if not index:
raise MissingParameter("index")
else:
arg = int(index)
elif action == "setGain":
if not gain:
raise MissingParameter("gain")
else:
arg = float(gain)
try:
status = DaemonClient(current_app.config["DAEMON"]["socket"]).jukebox_control(
action, arg
)
except DaemonUnavailableError:
raise GenericError("Jukebox unavaliable")
rv = dict(currentIndex=status.index, playing=status.playing, gain=status.gain)
if action == "get":
playlist = []
for path in status.playlist:
try:
playlist.append(Track.get(path=path))
except ObjectNotFound:
pass
rv["entry"] = [
t.as_subsonic_child(request.user, request.client) for t in playlist
]
return request.formatter("jukeboxPlaylist", rv)
else:
return request.formatter("jukeboxStatus", rv)

View File

@ -119,6 +119,7 @@ class JukeboxResult(DaemonCommandResult):
self.playing = jukebox.playing
self.index = jukebox.index
self.gain = jukebox.gain
self.playlist = ()
class DaemonClient(object):
@ -159,9 +160,9 @@ class DaemonClient(object):
with self.__get_connection() as c:
c.send(ScannerStartCommand(folders, force))
def jukebox_control(self, action, *args):
def jukebox_control(self, action, arg):
if not isinstance(action, strtype):
raise TypeError("Expecting string, got " + str(type(action)))
with self.__get_connection() as c:
c.send(JukeboxCommand(action, args))
c.send(JukeboxCommand(action, arg))
return c.recv()

View File

@ -37,7 +37,7 @@ class Daemon(object):
watcher = property(lambda self: self.__watcher)
scanner = property(lambda self: self.__scanner)
jukbox = property(lambda self: self.__jukebox)
jukebox = property(lambda self: self.__jukebox)
def __handle_connection(self, connection):
cmd = connection.recv()

View File

@ -11,7 +11,7 @@ import logging
import shlex
import time
from pony.orm import select
from pony.orm import db_session, ObjectNotFound
from random import shuffle
from subprocess import Popen, DEVNULL
from threading import Thread, Event, RLock
@ -59,20 +59,22 @@ class Jukebox(object):
self.__stop.set()
def skip(self, index):
if not self.playing:
return
if index < 0 or index >= len(self.__playlist):
raise IndexError()
with self.__lock:
self.__index = index - 1
self.__skip.set()
self.start()
def add(self, tracks):
paths = select(t.path for t in Track if t.id in tracks)
with self.__lock:
self.__playlist += paths[:]
with db_session:
for t in tracks:
try:
self.__playlist.append(Track[t].path)
except ObjectNotFound:
pass
def clear(self):
with self.__lock:
@ -101,10 +103,11 @@ class Jukebox(object):
self.__thread.join()
def __play_thread(self):
proc = None
while not self.__stop.is_set():
if self.__skip.is_set():
proc.terminate()
proc.join()
proc.wait()
self.__skip.clear()
if proc is None or proc.poll() is not None: