Class: DBus::ProxyObject
- Inherits:
-
Object
- Object
- DBus::ProxyObject
- Defined in:
- lib/dbus/proxy_object.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
- #api ⇒ ApiOptions readonly private
-
#bus ⇒ Object
readonly
The bus the object is reachable via.
-
#default_iface ⇒ String
The name of the default interface of the object.
-
#destination ⇒ Object
readonly
The (remote) destination of the object.
-
#introspected ⇒ Object
Flag determining whether the object has been introspected.
-
#path ⇒ Object
readonly
The path to the object.
-
#subnodes ⇒ Object
The names of direct subnodes of the object in the tree.
Instance Method Summary collapse
-
#[](intfname) ⇒ ProxyObjectInterface
Retrieves an interface of the proxy object.
-
#[]=(intfname, intf) ⇒ ProxyObjectInterface
private
Maps the given interface name intfname to the given interface _intf.
-
#define_shortcut_methods ⇒ Object
For each non duplicated method name in any interface present on the caller, defines a shortcut method dynamically.
-
#has_iface?(name) ⇒ Boolean
Returns whether the object has an interface with the given name.
-
#initialize(bus, dest, path, api: ApiOptions::CURRENT) ⇒ ProxyObject
constructor
Creates a new proxy object living on the given bus at destination dest on the given path.
-
#interfaces ⇒ Array<String>
Returns the interfaces of the object.
-
#introspect ⇒ Object
Introspects the remote object.
-
#on_signal(name, &block) ⇒ void
Registers a handler, the code block, for a signal with the given name.
Constructor Details
#initialize(bus, dest, path, api: ApiOptions::CURRENT) ⇒ ProxyObject
Creates a new proxy object living on the given bus at destination dest on the given path.
38 39 40 41 42 43 44 45 46 |
# File 'lib/dbus/proxy_object.rb', line 38 def initialize(bus, dest, path, api: ApiOptions::CURRENT) @bus = bus @destination = dest @path = ObjectPath.new(path) @introspected = false @interfaces = {} @subnodes = [] @api = api 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.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/dbus/proxy_object.rb', line 147 def method_missing(name, *args, &reply_handler) unless @default_iface && has_iface?(@default_iface) # 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 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 end |
Instance Attribute Details
#api ⇒ ApiOptions (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
34 35 36 |
# File 'lib/dbus/proxy_object.rb', line 34 def api @api end |
#bus ⇒ Object (readonly)
The bus the object is reachable via.
29 30 31 |
# File 'lib/dbus/proxy_object.rb', line 29 def bus @bus end |
#default_iface ⇒ String
Returns The name of the default interface of the object.
31 32 33 |
# File 'lib/dbus/proxy_object.rb', line 31 def default_iface @default_iface end |
#destination ⇒ Object (readonly)
The (remote) destination of the object.
25 26 27 |
# File 'lib/dbus/proxy_object.rb', line 25 def destination @destination end |
#introspected ⇒ Object
Flag determining whether the object has been introspected.
23 24 25 |
# File 'lib/dbus/proxy_object.rb', line 23 def introspected @introspected end |
#path ⇒ Object (readonly)
The path to the object.
27 28 29 |
# File 'lib/dbus/proxy_object.rb', line 27 def path @path end |
#subnodes ⇒ Object
The names of direct subnodes of the object in the tree.
21 22 23 |
# File 'lib/dbus/proxy_object.rb', line 21 def subnodes @subnodes end |
Instance Method Details
#[](intfname) ⇒ ProxyObjectInterface
Retrieves an interface of the proxy object
58 59 60 61 62 63 64 |
# File 'lib/dbus/proxy_object.rb', line 58 def [](intfname) introspect unless introspected ifc = @interfaces[intfname] raise DBus::Error, "no such interface `#{intfname}' on object `#{@path}'" unless ifc ifc end |
#[]=(intfname, intf) ⇒ ProxyObjectInterface
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Maps the given interface name intfname to the given interface _intf.
71 72 73 |
# File 'lib/dbus/proxy_object.rb', line 71 def []=(intfname, intf) @interfaces[intfname] = intf end |
#define_shortcut_methods ⇒ Object
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.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/dbus/proxy_object.rb', line 89 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| name = meth.name.to_sym # don't overwrite instance methods! next if dup_meths.include?(name) next if self.class.instance_methods.include?(name) if 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 redefine_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.
120 121 122 123 |
# File 'lib/dbus/proxy_object.rb', line 120 def has_iface?(name) introspect unless introspected @interfaces.key?(name) end |
#interfaces ⇒ Array<String>
Returns the interfaces of the object.
50 51 52 53 |
# File 'lib/dbus/proxy_object.rb', line 50 def interfaces introspect unless introspected @interfaces.keys end |
#introspect ⇒ Object
Introspects the remote object. Allows you to find and select interfaces on the object.
77 78 79 80 81 82 83 |
# File 'lib/dbus/proxy_object.rb', line 77 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.
128 129 130 131 132 133 |
# File 'lib/dbus/proxy_object.rb', line 128 def on_signal(name, &block) # TODO: improve raise NoMethodError unless @default_iface && has_iface?(@default_iface) @interfaces[@default_iface].on_signal(name, &block) end |