def send_command(self, command): if not self.attachment_status == apiAttachSuccess: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = u'#%d %s' % (command.Id, command.Command) if command.Blocking: if self.run_main_loop: command._event = event = threading.Event() else: command._loop = EventLoop() else: command._timer = timer = threading.Timer(command.timeout2float(), self.pop_command, (command.Id, )) self.logger.debug('sending %s', repr(cmd)) userInfo = CFDictionary({ CFString('SKYPE_API_COMMAND'): CFString(cmd), CFString('SKYPE_API_CLIENT_ID'): CFNumber(self.client_id) }) self.post('SKSkypeAPICommand', userInfo) if command.Blocking: if self.run_main_loop: event.wait(command.timeout2float()) if not event.isSet(): raise SkypeAPIError('Skype command timeout') else: if not EventLoop.run(command.timeout2float()): raise SkypeAPIError('Skype command timeout') else: timer.start()
def send_command(self, command): if not self.skype_out: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = '#%d %s' % (command.Id, command.Command) self.logger.debug('sending %s', repr(cmd)) if command.Blocking: if self.run_main_loop: command._event = event = threading.Event() else: command._loop = loop = gobject.MainLoop() command._set = False else: command._timer = timer = threading.Timer(command.timeout2float(), self.pop_command, (command.Id,)) try: result = self.skype_out.Invoke(cmd) except dbus.DBusException as err: raise SkypeAPIError(str(err)) if result.startswith('#%d ' % command.Id): self.notify(result) if command.Blocking: if self.run_main_loop: event.wait(command.timeout2float()) if not event.isSet(): raise SkypeAPIError('Skype command timeout') elif not command._set: gobject.timeout_add_seconds(int(command.timeout2float()), loop.quit) loop.run() if not command._set: raise SkypeAPIError('Skype command timeout') else: timer.start()
def attach(self, timeout, wait=True): if self.skype is not None and windll.user32.IsWindow(self.skype): return self.acquire() self.skype = None try: if not self.isAlive(): try: self.start() except AssertionError: raise SkypeAPIError('Skype API closed') # wait till the thread initializes while not self.hwnd: time.sleep(0.01) self.logger.debug('broadcasting SkypeControlAPIDiscover') fhwnd = self.get_foreground_window() try: if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if not windll.user32.SendMessageTimeoutA( HWND_BROADCAST, self.SkypeControlAPIDiscover, self.hwnd, None, 2, 5000, None): raise SkypeAPIError( 'Could not broadcast Skype discover message') # wait (with timeout) till the WindProc() attaches self.wait = True t = threading.Timer(timeout2float(timeout), lambda: setattr(self, 'wait', False)) if wait: t.start() while self.wait and self.attachment_status not in ( apiAttachSuccess, apiAttachRefused): if self.attachment_status == apiAttachPendingAuthorization: # disable the timeout t.cancel() elif self.attachment_status == apiAttachAvailable: # rebroadcast self.logger.debug( 'broadcasting SkypeControlAPIDiscover') windll.user32.SetForegroundWindow(self.hwnd) if not windll.user32.SendMessageTimeoutA( HWND_BROADCAST, self.SkypeControlAPIDiscover, self.hwnd, None, 2, 5000, None): raise SkypeAPIError( 'Could not broadcast Skype discover message') time.sleep(0.01) t.cancel() finally: if fhwnd: windll.user32.SetForegroundWindow(fhwnd) finally: self.release() # check if we got the Skype window's hwnd if self.skype is not None: command = Command('PROTOCOL %s' % self.protocol, Blocking=True) self.send_command(command) self.protocol = int(command.Reply.rsplit(None, 1)[-1]) elif not self.wait: raise SkypeAPIError('Skype attach timeout')
def get_skype_path(self): key = c_long() # try to find Skype in HKEY_CURRENT_USER registry tree if windll.advapi32.RegOpenKeyA(0x80000001, 'Software\\Skype\\Phone', byref(key)) != 0: # try to find Skype in HKEY_LOCAL_MACHINE registry tree if windll.advapi32.RegOpenKeyA(0x80000002, 'Software\\Skype\\Phone', byref(key)) != 0: raise SkypeAPIError('Skype not installed') pathlen = c_long(512) path = create_string_buffer(pathlen.value) if windll.advapi32.RegQueryValueExA(key, 'SkypePath', None, None, path, byref(pathlen)) != 0: windll.advapi32.RegCloseKey(key) raise SkypeAPIError('Cannot find Skype path') windll.advapi32.RegCloseKey(key) return path.value
def __init__(self, opts): self.logger = logging.getLogger('Skype4Py.api.posix_x11.SkypeAPI') SkypeAPIBase.__init__(self) finalize_opts(opts) # initialize threads if not done already by the user threads_init(gtk=False) # init Xlib display self.disp = x11.XOpenDisplay(None) if not self.disp: raise SkypeAPIError('Could not open XDisplay') self.win_root = x11.XDefaultRootWindow(self.disp) self.win_self = x11.XCreateSimpleWindow(self.disp, self.win_root, 100, 100, 100, 100, 1, 0, 0) x11.XSelectInput(self.disp, self.win_root, PropertyChangeMask) self.win_skype = self.get_skype() ctrl = 'SKYPECONTROLAPI_MESSAGE' self.atom_msg = x11.XInternAtom(self.disp, ctrl, False) self.atom_msg_begin = x11.XInternAtom(self.disp, ctrl + '_BEGIN', False) self.loop_event = threading.Event() self.loop_timeout = 0.0001 self.loop_break = False
def send_command(self, command, force=False): if self.attachment_status != apiAttachSuccess and not force: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = u'#%d %s' % (command.Id, command.Command) self.logger.debug('sending %s', repr(cmd)) if command.Blocking: command._event = bevent = threading.Event() else: command._timer = timer = threading.Timer(command.timeout2float(), self.pop_command, (command.Id, )) event = XEvent() event.xclient.type = ClientMessage event.xclient.display = self.disp event.xclient.window = self.win_self event.xclient.message_type = self.atom_msg_begin event.xclient.format = 8 cmd = cmd.encode('utf-8') + '\x00' for i in xrange(0, len(cmd), 20): event.xclient.data = cmd[i:i + 20] x11.XSendEvent(self.disp, self.win_skype, False, 0, byref(event)) event.xclient.message_type = self.atom_msg self.loop_event.set() if command.Blocking: bevent.wait(command.timeout2float()) if not bevent.isSet(): raise SkypeAPIError('Skype command timeout') else: timer.start()
def attach(self, timeout, wait=True): if self.attachment_status in (apiAttachPendingAuthorization, apiAttachSuccess): return self.acquire() try: try: self.start() except AssertionError: pass t = threading.Timer(timeout2float(timeout), lambda: setattr(self, 'wait', False)) try: self.init_observer() self.client_id = -1 self.set_attachment_status(apiAttachPendingAuthorization) self.post('SKSkypeAPIAttachRequest') self.wait = True if wait: t.start() while self.wait and self.attachment_status == apiAttachPendingAuthorization: if self.run_main_loop: time.sleep(1.0) else: EventLoop.run(1.0) finally: t.cancel() if not self.wait: self.set_attachment_status(apiAttachUnknown) raise SkypeAPIError('Skype attach timeout') finally: self.release() command = Command('PROTOCOL %s' % self.protocol, Blocking=True) self.send_command(command) self.protocol = int(command.Reply.rsplit(None, 1)[-1])
def SkypeAPI(opts): trans = opts.pop('Transport', 'dbus') if trans == 'dbus': from .posix_dbus import SkypeAPI elif trans == 'x11': from .posix_x11 import SkypeAPI else: raise SkypeAPIError('Unknown transport: %s' % trans) return SkypeAPI(opts)
def attach(self, timeout, wait=True): if self.attachment_status == apiAttachSuccess: return self.acquire() try: if not self.isAlive(): try: self.start() except AssertionError: raise SkypeAPIError('Skype API closed') try: self.wait = True t = threading.Timer(timeout2float(timeout), lambda: setattr(self, 'wait', False)) if wait: t.start() while self.wait: self.win_skype = self.get_skype() if self.win_skype is not None: break else: time.sleep(1.0) else: raise SkypeAPIError('Skype attach timeout') finally: t.cancel() command = Command('NAME %s' % self.friendly_name, '', True, timeout) self.release() try: self.send_command(command, True) finally: self.acquire() if command.Reply != 'OK': self.win_skype = None self.set_attachment_status(apiAttachRefused) return self.set_attachment_status(apiAttachSuccess) finally: self.release() command = Command('PROTOCOL %s' % self.protocol, Blocking=True) self.send_command(command, True) self.protocol = int(command.Reply.rsplit(None, 1)[-1])
def shutdown(self): try: if self.hwnd: fhwnd = self.get_foreground_window() if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if windll.shell32.ShellExecuteA(None, 'open', self.get_skype_path(), '/SHUTDOWN', None, 0) <= 32: raise SkypeAPIError('Could not shutdown Skype') finally: if self.hwnd and fhwnd: windll.user32.SetForegroundWindow(fhwnd)
def push_command(self, command): self.acquire() try: if command.Id < 0: command.Id = 0 while command.Id in self.commands: command.Id += 1 elif command.Id in self.commands: raise SkypeAPIError('Command Id conflict') self.commands[command.Id] = command finally: self.release()
def attach(self, timeout, wait=True): self.acquire() try: try: if not self.isAlive(): self.start_watcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(timeout2float(timeout), lambda: setattr(self, 'wait', False)) if wait: t.start() while self.wait: if not wait: self.wait = False try: if not self.skype_out: self.skype_out = self.bus.get_object( 'com.Skype.API', '/com/Skype') if not self.skype_in: self.skype_in = SkypeNotify(self.bus, self.notify) except dbus.DBusException: if not wait: break time.sleep(1.0) else: break else: raise SkypeAPIError('Skype attach timeout') finally: t.cancel() command = Command('NAME %s' % self.friendly_name, '', True, timeout) if self.skype_out: self.release() try: self.send_command(command) finally: self.acquire() if command.Reply != 'OK': self.skype_out = None self.set_attachment_status(apiAttachRefused) return self.set_attachment_status(apiAttachSuccess) finally: self.release() command = Command('PROTOCOL %s' % self.protocol, Blocking=True) self.send_command(command) self.protocol = int(command.Reply.rsplit(None, 1)[-1])
def send_command(self, command): for retry in range(2): if self.skype is None: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = '#%d %s' % (command.Id, command.Command) cmd8 = cmd.encode('utf-8') + '\0' copydata = COPYDATASTRUCT(None, len(cmd8), cmd8) if command.Blocking: command._event = event = threading.Event() else: command._timer = timer = threading.Timer( command.timeout2float(), self.pop_command, (command.Id, )) self.logger.debug('sending %s', repr(cmd)) fhwnd = self.get_foreground_window() try: if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if windll.user32.SendMessageA(self.skype, WM_COPYDATA, self.hwnd, byref(copydata)): if command.Blocking: event.wait(command.timeout2float()) if not event.isSet(): raise SkypeAPIError('Skype command timeout') else: timer.start() break else: # SendMessage failed self.pop_command(command.Id) self.skype = None # let the loop go back and try to reattach but only once finally: if fhwnd: windll.user32.SetForegroundWindow(fhwnd) else: raise SkypeAPIError( 'Skype API error, check if Skype wasn\'t closed')
def startup(self, minimized, nosplash): args = [] if minimized: args.append('/MINIMIZED') if nosplash: args.append('/NOSPLASH') try: if self.hwnd: fhwnd = self.get_foreground_window() if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if windll.shell32.ShellExecuteA(None, 'open', self.get_skype_path(), ' '.join(args), None, 0) <= 32: raise SkypeAPIError('Could not start Skype') finally: if self.hwnd and fhwnd: windll.user32.SetForegroundWindow(fhwnd)
def send_command(self, command): if not self.skype_out: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = u'#%d %s' % (command.Id, command.Command) self.logger.debug('sending %s', repr(cmd)) if command.Blocking: if self.run_main_loop: command._event = event = threading.Event() else: command._loop = loop = gobject.MainLoop() command._set = False else: command._timer = timer = threading.Timer(command.timeout2float(), self.pop_command, (command.Id,)) try: result = self.skype_out.Invoke(cmd) except dbus.DBusException, err: raise SkypeAPIError(str(err))
class SkypeAPI(SkypeAPIBase): def __init__(self, opts): self.logger = logging.getLogger('Skype4Py.api.posix_dbus.SkypeAPI') SkypeAPIBase.__init__(self) self.run_main_loop = opts.pop('RunMainLoop', True) finalize_opts(opts) self.skype_in = self.skype_out = self.dbus_name_owner_watch = None # initialize glib multithreading support gobject.threads_init() # dbus-python calls object.__init__() with arguments passed to SessionBus(), # this throws a warning on newer Python versions; here we suppress it warnings.simplefilter('ignore') try: self.bus = dbus.SessionBus(mainloop=DBusGMainLoop()) finally: warnings.simplefilter('default') if self.run_main_loop: self.mainloop = gobject.MainLoop() def run(self): self.logger.info('thread started') if self.run_main_loop: self.mainloop.run() self.logger.info('thread finished') def close(self): if self.run_main_loop: self.mainloop.quit() self.skype_in = self.skype_out = None if self.dbus_name_owner_watch is not None: self.bus.remove_signal_receiver(self.dbus_name_owner_watch) self.dbus_name_owner_watch = None SkypeAPIBase.close(self) def set_friendly_name(self, friendly_name): SkypeAPIBase.set_friendly_name(self, friendly_name) if self.skype_out: self.send_command(Command('NAME %s' % friendly_name)) def start_watcher(self): # starts a signal receiver detecting Skype being closed/opened self.dbus_name_owner_watch = self.bus.add_signal_receiver(self.dbus_name_owner_changed, 'NameOwnerChanged', 'org.freedesktop.DBus', 'org.freedesktop.DBus', '/org/freedesktop/DBus', arg0='com.Skype.API') def attach(self, timeout, wait=True): self.acquire() try: try: if not self.isAlive(): self.start_watcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(timeout2float(timeout), lambda: setattr(self, 'wait', False)) if wait: t.start() while self.wait: if not wait: self.wait = False try: if not self.skype_out: self.skype_out = self.bus.get_object('com.Skype.API', '/com/Skype') if not self.skype_in: self.skype_in = SkypeNotify(self.bus, self.notify) except dbus.DBusException: if not wait: break time.sleep(1.0) else: break else: raise SkypeAPIError('Skype attach timeout') finally: t.cancel() command = Command('NAME %s' % self.friendly_name, '', True, timeout) if self.skype_out: self.release() try: self.send_command(command) finally: self.acquire() if command.Reply != 'OK': self.skype_out = None self.set_attachment_status(apiAttachRefused) return self.set_attachment_status(apiAttachSuccess) finally: self.release() command = Command('PROTOCOL %s' % self.protocol, Blocking=True) self.send_command(command) self.protocol = int(command.Reply.rsplit(None, 1)[-1]) def is_running(self): try: self.bus.get_object('com.Skype.API', '/com/Skype') return True except dbus.DBusException: return False def startup(self, minimized, nosplash): # options are not supported as of Skype 1.4 Beta for Linux if not self.is_running(): import os if os.fork() == 0: # we're child os.setsid() os.execlp('skype') def shutdown(self): import os from signal import SIGINT fh = os.popen('ps -o %p --no-heading -C skype') pid = fh.readline().strip() fh.close() if pid: os.kill(int(pid), SIGINT) self.skype_in = self.skype_out = None def send_command(self, command): if not self.skype_out: self.attach(command.Timeout) self.push_command(command) self.notifier.sending_command(command) cmd = u'#%d %s' % (command.Id, command.Command) self.logger.debug('sending %s', repr(cmd)) if command.Blocking: if self.run_main_loop: command._event = event = threading.Event() else: command._loop = loop = gobject.MainLoop() command._set = False else: command._timer = timer = threading.Timer(command.timeout2float(), self.pop_command, (command.Id,)) try: result = self.skype_out.Invoke(cmd) except dbus.DBusException, err: raise SkypeAPIError(str(err)) if result.startswith(u'#%d ' % command.Id): self.notify(result) if command.Blocking: if self.run_main_loop: event.wait(command.timeout2float()) if not event.isSet(): raise SkypeAPIError('Skype command timeout') elif not command._set: gobject.timeout_add_seconds(int(command.timeout2float()), loop.quit) loop.run() if not command._set: raise SkypeAPIError('Skype command timeout') else: timer.start()
def _not_implemented(self): raise SkypeAPIError('Function not implemented')