def Attach(self, Timeout=30000, Wait=True): if self.AttachmentStatus == apiAttachSuccess: return if not self.isAlive(): try: self.start() except AssertionError: raise ISkypeAPIError('Skype API closed') try: self.wait = True t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) if Wait: t.start() while self.wait: self.win_skype = self.get_skype() if self.win_skype != None: break else: time.sleep(1.0) else: raise ISkypeAPIError('Skype attach timeout') finally: t.cancel() c = ICommand(-1, 'NAME %s' % self.FriendlyName, '', True, Timeout) self.SendCommand(c, True) if c.Reply != 'OK': self.win_skype = None self.SetAttachmentStatus(apiAttachRefused) return self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol), True) self.SetAttachmentStatus(apiAttachSuccess)
def SendCommand(self, Command): if not self.AttachmentStatus == apiAttachSuccess: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id, )) self.DebugPrint('->', repr(com)) userInfo = self.coref.CFDictionary({ self.coref.CFSTR('SKYPE_API_COMMAND'): self.coref.CFString(com), self.coref.CFSTR('SKYPE_API_CLIENT_ID'): self.coref.CFNumber(self.client_id) }) self.post('SKSkypeAPICommand', userInfo) if Command.Blocking: event.wait(Command.Timeout / 1000.0) if not event.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start()
def Attach(self, Timeout=30000, Wait=True): if self.AttachmentStatus in (apiAttachPendingAuthorization, apiAttachSuccess): return try: self.start() except AssertionError: pass t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) try: self.init_observer() self.client_id = -1 self.SetAttachmentStatus(apiAttachPendingAuthorization) self.post('SKSkypeAPIAttachRequest') self.wait = True if Wait: t.start() while self.wait and self.AttachmentStatus == apiAttachPendingAuthorization: time.sleep(1.0) finally: t.cancel() if not self.wait: self.SetAttachmentStatus(apiAttachUnknown) raise ISkypeAPIError('Skype attach timeout') self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol))
def SendCommand(self, Command, Force=False): if self.AttachmentStatus != apiAttachSuccess and not Force: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) self.DebugPrint('->', repr(com)) if Command.Blocking: Command._event = bevent = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (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 com = unicode(com).encode('utf-8') + '\x00' for i in xrange(0, len(com), 20): event.xclient.data = com[i:i + 20] if self.x11.XSendEvent(self.disp, self.win_skype, False, 0, byref(event)) == 0: self.error_check() event.xclient.message_type = self.atom_msg self.loop_event.set() self.error_check() if Command.Blocking: bevent.wait(Command.Timeout / 1000.0) self.error_check() if not bevent.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start()
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 ISkypeAPIError('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 ISkypeAPIError('Cannot find Skype path') windll.advapi32.RegCloseKey(key) return path.value
def _ISkypeAPI(handler, opts): trans = opts.pop('Transport', 'x11') if trans == 'dbus': from posix_dbus import _ISkypeAPI elif trans == 'x11': from posix_x11 import _ISkypeAPI else: raise ISkypeAPIError('Unknown transport: %s' % trans) return _ISkypeAPI(handler, opts)
def Attach(self, Timeout=30000, Wait=True): if self.Skype: return if not self.isAlive(): raise ISkypeAPIError('Skype API closed') self.DebugPrint('->', 'SkypeControlAPIDiscover') fhwnd = self.GetForegroundWindow() try: if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if not windll.user32.SendMessageTimeoutA( _HWND_BROADCAST, self._SkypeControlAPIDiscover, self.hwnd, None, 2, 5000, None): raise ISkypeAPIError( 'Could not broadcast Skype discover message') # wait (with timeout) till the WindProc() attaches self.Wait = True t = threading.Timer(Timeout / 1000, self.__Attach_ftimeout) if Wait: t.start() while self.Wait and self.AttachmentStatus not in ( apiAttachSuccess, apiAttachRefused): if self.AttachmentStatus == apiAttachPendingAuthorization: # disable the timeout t.cancel() elif self.AttachmentStatus == apiAttachAvailable: # rebroadcast self.DebugPrint('->', 'SkypeControlAPIDiscover') windll.user32.SetForegroundWindow(self.hwnd) if not windll.user32.SendMessageTimeoutA( _HWND_BROADCAST, self._SkypeControlAPIDiscover, self.hwnd, None, 2, 5000, None): raise ISkypeAPIError( 'Could not broadcast Skype discover message') time.sleep(0.01) t.cancel() finally: if fhwnd: windll.user32.SetForegroundWindow(fhwnd) # check if we got the Skype window's hwnd if self.Skype: self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol)) elif not self.Wait: raise ISkypeAPIError('Skype attach timeout')
def CommandsStackPush(self, Command): self.CommandsLock.acquire() if Command.Id < 0: Command.Id = 0 while Command.Id in self.Commands: Command.Id += 1 if Command.Id in self.Commands: self.CommandsLock.release() raise ISkypeAPIError('Command Id conflict') self.Commands[Command.Id] = Command self.CommandsLock.release()
def error_check(self): '''Checks last Xlib error and raises an exception if needed.''' if self.error != None: if self.error == 3: # BadWindow self.win_skype = None self.SetAttachmentStatus(apiAttachNotAvailable) buf = create_string_buffer(256) self.x11.XGetErrorText(self.disp, self.error, buf, 256) error = ISkypeAPIError('X11 error: %s' % buf.value) self.error = None raise error
def Shutdown(self): try: if self.hwnd: fhwnd = self.GetForegroundWindow() if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if windll.shell32.ShellExecuteA( None, 'open', self.get_skype_path(), '/SHUTDOWN', None, 0) <= 32: raise ISkypeAPIError('Could not shutdown Skype') finally: if self.hwnd and fhwnd: windll.user32.SetForegroundWindow(fhwnd)
def SendCommand(self, Command): for retry in xrange(2): if not self.Skype: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) com8 = com.encode('utf-8') + '\0' copydata = _COPYDATASTRUCT(None, len(com8), com8) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer( Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id, )) self.DebugPrint('->', repr(com)) fhwnd = self.GetForegroundWindow() 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.Timeout / 1000.0) if not event.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start() break else: self.CommandsStackPop(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 ISkypeAPIError( 'Skype API error, check if Skype wasn\'t closed')
def SendCommand(self, Command): if not self.skype_out: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) self.DebugPrint('->', repr(com)) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id, )) try: result = self.skype_out.Invoke(com) except dbus.DBusException, err: raise ISkypeAPIError(str(err))
def Start(self, Minimized=False, Nosplash=False): args = [] if Minimized: args.append('/MINIMIZED') if Nosplash: args.append('/NOSPLASH') try: if self.hwnd: fhwnd = self.GetForegroundWindow() if fhwnd: windll.user32.SetForegroundWindow(self.hwnd) if windll.shell32.ShellExecuteA( None, 'open', self.get_skype_path(), ' '.join(args), None, 0) <= 32: raise ISkypeAPIError('Could not start Skype') finally: if self.hwnd and fhwnd: windll.user32.SetForegroundWindow(fhwnd)
def Attach(self, Timeout=30000, Wait=True): try: if not self.isAlive(): self.StartWatcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) 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 = _SkypeNotifyCallback( self.bus, self.notify) except dbus.DBusException: if not Wait: break time.sleep(1.0) else: break else: raise ISkypeAPIError('Skype attach timeout') finally: t.cancel() c = ICommand(-1, 'NAME %s' % self.FriendlyName, '', True, Timeout) if self.skype_out: self.SendCommand(c) if c.Reply != 'OK': self.skype_out = None self.SetAttachmentStatus(apiAttachRefused) return self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol)) self.SetAttachmentStatus(apiAttachSuccess)
def _NotImplemented(self): raise ISkypeAPIError('Functionality not implemented')
class _ISkypeAPI(_ISkypeAPIBase): def __init__(self, handler, opts): _ISkypeAPIBase.__init__(self, opts) self.RegisterHandler(handler) self.skype_in = self.skype_out = self.dbus_name_owner_watch = None self.bus = opts.pop('Bus', None) try: mainloop = opts.pop('MainLoop') if self.bus is not None: raise TypeError( 'Bus and MainLoop cannot be used at the same time!') except KeyError: if self.bus is None: import dbus.mainloop.glib import gobject gobject.threads_init() dbus.mainloop.glib.threads_init() mainloop = dbus.mainloop.glib.DBusGMainLoop() self.mainloop = gobject.MainLoop() if self.bus is None: from dbus import SessionBus self.bus = SessionBus(private=True, mainloop=mainloop) if opts: raise TypeError('Unexpected parameter(s): %s' % ', '.join(opts.keys())) def run(self): self.DebugPrint('thread started') if hasattr(self, 'mainloop'): self.mainloop.run() self.DebugPrint('thread finished') def Close(self): if hasattr(self, 'mainloop'): 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 self.DebugPrint('closed') def SetFriendlyName(self, FriendlyName): self.FriendlyName = FriendlyName if self.skype_out: self.SendCommand(ICommand(-1, 'NAME %s' % FriendlyName)) def StartWatcher(self): 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_ftimeout(self): self.wait = False def Attach(self, Timeout=30000, Wait=True): try: if not self.isAlive(): self.StartWatcher() self.start() except AssertionError: pass try: self.wait = True t = threading.Timer(Timeout / 1000.0, self.__Attach_ftimeout) 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 = _SkypeNotifyCallback( self.bus, self.notify) except dbus.DBusException: if not Wait: break time.sleep(1.0) else: break else: raise ISkypeAPIError('Skype attach timeout') finally: t.cancel() c = ICommand(-1, 'NAME %s' % self.FriendlyName, '', True, Timeout) if self.skype_out: self.SendCommand(c) if c.Reply != 'OK': self.skype_out = None self.SetAttachmentStatus(apiAttachRefused) return self.SendCommand(ICommand(-1, 'PROTOCOL %s' % self.Protocol)) self.SetAttachmentStatus(apiAttachSuccess) def IsRunning(self): try: self.bus.get_object('com.Skype.API', '/com/Skype') return True except dbus.DBusException: return False def Start(self, Minimized=False, Nosplash=False): # options are not supported as of Skype 1.4 Beta for Linux if not self.IsRunning(): 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 SendCommand(self, Command): if not self.skype_out: self.Attach(Command.Timeout) self.CommandsStackPush(Command) self.CallHandler('send', Command) com = u'#%d %s' % (Command.Id, Command.Command) self.DebugPrint('->', repr(com)) if Command.Blocking: Command._event = event = threading.Event() else: Command._timer = timer = threading.Timer(Command.Timeout / 1000.0, self.CommandsStackPop, (Command.Id, )) try: result = self.skype_out.Invoke(com) except dbus.DBusException, err: raise ISkypeAPIError(str(err)) if result.startswith(u'#%d ' % Command.Id): self.notify(result) if Command.Blocking: event.wait(Command.Timeout / 1000.0) if not event.isSet(): raise ISkypeAPIError('Skype command timeout') else: timer.start()
def __init__(self, handler, opts): _ISkypeAPIBase.__init__(self, opts) self.RegisterHandler(handler) # check options if opts: raise TypeError('Unexpected parameter(s): %s' % ', '.join(opts.keys())) # setup Xlib libpath = find_library('X11') if not libpath: raise ImportError('Could not find X11 library') self.x11 = cdll.LoadLibrary(libpath) # setup Xlib function prototypes self.x11.XCloseDisplay.argtypes = (DisplayP, ) self.x11.XCloseDisplay.restype = None self.x11.XCreateSimpleWindow.argtypes = (DisplayP, Window, c_int, c_int, c_uint, c_uint, c_uint, c_ulong, c_ulong) self.x11.XCreateSimpleWindow.restype = Window self.x11.XDefaultRootWindow.argtypes = (DisplayP, ) self.x11.XDefaultRootWindow.restype = Window self.x11.XDeleteProperty.argtypes = (DisplayP, Window, Atom) self.x11.XDeleteProperty.restype = None self.x11.XDestroyWindow.argtypes = (DisplayP, Window) self.x11.XDestroyWindow.restype = None self.x11.XPending.argtypes = (DisplayP, ) self.x11.XPending.restype = c_int self.x11.XGetAtomName.argtypes = (DisplayP, Atom) self.x11.XGetAtomName.restype = c_char_p self.x11.XGetErrorText.argtypes = (DisplayP, c_int, c_char_p, c_int) self.x11.XGetErrorText.restype = None self.x11.XGetWindowProperty.argtypes = (DisplayP, Window, Atom, c_long, c_long, Bool, Atom, AtomP, c_int_p, c_ulong_p, c_ulong_p, POINTER(POINTER(Window))) self.x11.XGetWindowProperty.restype = c_int self.x11.XInitThreads.argtypes = () self.x11.XInitThreads.restype = Status self.x11.XInternAtom.argtypes = (DisplayP, c_char_p, Bool) self.x11.XInternAtom.restype = Atom self.x11.XNextEvent.argtypes = (DisplayP, XEventP) self.x11.XNextEvent.restype = None self.x11.XOpenDisplay.argtypes = (c_char_p, ) self.x11.XOpenDisplay.restype = DisplayP self.x11.XSelectInput.argtypes = (DisplayP, Window, c_long) self.x11.XSelectInput.restype = None self.x11.XSendEvent.argtypes = (DisplayP, Window, Bool, c_long, XEventP) self.x11.XSendEvent.restype = Status self.x11.XSetErrorHandler.argtypes = (XErrorHandlerP, ) self.x11.XSetErrorHandler.restype = None self.x11.XLockDisplay.argtypes = (DisplayP, ) self.x11.XLockDisplay.restype = None self.x11.XUnlockDisplay.argtypes = (DisplayP, ) self.x11.XUnlockDisplay.restype = None # init Xlib self.x11.XInitThreads() self.error = None # callback has to be saved to keep reference to bound method self._error_handler_callback = XErrorHandlerP(self._error_handler) self.x11.XSetErrorHandler(self._error_handler_callback) self.disp = self.x11.XOpenDisplay(None) if not self.disp: raise ISkypeAPIError('Could not open XDisplay') self.win_root = self.x11.XDefaultRootWindow(self.disp) self.win_self = self.x11.XCreateSimpleWindow(self.disp, self.win_root, 100, 100, 100, 100, 1, 0, 0) self.x11.XSelectInput(self.disp, self.win_root, _PropertyChangeMask) self.win_skype = self.get_skype() ctrl = 'SKYPECONTROLAPI_MESSAGE' self.atom_msg = self.x11.XInternAtom(self.disp, ctrl, False) self.atom_msg_begin = self.x11.XInternAtom(self.disp, ctrl + '_BEGIN', False) self.loop_event = threading.Event() self.loop_timeout = 0.0001 self.loop_break = False