File: proxy_object_interface.rb

package info (click to toggle)
ruby-dbus 0.16.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 520 kB
  • sloc: ruby: 3,786; sh: 53; makefile: 8
file content (145 lines) | stat: -rw-r--r-- 4,389 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# This file is part of the ruby-dbus project
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
# Copyright (C) 2009-2014 Martin Vidner
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License, version 2.1 as published by the Free Software Foundation.
# See the file "COPYING" for the exact licensing terms.

module DBus
  # = D-Bus proxy object interface class
  #
  # A class similar to the normal Interface used as a proxy for remote
  # object interfaces.
  class ProxyObjectInterface
    # The proxied methods contained in the interface.
    attr_accessor :methods
    # The proxied signals contained in the interface.
    attr_accessor :signals
    # The proxy object to which this interface belongs.
    attr_reader :object
    # The name of the interface.
    attr_reader :name

    # Creates a new proxy interface for the given proxy _object_
    # and the given _name_.
    def initialize(object, name)
      @object = object
      @name = name
      @methods = {}
      @signals = {}
    end

    # Returns the string representation of the interface (the name).
    def to_str
      @name
    end

    # Defines a method on the interface from the Method descriptor _m_.
    def define_method_from_descriptor(m)
      m.params.each do |fpar|
        par = fpar.type
        # This is the signature validity check
        Type::Parser.new(par).parse
      end

      singleton_class.class_eval do
        define_method m.name do |*args, &reply_handler|
          if m.params.size != args.size
            raise ArgumentError, "wrong number of arguments (#{args.size} for #{m.params.size})"
          end

          msg = Message.new(Message::METHOD_CALL)
          msg.path = @object.path
          msg.interface = @name
          msg.destination = @object.destination
          msg.member = m.name
          msg.sender = @object.bus.unique_name
          m.params.each do |fpar|
            par = fpar.type
            msg.add_param(par, args.shift)
          end
          ret = @object.bus.send_sync_or_async(msg, &reply_handler)
          if ret.nil? || @object.api.proxy_method_returns_array
            ret
          else
            m.rets.size == 1 ? ret.first : ret
          end
        end
      end

      @methods[m.name] = m
    end

    # Defines a signal from the descriptor _s_.
    def define_signal_from_descriptor(s)
      @signals[s.name] = s
    end

    # Defines a signal or method based on the descriptor _m_.
    def define(m)
      if m.is_a?(Method)
        define_method_from_descriptor(m)
      elsif m.is_a?(Signal)
        define_signal_from_descriptor(m)
      end
    end

    # Defines a proxied method on the interface.
    def define_method(methodname, prototype)
      m = Method.new(methodname)
      m.from_prototype(prototype)
      define(m)
    end

    # @overload on_signal(name, &block)
    # @overload on_signal(bus, name, &block)
    # Registers a handler (code block) for a signal with _name_ arriving
    # over the given _bus_. If no block is given, the signal is unregistered.
    # Note that specifying _bus_ is discouraged and the option is kept only for
    # backward compatibility.
    # @return [void]
    def on_signal(bus = @object.bus, name, &block)
      mr = DBus::MatchRule.new.from_signal(self, name)
      if block.nil?
        bus.remove_match(mr)
      else
        bus.add_match(mr) { |msg| block.call(*msg.params) }
      end
    end

    PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze

    # Read a property.
    # @param propname [String]
    def [](propname)
      ret = object[PROPERTY_INTERFACE].Get(name, propname)
      # this method always returns the single property
      if @object.api.proxy_method_returns_array
        ret[0]
      else
        ret
      end
    end

    # Write a property.
    # @param propname [String]
    # @param value [Object]
    def []=(propname, value)
      object[PROPERTY_INTERFACE].Set(name, propname, value)
    end

    # Read all properties at once, as a hash.
    # @return [Hash{String}]
    def all_properties
      ret = object[PROPERTY_INTERFACE].GetAll(name)
      # this method always returns the single property
      if @object.api.proxy_method_returns_array
        ret[0]
      else
        ret
      end
    end
  end # class ProxyObjectInterface
end