Adding osd support
Refactorization of code
This commit is contained in:
parent
01ab30f8c6
commit
e9e7e31de6
@ -34,7 +34,8 @@ class SyncClientProtocol(CommandProtocol):
|
|||||||
|
|
||||||
@arg_count(1)
|
@arg_count(1)
|
||||||
def handle_init_hello(self, args):
|
def handle_init_hello(self, args):
|
||||||
print 'Connected as', args[0]
|
message ='Connected as ' + args[0]
|
||||||
|
print message
|
||||||
self.manager.name = args[0]
|
self.manager.name = args[0]
|
||||||
self.change_state('connected')
|
self.change_state('connected')
|
||||||
self.send_list()
|
self.send_list()
|
||||||
@ -47,9 +48,13 @@ class SyncClientProtocol(CommandProtocol):
|
|||||||
else:
|
else:
|
||||||
who, where, what = args[0], args[1], None
|
who, where, what = args[0], args[1], None
|
||||||
if what:
|
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:
|
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)
|
@arg_count(4, 5)
|
||||||
def handle_connected_state(self, args):
|
def handle_connected_state(self, args):
|
||||||
@ -83,19 +88,27 @@ class SyncClientProtocol(CommandProtocol):
|
|||||||
@arg_count(3)
|
@arg_count(3)
|
||||||
def handle_connected_playing(self, args):
|
def handle_connected_playing(self, args):
|
||||||
who, where, what = 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)
|
@arg_count(1)
|
||||||
def handle_connected_joined(self, args):
|
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)
|
@arg_count(2)
|
||||||
def handle_connected_room(self, args):
|
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)
|
@arg_count(1)
|
||||||
def handle_connected_left(self, args):
|
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):
|
def send_list(self):
|
||||||
self.send_message('list')
|
self.send_message('list')
|
||||||
@ -147,9 +160,17 @@ class SyncClientFactory(ClientFactory):
|
|||||||
print 'Connection lost, reconnecting'
|
print 'Connection lost, reconnecting'
|
||||||
reactor.callLater(0.1, connector.connect)
|
reactor.callLater(0.1, connector.connect)
|
||||||
else:
|
else:
|
||||||
print 'Disconnected'
|
if(self.manager.player):
|
||||||
|
message = 'Disconnected'
|
||||||
|
print message
|
||||||
|
self.manager.player.display_message(message)
|
||||||
|
|
||||||
def clientConnectionFailed(self, connector, reason):
|
def clientConnectionFailed(self, connector, reason):
|
||||||
|
if(self.manager.player):
|
||||||
|
message = 'Disconnected'
|
||||||
|
print message
|
||||||
|
self.manager.player.display_message(message)
|
||||||
|
|
||||||
print 'Connection failed'
|
print 'Connection failed'
|
||||||
self.manager.stop()
|
self.manager.stop()
|
||||||
|
|
||||||
@ -284,7 +305,10 @@ class Manager(object):
|
|||||||
return
|
return
|
||||||
self.counter += 10
|
self.counter += 10
|
||||||
self.protocol.send_seek(self.counter, time.time(), self.player_position)
|
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):
|
def send_filename(self):
|
||||||
if self.protocol and self.player_filename:
|
if self.protocol and self.player_filename:
|
||||||
@ -346,12 +370,18 @@ class Manager(object):
|
|||||||
if old_paused != paused and self.global_paused != paused:
|
if old_paused != paused and self.global_paused != paused:
|
||||||
self.send_status(True)
|
self.send_status(True)
|
||||||
if paused:
|
if paused:
|
||||||
print '%s paused' % self.name
|
message = '%s paused' % self.name
|
||||||
|
print message
|
||||||
|
self.player.display_message(message)
|
||||||
|
|
||||||
if(diff > 0):
|
if(diff > 0):
|
||||||
self.player.set_position(self.get_global_position())
|
self.player.set_position(self.get_global_position())
|
||||||
self.ask_player()
|
self.ask_player()
|
||||||
else:
|
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 not (self.global_paused or self.seek_sent_wait):
|
||||||
if (0.4 if self.player_speed_fix else 0.6) <= diff <= 4:
|
if (0.4 if self.player_speed_fix else 0.6) <= diff <= 4:
|
||||||
@ -412,17 +442,26 @@ class Manager(object):
|
|||||||
if abs(diff) > 4:
|
if abs(diff) > 4:
|
||||||
self.player.set_position(position)
|
self.player.set_position(position)
|
||||||
#self.player.set_paused(True)
|
#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:
|
if self.player_paused and not paused:
|
||||||
self.player_paused_at = None
|
self.player_paused_at = None
|
||||||
self.player.set_paused(False)
|
self.player.set_paused(False)
|
||||||
if self.global_noted_pause_change != paused:
|
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:
|
elif paused and not self.player_paused:
|
||||||
self.player_paused_at = position
|
self.player_paused_at = position
|
||||||
if self.global_noted_pause_change != paused:
|
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:
|
if diff < 0:
|
||||||
self.player.set_paused(True)
|
self.player.set_paused(True)
|
||||||
self.global_noted_pause_change = paused
|
self.global_noted_pause_change = paused
|
||||||
@ -440,6 +479,9 @@ class Manager(object):
|
|||||||
self.player_position_before_last_seek = self.player_position
|
self.player_position_before_last_seek = self.player_position
|
||||||
self.player.set_position(position)
|
self.player.set_position(position)
|
||||||
self.ask_player()
|
self.ask_player()
|
||||||
print who, 'seeked to', format_time(position)
|
message = who + ' seeked to ' + format_time(position)
|
||||||
|
print message
|
||||||
|
self.player.display_message(message)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,113 +1,213 @@
|
|||||||
#coding:utf8
|
#coding:utf8
|
||||||
|
|
||||||
import win32con, win32api, win32gui, ctypes, ctypes.wintypes
|
import win32con, win32api, win32gui, ctypes, ctypes.wintypes
|
||||||
import sys, os, thread
|
import os, thread
|
||||||
|
|
||||||
class MPC_API:
|
class MPC_API:
|
||||||
def __init__(self):
|
def __init__(self, enforce_custom_handler = False):
|
||||||
self.listener = None
|
self.enforce_custom_handler = enforce_custom_handler
|
||||||
|
self.__listener = None
|
||||||
thread.start_new_thread(self.__Listener, (self,))
|
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.loadstate = None
|
||||||
self.playstate = None
|
self.playstate = None
|
||||||
self.fileplaying = None
|
self.fileplaying = None
|
||||||
self.fileduration = None
|
self.fileduration = None
|
||||||
|
'''
|
||||||
|
Most likely won't be up to date unless you ask API to refresh it
|
||||||
|
'''
|
||||||
self.lastfileposition = None
|
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):
|
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):
|
def is_api_ready(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
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
|
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)
|
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):
|
def is_file_ready(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
return (self.loadstate == self.__MPC_LOADSTATE.MLS_LOADED and self.fileplaying and self.playstate <> None)
|
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
|
Opens a file given in an argument in player
|
||||||
while(self.listener.mpc_handle == None and is_starting): continue
|
Throws MPC_API.NoSlaveDetectedException if mpc window is not found
|
||||||
|
'''
|
||||||
def open_file(self, file_path):
|
def open_file(self, file_path):
|
||||||
self.__mpc_ready_in_slave_mode()
|
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):
|
def is_paused(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
return (self.playstate <> self.__MPC_PLAYSTATE.PS_PLAY and self.playstate <> None)
|
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):
|
def pause(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
if(not self.is_paused()):
|
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()
|
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):
|
def unpause(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
if(self.is_paused()):
|
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()
|
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):
|
def playpause(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
tmp = self.playstate
|
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()
|
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):
|
def ask_for_current_position(self):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
if(not self.position_request_warden):
|
if(not self.__position_request_warden):
|
||||||
self.position_request_warden = True
|
self.__position_request_warden = True
|
||||||
self.listener.SendCommand(self.__API_COMMANDS.CMD_GETCURRENTPOSITION)
|
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()
|
while(self.__position_request_warden and not self.callbacks.on_update_position): self.__mpc_ready_in_slave_mode()
|
||||||
return self.lastfileposition
|
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):
|
def seek(self, position):
|
||||||
self.__mpc_ready_in_slave_mode()
|
self.__mpc_ready_in_slave_mode()
|
||||||
self.seek_warden = True
|
self.__seek_warden = True
|
||||||
self.listener.SendCommand(self.__API_COMMANDS.CMD_SETPOSITION, unicode(position))
|
self.__listener.SendCommand(MPC_API_COMMANDS.CMD_SETPOSITION, unicode(position))
|
||||||
while(self.seek_warden):
|
while(self.__seek_warden): continue
|
||||||
continue
|
|
||||||
|
|
||||||
def __mpc_ready_in_slave_mode(self):
|
'''
|
||||||
if not win32gui.IsWindow(self.listener.mpc_handle):
|
@param message: unicode string to display in player
|
||||||
raise MPC_API.NoSlaveDetectedException("MPC Slave Window not detected")
|
@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)
|
||||||
|
|
||||||
def handle_command(self,cmd, value):
|
'''
|
||||||
#print '>>>'+hex(cmd).upper(), value
|
Send raw cmd and value to mpc
|
||||||
if (cmd == self.__API_COMMANDS.CMD_CONNECT):
|
Commands are available in MPC_API_COMMANDS class
|
||||||
self.listener.mpc_handle = int(value)
|
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:
|
||||||
|
if (cmd == MPC_API_COMMANDS.CMD_CONNECT):
|
||||||
|
self.__listener.mpc_handle = int(value)
|
||||||
if(self.callbacks.on_connected):
|
if(self.callbacks.on_connected):
|
||||||
self.callbacks.on_connected()
|
self.callbacks.on_connected(())
|
||||||
elif(cmd == self.__API_COMMANDS.CMD_STATE):
|
|
||||||
|
elif(cmd == MPC_API_COMMANDS.CMD_STATE):
|
||||||
self.loadstate = int(value)
|
self.loadstate = int(value)
|
||||||
elif(cmd == self.__API_COMMANDS.CMD_PLAYMODE):
|
|
||||||
|
elif(cmd == MPC_API_COMMANDS.CMD_PLAYMODE):
|
||||||
self.playstate = int(value)
|
self.playstate = int(value)
|
||||||
if(self.callbacks.on_update_playstate): self.callbacks.on_update_playstate(self.playstate)
|
if(self.callbacks.on_update_playstate): self.callbacks.on_update_playstate((self.playstate,))
|
||||||
elif(cmd == self.__API_COMMANDS.CMD_NOWPLAYING):
|
|
||||||
|
elif(cmd == MPC_API_COMMANDS.CMD_NOWPLAYING):
|
||||||
if(self.callbacks.on_file_ready): self.callbacks.on_file_ready()
|
if(self.callbacks.on_file_ready): self.callbacks.on_file_ready()
|
||||||
self.fileplaying = value.split('|')[3].split('\\').pop()
|
self.fileplaying = value.split('|')[3].split('\\').pop()
|
||||||
if(self.callbacks.on_update_filename): self.callbacks.on_update_filename(self.fileplaying)
|
if(self.callbacks.on_update_filename): self.callbacks.on_update_filename((self.fileplaying,))
|
||||||
self.fileduration = int(value.split('|')[4])
|
self.fileduration = int(value.split('|')[4])
|
||||||
if(self.callbacks.on_update_file_duration): self.callbacks.on_update_file_duration(self.fileplaying)
|
if(self.callbacks.on_update_file_duration): self.callbacks.on_update_file_duration((self.fileplaying,))
|
||||||
elif(cmd == self.__API_COMMANDS.CMD_CURRENTPOSITION):
|
|
||||||
|
elif(cmd == MPC_API_COMMANDS.CMD_CURRENTPOSITION):
|
||||||
self.lastfileposition = float(value)
|
self.lastfileposition = float(value)
|
||||||
self.position_request_warden = False
|
self.__position_request_warden = False
|
||||||
if(self.callbacks.on_update_position): self.callbacks.on_update_position(self.lastfileposition)
|
if(self.callbacks.on_update_position): self.callbacks.on_update_position((self.lastfileposition,))
|
||||||
elif(cmd == self.__API_COMMANDS.CMD_NOTIFYSEEK):
|
|
||||||
self.seek_warden = False
|
elif(cmd == MPC_API_COMMANDS.CMD_NOTIFYSEEK):
|
||||||
|
self.__seek_warden = False
|
||||||
if(self.lastfileposition <> float(value)): #Notify seek is sometimes sent twice
|
if(self.lastfileposition <> float(value)): #Notify seek is sometimes sent twice
|
||||||
self.lastfileposition = float(value)
|
self.lastfileposition = float(value)
|
||||||
if(self.callbacks.on_seek): self.callbacks.on_seek(self.lastfileposition)
|
if(self.callbacks.on_seek): self.callbacks.on_seek((self.lastfileposition,))
|
||||||
else:
|
else:
|
||||||
pass
|
if(self.callbacks.custom_handler <> None):
|
||||||
|
self.callbacks.custom_handler((cmd, value,))
|
||||||
|
|
||||||
class NoSlaveDetectedException(Exception):
|
class NoSlaveDetectedException(Exception):
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
@ -122,6 +222,12 @@ class MPC_API:
|
|||||||
self.on_update_position = None
|
self.on_update_position = None
|
||||||
self.on_update_playstate = None
|
self.on_update_playstate = None
|
||||||
self.on_file_ready = 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:
|
class __MPC_LOADSTATE:
|
||||||
MLS_CLOSED = 0
|
MLS_CLOSED = 0
|
||||||
@ -136,14 +242,75 @@ class MPC_API:
|
|||||||
PS_UNUSED = 3
|
PS_UNUSED = 3
|
||||||
|
|
||||||
'''
|
'''
|
||||||
class MPC_OSDDATA():
|
class __OSD_MESSAGEPOS:
|
||||||
_fields_ = [
|
OSD_NOMESSAGE = 0
|
||||||
('nMsgPos'),
|
OSD_TOPLEFT = 1
|
||||||
('nDurationMS'),
|
OSD_TOPRIGHT = 2
|
||||||
('strMsg')
|
|
||||||
]
|
|
||||||
'''
|
'''
|
||||||
class __API_COMMANDS():
|
|
||||||
|
class __Listener:
|
||||||
|
def __init__(self, mpc_api):
|
||||||
|
self.mpc_handle = None
|
||||||
|
message_map = {
|
||||||
|
win32con.WM_COPYDATA: self.OnCopyData
|
||||||
|
}
|
||||||
|
wc = win32gui.WNDCLASS()
|
||||||
|
wc.lpfnWndProc = message_map
|
||||||
|
wc.lpszClassName = 'MPCApiListener'
|
||||||
|
hinst = wc.hInstance = win32api.GetModuleHandle(None)
|
||||||
|
classAtom = win32gui.RegisterClass(wc)
|
||||||
|
self.hwnd = win32gui.CreateWindow (
|
||||||
|
classAtom,
|
||||||
|
"ListenerGUI",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
win32con.CW_USEDEFAULT,
|
||||||
|
win32con.CW_USEDEFAULT,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
hinst,
|
||||||
|
None
|
||||||
|
)
|
||||||
|
self.__PCOPYDATASTRUCT = ctypes.POINTER(self.__COPYDATASTRUCT)
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
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
|
# Send after connection
|
||||||
# Par 1 : MPC window handle (command should be send to this HWnd)
|
# Par 1 : MPC window handle (command should be send to this HWnd)
|
||||||
CMD_CONNECT = 0x50000000
|
CMD_CONNECT = 0x50000000
|
||||||
@ -269,52 +436,3 @@ class MPC_API:
|
|||||||
# show host defined OSD message string
|
# show host defined OSD message string
|
||||||
CMD_OSDSHOWMESSAGE = 0xA0005000
|
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):
|
|
||||||
message_map = {
|
|
||||||
win32con.WM_COPYDATA: self.OnCopyData
|
|
||||||
}
|
|
||||||
wc = win32gui.WNDCLASS()
|
|
||||||
wc.lpfnWndProc = message_map
|
|
||||||
wc.lpszClassName = 'MPCApiListener'
|
|
||||||
hinst = wc.hInstance = win32api.GetModuleHandle(None)
|
|
||||||
classAtom = win32gui.RegisterClass(wc)
|
|
||||||
self.hwnd = win32gui.CreateWindow (
|
|
||||||
classAtom,
|
|
||||||
"ListenerGUI",
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
win32con.CW_USEDEFAULT,
|
|
||||||
win32con.CW_USEDEFAULT,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
hinst,
|
|
||||||
None
|
|
||||||
)
|
|
||||||
self.__PCOPYDATASTRUCT = ctypes.POINTER(self.__COPYDATASTRUCT)
|
|
||||||
self.mpc_api = mpc_api
|
|
||||||
self.mpc_handle = None
|
|
||||||
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))
|
|
||||||
|
|||||||
@ -82,6 +82,9 @@ class MPCHCPlayer(object):
|
|||||||
def set_speed(self, value):
|
def set_speed(self, value):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def display_message(self, message):
|
||||||
|
pass
|
||||||
|
|
||||||
def make_ping(self):
|
def make_ping(self):
|
||||||
self.ask_for_status()
|
self.ask_for_status()
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,12 @@ class MPCHCAPIPlayer(object):
|
|||||||
def make_ping(self):
|
def make_ping(self):
|
||||||
self.ask_for_status()
|
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):
|
def set_paused(self, value):
|
||||||
try:
|
try:
|
||||||
if value:
|
if value:
|
||||||
@ -66,6 +72,6 @@ class MPCHCAPIPlayer(object):
|
|||||||
def run_mpc(manager, mpc_path, file_path, args):
|
def run_mpc(manager, mpc_path, file_path, args):
|
||||||
mpc = MPCHCAPIPlayer(manager)
|
mpc = MPCHCAPIPlayer(manager)
|
||||||
mpc.mpc_api.callbacks.on_file_ready = mpc.make_ping
|
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)
|
mpc.mpc_api.start_mpc(mpc_path, args)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user