4

(i know this resembles Python and d-bus: How to set up main loop? , but without complete code in the "Answer", i'm unable to figure out where i'm going wrong. it might just be a change in a Skype)

Here is my program:

import gobject
import dbus
import dbus.mainloop.glib
dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()
skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skypec = sessbus.get_object('com.Skype.API', '/com/Skype/Client')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
# ... waits for user click in Skype ...
#==> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
#==> dbus.String(u'PROTOCOL 7')
def got_signal(sender, destination, member, interface, path):
  print "got_signal(sender=%s, dest=%s, member=%s, iface=%s, path=%s)" \
    % (sender, destination, member, interface, path)

skypec.connect_to_signal('Notify', got_signal, sender_keyword='sender', \
  destination_keyword='destination', member_keyword='member', \
  interface_keyword='interface', path_keyword='path')

mainloop = gobject.MainLoop()
mainloop.run()

When run (e.g. python skype-call.py), it pauses after sending the NAME py1 command to Skype and waits for an interactive confirmation in the Skype UI, then continues. As such, the skype_iface object is clearly working at least to a certain degree.

However, python then emits the following error:

ERROR:dbus.proxies:Introspect error on :1.152:/com/Skype/Client: dbus.exceptions.DBusException: org.freedesktop.DBus.Error.UnknownObject: No such object path '/com/Skype/Client'

I also tried the following (instead of connect_to_signal, just before starting the gobject mainloop at the end):

def receiver(x, **kwargs):
  print "receiver(%s)" % (x,)

sessbus.add_signal_receiver(receiver, signal_name='Notify', \
  dbus_interface='com.Skype.API', bus_name='com.Skype.API', path='/com/Skype/Client')

And while that didn't complain, it never gets called. I tried sending the Skype user a message. What sorts of events should trigger it?

The docs at https://dev.skype.com/desktop-api-reference#DBUSUsage aren't terribly helpful.

This is Skype for Linux 4.2.0.11 on Debian 7.0 multiarch (amd64/i386).

Community
  • 1
  • 1
Rob Starling
  • 3,868
  • 3
  • 23
  • 40

2 Answers2

3

looking back at http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html#exporting-methods-with-dbus-service-method , i tried taking their example:

import gobject
import dbus
from dbus.decorators import method
import dbus.mainloop.glib
import dbus.service

dbus_gmainloop = dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
sessbus = dbus.SessionBus()

class Example(dbus.service.Object):
    def __init__(self, bus):
        dbus.service.Object.__init__(self, bus, '/com/Skype/Client')

    @method(dbus_interface='com.Skype.API.Client', in_signature='s', \
            sender_keyword='sender', destination_keyword='dest', \
            rel_path_keyword='rel_path', path_keyword='path', \
            message_keyword='message', connection_keyword='conn')
    def Notify(self, s, sender=None, dest=None, rel_path=None, path=None, \
               message=None, conn=None):
        print "Notify(%s, sender=%s, dest=%s, rel_path=%s, path=%s, message=%s, conn=%s)" \
              % (s, sender, path, dest, message, rel_path, conn,)

# make one:
ex = Example(sessbus)

skype = sessbus.get_object('com.Skype.API', '/com/Skype')
skype_iface = dbus.Interface(skype, dbus_interface='com.Skype.API')
skype_iface.Invoke("NAME py1")
##=> dbus.String(u'OK')
skype_iface.Invoke("PROTOCOL 7")
##=> dbus.String(u'PROTOCOL 7')

mainloop = gobject.MainLoop()
mainloop.run()

and lo and behold i get Notify calls:

Notify(CONNSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(CURRENTUSERHANDLE ******, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Notify(USERSTATUS ONLINE, sender=:1.152, path=/com/Skype/Client, dest=:1.275, message=<dbus.lowlevel.MethodCallMessage path: /com/Skype/Client, iface: com.Skype.API.Client, member: Notify dest: :1.275>, rel_path=/, conn=<dbus._dbus.SessionBus (session) at 0x2118e90>)

Obviously, this isn't a great example of a well-structured program, but the d-bus bits do appear to connect.

Rob Starling
  • 3,868
  • 3
  • 23
  • 40
  • Cool, I didn't know about exposing methods to receive signals that way, but apparently it works.. – redShadow Jun 08 '13 at 15:51
  • These two other questions do it that way, too: http://stackoverflow.com/questions/14901615/how-to-listen-to-only-certain-signals-using-python-dbus , http://stackoverflow.com/questions/6379553/calling-dbus-python-inside-a-thread – Rob Starling Jun 08 '13 at 17:26
2

I'm trying to debug the same thing, maybe we can sort something out together (I'm using wheezy amd64 too, btw)...

From what I understood, it looks like com.Skype.API is not exposing an object named /com/Skype/Client (and d-feet confirms that).

I used dbus-monitor to monitor the bus while sending a message to my skype account. Amongst the other output, I got this:

method call sender=:1.43 -> dest=:1.132 serial=324 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHAT #rshk-testuser1/$myusername;<hex-code-here> ACTIVITY_TIMESTAMP 1370647479"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=324
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"
method call sender=:1.43 -> dest=:1.132 serial=325 path=/com/Skype/Client; interface=com.Skype.API.Client; member=Notify
   string "CHATMESSAGE 1538281 STATUS RECEIVED"
error sender=:1.132 -> dest=:1.43 error_name=org.freedesktop.DBus.Error.UnknownMethod reply_serial=325
   string "Method "Notify" with signature "s" on interface "com.Skype.API.Client" doesn't exist
"

So, it looks like there's another interface named com.Skype.API.Client that's exposing the /com/Skype/Client object, but for some reason that interface is unreachable..

I had a look at /etc/dbus-1/system.d/skype.conf that's only listing com.Skype.API.

I'm not very experienced with dbus, but I'm trying to dig further and understand what's wrongs..

redShadow
  • 6,687
  • 2
  • 31
  • 34
  • oh... i wonder if adding something to the `skype.conf` is what we need. – Rob Starling Jun 08 '13 at 05:35
  • also, we should figure out if this is still true: "Skype uses a very old version of D-Bus that is incompatible with the current daemon and library. Until they update that, you cannot use it." -- http://lists.freedesktop.org/archives/dbus/2006-November/006492.html -- doesn't feel like it, since we can send, but maybe... – Rob Starling Jun 08 '13 at 05:50