Adding osd support

Refactorization of code
This commit is contained in:
Uriziel 2012-06-27 11:51:49 +02:00
parent 01ab30f8c6
commit e9e7e31de6
4 changed files with 399 additions and 230 deletions

View File

@ -34,7 +34,8 @@ class SyncClientProtocol(CommandProtocol):
@arg_count(1)
def handle_init_hello(self, args):
print 'Connected as', args[0]
message ='Connected as ' + args[0]
print message
self.manager.name = args[0]
self.change_state('connected')
self.send_list()
@ -47,9 +48,13 @@ class SyncClientProtocol(CommandProtocol):
else:
who, where, what = args[0], args[1], None
if what:
print '%s is present and is playing \'%s\' in the room: \'%s\'' % (who, what, where)
message = '%s is present and is playing \'%s\' in the room: \'%s\'' % (who, what, where)
print message
self.manager.player.display_message(message)
else:
print '%s is present in the room: \'%s\'' % (who, where)
message = '%s is present in the room: \'%s\'' % (who, where)
print message
self.manager.player.display_message(message)
@arg_count(4, 5)
def handle_connected_state(self, args):
@ -83,19 +88,27 @@ class SyncClientProtocol(CommandProtocol):
@arg_count(3)
def handle_connected_playing(self, args):
who, where, what = args
print '%s is playing \'%s\' in the room: \'%s\'' % (who, what, where)
message = '%s is playing \'%s\' in the room: \'%s\'' % (who, what, where)
print message
self.manager.player.display_message(message)
@arg_count(1)
def handle_connected_joined(self, args):
print '%s joined' % args[0]
message = '%s joined' % args[0]
print message
self.manager.player.display_message(message)
@arg_count(2)
def handle_connected_room(self, args):
print '%s entered the room: \'%s\'' % (args[0], args[1])
message = '%s entered the room: \'%s\'' % (args[0], args[1])
print message
self.manager.player.display_message(message)
@arg_count(1)
def handle_connected_left(self, args):
print '%s left' % args[0]
message = '%s left' % args[0]
print message
self.manager.player.display_message(message)
def send_list(self):
self.send_message('list')
@ -147,9 +160,17 @@ class SyncClientFactory(ClientFactory):
print 'Connection lost, reconnecting'
reactor.callLater(0.1, connector.connect)
else:
print 'Disconnected'
if(self.manager.player):
message = 'Disconnected'
print message
self.manager.player.display_message(message)
def clientConnectionFailed(self, connector, reason):
if(self.manager.player):
message = 'Disconnected'
print message
self.manager.player.display_message(message)
print 'Connection failed'
self.manager.stop()
@ -284,7 +305,10 @@ class Manager(object):
return
self.counter += 10
self.protocol.send_seek(self.counter, time.time(), self.player_position)
print self.name,'seeked to', format_time(self.player_position)
message = self.name +' seeked to ' + format_time(self.player_position)
print message
self.player.display_message(message)
def send_filename(self):
if self.protocol and self.player_filename:
@ -346,12 +370,18 @@ class Manager(object):
if old_paused != paused and self.global_paused != paused:
self.send_status(True)
if paused:
print '%s paused' % self.name
message = '%s paused' % self.name
print message
self.player.display_message(message)
if(diff > 0):
self.player.set_position(self.get_global_position())
self.ask_player()
else:
print '%s resumed' % self.name
message = '%s resumed' % self.name
print message
self.player.display_message(message)
if not (self.global_paused or self.seek_sent_wait):
if (0.4 if self.player_speed_fix else 0.6) <= diff <= 4:
@ -412,17 +442,26 @@ class Manager(object):
if abs(diff) > 4:
self.player.set_position(position)
#self.player.set_paused(True)
print "Rewinded due to time difference"
message = "Rewinded due to time difference"
print message
self.player.display_message(message)
if self.player_paused and not paused:
self.player_paused_at = None
self.player.set_paused(False)
if self.global_noted_pause_change != paused:
print '%s unpaused' % name
message = '%s unpaused' % name
print message
self.player.display_message(message)
elif paused and not self.player_paused:
self.player_paused_at = position
if self.global_noted_pause_change != paused:
print '%s paused' % name
message = '%s paused' % name
print message
self.player.display_message(message)
if diff < 0:
self.player.set_paused(True)
self.global_noted_pause_change = paused
@ -440,6 +479,9 @@ class Manager(object):
self.player_position_before_last_seek = self.player_position
self.player.set_position(position)
self.ask_player()
print who, 'seeked to', format_time(position)
message = who + ' seeked to ' + format_time(position)
print message
self.player.display_message(message)

