Exemple #1
0
 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)
Exemple #2
0
    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()
Exemple #3
0
 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))
Exemple #4
0
 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()
Exemple #5
0
 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
Exemple #6
0
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)
Exemple #7
0
 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')
Exemple #8
0
 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()
Exemple #9
0
 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
Exemple #10
0
 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)
Exemple #11
0
 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')
Exemple #12
0
 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))
Exemple #13
0
 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)
Exemple #14
0
 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)
Exemple #15
0
 def _NotImplemented(self):
     raise ISkypeAPIError('Functionality not implemented')
Exemple #16
0
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()
Exemple #17
0
    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