added the new http player and lf command

This commit is contained in:
tom lot 2021-02-22 00:28:54 +02:00
parent 9b90dd50a7
commit c9cbfdb705
12 changed files with 272 additions and 25 deletions

View File

@ -128,6 +128,7 @@ COMMANDS_QUEUE = ['queue', 'qa', 'add']
COMMANDS_PLAYLIST = ['playlist', 'ql', 'pl'] COMMANDS_PLAYLIST = ['playlist', 'ql', 'pl']
COMMANDS_SELECT = ['select', 'qs'] COMMANDS_SELECT = ['select', 'qs']
COMMANDS_DELETE = ['delete', 'd', 'qd'] COMMANDS_DELETE = ['delete', 'd', 'qd']
COMMANDS_FILE = ['lf']
MPC_MIN_VER = "1.6.4" MPC_MIN_VER = "1.6.4"
MPC_BE_MIN_VER = "1.5.2.3123" MPC_BE_MIN_VER = "1.5.2.3123"
VLC_MIN_VERSION = "2.2.1" VLC_MIN_VERSION = "2.2.1"

View File

@ -91,6 +91,7 @@ de = {
"commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate "commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate "commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Syncplay Version: {}", # syncplay.version "syncplay-version-notification": "Syncplay Version: {}", # syncplay.version
"more-info-notification": "Weitere Informationen auf: {}", # projectURL "more-info-notification": "Weitere Informationen auf: {}", # projectURL

View File

@ -91,6 +91,7 @@ en = {
"commandList-notification/playlist": "\tql - show the current playlist", "commandList-notification/playlist": "\tql - show the current playlist",
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", "commandList-notification/select": "\tqs [index] - select given entry in the playlist",
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist",
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Syncplay version: {}", # syncplay.version "syncplay-version-notification": "Syncplay version: {}", # syncplay.version
"more-info-notification": "More info available at: {}", # projectURL "more-info-notification": "More info available at: {}", # projectURL

View File

@ -91,6 +91,7 @@ es = {
"commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate "commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate "commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Versión de Syncplay: {}", # syncplay.version "syncplay-version-notification": "Versión de Syncplay: {}", # syncplay.version
"more-info-notification": "Más información disponible en: {}", # projectURL "more-info-notification": "Más información disponible en: {}", # projectURL

View File

@ -91,6 +91,7 @@ it = {
"commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate "commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate "commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Versione di Syncplay: {}", # syncplay.version "syncplay-version-notification": "Versione di Syncplay: {}", # syncplay.version
"more-info-notification": "Maggiori informazioni a: {}", # projectURL "more-info-notification": "Maggiori informazioni a: {}", # projectURL

View File

@ -91,6 +91,7 @@ pt_BR = {
"commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate "commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate "commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Versão do Syncplay: {}", # syncplay.version "syncplay-version-notification": "Versão do Syncplay: {}", # syncplay.version
"more-info-notification": "Mais informações disponíveis em: {}", # projectURL "more-info-notification": "Mais informações disponíveis em: {}", # projectURL

View File

@ -91,6 +91,7 @@ pt_PT = {
"commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate "commandList-notification/playlist": "\tql - show the current playlist", # TO DO: Translate
"commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate "commandList-notification/select": "\tqs [index] - select given entry in the playlist", # TO DO: Translate
"commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate "commandList-notification/delete": "\tqd [index] - delete the given entry from the playlist", # TO DO: Translate
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Versão do Syncplay: {}", # syncplay.version "syncplay-version-notification": "Versão do Syncplay: {}", # syncplay.version
"more-info-notification": "Mais informações disponíveis em: {}", # projectURL "more-info-notification": "Mais informações disponíveis em: {}", # projectURL

View File

@ -90,6 +90,7 @@ ru = {
"commandList-notification/playlist": "\tql - показать текущий список воспроизведения", "commandList-notification/playlist": "\tql - показать текущий список воспроизведения",
"commandList-notification/select": "\tqs [индекс] - выделить указанный пункт в списке воспроизведения", "commandList-notification/select": "\tqs [индекс] - выделить указанный пункт в списке воспроизведения",
"commandList-notification/delete": "\tqd [индекс] - удалить указанный пункт из списка воспроизведения", "commandList-notification/delete": "\tqd [индекс] - удалить указанный пункт из списка воспроизведения",
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Версия Syncplay: {}", # syncplay.version "syncplay-version-notification": "Версия Syncplay: {}", # syncplay.version
"more-info-notification": "Больше информации на {}", # projectURL "more-info-notification": "Больше информации на {}", # projectURL

View File

@ -91,6 +91,7 @@ tr = {
"commandList-notification/playlist": "\tql - mevcut oynatma listesini gösterir", "commandList-notification/playlist": "\tql - mevcut oynatma listesini gösterir",
"commandList-notification/select": "\tqs [index] - oynatma listesinde verilen girişi seçer", "commandList-notification/select": "\tqs [index] - oynatma listesinde verilen girişi seçer",
"commandList-notification/delete": "\tqd [index] - verilen girişi oynatma listesinden siler", "commandList-notification/delete": "\tqd [index] - verilen girişi oynatma listesinden siler",
"commandList-notification/load": "\tlf [path] - load file",
"syncplay-version-notification": "Syncplay sürümü: {}", # syncplay.version "syncplay-version-notification": "Syncplay sürümü: {}", # syncplay.version
"more-info-notification": "Daha fazla bilgiye şu adresten ulaşabilirsiniz: {}", # projectURL "more-info-notification": "Daha fazla bilgiye şu adresten ulaşabilirsiniz: {}", # projectURL

View File

@ -18,6 +18,7 @@ except ImportError:
from syncplay.players.basePlayer import DummyPlayer from syncplay.players.basePlayer import DummyPlayer
IinaPlayer = DummyPlayer IinaPlayer = DummyPlayer
from syncplay.players.httpPlayer import HttpPlayer
def getAvailablePlayers(): def getAvailablePlayers():
return [MPCHCAPIPlayer, MpvPlayer, MpvnetPlayer, VlcPlayer, MpcBePlayer, MplayerPlayer, IinaPlayer] return [MPCHCAPIPlayer, MpvPlayer, MpvnetPlayer, VlcPlayer, MpcBePlayer, MplayerPlayer, IinaPlayer, HttpPlayer]

View File

@ -0,0 +1,201 @@
from syncplay.players.basePlayer import BasePlayer
from syncplay import constants
from mutagen.mp3 import MP3
from time import time
import requests
import os
class StreamData():
def __init__(self):
pass
def close(self):
pass
'''
@type file_name: string
@type position: float
@type speed: float
@type paused: bool
@type address: tuple
Send formatted data to the given address
'''
def sendto(self, position, speed, paused, address):
try:
data = {"position": position, "speed": speed,
"paused": paused, "time": time()}
requests.post(address, json=data)
except:
print("can't connect to the server right now")
class HttpPlayer(BasePlayer):
speedSupported = True
customOpenDialog = False
chatOSDSupported = False
alertOSDSupported = False
osdMessageSeparator = ""
SEND_ADDRESS = "http://127.0.0.1:5000/data"
DEFAULT_PATH = "/HttpPlayer"
DEFAULT_FILE = "want.mp3"
def __init__(self, client, playerPath, filePath, args):
self._stream = StreamData()
self._client = client
self._filepath = filePath if filePath else self.DEFAULT_FILE # For the audio file
self._position = 0.0 # In seconds
self._speed = 1.0 # Percentage
self._paused = False
self._done = False
self._last_send = time()
try:
self.openFile(self._filepath)
self._client.updateFile(os.path.basename(self._filepath), MP3(
self._filepath).info.length, self._filepath)
self.setPaused(True)
self.setPosition(0.0)
except Exception as e:
print(e)
self._client.initPlayer(self)
'''
Send stream properties to the server through the StreamData object
'''
def streamUpdate(self):
self._stream.sendto(self._position, self._speed,
self._paused, self.SEND_ADDRESS)
'''
This method is supposed to
execute updatePlayerStatus(paused, position) on client
Given the arguments: boolean paused and float position in seconds
'''
def askForStatus(self):
if not self._client.userlist.currentUser.ready:
self._client.toggleReady()
if time() - self._last_send >= 5:
self._position = self._client.getGlobalPosition()
self._paused = self._client.getGlobalPaused()
self.streamUpdate()
self._last_send = time()
self._client.updatePlayerStatus(
self._client.getGlobalPaused(), self._client.getGlobalPosition())
'''
Display given message on player's OSD or similar means
'''
def displayMessage(
self, message, duration=(constants.OSD_DURATION*1000), secondaryOSD=False, mood=constants.MESSAGE_NEUTRAL
):
pass # Nothing to see here
'''
Cleanup connection with player before syncplay will close down
'''
def drop(self):
self._stream.close()
self._done = True
'''
Start up the player, returns its instance
'''
@ staticmethod
def run(client, playerPath, filePath, args):
return HttpPlayer(client, playerPath, filePath, args)
'''
@type value: boolean
'''
def setPaused(self, value):
print(f"set pause {value}")
self._paused = value
self.streamUpdate()
'''
@type value: list
'''
def setFeatures(self, featureList):
pass # Nothing to see here...
'''
@type value: float
'''
def setPosition(self, value):
print(f"set position: {value}")
self._position = value
self.streamUpdate()
'''
@type value: float
'''
def setSpeed(self, value):
print(f"set speed {value}")
self._speed = value
self.streamUpdate()
'''
@type filePath: string
'''
def openFile(self, filePath, resetPosition=False):
print(f"open file: {filePath}")
self._filepath = filePath
self.streamUpdate()
'''
@return: list of strings
'''
@ staticmethod
def getDefaultPlayerPathsList():
pass
'''
@type path: string
'''
@ staticmethod
def isValidPlayerPath(path):
# Always true because it's really a player
return path == HTTPPlayer.DEFAULT_PATH
'''
@type path: string
@return: string
'''
@ staticmethod
def getIconPath(path):
return None # Nothing to see here
'''
@type path: string
@return: string
'''
@ staticmethod
def getExpandedPath(path):
return path # Not really a player
'''
@type playerPath: string
@type filePath: string
@return errorMessage: string
Checks if the player has any problems with the given player/file path
'''
@ staticmethod
def getPlayerPathErrors(playerPath, filePath):
return None # Nothing to see here

View File

@ -10,6 +10,7 @@ from syncplay import constants
from syncplay import utils from syncplay import utils
from syncplay.messages import getMessage from syncplay.messages import getMessage
from syncplay.utils import formatTime, isURL from syncplay.utils import formatTime, isURL
from mutagen.mp3 import MP3
class ConsoleUI(threading.Thread): class ConsoleUI(threading.Thread):
@ -73,17 +74,22 @@ class ConsoleUI(threading.Thread):
if user.isReady(): if user.isReady():
userflags += "({}) ".format(getMessage("ready-userlist-userflag")) userflags += "({}) ".format(getMessage("ready-userlist-userflag"))
username = userflags + "*<{}>*".format(user.username) if user == currentUser else userflags + "<{}>".format(user.username) username = userflags + \
"*<{}>*".format(user.username) if user == currentUser else userflags + \
"<{}>".format(user.username)
if user.file: if user.file:
message = getMessage("userlist-playing-notification").format(username) message = getMessage(
"userlist-playing-notification").format(username)
self.showMessage(message, True) self.showMessage(message, True)
message = " {}: '{}' ({})".format(getMessage("userlist-file-notification"), user.file['name'], formatTime(user.file['duration'])) message = " {}: '{}' ({})".format(getMessage(
"userlist-file-notification"), user.file['name'], formatTime(user.file['duration']))
if currentUser.file: if currentUser.file:
if user.file['name'] == currentUser.file['name'] and user.file['size'] != currentUser.file['size']: if user.file['name'] == currentUser.file['name'] and user.file['size'] != currentUser.file['size']:
message += getMessage("different-filesize-notification") message += getMessage("different-filesize-notification")
self.showMessage(message, True) self.showMessage(message, True)
else: else:
message = getMessage("no-file-played-notification").format(username) message = getMessage(
"no-file-played-notification").format(username)
self.showMessage(message, True) self.showMessage(message, True)
def userListChange(self): def userListChange(self):
@ -107,7 +113,8 @@ class ConsoleUI(threading.Thread):
if noTimestamp: if noTimestamp:
print(message) print(message)
else: else:
print(time.strftime(constants.UI_TIME_FORMAT, time.localtime()) + message) print(time.strftime(constants.UI_TIME_FORMAT,
time.localtime()) + message)
def showDebugMessage(self, message): def showDebugMessage(self, message):
print(message) print(message)
@ -136,9 +143,9 @@ class ConsoleUI(threading.Thread):
if t is None: if t is None:
return return
if o.group('sign') == "/": if o.group('sign') == "/":
t = self._syncplayClient.getPlayerPosition() - t t = self._syncplayClient.getPlayerPosition() - t
elif sign: elif sign:
t = self._syncplayClient.getUserOffset() + sign * t t = self._syncplayClient.getUserOffset() + sign * t
self._syncplayClient.setUserOffset(t) self._syncplayClient.setUserOffset(t)
return True return True
elif s: elif s:
@ -158,7 +165,8 @@ class ConsoleUI(threading.Thread):
return return
if command.group('command') in constants.COMMANDS_UNDO: if command.group('command') in constants.COMMANDS_UNDO:
tmp_pos = self._syncplayClient.getPlayerPosition() tmp_pos = self._syncplayClient.getPlayerPosition()
self._syncplayClient.setPosition(self._syncplayClient.playerPositionBeforeLastSeek) self._syncplayClient.setPosition(
self._syncplayClient.playerPositionBeforeLastSeek)
self._syncplayClient.playerPositionBeforeLastSeek = tmp_pos self._syncplayClient.playerPositionBeforeLastSeek = tmp_pos
elif command.group('command') in constants.COMMANDS_LIST: elif command.group('command') in constants.COMMANDS_LIST:
self.getUserlist() self.getUserlist()
@ -166,7 +174,8 @@ class ConsoleUI(threading.Thread):
message = command.group('parameter') message = command.group('parameter')
self._syncplayClient.sendChat(message) self._syncplayClient.sendChat(message)
elif command.group('command') in constants.COMMANDS_PAUSE: elif command.group('command') in constants.COMMANDS_PAUSE:
self._syncplayClient.setPaused(not self._syncplayClient.getPlayerPaused()) self._syncplayClient.setPaused(
not self._syncplayClient.getPlayerPaused())
elif command.group('command') in constants.COMMANDS_ROOM: elif command.group('command') in constants.COMMANDS_ROOM:
room = command.group('parameter') room = command.group('parameter')
if room is None: if room is None:
@ -197,7 +206,8 @@ class ConsoleUI(threading.Thread):
self._syncplayClient.ui.addFileToPlaylist(filename) self._syncplayClient.ui.addFileToPlaylist(filename)
elif command.group('command') in constants.COMMANDS_PLAYLIST: elif command.group('command') in constants.COMMANDS_PLAYLIST:
playlist = self._syncplayClient.playlist playlist = self._syncplayClient.playlist
playlist_elements = ["\t{}: {}".format(i+1, el) for i, el in enumerate(playlist._playlist)] playlist_elements = ["\t{}: {}".format(
i+1, el) for i, el in enumerate(playlist._playlist)]
if playlist_elements: if playlist_elements:
i = playlist._playlistIndex i = playlist._playlistIndex
@ -213,41 +223,67 @@ class ConsoleUI(threading.Thread):
if index < 0 or index >= len(self._syncplayClient.playlist._playlist): if index < 0 or index >= len(self._syncplayClient.playlist._playlist):
raise TypeError("Invalid playlist index") raise TypeError("Invalid playlist index")
self._syncplayClient.playlist.changeToPlaylistIndex(index, resetPosition=True) self._syncplayClient.playlist.changeToPlaylistIndex(
index, resetPosition=True)
self._syncplayClient.rewindFile() self._syncplayClient.rewindFile()
except (TypeError, AttributeError): except (TypeError, AttributeError):
self.showErrorMessage(getMessage("playlist-invalid-index-error")) self.showErrorMessage(getMessage(
"playlist-invalid-index-error"))
elif command.group('command') in constants.COMMANDS_DELETE: elif command.group('command') in constants.COMMANDS_DELETE:
try: try:
index = int(command.group('parameter').strip()) - 1 index = int(command.group('parameter').strip()) - 1
self._syncplayClient.playlist.deleteAtIndex(index) self._syncplayClient.playlist.deleteAtIndex(index)
except (TypeError, AttributeError): except (TypeError, AttributeError):
self.showErrorMessage(getMessage("playlist-invalid-index-error")) self.showErrorMessage(getMessage(
"playlist-invalid-index-error"))
elif command.group('command') in constants.COMMANDS_FILE:
try:
path = command.group('parameter'.strip())
if os.path.exists(path):
self.showMessage(f'loading {path}', True)
self._syncplayClient.updateFile(
os.path.basename(path), MP3(path).info.length, path)
self._syncplayClient._player.openFile(path)
self.showMessage(f'{path} loaded', True)
else:
self.showErrorMessage("File doesn't exists")
except Exception as e:
print(e)
else: else:
if self._tryAdvancedCommands(data): if self._tryAdvancedCommands(data):
return return
if command.group('command') not in constants.COMMANDS_HELP: if command.group('command') not in constants.COMMANDS_HELP:
self.showMessage(getMessage("unrecognized-command-notification")) self.showMessage(getMessage(
"unrecognized-command-notification"))
self.showMessage(getMessage("commandlist-notification"), True) self.showMessage(getMessage("commandlist-notification"), True)
self.showMessage(getMessage("commandlist-notification/room"), True) self.showMessage(getMessage("commandlist-notification/room"), True)
self.showMessage(getMessage("commandlist-notification/list"), True) self.showMessage(getMessage("commandlist-notification/list"), True)
self.showMessage(getMessage("commandlist-notification/undo"), True) self.showMessage(getMessage("commandlist-notification/undo"), True)
self.showMessage(getMessage("commandlist-notification/pause"), True) self.showMessage(getMessage(
"commandlist-notification/pause"), True)
self.showMessage(getMessage("commandlist-notification/seek"), True) self.showMessage(getMessage("commandlist-notification/seek"), True)
self.showMessage(getMessage("commandlist-notification/help"), True) self.showMessage(getMessage("commandlist-notification/help"), True)
self.showMessage(getMessage("commandlist-notification/toggle"), True) self.showMessage(getMessage(
self.showMessage(getMessage("commandlist-notification/create"), True) "commandlist-notification/toggle"), True)
self.showMessage(getMessage(
"commandlist-notification/create"), True)
self.showMessage(getMessage("commandlist-notification/auth"), True) self.showMessage(getMessage("commandlist-notification/auth"), True)
self.showMessage(getMessage("commandlist-notification/chat"), True) self.showMessage(getMessage("commandlist-notification/chat"), True)
self.showMessage(getMessage("commandList-notification/queue"), True) self.showMessage(getMessage(
self.showMessage(getMessage("commandList-notification/playlist"), True) "commandList-notification/queue"), True)
self.showMessage(getMessage("commandList-notification/select"), True) self.showMessage(getMessage(
self.showMessage(getMessage("commandList-notification/delete"), True) "commandList-notification/playlist"), True)
self.showMessage(getMessage("syncplay-version-notification").format(syncplay.version), True) self.showMessage(getMessage(
self.showMessage(getMessage("more-info-notification").format(syncplay.projectURL), True) "commandList-notification/select"), True)
self.showMessage(getMessage(
"commandList-notification/delete"), True)
self.showMessage(getMessage("commandList-notification/load"), True)
self.showMessage(getMessage(
"syncplay-version-notification").format(syncplay.version), True)
self.showMessage(getMessage(
"more-info-notification").format(syncplay.projectURL), True)
def getUserlist(self): def getUserlist(self):
self._syncplayClient.getUserList() self._syncplayClient.getUserList()