class DBus::ProxyObject
Represents 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 corresponding object.
Attributes
@api private @return [ApiOptions]
The bus the object is reachable via.
@return [String] The name of the default interface of the object.
The (remote) destination of the object.
Flag determining whether the object has been introspected. @return [Boolean]
The path to the object. @return [ObjectPath]
The names of direct subnodes of the object in the tree.
Public Class Methods
Creates a new proxy object living on the given bus at destination dest on the given path.
# 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
Public Instance Methods
Retrieves an interface of the proxy object @param [String] intfname @return [ProxyObjectInterface]
# 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
Maps the given interface name intfname to the given interface _intf. @param [String] intfname @param [ProxyObjectInterface] intf @return [ProxyObjectInterface] @api private
# File lib/dbus/proxy_object.rb, line 71 def []=(intfname, intf) @interfaces[intfname] = intf end
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 {ProxyObject} is introspected.
# 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
Returns whether the object has an interface with the given name.
# File lib/dbus/proxy_object.rb, line 120 def has_iface?(name) introspect unless introspected @interfaces.key?(name) end
Returns the interfaces of the object. @return [Array<String>] names of the interfaces
# File lib/dbus/proxy_object.rb, line 50 def interfaces introspect unless introspected @interfaces.keys end
Introspects the remote object. Allows you to find and select interfaces on the object.
# 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
Registers a handler, the code block, for a signal with the given name. It uses default_iface which must have been set. @return [void]
# File lib/dbus/proxy_object.rb, line 128 def on_signal(name, &block) unless @default_iface && has_iface?(@default_iface) raise NoMethodError, "undefined signal `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'" end @interfaces[@default_iface].on_signal(name, &block) end
Private Instance Methods
Handles all unkown methods, mostly to route method calls to the default interface.
# File lib/dbus/proxy_object.rb, line 148 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
rubocop:enable Lint/MissingSuper
# File lib/dbus/proxy_object.rb, line 170 def respond_to_missing?(name, _include_private = false) @default_iface && has_iface?(@default_iface) && @interfaces[@default_iface].methods.key?(name) or super end