Move to JSON IPC API for mpv using iwaltons3's library (#261)
This commit is contained in:
parent
7887c2bf14
commit
4ad28df08b
@ -236,7 +236,7 @@ USERLIST_GUI_FILENAME_COLUMN = 3
|
|||||||
|
|
||||||
MPLAYER_SLAVE_ARGS = ['-slave', '--hr-seek=always', '-nomsgcolor', '-msglevel', 'all=1:global=4:cplayer=4', '-af-add', 'scaletempo']
|
MPLAYER_SLAVE_ARGS = ['-slave', '--hr-seek=always', '-nomsgcolor', '-msglevel', 'all=1:global=4:cplayer=4', '-af-add', 'scaletempo']
|
||||||
MPV_ARGS = ['--force-window', '--idle', '--hr-seek=always', '--keep-open']
|
MPV_ARGS = ['--force-window', '--idle', '--hr-seek=always', '--keep-open']
|
||||||
MPV_SLAVE_ARGS = ['--msg-level=all=error,cplayer=info,term-msg=info', '--input-terminal=no', '--input-file=/dev/stdin']
|
MPV_SLAVE_ARGS = ['--msg-level=all=error,cplayer=info,term-msg=info', '--input-terminal=no']
|
||||||
MPV_SLAVE_ARGS_NEW = ['--term-playing-msg=<SyncplayUpdateFile>\nANS_filename=${filename}\nANS_length=${=duration:${=length:0}}\nANS_path=${path}\n</SyncplayUpdateFile>', '--terminal=yes']
|
MPV_SLAVE_ARGS_NEW = ['--term-playing-msg=<SyncplayUpdateFile>\nANS_filename=${filename}\nANS_length=${=duration:${=length:0}}\nANS_path=${path}\n</SyncplayUpdateFile>', '--terminal=yes']
|
||||||
MPV_NEW_VERSION = False
|
MPV_NEW_VERSION = False
|
||||||
MPV_OSC_VISIBILITY_CHANGE_VERSION = False
|
MPV_OSC_VISIBILITY_CHANGE_VERSION = False
|
||||||
@ -261,7 +261,7 @@ VLC_SLAVE_ARGS = ['--extraintf=luaintf', '--lua-intf=syncplay', '--no-quiet', '-
|
|||||||
VLC_SLAVE_EXTRA_ARGS = getValueForOS({
|
VLC_SLAVE_EXTRA_ARGS = getValueForOS({
|
||||||
OS_DEFAULT: ['--no-one-instance', '--no-one-instance-when-started-from-file'],
|
OS_DEFAULT: ['--no-one-instance', '--no-one-instance-when-started-from-file'],
|
||||||
OS_MACOS: ['--verbose=2', '--no-file-logging']})
|
OS_MACOS: ['--verbose=2', '--no-file-logging']})
|
||||||
MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS = ["no-osd set time-pos ", "loadfile "]
|
MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS = ["set_property time-pos ", "loadfile "]
|
||||||
MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS = ["cycle pause"]
|
MPV_REMOVE_BOTH_IF_DUPLICATE_COMMANDS = ["cycle pause"]
|
||||||
MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$"
|
MPLAYER_ANSWER_REGEX = "^ANS_([a-zA-Z_-]+)=(.+)$|^(Exiting)\.\.\. \((.+)\)$"
|
||||||
VLC_ANSWER_REGEX = r"(?:^(?P<command>[a-zA-Z_]+)(?:\: )?(?P<argument>.*))"
|
VLC_ANSWER_REGEX = r"(?:^(?P<command>[a-zA-Z_]+)(?:\: )?(?P<argument>.*))"
|
||||||
|
|||||||
@ -6,15 +6,16 @@ import time
|
|||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import ast
|
import ast
|
||||||
|
import random
|
||||||
|
|
||||||
from syncplay import constants
|
from syncplay import constants
|
||||||
from syncplay.messages import getMessage
|
from syncplay.messages import getMessage
|
||||||
from syncplay.utils import isURL, findResourcePath
|
from syncplay.utils import isURL, findResourcePath
|
||||||
from syncplay.utils import isMacOS, isWindows, isASCII
|
from syncplay.utils import isMacOS, isWindows, isASCII
|
||||||
|
from syncplay.players.python_mpv_jsonipc.python_mpv_jsonipc import MPV
|
||||||
|
|
||||||
from syncplay.players.basePlayer import BasePlayer
|
from syncplay.players.basePlayer import BasePlayer
|
||||||
|
|
||||||
|
|
||||||
class MpvPlayer(BasePlayer):
|
class MpvPlayer(BasePlayer):
|
||||||
RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*')
|
RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*')
|
||||||
osdMessageSeparator = "\\n"
|
osdMessageSeparator = "\\n"
|
||||||
@ -53,7 +54,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
return MpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
return MpvPlayer(client, MpvPlayer.getExpandedPath(playerPath), filePath, args)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def getStartupArgs(path, userArgs):
|
def getStartupArgs(path, userArgs, socketName=None):
|
||||||
args = constants.MPV_ARGS
|
args = constants.MPV_ARGS
|
||||||
if userArgs:
|
if userArgs:
|
||||||
args.extend(userArgs)
|
args.extend(userArgs)
|
||||||
@ -61,6 +62,9 @@ class MpvPlayer(BasePlayer):
|
|||||||
if constants.MPV_NEW_VERSION:
|
if constants.MPV_NEW_VERSION:
|
||||||
args.extend(constants.MPV_SLAVE_ARGS_NEW)
|
args.extend(constants.MPV_SLAVE_ARGS_NEW)
|
||||||
args.extend(["--script={}".format(findResourcePath("syncplayintf.lua"))])
|
args.extend(["--script={}".format(findResourcePath("syncplayintf.lua"))])
|
||||||
|
if socketName:
|
||||||
|
args.extend((["--input-ipc-server={}".format(socketName)]))
|
||||||
|
print(args)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -103,7 +107,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _setProperty(self, property_, value):
|
def _setProperty(self, property_, value):
|
||||||
self._listener.sendLine("no-osd set {} {}".format(property_, value))
|
self._listener.sendLine(["set_property", property_, value])
|
||||||
|
|
||||||
def mpvErrorCheck(self, line):
|
def mpvErrorCheck(self, line):
|
||||||
if "Error parsing option" in line or "Error parsing commandline option" in line:
|
if "Error parsing option" in line or "Error parsing commandline option" in line:
|
||||||
@ -116,37 +120,27 @@ class MpvPlayer(BasePlayer):
|
|||||||
if constants and any(errormsg in line for errormsg in constants.MPV_ERROR_MESSAGES_TO_REPEAT):
|
if constants and any(errormsg in line for errormsg in constants.MPV_ERROR_MESSAGES_TO_REPEAT):
|
||||||
self._client.ui.showErrorMessage(line)
|
self._client.ui.showErrorMessage(line)
|
||||||
|
|
||||||
|
|
||||||
def oldDisplayMessage(
|
|
||||||
self, message,
|
|
||||||
duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION,
|
|
||||||
mood=constants.MESSAGE_NEUTRAL
|
|
||||||
):
|
|
||||||
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
|
||||||
self._listener.sendLine('{} "{!s}" {} {}'.format(
|
|
||||||
self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
|
||||||
|
|
||||||
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION,
|
def displayMessage(self, message, duration=(constants.OSD_DURATION * 1000), OSDType=constants.OSD_NOTIFICATION,
|
||||||
mood=constants.MESSAGE_NEUTRAL):
|
mood=constants.MESSAGE_NEUTRAL):
|
||||||
if not self._client._config["chatOutputEnabled"]:
|
if not self._client._config["chatOutputEnabled"]:
|
||||||
self.oldDisplayMessage(self, message=message, duration=duration, OSDType=OSDType, mood=mood)
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
||||||
|
self._listener.mpvpipe.show_text(messageString, duration, constants.MPLAYER_OSD_LEVEL)
|
||||||
return
|
return
|
||||||
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace(
|
messageString = self._sanitizeText(message.replace("\\n", "<NEWLINE>")).replace(
|
||||||
"\\\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
"\\\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER).replace("<NEWLINE>", "\\n")
|
||||||
self._listener.sendLine('script-message-to syncplayintf {}-osd-{} "{}"'.format(OSDType, mood, messageString))
|
self._listener.sendLine(["script-message-to", "syncplayintf", "{}-osd-{}".format(OSDType, mood), messageString])
|
||||||
|
|
||||||
def displayChatMessage(self, username, message):
|
def displayChatMessage(self, username, message):
|
||||||
if not self._client._config["chatOutputEnabled"]:
|
if not self._client._config["chatOutputEnabled"]:
|
||||||
messageString = "<{}> {}".format(username, message)
|
messageString = "<{}> {}".format(username, message)
|
||||||
messageString = self._sanitizeText(messageString.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
messageString = self._sanitizeText(messageString.replace("\\n", "<NEWLINE>")).replace("<NEWLINE>", "\\n")
|
||||||
duration = int(constants.OSD_DURATION * 1000)
|
duration = int(constants.OSD_DURATION * 1000)
|
||||||
self._listener.sendLine('{} "{!s}" {} {}'.format(
|
self._listener.mpvpipe.show_text(messageString, duration, constants.MPLAYER_OSD_LEVEL)
|
||||||
self.OSD_QUERY, messageString, duration, constants.MPLAYER_OSD_LEVEL))
|
|
||||||
return
|
return
|
||||||
username = self._sanitizeText(username.replace("\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
username = self._sanitizeText(username.replace("\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
||||||
message = self._sanitizeText(message.replace("\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
message = self._sanitizeText(message.replace("\\", constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER))
|
||||||
messageString = "<{}> {}".format(username, message)
|
messageString = "<{}> {}".format(username, message)
|
||||||
self._listener.sendLine('script-message-to syncplayintf chat "{}"'.format(messageString))
|
self._listener.sendLine(["script-message-to", "syncplayintf", "chat", messageString])
|
||||||
|
|
||||||
def setSpeed(self, value):
|
def setSpeed(self, value):
|
||||||
self._setProperty('speed', "{:.2f}".format(value))
|
self._setProperty('speed', "{:.2f}".format(value))
|
||||||
@ -178,7 +172,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
propertyID = '=duration:${=length:0}'
|
propertyID = '=duration:${=length:0}'
|
||||||
else:
|
else:
|
||||||
propertyID = property_
|
propertyID = property_
|
||||||
self._listener.sendLine("print_text ""ANS_{}=${{{}}}""".format(property_, propertyID))
|
self._listener.sendLine(["print_text", '"ANS_{}=${{{}}}"'.format(property_, propertyID)])
|
||||||
|
|
||||||
def getCalculatedPosition(self):
|
def getCalculatedPosition(self):
|
||||||
if self.fileLoaded == False:
|
if self.fileLoaded == False:
|
||||||
@ -214,6 +208,10 @@ class MpvPlayer(BasePlayer):
|
|||||||
return self._position
|
return self._position
|
||||||
|
|
||||||
def _storePosition(self, value):
|
def _storePosition(self, value):
|
||||||
|
if value is None:
|
||||||
|
self._client.ui.showDebugMessage("NONE TYPE POSITION!")
|
||||||
|
return
|
||||||
|
|
||||||
if self._client.isPlayingMusic() and self._paused == False and self._position == value and abs(self._position-self._position) < 0.5:
|
if self._client.isPlayingMusic() and self._paused == False and self._position == value and abs(self._position-self._position) < 0.5:
|
||||||
self._client.ui.showDebugMessage("EOF DETECTED!")
|
self._client.ui.showDebugMessage("EOF DETECTED!")
|
||||||
self._position = 0
|
self._position = 0
|
||||||
@ -223,17 +221,25 @@ class MpvPlayer(BasePlayer):
|
|||||||
self._client.ui.showDebugMessage("Recently reset, so storing position as 0")
|
self._client.ui.showDebugMessage("Recently reset, so storing position as 0")
|
||||||
self._position = 0
|
self._position = 0
|
||||||
elif self._fileIsLoaded() or (value < constants.MPV_NEWFILE_IGNORE_TIME and self._fileIsLoaded(ignoreDelay=True)):
|
elif self._fileIsLoaded() or (value < constants.MPV_NEWFILE_IGNORE_TIME and self._fileIsLoaded(ignoreDelay=True)):
|
||||||
|
old_position = float(self._position)
|
||||||
self._position = max(value, 0)
|
self._position = max(value, 0)
|
||||||
|
#self._client.ui.showDebugMessage("Position changed from {} to {}".format(old_position, self._position))
|
||||||
else:
|
else:
|
||||||
self._client.ui.showDebugMessage(
|
self._client.ui.showDebugMessage(
|
||||||
"No file loaded so storing position as GlobalPosition ({})".format(self._client.getGlobalPosition()))
|
"No file loaded so storing position {} as GlobalPosition ({})".format(value, self._client.getGlobalPosition()))
|
||||||
self._position = self._client.getGlobalPosition()
|
self._position = self._client.getGlobalPosition()
|
||||||
|
|
||||||
def _storePauseState(self, value):
|
def _storePauseState(self, value):
|
||||||
|
if value is None:
|
||||||
|
self._client.ui.showDebugMessage("NONE TYPE PAUSE STATE!")
|
||||||
|
return
|
||||||
if self._fileIsLoaded():
|
if self._fileIsLoaded():
|
||||||
self._paused = value
|
self._paused = value
|
||||||
|
#self._client.ui.showDebugMessage("PAUSE STATE STORED AS {}".format(self._paused))
|
||||||
else:
|
else:
|
||||||
self._paused = self._client.getGlobalPaused()
|
self._paused = self._client.getGlobalPaused()
|
||||||
|
#self._client.ui.showDebugMessage("STORING GLOBAL PAUSED AS FILE IS NOT LOADED")
|
||||||
|
|
||||||
|
|
||||||
def lineReceived(self, line):
|
def lineReceived(self, line):
|
||||||
if line:
|
if line:
|
||||||
@ -303,7 +309,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
self._paused if self.fileLoaded else self._client.getGlobalPaused(), self.getCalculatedPosition())
|
||||||
|
|
||||||
def drop(self):
|
def drop(self):
|
||||||
self._listener.sendLine('quit')
|
self._listener.sendLine(['quit'])
|
||||||
self._takeLocksDown()
|
self._takeLocksDown()
|
||||||
self.reactor.callFromThread(self._client.stop, False)
|
self.reactor.callFromThread(self._client.stop, False)
|
||||||
|
|
||||||
@ -316,7 +322,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
|
|
||||||
|
|
||||||
def _getPausedAndPosition(self):
|
def _getPausedAndPosition(self):
|
||||||
self._listener.sendLine("print_text ANS_pause=${pause}\r\nprint_text ANS_time-pos=${=time-pos}")
|
self._listener.sendLine(["script-message-to", "syncplayintf", "get_paused_and_position"])
|
||||||
|
|
||||||
def _getPaused(self):
|
def _getPaused(self):
|
||||||
self._getProperty('pause')
|
self._getProperty('pause')
|
||||||
@ -356,7 +362,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
|
|
||||||
def _loadFile(self, filePath):
|
def _loadFile(self, filePath):
|
||||||
self._clearFileLoaded()
|
self._clearFileLoaded()
|
||||||
self._listener.sendLine('loadfile {}'.format(self._quoteArg(filePath)), notReadyAfterThis=True)
|
self._listener.sendLine(['loadfile', filePath], notReadyAfterThis=True)
|
||||||
|
|
||||||
def setFeatures(self, featureList):
|
def setFeatures(self, featureList):
|
||||||
self.sendMpvOptions()
|
self.sendMpvOptions()
|
||||||
@ -367,6 +373,8 @@ class MpvPlayer(BasePlayer):
|
|||||||
"Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
|
"Did not seek as recently reset and {} below 'do not reset position' threshold".format(value))
|
||||||
return
|
return
|
||||||
self._position = max(value, 0)
|
self._position = max(value, 0)
|
||||||
|
self._client.ui.showDebugMessage(
|
||||||
|
"Setting position to {}...".format(self._position))
|
||||||
self._setProperty(self.POSITION_QUERY, "{}".format(value))
|
self._setProperty(self.POSITION_QUERY, "{}".format(value))
|
||||||
time.sleep(0.03)
|
time.sleep(0.03)
|
||||||
self.lastMPVPositionUpdate = time.time()
|
self.lastMPVPositionUpdate = time.time()
|
||||||
@ -376,6 +384,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
if resetPosition:
|
if resetPosition:
|
||||||
self.lastResetTime = time.time()
|
self.lastResetTime = time.time()
|
||||||
if isURL(filePath):
|
if isURL(filePath):
|
||||||
|
self._client.ui.showDebugMessage("Setting additional lastResetTime due to stream")
|
||||||
self.lastResetTime += constants.STREAM_ADDITIONAL_IGNORE_TIME
|
self.lastResetTime += constants.STREAM_ADDITIONAL_IGNORE_TIME
|
||||||
self._loadFile(filePath)
|
self._loadFile(filePath)
|
||||||
if self._paused != self._client.getGlobalPaused():
|
if self._paused != self._client.getGlobalPaused():
|
||||||
@ -383,9 +392,11 @@ class MpvPlayer(BasePlayer):
|
|||||||
else:
|
else:
|
||||||
self._client.ui.showDebugMessage("Don't want to set paused to {}".format(self._client.getGlobalPaused()))
|
self._client.ui.showDebugMessage("Don't want to set paused to {}".format(self._client.getGlobalPaused()))
|
||||||
if resetPosition == False:
|
if resetPosition == False:
|
||||||
|
self._client.ui.showDebugMessage("OpenFile setting position to global position: {}".format(self._client.getGlobalPosition()))
|
||||||
self.setPosition(self._client.getGlobalPosition())
|
self.setPosition(self._client.getGlobalPosition())
|
||||||
else:
|
else:
|
||||||
self._storePosition(0)
|
self._storePosition(0)
|
||||||
|
# TO TRY: self._listener.setReadyToSend(False)
|
||||||
|
|
||||||
def sendMpvOptions(self):
|
def sendMpvOptions(self):
|
||||||
options = []
|
options = []
|
||||||
@ -397,7 +408,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
options.append("{}={}".format(option, getMessage(option)))
|
options.append("{}={}".format(option, getMessage(option)))
|
||||||
options.append("OscVisibilityChangeCompatible={}".format(constants.MPV_OSC_VISIBILITY_CHANGE_VERSION))
|
options.append("OscVisibilityChangeCompatible={}".format(constants.MPV_OSC_VISIBILITY_CHANGE_VERSION))
|
||||||
options_string = ", ".join(options)
|
options_string = ", ".join(options)
|
||||||
self._listener.sendLine('script-message-to syncplayintf set_syncplayintf_options "{}"'.format(options_string))
|
self._listener.sendLine(["script-message-to", "syncplayintf", "set_syncplayintf_options", options_string])
|
||||||
self._setOSDPosition()
|
self._setOSDPosition()
|
||||||
|
|
||||||
def _handleUnknownLine(self, line):
|
def _handleUnknownLine(self, line):
|
||||||
@ -407,18 +418,37 @@ class MpvPlayer(BasePlayer):
|
|||||||
line = line.replace(constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER, "\\")
|
line = line.replace(constants.MPV_INPUT_BACKSLASH_SUBSTITUTE_CHARACTER, "\\")
|
||||||
self._listener.sendChat(line[6:-7])
|
self._listener.sendChat(line[6:-7])
|
||||||
|
|
||||||
|
if "<paused>" in line and "<position>" in line:
|
||||||
|
update_string = line.replace(">", "<").split("<")
|
||||||
|
paused_update = update_string[2]
|
||||||
|
position_update = update_string[6]
|
||||||
|
if paused_update == "nil":
|
||||||
|
self._storePauseState(True)
|
||||||
|
else:
|
||||||
|
self._storePauseState(bool(paused_update == 'true'))
|
||||||
|
self._pausedAsk.set()
|
||||||
|
if position_update == "nil":
|
||||||
|
self._storePosition(float(0))
|
||||||
|
else:
|
||||||
|
self._storePosition(float(position_update))
|
||||||
|
self._positionAsk.set()
|
||||||
|
#self._client.ui.showDebugMessage("{} = {} / {}".format(update_string, paused_update, position_update))
|
||||||
|
|
||||||
if "<get_syncplayintf_options>" in line:
|
if "<get_syncplayintf_options>" in line:
|
||||||
self.sendMpvOptions()
|
self.sendMpvOptions()
|
||||||
|
|
||||||
if line == "<SyncplayUpdateFile>" or "Playing:" in line:
|
if line == "<SyncplayUpdateFile>" or "Playing:" in line:
|
||||||
|
self._client.ui.showDebugMessage("Not ready to send due to <SyncplayUpdateFile>")
|
||||||
self._listener.setReadyToSend(False)
|
self._listener.setReadyToSend(False)
|
||||||
self._clearFileLoaded()
|
self._clearFileLoaded()
|
||||||
|
|
||||||
elif line == "</SyncplayUpdateFile>":
|
elif line == "</SyncplayUpdateFile>":
|
||||||
self._onFileUpdate()
|
self._onFileUpdate()
|
||||||
self._listener.setReadyToSend(True)
|
self._listener.setReadyToSend(True)
|
||||||
|
self._client.ui.showDebugMessage("Ready to send due to </SyncplayUpdateFile>")
|
||||||
|
|
||||||
elif "Failed" in line or "failed" in line or "No video or audio streams selected" in line or "error" in line:
|
elif "Failed" in line or "failed" in line or "No video or audio streams selected" in line or "error" in line:
|
||||||
|
self._client.ui.showDebugMessage("Not ready to send due to error")
|
||||||
self._listener.setReadyToSend(True)
|
self._listener.setReadyToSend(True)
|
||||||
|
|
||||||
def _setOSDPosition(self):
|
def _setOSDPosition(self):
|
||||||
@ -442,12 +472,15 @@ class MpvPlayer(BasePlayer):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _onFileUpdate(self):
|
def _onFileUpdate(self):
|
||||||
|
self._client.ui.showDebugMessage("File update")
|
||||||
self.fileLoaded = True
|
self.fileLoaded = True
|
||||||
self.lastLoadedTime = time.time()
|
self.lastLoadedTime = time.time()
|
||||||
self.reactor.callFromThread(self._client.updateFile, self._filename, self._duration, self._filepath)
|
self.reactor.callFromThread(self._client.updateFile, self._filename, self._duration, self._filepath)
|
||||||
if not (self._recentlyReset()):
|
if not (self._recentlyReset()):
|
||||||
|
self._client.ui.showDebugMessage("onFileUpdate setting position to global position: {}".format(self._client.getGlobalPosition()))
|
||||||
self.reactor.callFromThread(self.setPosition, self._client.getGlobalPosition())
|
self.reactor.callFromThread(self.setPosition, self._client.getGlobalPosition())
|
||||||
if self._paused != self._client.getGlobalPaused():
|
if self._paused != self._client.getGlobalPaused():
|
||||||
|
self._client.ui.showDebugMessage("onFileUpdate setting position to global paused: {}".format(self._client.getGlobalPaused()))
|
||||||
self.reactor.callFromThread(self._client.getGlobalPaused)
|
self.reactor.callFromThread(self._client.getGlobalPaused)
|
||||||
|
|
||||||
def _fileIsLoaded(self, ignoreDelay=False):
|
def _fileIsLoaded(self, ignoreDelay=False):
|
||||||
@ -503,12 +536,19 @@ class MpvPlayer(BasePlayer):
|
|||||||
self._filenameAsk.wait()
|
self._filenameAsk.wait()
|
||||||
self._pathAsk.wait()
|
self._pathAsk.wait()
|
||||||
|
|
||||||
|
def mpv_log_handler(self, level, prefix, text):
|
||||||
|
self.lineReceived(text)
|
||||||
|
|
||||||
class __Listener(threading.Thread):
|
class __Listener(threading.Thread):
|
||||||
def __init__(self, playerController, playerPath, filePath, args):
|
def __init__(self, playerController, playerPath, filePath, args):
|
||||||
|
self.mpv_running = True
|
||||||
self.sendQueue = []
|
self.sendQueue = []
|
||||||
self.readyToSend = True
|
self.readyToSend = True
|
||||||
self.lastSendTime = None
|
self.lastSendTime = None
|
||||||
self.lastNotReadyTime = None
|
self.lastNotReadyTime = None
|
||||||
|
self.mpvGUID = random.randrange(constants.VLC_MIN_PORT, constants.VLC_MAX_PORT) if (
|
||||||
|
constants.VLC_MIN_PORT < constants.VLC_MAX_PORT) else constants.VLC_MIN_PORT
|
||||||
|
self.socketName = "/tmp/syncplay-mpv-socket-{}".format(self.mpvGUID)
|
||||||
self.__playerController = playerController
|
self.__playerController = playerController
|
||||||
if not self.__playerController._client._config["chatOutputEnabled"]:
|
if not self.__playerController._client._config["chatOutputEnabled"]:
|
||||||
self.__playerController.alertOSDSupported = False
|
self.__playerController.alertOSDSupported = False
|
||||||
@ -527,7 +567,8 @@ class MpvPlayer(BasePlayer):
|
|||||||
filePath = None
|
filePath = None
|
||||||
else:
|
else:
|
||||||
call.extend([filePath])
|
call.extend([filePath])
|
||||||
call.extend(playerController.getStartupArgs(playerPath, args))
|
call.extend(playerController.getStartupArgs(playerPath, args, self.socketName))
|
||||||
|
|
||||||
# At least mpv may output escape sequences which result in syncplay
|
# At least mpv may output escape sequences which result in syncplay
|
||||||
# trying to parse something like
|
# trying to parse something like
|
||||||
# "\x1b[?1l\x1b>ANS_filename=blah.mkv". Work around this by
|
# "\x1b[?1l\x1b>ANS_filename=blah.mkv". Work around this by
|
||||||
@ -557,8 +598,11 @@ class MpvPlayer(BasePlayer):
|
|||||||
self.__process = subprocess.Popen(
|
self.__process = subprocess.Popen(
|
||||||
call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
|
call, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
|
||||||
env=env, bufsize=0)
|
env=env, bufsize=0)
|
||||||
|
self.mpvpipe = MPV(start_mpv=False, ipc_socket=self.socketName, log_handler=self.__playerController.mpv_log_handler, loglevel="info")
|
||||||
|
#self.mpvpipe.show_text("HELLO WORLD!", 1000)
|
||||||
threading.Thread.__init__(self, name="MPV Listener")
|
threading.Thread.__init__(self, name="MPV Listener")
|
||||||
|
|
||||||
|
|
||||||
def __getCwd(self, filePath, env):
|
def __getCwd(self, filePath, env):
|
||||||
if not filePath:
|
if not filePath:
|
||||||
return None
|
return None
|
||||||
@ -574,16 +618,13 @@ class MpvPlayer(BasePlayer):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
line = self.__process.stdout.readline()
|
line = self.__process.stdout.readline()
|
||||||
line = line.decode('utf-8')
|
|
||||||
line = line.rstrip("\r\n")
|
|
||||||
self.__playerController.lineReceived(line)
|
|
||||||
while self.__process.poll() is None:
|
while self.__process.poll() is None:
|
||||||
line = self.__process.stdout.readline()
|
line = self.__process.stdout.readline()
|
||||||
line = line.decode('utf-8')
|
self.mpvpipe.terminate()
|
||||||
line = line.rstrip("\r\n")
|
time.sleep(0.5)
|
||||||
self.__playerController.lineReceived(line)
|
|
||||||
self.__playerController.drop()
|
self.__playerController.drop()
|
||||||
|
|
||||||
|
|
||||||
def sendChat(self, message):
|
def sendChat(self, message):
|
||||||
if message:
|
if message:
|
||||||
if message[:1] == "/" and message != "/":
|
if message[:1] == "/" and message != "/":
|
||||||
@ -617,16 +658,16 @@ class MpvPlayer(BasePlayer):
|
|||||||
|
|
||||||
def sendLine(self, line, notReadyAfterThis=None):
|
def sendLine(self, line, notReadyAfterThis=None):
|
||||||
self.checkForReadinessOverride()
|
self.checkForReadinessOverride()
|
||||||
if self.readyToSend == False and "print_text ANS_pause" in line:
|
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Not ready to get status update, so skipping")
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
if self.sendQueue:
|
if self.sendQueue:
|
||||||
if constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
|
if constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
|
||||||
for command in constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
|
for command in constants.MPV_SUPERSEDE_IF_DUPLICATE_COMMANDS:
|
||||||
if line.startswith(command):
|
line_command = " ".join(line)
|
||||||
|
answer = line_command.startswith(command)
|
||||||
|
#self.__playerController._client.ui.showDebugMessage("Does line_command {} start with {}? {}".format(line_command, command, answer))
|
||||||
|
if line_command.startswith(command):
|
||||||
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
for itemID, deletionCandidate in enumerate(self.sendQueue):
|
||||||
if deletionCandidate.startswith(command):
|
if " ".join(deletionCandidate).startswith(command):
|
||||||
self.__playerController._client.ui.showDebugMessage(
|
self.__playerController._client.ui.showDebugMessage(
|
||||||
"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
"<mpv> Remove duplicate (supersede): {}".format(self.sendQueue[itemID]))
|
||||||
try:
|
try:
|
||||||
@ -647,8 +688,8 @@ class MpvPlayer(BasePlayer):
|
|||||||
"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
"<mpv> Remove duplicate (delete both): {}".format(self.sendQueue[itemID]))
|
||||||
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
self.__playerController._client.ui.showDebugMessage(self.sendQueue[itemID])
|
||||||
return
|
return
|
||||||
except:
|
except Exception as e:
|
||||||
self.__playerController._client.ui.showDebugMessage("<mpv> Problem removing duplicates, etc")
|
self.__playerController._client.ui.showDebugMessage("<mpv> Problem removing duplicates, etc: {}".format(e))
|
||||||
self.sendQueue.append(line)
|
self.sendQueue.append(line)
|
||||||
self.processSendQueue()
|
self.processSendQueue()
|
||||||
if notReadyAfterThis:
|
if notReadyAfterThis:
|
||||||
@ -671,11 +712,7 @@ class MpvPlayer(BasePlayer):
|
|||||||
|
|
||||||
def actuallySendLine(self, line):
|
def actuallySendLine(self, line):
|
||||||
try:
|
try:
|
||||||
# if not isinstance(line, str):
|
|
||||||
# line = line.decode('utf8')
|
|
||||||
line = line + "\n"
|
|
||||||
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
self.__playerController._client.ui.showDebugMessage("player >> {}".format(line))
|
||||||
line = line.encode('utf-8')
|
self.mpvpipe.command(*line)
|
||||||
self.__process.stdin.write(line)
|
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -341,6 +341,18 @@ mp.register_script_message('set_syncplayintf_options', function(e)
|
|||||||
set_syncplayintf_options(e)
|
set_syncplayintf_options(e)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
function state_paused_and_position()
|
||||||
|
-- bob
|
||||||
|
local pause_status = tostring(mp.get_property_native("pause"))
|
||||||
|
local position_status = tostring(mp.get_property_native("time-pos"))
|
||||||
|
mp.command('print-text "<paused>'..pause_status..'</paused><position>'..position_status..'</position>"')
|
||||||
|
-- mp.command('print-text "<paused>true</paused><position>7.6</position>"')
|
||||||
|
end
|
||||||
|
|
||||||
|
mp.register_script_message('get_paused_and_position', function()
|
||||||
|
state_paused_and_position()
|
||||||
|
end)
|
||||||
|
|
||||||
-- Default options
|
-- Default options
|
||||||
local utils = require 'mp.utils'
|
local utils = require 'mp.utils'
|
||||||
local options = require 'mp.options'
|
local options = require 'mp.options'
|
||||||
|
|||||||
@ -1,489 +1,463 @@
|
|||||||
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf600
|
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deftab529{\fonttbl{\f0\fswiss\fcharset0 Helvetica;}{\f1\fswiss\fcharset238 Helvetica;}}
|
||||||
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
|
{\colortbl ;\red0\green0\blue255;}
|
||||||
{\colortbl;\red255\green255\blue255;}
|
{\*\generator Riched20 10.0.18362}\viewkind4\uc1
|
||||||
{\*\expandedcolortbl;;}
|
\pard\tx529\f0\fs24\lang9 Syncplay relies on the following softwares, in compliance with their licenses. \par
|
||||||
\vieww13920\viewh8980\viewkind0
|
\par
|
||||||
\deftab529
|
\b Qt.py\b0\par
|
||||||
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0
|
\par
|
||||||
|
Copyright (c) 2016 Marcus Ottosson\par
|
||||||
\f0\fs24 \cf0 \CocoaLigature0 Syncplay relies on the following softwares, in compliance with their licenses. \
|
\par
|
||||||
\
|
Permission is hereby granted, free of charge, to any person obtaining a copy\par
|
||||||
|
of this software and associated documentation files (the "Software"), to deal\par
|
||||||
\b Qt.py
|
in the Software without restriction, including without limitation the rights\par
|
||||||
\b0 \
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\par
|
||||||
\
|
copies of the Software, and to permit persons to whom the Software is\par
|
||||||
Copyright (c) 2016 Marcus Ottosson\
|
furnished to do so, subject to the following conditions:\par
|
||||||
\
|
\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy\
|
The above copyright notice and this permission notice shall be included in all\par
|
||||||
of this software and associated documentation files (the "Software"), to deal\
|
copies or substantial portions of the Software.\par
|
||||||
in the Software without restriction, including without limitation the rights\
|
\par
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\
|
\b Qt for Python\par
|
||||||
copies of the Software, and to permit persons to whom the Software is\
|
\b0\par
|
||||||
furnished to do so, subject to the following conditions:\
|
Copyright (C) 2018 The Qt Company Ltd.\par
|
||||||
\
|
Contact: {{\field{\*\fldinst{HYPERLINK https://www.qt.io/licensing/ }}{\fldrslt{https://www.qt.io/licensing/\ul0\cf0}}}}\f0\fs24\par
|
||||||
The above copyright notice and this permission notice shall be included in all\
|
\par
|
||||||
copies or substantial portions of the Software.\
|
This program is free software: you can redistribute it and/or modify\par
|
||||||
\
|
it under the terms of the GNU Lesser General Public License as published\par
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or\par
|
||||||
\b Qt for Python\
|
(at your option) any later version.\par
|
||||||
|
\par
|
||||||
\b0 \
|
This program is distributed in the hope that it will be useful,\par
|
||||||
Copyright (C) 2018 The Qt Company Ltd.\
|
but WITHOUT ANY WARRANTY; without even the implied warranty of\par
|
||||||
Contact: https://www.qt.io/licensing/\
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\par
|
||||||
\
|
GNU Lesser General Public License for more details.\par
|
||||||
This program is free software: you can redistribute it and/or modify\
|
\par
|
||||||
it under the terms of the GNU Lesser General Public License as published\
|
You should have received a copy of the GNU Lesser General Public License\par
|
||||||
by the Free Software Foundation, either version 3 of the License, or\
|
along with this program. If not, see <{{\field{\*\fldinst{HYPERLINK "http://www.gnu.org/licenses/"}}{\fldrslt{http://www.gnu.org/licenses/\ul0\cf0}}}}\f0\fs24 >.\par
|
||||||
(at your option) any later version.\
|
\par
|
||||||
\
|
\b Qt\b0\par
|
||||||
This program is distributed in the hope that it will be useful,\
|
\par
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of\
|
This program uses Qt under the GNU LGPL version 3.\par
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\
|
\par
|
||||||
GNU Lesser General Public License for more details.\
|
Qt is a C++ toolkit for cross-platform application development.\par
|
||||||
\
|
\par
|
||||||
You should have received a copy of the GNU Lesser General Public License\
|
Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.\par
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.\
|
\par
|
||||||
\
|
Qt is available under three different licensing options designed to accommodate the needs of our various users.\par
|
||||||
|
\par
|
||||||
\b Qt
|
Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 3 or GNU LGPL version 2.1.\par
|
||||||
\b0 \
|
\par
|
||||||
\
|
Qt licensed under the GNU LGPL version 3 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 3.\par
|
||||||
This program uses Qt under the GNU LGPL version 3.\
|
\par
|
||||||
\
|
Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 2.1.\par
|
||||||
Qt is a C++ toolkit for cross-platform application development.\
|
\par
|
||||||
\
|
Please see qt.io/licensing for an overview of Qt licensing.\par
|
||||||
Qt provides single-source portability across all major desktop operating systems. It is also available for embedded Linux and other embedded and mobile operating systems.\
|
\par
|
||||||
\
|
Copyright (C) 2017 The Qt Company Ltd and other contributors.\par
|
||||||
Qt is available under three different licensing options designed to accommodate the needs of our various users.\
|
\par
|
||||||
\
|
Qt and the Qt logo are trademarks of The Qt Company Ltd.\par
|
||||||
Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 3 or GNU LGPL version 2.1.\
|
\par
|
||||||
\
|
Qt is The Qt Company Ltd product developed as an open source project. See qt.io for more information.\par
|
||||||
Qt licensed under the GNU LGPL version 3 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 3.\
|
\par
|
||||||
\
|
\b Twisted\par
|
||||||
Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications provided you can comply with the terms and conditions of the GNU LGPL version 2.1.\
|
\par
|
||||||
\
|
\b0 Copyright (c) 2001-2017\par
|
||||||
Please see qt.io/licensing for an overview of Qt licensing.\
|
Allen Short\par
|
||||||
\
|
Amber Hawkie Brown\par
|
||||||
Copyright (C) 2017 The Qt Company Ltd and other contributors.\
|
Andrew Bennetts\par
|
||||||
\
|
Andy Gayton\par
|
||||||
Qt and the Qt logo are trademarks of The Qt Company Ltd.\
|
Antoine Pitrou\par
|
||||||
\
|
Apple Computer, Inc.\par
|
||||||
Qt is The Qt Company Ltd product developed as an open source project. See qt.io for more information.\
|
Ashwini Oruganti\par
|
||||||
\
|
Benjamin Bruheim\par
|
||||||
|
Bob Ippolito\par
|
||||||
\b Twisted\
|
Canonical Limited\par
|
||||||
\
|
Christopher Armstrong\par
|
||||||
|
David Reid\par
|
||||||
\b0 Copyright (c) 2001-2017\
|
Divmod Inc.\par
|
||||||
Allen Short\
|
Donovan Preston\par
|
||||||
Amber Hawkie Brown\
|
Eric Mangold\par
|
||||||
Andrew Bennetts\
|
Eyal Lotem\par
|
||||||
Andy Gayton\
|
Google Inc.\par
|
||||||
Antoine Pitrou\
|
Hybrid Logic Ltd.\par
|
||||||
Apple Computer, Inc.\
|
Hynek Schlawack\par
|
||||||
Ashwini Oruganti\
|
Itamar Turner-Trauring\par
|
||||||
Benjamin Bruheim\
|
James Knight\par
|
||||||
Bob Ippolito\
|
Jason A. Mobarak\par
|
||||||
Canonical Limited\
|
Jean-Paul Calderone\par
|
||||||
Christopher Armstrong\
|
Jessica McKellar\par
|
||||||
David Reid\
|
Jonathan D. Simms\par
|
||||||
Divmod Inc.\
|
Jonathan Jacobs\par
|
||||||
Donovan Preston\
|
Jonathan Lange\par
|
||||||
Eric Mangold\
|
Julian Berman\par
|
||||||
Eyal Lotem\
|
J\'fcrgen Hermann\par
|
||||||
Google Inc.\
|
Kevin Horn\par
|
||||||
Hybrid Logic Ltd.\
|
Kevin Turner\par
|
||||||
Hynek Schlawack\
|
Laurens Van Houtven\par
|
||||||
Itamar Turner-Trauring\
|
Mary Gardiner\par
|
||||||
James Knight\
|
Massachusetts Institute of Technology\par
|
||||||
Jason A. Mobarak\
|
Matthew Lefkowitz\par
|
||||||
Jean-Paul Calderone\
|
Moshe Zadka\par
|
||||||
Jessica McKellar\
|
Paul Swartz\par
|
||||||
Jonathan D. Simms\
|
Pavel Pergamenshchik\par
|
||||||
Jonathan Jacobs\
|
Rackspace, US Inc.\par
|
||||||
Jonathan Lange\
|
Ralph Meijer\par
|
||||||
Julian Berman\
|
Richard Wall\par
|
||||||
J\'fcrgen Hermann\
|
Sean Riley\par
|
||||||
Kevin Horn\
|
Software Freedom Conservancy\par
|
||||||
Kevin Turner\
|
Tavendo GmbH\par
|
||||||
Laurens Van Houtven\
|
Thijs Triemstra\par
|
||||||
Mary Gardiner\
|
Thomas Herve\par
|
||||||
Massachusetts Institute of Technology\
|
Timothy Allen\par
|
||||||
Matthew Lefkowitz\
|
Tom Prince\par
|
||||||
Moshe Zadka\
|
Travis B. Hartwell\par
|
||||||
Paul Swartz\
|
\par
|
||||||
Pavel Pergamenshchik\
|
and others that have contributed code to the public domain.\par
|
||||||
Rackspace, US Inc.\
|
\par
|
||||||
Ralph Meijer\
|
Permission is hereby granted, free of charge, to any person obtaining\par
|
||||||
Richard Wall\
|
a copy of this software and associated documentation files (the\par
|
||||||
Sean Riley\
|
"Software"), to deal in the Software without restriction, including\par
|
||||||
Software Freedom Conservancy\
|
without limitation the rights to use, copy, modify, merge, publish,\par
|
||||||
Tavendo GmbH\
|
distribute, sublicense, and/or sell copies of the Software, and to\par
|
||||||
Thijs Triemstra\
|
permit persons to whom the Software is furnished to do so, subject to\par
|
||||||
Thomas Herve\
|
the following conditions:\par
|
||||||
Timothy Allen\
|
\par
|
||||||
Tom Prince\
|
The above copyright notice and this permission notice shall be\par
|
||||||
Travis B. Hartwell\
|
included in all copies or substantial portions of the Software.\par
|
||||||
\
|
\b\par
|
||||||
and others that have contributed code to the public domain.\
|
qt5reactor\par
|
||||||
\
|
\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining\
|
\b0 Copyright (c) 2001-2018\par
|
||||||
a copy of this software and associated documentation files (the\
|
Allen Short\par
|
||||||
"Software"), to deal in the Software without restriction, including\
|
Andy Gayton\par
|
||||||
without limitation the rights to use, copy, modify, merge, publish,\
|
Andrew Bennetts\par
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to\
|
Antoine Pitrou\par
|
||||||
permit persons to whom the Software is furnished to do so, subject to\
|
Apple Computer, Inc.\par
|
||||||
the following conditions:\
|
Ashwini Oruganti\par
|
||||||
\
|
bakbuk\par
|
||||||
The above copyright notice and this permission notice shall be\
|
Benjamin Bruheim\par
|
||||||
included in all copies or substantial portions of the Software.\
|
Bob Ippolito\par
|
||||||
|
Burak Nehbit\par
|
||||||
\b \
|
Canonical Limited\par
|
||||||
qt5reactor\
|
Christopher Armstrong\par
|
||||||
\
|
Christopher R. Wood\par
|
||||||
|
David Reid\par
|
||||||
\b0 Copyright (c) 2001-2018\
|
Donovan Preston\par
|
||||||
Allen Short\
|
Elvis Stansvik\par
|
||||||
Andy Gayton\
|
Eric Mangold\par
|
||||||
Andrew Bennetts\
|
Eyal Lotem\par
|
||||||
Antoine Pitrou\
|
Glenn Tarbox\par
|
||||||
Apple Computer, Inc.\
|
Google Inc.\par
|
||||||
Ashwini Oruganti\
|
Hybrid Logic Ltd.\par
|
||||||
bakbuk\
|
Hynek Schlawack\par
|
||||||
Benjamin Bruheim\
|
Itamar Turner-Trauring\par
|
||||||
Bob Ippolito\
|
James Knight\par
|
||||||
Burak Nehbit\
|
Jason A. Mobarak\par
|
||||||
Canonical Limited\
|
Jean-Paul Calderone\par
|
||||||
Christopher Armstrong\
|
Jessica McKellar\par
|
||||||
Christopher R. Wood\
|
Jonathan Jacobs\par
|
||||||
David Reid\
|
Jonathan Lange\par
|
||||||
Donovan Preston\
|
Jonathan D. Simms\par
|
||||||
Elvis Stansvik\
|
J\'fcrgen Hermann\par
|
||||||
Eric Mangold\
|
Julian Berman\par
|
||||||
Eyal Lotem\
|
Kevin Horn\par
|
||||||
Glenn Tarbox\
|
Kevin Turner\par
|
||||||
Google Inc.\
|
Kyle Altendorf\par
|
||||||
Hybrid Logic Ltd.\
|
Laurens Van Houtven\par
|
||||||
Hynek Schlawack\
|
Mary Gardiner\par
|
||||||
Itamar Turner-Trauring\
|
Matthew Lefkowitz\par
|
||||||
James Knight\
|
Massachusetts Institute of Technology\par
|
||||||
Jason A. Mobarak\
|
Moshe Zadka\par
|
||||||
Jean-Paul Calderone\
|
Paul Swartz\par
|
||||||
Jessica McKellar\
|
Pavel Pergamenshchik\par
|
||||||
Jonathan Jacobs\
|
Ralph Meijer\par
|
||||||
Jonathan Lange\
|
Richard Wall\par
|
||||||
Jonathan D. Simms\
|
Sean Riley\par
|
||||||
J\'fcrgen Hermann\
|
Software Freedom Conservancy\par
|
||||||
Julian Berman\
|
Tarashish Mishra\par
|
||||||
Kevin Horn\
|
Travis B. Hartwell\par
|
||||||
Kevin Turner\
|
Thijs Triemstra\par
|
||||||
Kyle Altendorf\
|
Thomas Herve\par
|
||||||
Laurens Van Houtven\
|
Timothy Allen\par
|
||||||
Mary Gardiner\
|
Tom Prince\par
|
||||||
Matthew Lefkowitz\
|
\par
|
||||||
Massachusetts Institute of Technology\
|
Permission is hereby granted, free of charge, to any person obtaining\par
|
||||||
Moshe Zadka\
|
a copy of this software and associated documentation files (the\par
|
||||||
Paul Swartz\
|
"Software"), to deal in the Software without restriction, including\par
|
||||||
Pavel Pergamenshchik\
|
without limitation the rights to use, copy, modify, merge, publish,\par
|
||||||
Ralph Meijer\
|
distribute, sublicense, and/or sell copies of the Software, and to\par
|
||||||
Richard Wall\
|
permit persons to whom the Software is furnished to do so, subject to\par
|
||||||
Sean Riley\
|
the following conditions:\par
|
||||||
Software Freedom Conservancy\
|
\par
|
||||||
Tarashish Mishra\
|
The above copyright notice and this permission notice shall be\par
|
||||||
Travis B. Hartwell\
|
included in all copies or substantial portions of the Software.\par
|
||||||
Thijs Triemstra\
|
\par
|
||||||
Thomas Herve\
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\par
|
||||||
Timothy Allen\
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\par
|
||||||
Tom Prince\
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\par
|
||||||
\
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining\
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\par
|
||||||
a copy of this software and associated documentation files (the\
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\par
|
||||||
"Software"), to deal in the Software without restriction, including\
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\b\par
|
||||||
without limitation the rights to use, copy, modify, merge, publish,\
|
\par
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to\
|
appnope\par
|
||||||
permit persons to whom the Software is furnished to do so, subject to\
|
\b0\par
|
||||||
the following conditions:\
|
Copyright (c) 2013, Min Ragan-Kelley\par
|
||||||
\
|
\par
|
||||||
The above copyright notice and this permission notice shall be\
|
All rights reserved.\par
|
||||||
included in all copies or substantial portions of the Software.\
|
\par
|
||||||
\
|
Redistribution and use in source and binary forms, with or without\par
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\
|
modification, are permitted provided that the following conditions are met:\par
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\
|
\par
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\
|
Redistributions of source code must retain the above copyright notice, this\par
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\
|
list of conditions and the following disclaimer.\par
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\
|
\par
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\par
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\par
|
||||||
\b \
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\par
|
||||||
\
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\par
|
||||||
appnope\
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\par
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\par
|
||||||
\b0 \
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\par
|
||||||
Copyright (c) 2013, Min Ragan-Kelley\
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\par
|
||||||
\
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\par
|
||||||
All rights reserved.\
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\par
|
||||||
\
|
\par
|
||||||
Redistribution and use in source and binary forms, with or without\
|
\b py2exe\par
|
||||||
modification, are permitted provided that the following conditions are met:\
|
\b0\par
|
||||||
\
|
Copyright (c) 2000-2013 Thomas Heller, Jimmy Retzlaff\par
|
||||||
Redistributions of source code must retain the above copyright notice, this\
|
\par
|
||||||
list of conditions and the following disclaimer.\
|
Permission is hereby granted, free of charge, to any person obtaining\par
|
||||||
\
|
a copy of this software and associated documentation files (the\par
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\
|
"Software"), to deal in the Software without restriction, including\par
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\
|
without limitation the rights to use, copy, modify, merge, publish,\par
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\
|
distribute, sublicense, and/or sell copies of the Software, and to\par
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\
|
permit persons to whom the Software is furnished to do so, subject to\par
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\
|
the following conditions:\par
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\
|
\par
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\
|
The above copyright notice and this permission notice shall be\par
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\
|
included in all copies or substantial portions of the Software.\par
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\
|
\par
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\
|
\b py2app\par
|
||||||
\
|
\par
|
||||||
|
\b0 Copyright (c) 2004 Bob Ippolito.\par
|
||||||
\b py2exe\
|
\par
|
||||||
|
Some parts copyright (c) 2010-2014 Ronald Oussoren\par
|
||||||
\b0 \
|
\par
|
||||||
Copyright (c) 2000-2013 Thomas Heller, Jimmy Retzlaff\
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\par
|
||||||
\
|
\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining\
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\par
|
||||||
a copy of this software and associated documentation files (the\
|
\par
|
||||||
"Software"), to deal in the Software without restriction, including\
|
\b dmgbuild\par
|
||||||
without limitation the rights to use, copy, modify, merge, publish,\
|
\par
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to\
|
\b0 Copyright (c) 2014 Alastair Houghton\par
|
||||||
permit persons to whom the Software is furnished to do so, subject to\
|
Copyright (c) 2017 The Qt Company Ltd.\par
|
||||||
the following conditions:\
|
\par
|
||||||
\
|
Permission is hereby granted, free of charge, to any person obtaining a copy\par
|
||||||
The above copyright notice and this permission notice shall be\
|
of this software and associated documentation files (the "Software"), to deal\par
|
||||||
included in all copies or substantial portions of the Software.\
|
in the Software without restriction, including without limitation the rights\par
|
||||||
\
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\par
|
||||||
|
copies of the Software, and to permit persons to whom the Software is\par
|
||||||
\b py2app\
|
furnished to do so, subject to the following conditions:\par
|
||||||
\
|
\par
|
||||||
|
The above copyright notice and this permission notice shall be included in\par
|
||||||
\b0 Copyright (c) 2004 Bob Ippolito.\
|
all copies or substantial portions of the Software.\par
|
||||||
\
|
\par
|
||||||
Some parts copyright (c) 2010-2014 Ronald Oussoren\
|
\b Requests\par
|
||||||
\
|
\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\
|
\b0 Copyright 2018 Kenneth Reitz\par
|
||||||
\
|
\par
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\
|
Licensed under the Apache License, Version 2.0 (the \ldblquote License\rdblquote ); you may not use this file\par
|
||||||
\
|
except in compliance with the License. You may obtain a copy of the License at\par
|
||||||
|
\par
|
||||||
\b dmgbuild\
|
{{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f0\fs24\par
|
||||||
\
|
\par
|
||||||
|
Unless required by applicable law or agreed to in writing, software distributed under the \par
|
||||||
\b0 Copyright (c) 2014 Alastair Houghton\
|
License is distributed on an \ldblquote AS IS\rdblquote BASIS, WITHOUT WARRANTIES OR CONDI-\par
|
||||||
Copyright (c) 2017 The Qt Company Ltd.\
|
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\par
|
||||||
\
|
uage governing permissions and limitations under the License.\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy\
|
\par
|
||||||
of this software and associated documentation files (the "Software"), to deal\
|
\b mpv-repl\b0\par
|
||||||
in the Software without restriction, including without limitation the rights\
|
\par
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\
|
Copyright 2016, James Ross-Gowan\par
|
||||||
copies of the Software, and to permit persons to whom the Software is\
|
\par
|
||||||
furnished to do so, subject to the following conditions:\
|
Permission to use, copy, modify, and/or distribute this software for any\par
|
||||||
\
|
purpose with or without fee is hereby granted, provided that the above\par
|
||||||
The above copyright notice and this permission notice shall be included in\
|
copyright notice and this permission notice appear in all copies.\par
|
||||||
all copies or substantial portions of the Software.\
|
\par
|
||||||
\
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\par
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\par
|
||||||
\b Requests\
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\par
|
||||||
\
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\par
|
||||||
|
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\par
|
||||||
\b0 Copyright 2018 Kenneth Reitz\
|
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\par
|
||||||
\
|
PERFORMANCE OF THIS SOFTWARE.\par
|
||||||
Licensed under the Apache License, Version 2.0 (the \'93License\'94); you may not use this file\
|
\par
|
||||||
except in compliance with the License. You may obtain a copy of the License at\
|
\b python-certifi\b0\par
|
||||||
\
|
\par
|
||||||
http://www.apache.org/licenses/LICENSE-2.0\
|
This Source Code Form is subject to the terms of the Mozilla Public License,\par
|
||||||
\
|
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain\par
|
||||||
Unless required by applicable law or agreed to in writing, software distributed under the \
|
one at {{\field{\*\fldinst{HYPERLINK http://mozilla.org/MPL/2.0/ }}{\fldrslt{http://mozilla.org/MPL/2.0/\ul0\cf0}}}}\f0\fs24 .\par
|
||||||
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
|
\par
|
||||||
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
|
\b cffi\b0\par
|
||||||
uage governing permissions and limitations under the License.\
|
\par
|
||||||
\
|
|
||||||
|
\pard This package has been mostly done by Armin Rigo with help from\par
|
||||||
\b mpv-repl
|
Maciej Fija\f1\'b3kowski. The idea is heavily based (although not directly\par
|
||||||
\b0 \
|
copied) from LuaJIT ffi by Mike Pall.\par
|
||||||
\
|
\par
|
||||||
Copyright 2016, James Ross-Gowan\
|
Other contributors:\par
|
||||||
\
|
\par
|
||||||
Permission to use, copy, modify, and/or distribute this software for any\
|
Google Inc.\par
|
||||||
purpose with or without fee is hereby granted, provided that the above\
|
|
||||||
copyright notice and this permission notice appear in all copies.\
|
\pard\tx529\par
|
||||||
\
|
The MIT License\par
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\
|
\par
|
||||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\
|
Permission is hereby granted, free of charge, to any person \par
|
||||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\
|
obtaining a copy of this software and associated documentation \par
|
||||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\
|
files (the "Software"), to deal in the Software without \par
|
||||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\
|
restriction, including without limitation the rights to use, \par
|
||||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\
|
copy, modify, merge, publish, distribute, sublicense, and/or \par
|
||||||
PERFORMANCE OF THIS SOFTWARE.\
|
sell copies of the Software, and to permit persons to whom the \par
|
||||||
\
|
Software is furnished to do so, subject to the following conditions:\par
|
||||||
|
\par
|
||||||
\b python-certifi
|
The above copyright notice and this permission notice shall be included \par
|
||||||
\b0 \
|
in all copies or substantial portions of the Software.\par
|
||||||
\
|
\par
|
||||||
This Source Code Form is subject to the terms of the Mozilla Public License,\
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS \par
|
||||||
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain\
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \par
|
||||||
one at http://mozilla.org/MPL/2.0/.\
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \par
|
||||||
\
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \par
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \par
|
||||||
\b cffi
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \par
|
||||||
\b0 \
|
DEALINGS IN THE SOFTWARE.\par
|
||||||
\
|
\par
|
||||||
\pard\pardeftab720\partightenfactor0
|
\b service-identity\b0\par
|
||||||
\cf0 This package has been mostly done by Armin Rigo with help from\
|
\par
|
||||||
Maciej Fija\uc0\u322 kowski. The idea is heavily based (although not directly\
|
Copyright (c) 2014 Hynek Schlawack\par
|
||||||
copied) from LuaJIT ffi by Mike Pall.\
|
\par
|
||||||
\
|
Permission is hereby granted, free of charge, to any person obtaining a copy of\par
|
||||||
Other contributors:\
|
this software and associated documentation files (the "Software"), to deal in\par
|
||||||
\
|
the Software without restriction, including without limitation the rights to\par
|
||||||
Google Inc.\
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\par
|
||||||
\pard\tx529\pardeftab529\pardirnatural\partightenfactor0
|
of the Software, and to permit persons to whom the Software is furnished to do\par
|
||||||
\cf0 \
|
so, subject to the following conditions:\par
|
||||||
The MIT License\
|
\par
|
||||||
\
|
The above copyright notice and this permission notice shall be included in all\par
|
||||||
Permission is hereby granted, free of charge, to any person \
|
copies or substantial portions of the Software.\par
|
||||||
obtaining a copy of this software and associated documentation \
|
\par
|
||||||
files (the "Software"), to deal in the Software without \
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\par
|
||||||
restriction, including without limitation the rights to use, \
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\par
|
||||||
copy, modify, merge, publish, distribute, sublicense, and/or \
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\par
|
||||||
sell copies of the Software, and to permit persons to whom the \
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\par
|
||||||
Software is furnished to do so, subject to the following conditions:\
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\par
|
||||||
\
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\par
|
||||||
The above copyright notice and this permission notice shall be included \
|
SOFTWARE.\par
|
||||||
in all copies or substantial portions of the Software.\
|
\par
|
||||||
\
|
\b pyopenssl\b0\par
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS \
|
\par
|
||||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \
|
Licensed under the Apache License, Version 2.0 (the \ldblquote License\rdblquote ); you may not use this file\par
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL \
|
except in compliance with the License. You may obtain a copy of the License at\par
|
||||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER \
|
\par
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING \
|
{{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f1\fs24\par
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \
|
\par
|
||||||
DEALINGS IN THE SOFTWARE.\
|
Unless required by applicable law or agreed to in writing, software distributed under the \par
|
||||||
\
|
License is distributed on an \ldblquote AS IS\rdblquote BASIS, WITHOUT WARRANTIES OR CONDI-\par
|
||||||
|
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\par
|
||||||
\b service-identity
|
uage governing permissions and limitations under the License.\par
|
||||||
\b0 \
|
\par
|
||||||
\
|
\b cryptography\b0\par
|
||||||
Copyright (c) 2014 Hynek Schlawack\
|
\par
|
||||||
\
|
Authors listed here: {{\field{\*\fldinst{HYPERLINK https://github.com/pyca/cryptography/blob/master/AUTHORS.rst }}{\fldrslt{https://github.com/pyca/cryptography/blob/master/AUTHORS.rst\ul0\cf0}}}}\f1\fs24\par
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of\
|
\par
|
||||||
this software and associated documentation files (the "Software"), to deal in\
|
Licensed under the Apache License, Version 2.0 (the \ldblquote License\rdblquote ); you may not use this file\par
|
||||||
the Software without restriction, including without limitation the rights to\
|
except in compliance with the License. You may obtain a copy of the License at\par
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\
|
\par
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do\
|
{{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f1\fs24\par
|
||||||
so, subject to the following conditions:\
|
\par
|
||||||
\
|
Unless required by applicable law or agreed to in writing, software distributed under the \par
|
||||||
The above copyright notice and this permission notice shall be included in all\
|
License is distributed on an \ldblquote AS IS\rdblquote BASIS, WITHOUT WARRANTIES OR CONDI-\par
|
||||||
copies or substantial portions of the Software.\
|
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\par
|
||||||
\
|
uage governing permissions and limitations under the License.\par
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
|
\par
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
|
\b Darkdetect\b0\par
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
|
\par
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
|
Copyright (c) 2019, Alberto Sottile\par
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\
|
All rights reserved.\par
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\
|
\par
|
||||||
SOFTWARE.\
|
Redistribution and use in source and binary forms, with or without\par
|
||||||
\
|
modification, are permitted provided that the following conditions are met:\par
|
||||||
|
* Redistributions of source code must retain the above copyright\par
|
||||||
\b pyopenssl
|
notice, this list of conditions and the following disclaimer.\par
|
||||||
\b0 \
|
* Redistributions in binary form must reproduce the above copyright\par
|
||||||
\
|
notice, this list of conditions and the following disclaimer in the\par
|
||||||
Licensed under the Apache License, Version 2.0 (the \'93License\'94); you may not use this file\
|
documentation and/or other materials provided with the distribution.\par
|
||||||
except in compliance with the License. You may obtain a copy of the License at\
|
* Neither the name of "darkdetect" nor the\par
|
||||||
\
|
names of its contributors may be used to endorse or promote products\par
|
||||||
http://www.apache.org/licenses/LICENSE-2.0\
|
derived from this software without specific prior written permission.\par
|
||||||
\
|
\par
|
||||||
Unless required by applicable law or agreed to in writing, software distributed under the \
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\par
|
||||||
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\par
|
||||||
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\par
|
||||||
uage governing permissions and limitations under the License.\
|
DISCLAIMED. IN NO EVENT SHALL "Alberto Sottile" BE LIABLE FOR ANY\par
|
||||||
\
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\par
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\par
|
||||||
\b cryptography
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\par
|
||||||
\b0 \
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\par
|
||||||
\
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\par
|
||||||
Authors listed here: https://github.com/pyca/cryptography/blob/master/AUTHORS.rst\
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\par
|
||||||
\
|
\par
|
||||||
Licensed under the Apache License, Version 2.0 (the \'93License\'94); you may not use this file\
|
\b Python MPV JSONIPC\par
|
||||||
except in compliance with the License. You may obtain a copy of the License at\
|
\b0\f0\lang2057 Authors listed here: {{\field{\*\fldinst{HYPERLINK https://github.com/iwalton3/python-mpv-jsonipc/ }}{\fldrslt{https://github.com/iwalton3/python-mpv-jsonipc/\ul0\cf0}}}}\f0\fs24 (principal developer Ian Walton / iwalton3)\b\f1\lang9\par
|
||||||
\
|
\par
|
||||||
http://www.apache.org/licenses/LICENSE-2.0\
|
\b0 Licensed under the Apache License, Version 2.0 (the \ldblquote License\rdblquote ); you may not use this file\par
|
||||||
\
|
except in compliance with the License. You may obtain a copy of the License at\par
|
||||||
Unless required by applicable law or agreed to in writing, software distributed under the \
|
\par
|
||||||
License is distributed on an \'93AS IS\'94 BASIS, WITHOUT WARRANTIES OR CONDI-\
|
{{\field{\*\fldinst{HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }}{\fldrslt{http://www.apache.org/licenses/LICENSE-2.0\ul0\cf0}}}}\f1\fs24\par
|
||||||
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\
|
\par
|
||||||
uage governing permissions and limitations under the License.\
|
Unless required by applicable law or agreed to in writing, software distributed under the \par
|
||||||
\
|
License is distributed on an \ldblquote AS IS\rdblquote BASIS, WITHOUT WARRANTIES OR CONDI-\par
|
||||||
|
TIONS OF ANY KIND, either express or implied. See the License for the specific lang-\par
|
||||||
\b Darkdetect
|
uage governing permissions and limitations under the License.\par
|
||||||
\b0 \
|
\b\par
|
||||||
\
|
\par
|
||||||
Copyright (c) 2019, Alberto Sottile\
|
Icons\par
|
||||||
All rights reserved.\
|
\par
|
||||||
\
|
\b0 Syncplay uses the following icons and images:\par
|
||||||
Redistribution and use in source and binary forms, with or without\
|
\par
|
||||||
modification, are permitted provided that the following conditions are met:\
|
- Silk icon set 1.3\par
|
||||||
* Redistributions of source code must retain the above copyright\
|
_________________________________________\par
|
||||||
notice, this list of conditions and the following disclaimer.\
|
Mark James\par
|
||||||
* Redistributions in binary form must reproduce the above copyright\
|
{{\field{\*\fldinst{HYPERLINK http://www.famfamfam.com/lab/icons/silk/ }}{\fldrslt{http://www.famfamfam.com/lab/icons/silk/\ul0\cf0}}}}\f1\fs24\par
|
||||||
notice, this list of conditions and the following disclaimer in the\
|
_________________________________________\par
|
||||||
documentation and/or other materials provided with the distribution.\
|
\par
|
||||||
* Neither the name of "darkdetect" nor the\
|
This work is licensed under a\par
|
||||||
names of its contributors may be used to endorse or promote products\
|
Creative Commons Attribution 2.5 License.\par
|
||||||
derived from this software without specific prior written permission.\
|
[ {{\field{\*\fldinst{HYPERLINK http://creativecommons.org/licenses/by/2.5/ }}{\fldrslt{http://creativecommons.org/licenses/by/2.5/\ul0\cf0}}}}\f1\fs24 ]\par
|
||||||
\
|
\par
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\
|
This means you may use it for any purpose,\par
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\
|
and make any changes you like.\par
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\
|
All I ask is that you include a link back\par
|
||||||
DISCLAIMED. IN NO EVENT SHALL "Alberto Sottile" BE LIABLE FOR ANY\
|
to this page in your credits.\par
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\
|
\par
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\
|
Are you using this icon set? Send me an email\par
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\
|
(including a link or picture if available) to\par
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\
|
mjames@gmail.com\par
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\
|
\par
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\
|
Any other questions about this icon set please\par
|
||||||
\
|
contact mjames@gmail.com\par
|
||||||
|
\par
|
||||||
\b Icons\
|
- Silk Companion 1\par
|
||||||
\
|
\par
|
||||||
|
|
||||||
\b0 Syncplay uses the following icons and images:\
|
\pard Copyright Damien Guard - CC-BY 3.0\par
|
||||||
\
|
{{\field{\*\fldinst{HYPERLINK https://damieng.com/creative/icons/silk-companion-1-icons }}{\fldrslt{https://damieng.com/creative/icons/silk-companion-1-icons\ul0\cf0}}}}\f1\fs24\par
|
||||||
- Silk icon set 1.3\
|
\par
|
||||||
_________________________________________\
|
- Padlock free icon\par
|
||||||
Mark James\
|
CC-BY 3.0\par
|
||||||
http://www.famfamfam.com/lab/icons/silk/\
|
Icon made by Maxim Basinski from {{\field{\*\fldinst{HYPERLINK https://www.flaticon.com/free-icon/padlock_291248 }}{\fldrslt{https://www.flaticon.com/free-icon/padlock_291248\ul0\cf0}}}}\f1\fs24\par
|
||||||
_________________________________________\
|
\par
|
||||||
\
|
|
||||||
This work is licensed under a\
|
\pard\tx529\par
|
||||||
Creative Commons Attribution 2.5 License.\
|
}
|
||||||
[ http://creativecommons.org/licenses/by/2.5/ ]\
|
| ||||||