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 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))
def _not_implemented(self): raise SkypeAPIError('Function not implemented')
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()