Class: DBus::ProxyObject

Inherits:
Object
  • Object
show all
Defined in:
lib/dbus/introspect.rb

Overview

D-Bus proxy object class

Class representing a remote object in an external application. Typically, calling a method on an instance of a ProxyObject sends a message over the bus so that the method is executed remotely on the correctponding object.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bus, dest, path) ⇒ ProxyObject

Creates a new proxy object living on the given bus at destination dest on the given path.



370
371
372
373
374
# File 'lib/dbus/introspect.rb', line 370

def initialize(bus, dest, path)
  @bus, @destination, @path = bus, dest, path
  @interfaces = Hash.new
  @subnodes = Array.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &reply_handler) ⇒ Object (private)

Handles all unkown methods, mostly to route method calls to the default interface.



467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/dbus/introspect.rb', line 467

def method_missing(name, *args, &reply_handler)
  if @default_iface and has_iface?(@default_iface)
    begin
      @interfaces[@default_iface].method(name).call(*args, &reply_handler)
    rescue NameError => e
      # interesting, foo.method("unknown")
      # raises NameError, not NoMethodError
      raise unless e.to_s =~ /undefined method `#{name}'/
      # BTW e.exception("...") would preserve the class.
      raise NoMethodError,"undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
    end
  else
    # TODO distinguish:
    # - di not specified
    #TODO
    # - di is specified but not found in introspection data
    raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
  end
end

Instance Attribute Details

#busObject (readonly)

The bus the object is reachable via.



364
365
366
# File 'lib/dbus/introspect.rb', line 364

def bus
  @bus
end

#default_ifaceString

Returns The name of the default interface of the object.

Returns:

  • (String)

    The name of the default interface of the object.



366
367
368
# File 'lib/dbus/introspect.rb', line 366

def default_iface
  @default_iface
end

#destinationObject (readonly)

The (remote) destination of the object.



360
361
362
# File 'lib/dbus/introspect.rb', line 360

def destination
  @destination
end

#introspectedObject

Flag determining whether the object has been introspected.



358
359
360
# File 'lib/dbus/introspect.rb', line 358

def introspected
  @introspected
end

#pathObject (readonly)

The path to the object.



362
363
364
# File 'lib/dbus/introspect.rb', line 362

def path
  @path
end

#subnodesObject

The names of direct subnodes of the object in the tree.



356
357
358
# File 'lib/dbus/introspect.rb', line 356

def subnodes
  @subnodes
end

Instance Method Details

#[](intfname) ⇒ ProxyObjectInterface

Retrieves an interface of the proxy object

Parameters:

  • intfname (String)

Returns:



384
385
386
# File 'lib/dbus/introspect.rb', line 384

def [](intfname)
  @interfaces[intfname]
end

#[]=(intfname, intf) ⇒ ProxyObjectInterface

Maps the given interface name intfname to the given interface _intf.

Parameters:

Returns:



392
393
394
# File 'lib/dbus/introspect.rb', line 392

def []=(intfname, intf)
  @interfaces[intfname] = intf
end

#define_shortcut_methodsObject

For each non duplicated method name in any interface present on the caller, defines a shortcut method dynamically. This function is automatically called when a DBus::ProxyObject is introspected.



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/dbus/introspect.rb', line 410

def define_shortcut_methods
  # builds a list of duplicated methods
  dup_meths, univocal_meths = [],{}
  @interfaces.each_value do |intf|
    intf.methods.each_value do |meth|
      # Module#instance_methods give us an array of symbols or strings,
      # depending on which version
      name = if RUBY_VERSION >= "1.9"
               meth.name.to_sym
             else
               meth.name
             end
      # don't overwrite instance methods!
      if dup_meths.include? name or self.class.instance_methods.include? name
        next
      elsif univocal_meths.include? name
        univocal_meths.delete name
        dup_meths << name
      else
        univocal_meths[name] = intf
      end
    end
  end
  univocal_meths.each do |name, intf|
    # creates a shortcut function that forwards each call to the method on
    # the appropriate intf
    singleton_class.class_eval do
      define_method name do |*args, &reply_handler|
        intf.method(name).call(*args, &reply_handler)
      end
    end
  end
end

#has_iface?(name) ⇒ Boolean

Returns whether the object has an interface with the given name.

Returns:

  • (Boolean)


445
446
447
448
# File 'lib/dbus/introspect.rb', line 445

def has_iface?(name)
  raise "Cannot call has_iface? if not introspected" if not @introspected
  @interfaces.member?(name)
end

#interfacesObject

Returns the interfaces of the object.



377
378
379
# File 'lib/dbus/introspect.rb', line 377

def interfaces
  @interfaces.keys
end

#introspectObject

Introspects the remote object. Allows you to find and select interfaces on the object.



398
399
400
401
402
403
404
# File 'lib/dbus/introspect.rb', line 398

def introspect
  # Synchronous call here.
  xml = @bus.introspect_data(@destination, @path)
  ProxyObjectFactory.introspect_into(self, xml)
  define_shortcut_methods()
  xml
end

#on_signal(name, &block) ⇒ void

This method returns an undefined value.

Registers a handler, the code block, for a signal with the given name. It uses default_iface which must have been set.



453
454
455
456
457
458
459
460
# File 'lib/dbus/introspect.rb', line 453

def on_signal(name, &block)
  if @default_iface and has_iface?(@default_iface)
    @interfaces[@default_iface].on_signal(name, &block)
  else
    # TODO improve
    raise NoMethodError
  end
end