View File

@ -1,118 +1,218 @@
#coding:utf8
import win32con, win32api, win32gui, ctypes, ctypes.wintypes
import sys, os, thread
import os, thread
class MPC_API:
def __init__(self):
self.listener = None
def __init__(self, enforce_custom_handler = False):
self.enforce_custom_handler = enforce_custom_handler
self.__listener = None
thread.start_new_thread(self.__Listener, (self,))
while(self.listener == None): continue
while(self.__listener == None): continue
self.__position_request_warden = False
self.__seek_warden = False
'''
List of callbacks that can be set
on_connected
on_seek
on_update_filename
on_update_file_duration
on_update_position
on_update_playstate
on_file_ready
custom_handler
'''
self.callbacks = self.__CALLBACKS()
self.loadstate = None
self.playstate = None
self.fileplaying = None
self.fileduration = None
'''
Most likely won't be up to date unless you ask API to refresh it
'''
self.lastfileposition = None
self.position_request_warden = False
self.seek_warden = False
self.callbacks = self.__CALLBACKS()
'''
This is called from another thread and if it could it would be a private method
Developers should not bother with it
'''
def register_listener(self, listener):
self.listener = listener
self.__listener = listener
'''
Given a path fo mpc-hc.exe and optional additional arguments in tuple
will start mpc-hc in a slave mode
'''
def start_mpc(self, path, args = ()):
is_starting = os.spawnl(os.P_NOWAIT, path, ' ' + ' '.join(args),'/slave %s ' % str(self.__listener.hwnd)) #can be switched with win32api.ShellExecute
while(self.__listener.mpc_handle == None and is_starting): continue
'''
Checks if api is ready to receive commands
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def is_api_ready(self):
self.__mpc_ready_in_slave_mode()
file_state_ok = self.loadstate == self.__MPC_LOADSTATE.MLS_CLOSED or self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED or self.loadstate == None
listener_ok = self.listener <> None and self.listener.mpc_handle <> None
listener_ok = self.__listener <> None and self.__listener.mpc_handle <> None
return (file_state_ok and listener_ok)
'''
Checks if file is loaded in player
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def is_file_ready(self):
self.__mpc_ready_in_slave_mode()
return (self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED and self.fileplaying and self.playstate <> None)
def start_mpc(self, path, args = ()):
is_starting = os.spawnl(os.P_NOWAIT, path, ' ' + ' '.join(args),' /open /new /slave %s ' % str(self.listener.hwnd)) #can be switched with win32api.ShellExecute
while(self.listener.mpc_handle == None and is_starting): continue
'''
Opens a file given in an argument in player
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def open_file(self, file_path):
self.__mpc_ready_in_slave_mode()
self.listener.SendCommand(self.__API_COMMANDS.CMD_OPENFILE, file_path)
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_OPENFILE, file_path)
'''
Is player paused (Stop is considered pause)
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def is_paused(self):
self.__mpc_ready_in_slave_mode()
return (self.playstate <> self.__MPC_PLAYSTATE.PS_PLAY and self.playstate <> None)
'''
Pause playing file
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def pause(self):
self.__mpc_ready_in_slave_mode()
if(not self.is_paused()):
self.listener.SendCommand(self.__API_COMMANDS.CMD_PLAYPAUSE)
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_PLAYPAUSE)
while(not self.is_paused()): self.__mpc_ready_in_slave_mode()
'''
Play paused file
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def unpause(self):
self.__mpc_ready_in_slave_mode()
if(self.is_paused()):
self.listener.SendCommand(self.__API_COMMANDS.CMD_PLAYPAUSE)
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_PLAYPAUSE)
while(self.is_paused()): self.__mpc_ready_in_slave_mode()
'''
Toggle play/pause
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def playpause(self):
self.__mpc_ready_in_slave_mode()
tmp = self.playstate
self.listener.SendCommand(self.__API_COMMANDS.CMD_PLAYPAUSE)
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_PLAYPAUSE)
while(tmp == self.playstate): self.__mpc_ready_in_slave_mode()
'''
Asks mpc for it's current file position, if on_update_position callback is set
developers should rather rely on that rather than on a return value
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def ask_for_current_position(self):
self.__mpc_ready_in_slave_mode()
if(not self.position_request_warden):
self.position_request_warden = True
self.listener.SendCommand(self.__API_COMMANDS.CMD_GETCURRENTPOSITION)
while(self.position_request_warden and not self.callbacks.on_update_position): self.__mpc_ready_in_slave_mode()
if(not self.__position_request_warden):
self.__position_request_warden = True
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_GETCURRENTPOSITION)
while(self.__position_request_warden and not self.callbacks.on_update_position): self.__mpc_ready_in_slave_mode()
return self.lastfileposition
'''
Given a position in seconds will ask client to seek there
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def seek(self, position):
self.__mpc_ready_in_slave_mode()
self.seek_warden = True
self.listener.SendCommand(self.__API_COMMANDS.CMD_SETPOSITION, unicode(position))
while(self.seek_warden):
continue
def __mpc_ready_in_slave_mode(self):
if not win32gui.IsWindow(self.listener.mpc_handle):
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
def handle_command(self,cmd, value):
#print '>>>'+hex(cmd).upper(), value
if (cmd == self.__API_COMMANDS.CMD_CONNECT):
self.listener.mpc_handle = int(value)
if(self.callbacks.on_connected):
self.callbacks.on_connected()
elif(cmd == self.__API_COMMANDS.CMD_STATE):
self.loadstate = int(value)
elif(cmd == self.__API_COMMANDS.CMD_PLAYMODE):
self.playstate = int(value)
if(self.callbacks.on_update_playstate): self.callbacks.on_update_playstate(self.playstate)
elif(cmd == self.__API_COMMANDS.CMD_NOWPLAYING):
if(self.callbacks.on_file_ready): self.callbacks.on_file_ready()
self.fileplaying = value.split('|')[3].split('\\').pop()
if(self.callbacks.on_update_filename): self.callbacks.on_update_filename(self.fileplaying)
self.fileduration = int(value.split('|')[4])
if(self.callbacks.on_update_file_duration): self.callbacks.on_update_file_duration(self.fileplaying)
elif(cmd == self.__API_COMMANDS.CMD_CURRENTPOSITION):
self.lastfileposition = float(value)
self.position_request_warden = False
if(self.callbacks.on_update_position): self.callbacks.on_update_position(self.lastfileposition)
elif(cmd == self.__API_COMMANDS.CMD_NOTIFYSEEK):
self.seek_warden = False
if(self.lastfileposition <> float(value)): #Notify seek is sometimes sent twice
self.lastfileposition = float(value)
if(self.callbacks.on_seek): self.callbacks.on_seek(self.lastfileposition)
self.__seek_warden = True
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_SETPOSITION, unicode(position))
while(self.__seek_warden): continue
'''
@param message: unicode string to display in player
@param MsgPos: Either 1, left top corner or 2, right top corner, defaults to 2
@param DurationMs: Duration of osd display, defaults to 3000
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def send_osd(self, message, MsgPos = 2, DurationMs = 3000):
self.__mpc_ready_in_slave_mode()
class __OSDDATASTRUCT(ctypes.Structure):
_fields_ = [
('nMsgPos', ctypes.c_int32),
('nDurationMS', ctypes.c_int32),
('strMsg', ctypes.c_wchar * (len(message)+1))
]
cmessage = __OSDDATASTRUCT()
cmessage.nMsgPos = MsgPos
cmessage.nDurationMS = DurationMs
cmessage.strMsg = message
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_OSDSHOWMESSAGE, cmessage)
'''
Send raw cmd and value to mpc
Commands are available in MPC_API_COMMANDS class
Value has to be either ctype.Structure or unicode string
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
'''
def send_raw_command(self, cmd, value):
self.__mpc_ready_in_slave_mode()
self.__listener.SendCommand(cmd, value)
'''
Callback function to intercept commands sent by MPC
Handles only a handful of them
If callbacks.custom_handler is provided all not recognized commands will be redirected to it
If enforce_custom_handler is set it will redirect all the commands to it
'''
def handle_command(self,cmd, value, enforce_custom_handler = False):
if((self.enforce_custom_handler or enforce_custom_handler) and self.callbacks.custom_handler <> None):
self.callbacks.custom_handler((cmd, value,))
else:
pass
if (cmd == MPC_API_COMMANDS.CMD_CONNECT):
self.__listener.mpc_handle = int(value)
if(self.callbacks.on_connected):
self.callbacks.on_connected(())
elif(cmd == MPC_API_COMMANDS.CMD_STATE):
self.loadstate = int(value)
elif(cmd == MPC_API_COMMANDS.CMD_PLAYMODE):
self.playstate = int(value)
if(self.callbacks.on_update_playstate): self.callbacks.on_update_playstate((self.playstate,))
elif(cmd == MPC_API_COMMANDS.CMD_NOWPLAYING):
if(self.callbacks.on_file_ready): self.callbacks.on_file_ready()
self.fileplaying = value.split('|')[3].split('\\').pop()
if(self.callbacks.on_update_filename): self.callbacks.on_update_filename((self.fileplaying,))
self.fileduration = int(value.split('|')[4])
if(self.callbacks.on_update_file_duration): self.callbacks.on_update_file_duration((self.fileplaying,))
elif(cmd == MPC_API_COMMANDS.CMD_CURRENTPOSITION):
self.lastfileposition = float(value)
self.__position_request_warden = False
if(self.callbacks.on_update_position): self.callbacks.on_update_position((self.lastfileposition,))
elif(cmd == MPC_API_COMMANDS.CMD_NOTIFYSEEK):
self.__seek_warden = False
if(self.lastfileposition <> float(value)): #Notify seek is sometimes sent twice
self.lastfileposition = float(value)
if(self.callbacks.on_seek): self.callbacks.on_seek((self.lastfileposition,))
else:
if(self.callbacks.custom_handler <> None):
self.callbacks.custom_handler((cmd, value,))
class NoSlaveDetectedException(Exception):
def __init__(self, message):
Exception.__init__(self, message)
class __CALLBACKS:
def __init__(self):
self.on_connected = None
@ -122,7 +222,13 @@ class MPC_API:
self.on_update_position = None
self.on_update_playstate = None
self.on_file_ready = None
self.custom_handler = None
def __mpc_ready_in_slave_mode(self):
if not win32gui.IsWindow(self.__listener.mpc_handle):
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
class __MPC_LOADSTATE:
MLS_CLOSED = 0
MLS_LOADING = 1
@ -136,158 +242,16 @@ class MPC_API:
PS_UNUSED = 3
'''
class MPC_OSDDATA():
_fields_ = [
('nMsgPos'),
('nDurationMS'),
('strMsg')
]
class __OSD_MESSAGEPOS:
OSD_NOMESSAGE = 0
OSD_TOPLEFT = 1
OSD_TOPRIGHT = 2
'''
class __API_COMMANDS():
# Send after connection
# Par 1 : MPC window handle (command should be send to this HWnd)
CMD_CONNECT = 0x50000000
# Send when opening or closing file
# Par 1 : current state (see MPC_LOADSTATE enum)
CMD_STATE = 0x50000001
# Send when playing, pausing or closing file
# Par 1 : current play mode (see MPC_PLAYSTATE enum)
CMD_PLAYMODE = 0x50000002
# Send after opening a new file
# Par 1 : title
# Par 2 : author
# Par 3 : description
# Par 4 : complete filename (path included)
# Par 5 : duration in seconds
CMD_NOWPLAYING = 0x50000003
# List of subtitle tracks
# Par 1 : Subtitle track name 0
# Par 2 : Subtitle track name 1
# ...
# Par n : Active subtitle track, -1 if subtitles disabled
#
# if no subtitle track present, returns -1
# if no file loaded, returns -2
CMD_LISTSUBTITLETRACKS = 0x50000004
# List of audio tracks
# Par 1 : Audio track name 0
# Par 2 : Audio track name 1
# ...
# Par n : Active audio track
#
# if no audio track present, returns -1
# if no file loaded, returns -2
CMD_LISTAUDIOTRACKS = 0x50000005
# Send current playback position in responce
# of CMD_GETCURRENTPOSITION.
# Par 1 : current position in seconds
CMD_CURRENTPOSITION = 0x50000007
# Send the current playback position after a jump.
# (Automatically sent after a seek event).
# Par 1 : new playback position (in seconds).
CMD_NOTIFYSEEK = 0x50000008
# Notify the end of current playback
# (Automatically sent).
# Par 1 : none.
CMD_NOTIFYENDOFSTREAM = 0x50000009
# List of files in the playlist
# Par 1 : file path 0
# Par 2 : file path 1
# ...
# Par n : active file, -1 if no active file
CMD_PLAYLIST = 0x50000006
# ==== Commands from host to MPC
# Open new file
# Par 1 : file path
CMD_OPENFILE = 0xA0000000
# Stop playback, but keep file / playlist
CMD_STOP = 0xA0000001
# Stop playback and close file / playlist
CMD_CLOSEFILE = 0xA0000002
# Pause or restart playback
CMD_PLAYPAUSE = 0xA0000003
# Add a new file to playlist (did not start playing)
# Par 1 : file path
CMD_ADDTOPLAYLIST = 0xA0001000
# Remove all files from playlist
CMD_CLEARPLAYLIST = 0xA0001001
# Start playing playlist
CMD_STARTPLAYLIST = 0xA0001002
CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO
# Cue current file to specific position
# Par 1 : new position in seconds
CMD_SETPOSITION = 0xA0002000
# Set the audio delay
# Par 1 : new audio delay in ms
CMD_SETAUDIODELAY = 0xA0002001
# Set the subtitle delay
# Par 1 : new subtitle delay in ms
CMD_SETSUBTITLEDELAY = 0xA0002002
# Set the active file in the playlist
# Par 1 : index of the active file, -1 for no file selected
# DOESNT WORK
CMD_SETINDEXPLAYLIST = 0xA0002003
# Set the audio track
# Par 1 : index of the audio track
CMD_SETAUDIOTRACK = 0xA0002004
# Set the subtitle track
# Par 1 : index of the subtitle track, -1 for disabling subtitles
CMD_SETSUBTITLETRACK = 0xA0002005
# Ask for a list of the subtitles tracks of the file
# return a CMD_LISTSUBTITLETRACKS
CMD_GETSUBTITLETRACKS = 0xA0003000
# Ask for the current playback position,
# see CMD_CURRENTPOSITION.
# Par 1 : current position in seconds
CMD_GETCURRENTPOSITION = 0xA0003004
# Jump forward/backward of N seconds,
# Par 1 : seconds (negative values for backward)
CMD_JUMPOFNSECONDS = 0xA0003005
# Ask for a list of the audio tracks of the file
# return a CMD_LISTAUDIOTRACKS
CMD_GETAUDIOTRACKS = 0xA0003001
# Ask for the properties of the current loaded file
# return a CMD_NOWPLAYING
CMD_GETNOWPLAYING = 0xA0003002
# Ask for the current playlist
# return a CMD_PLAYLIST
CMD_GETPLAYLIST = 0xA0003003
# Toggle FullScreen
CMD_TOGGLEFULLSCREEN = 0xA0004000
# Jump forward(medium)
CMD_JUMPFORWARDMED = 0xA0004001
# Jump backward(medium)
CMD_JUMPBACKWARDMED = 0xA0004002
# Increase Volume
CMD_INCREASEVOLUME = 0xA0004003
# Decrease volume
CMD_DECREASEVOLUME = 0xA0004004
# Shader toggle
CMD_SHADER_TOGGLE = 0xA0004005
# Close App
CMD_CLOSEAPP = 0xA0004006
# show host defined OSD message string
CMD_OSDSHOWMESSAGE = 0xA0005000
class __Listener:
def SendCommand(self, cmd, message = ''):
#print "<<<" + (hex(cmd).upper()), str(message)
if not win32gui.IsWindow(self.mpc_handle):
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
cs = self.__COPYDATASTRUCT()
cs.dwData = cmd;
cs.lpData = ctypes.cast(ctypes.c_wchar_p(message), ctypes.c_void_p)
utf_size_multiplier = 2 if sys.maxunicode < 65536 else 4
cs.cbData = utf_size_multiplier*len(message)+1
ptr= ctypes.addressof(cs)
win32api.SendMessage(self.mpc_handle, win32con.WM_COPYDATA, self.hwnd, ptr)
class __COPYDATASTRUCT(ctypes.Structure):
_fields_ = [
('dwData', ctypes.wintypes.LPARAM),
('cbData', ctypes.wintypes.DWORD),
('lpData', ctypes.c_void_p)
]
def __init__(self, mpc_api):
self.mpc_handle = None
message_map = {
win32con.WM_COPYDATA: self.OnCopyData
}
@ -310,11 +274,165 @@ class MPC_API:
None
)
self.__PCOPYDATASTRUCT = ctypes.POINTER(self.__COPYDATASTRUCT)
self.mpc_api = mpc_api
self.mpc_handle = None
self.__mpc_api = mpc_api
mpc_api.register_listener(self)
win32gui.PumpMessages()
def OnCopyData(self, hwnd, msg, wparam, lparam):
pCDS = ctypes.cast(lparam, self.__PCOPYDATASTRUCT)
self.mpc_api.handle_command(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
self.__mpc_api.handle_command(pCDS.contents.dwData, ctypes.wstring_at(pCDS.contents.lpData))
def SendCommand(self, cmd, message = u''):
if not win32gui.IsWindow(self.mpc_handle):
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
cs = self.__COPYDATASTRUCT()
cs.dwData = cmd;
if(isinstance(message, (unicode, str))):
message = ctypes.create_unicode_buffer(message, len(message)+1)
elif(isinstance(message, ctypes.Structure)):
pass
else:
raise TypeError
cs.lpData = ctypes.addressof(message)
cs.cbData = ctypes.sizeof(message)
ptr= ctypes.addressof(cs)
win32api.SendMessage(self.mpc_handle, win32con.WM_COPYDATA, self.hwnd, ptr)
class __COPYDATASTRUCT(ctypes.Structure):
_fields_ = [
('dwData', ctypes.wintypes.LPARAM),
('cbData', ctypes.wintypes.DWORD),
('lpData', ctypes.c_void_p)
]
class MPC_API_COMMANDS():
# Send after connection
# Par 1 : MPC window handle (command should be send to this HWnd)
CMD_CONNECT = 0x50000000
# Send when opening or closing file
# Par 1 : current state (see MPC_LOADSTATE enum)
CMD_STATE = 0x50000001
# Send when playing, pausing or closing file
# Par 1 : current play mode (see MPC_PLAYSTATE enum)
CMD_PLAYMODE = 0x50000002
# Send after opening a new file
# Par 1 : title
# Par 2 : author
# Par 3 : description
# Par 4 : complete filename (path included)
# Par 5 : duration in seconds
CMD_NOWPLAYING = 0x50000003
# List of subtitle tracks
# Par 1 : Subtitle track name 0
# Par 2 : Subtitle track name 1
# ...
# Par n : Active subtitle track, -1 if subtitles disabled
#
# if no subtitle track present, returns -1
# if no file loaded, returns -2
CMD_LISTSUBTITLETRACKS = 0x50000004
# List of audio tracks
# Par 1 : Audio track name 0
# Par 2 : Audio track name 1
# ...
# Par n : Active audio track
#
# if no audio track present, returns -1
# if no file loaded, returns -2
CMD_LISTAUDIOTRACKS = 0x50000005
# Send current playback position in responce
# of CMD_GETCURRENTPOSITION.
# Par 1 : current position in seconds
CMD_CURRENTPOSITION = 0x50000007
# Send the current playback position after a jump.
# (Automatically sent after a seek event).
# Par 1 : new playback position (in seconds).
CMD_NOTIFYSEEK = 0x50000008
# Notify the end of current playback
# (Automatically sent).
# Par 1 : none.
CMD_NOTIFYENDOFSTREAM = 0x50000009
# List of files in the playlist
# Par 1 : file path 0
# Par 2 : file path 1
# ...
# Par n : active file, -1 if no active file
CMD_PLAYLIST = 0x50000006
# ==== Commands from host to MPC
# Open new file
# Par 1 : file path
CMD_OPENFILE = 0xA0000000
# Stop playback, but keep file / playlist
CMD_STOP = 0xA0000001
# Stop playback and close file / playlist
CMD_CLOSEFILE = 0xA0000002
# Pause or restart playback
CMD_PLAYPAUSE = 0xA0000003
# Add a new file to playlist (did not start playing)
# Par 1 : file path
CMD_ADDTOPLAYLIST = 0xA0001000
# Remove all files from playlist
CMD_CLEARPLAYLIST = 0xA0001001
# Start playing playlist
CMD_STARTPLAYLIST = 0xA0001002
CMD_REMOVEFROMPLAYLIST = 0xA0001003 # TODO
# Cue current file to specific position
# Par 1 : new position in seconds
CMD_SETPOSITION = 0xA0002000
# Set the audio delay
# Par 1 : new audio delay in ms
CMD_SETAUDIODELAY = 0xA0002001
# Set the subtitle delay
# Par 1 : new subtitle delay in ms
CMD_SETSUBTITLEDELAY = 0xA0002002
# Set the active file in the playlist
# Par 1 : index of the active file, -1 for no file selected
# DOESNT WORK
CMD_SETINDEXPLAYLIST = 0xA0002003
# Set the audio track
# Par 1 : index of the audio track
CMD_SETAUDIOTRACK = 0xA0002004
# Set the subtitle track
# Par 1 : index of the subtitle track, -1 for disabling subtitles
CMD_SETSUBTITLETRACK = 0xA0002005
# Ask for a list of the subtitles tracks of the file
# return a CMD_LISTSUBTITLETRACKS
CMD_GETSUBTITLETRACKS = 0xA0003000
# Ask for the current playback position,
# see CMD_CURRENTPOSITION.
# Par 1 : current position in seconds
CMD_GETCURRENTPOSITION = 0xA0003004
# Jump forward/backward of N seconds,
# Par 1 : seconds (negative values for backward)
CMD_JUMPOFNSECONDS = 0xA0003005
# Ask for a list of the audio tracks of the file
# return a CMD_LISTAUDIOTRACKS
CMD_GETAUDIOTRACKS = 0xA0003001
# Ask for the properties of the current loaded file
# return a CMD_NOWPLAYING
CMD_GETNOWPLAYING = 0xA0003002
# Ask for the current playlist
# return a CMD_PLAYLIST
CMD_GETPLAYLIST = 0xA0003003
# Toggle FullScreen
CMD_TOGGLEFULLSCREEN = 0xA0004000
# Jump forward(medium)
CMD_JUMPFORWARDMED = 0xA0004001
# Jump backward(medium)
CMD_JUMPBACKWARDMED = 0xA0004002
# Increase Volume
CMD_INCREASEVOLUME = 0xA0004003
# Decrease volume
CMD_DECREASEVOLUME = 0xA0004004
# Shader toggle
CMD_SHADER_TOGGLE = 0xA0004005
# Close App
CMD_CLOSEAPP = 0xA0004006
# show host defined OSD message string
CMD_OSDSHOWMESSAGE = 0xA0005000

View File

@ -82,6 +82,9 @@ class MPCHCPlayer(object):
def set_speed(self, value):
pass
def display_message(self, message):
pass
def make_ping(self):
self.ask_for_status()

View File

@ -19,6 +19,12 @@ class MPCHCAPIPlayer(object):
def make_ping(self):
self.ask_for_status()
def display_message(self, message):
try:
self.mpc_api.send_osd(message)
except:
self.mpc_error()
def set_paused(self, value):
try:
if value:
@ -66,6 +72,6 @@ class MPCHCAPIPlayer(object):
def run_mpc(manager, mpc_path, file_path, args):
mpc = MPCHCAPIPlayer(manager)
mpc.mpc_api.callbacks.on_file_ready = mpc.make_ping
mpc.mpc_api.callbacks.on_connected = lambda: mpc.mpc_api.open_file(file_path) if(file_path) else None
mpc.mpc_api.callbacks.on_connected = lambda _: mpc.mpc_api.open_file(file_path) if(file_path) else None
mpc.mpc_api.start_mpc(mpc_path, args)