ruby-dbus 0.17.0 → 0.18.0.beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +38 -0
- data/README.md +1 -1
- data/Rakefile +3 -11
- data/VERSION +1 -1
- data/doc/Reference.md +10 -3
- data/examples/doc/_extract_examples +2 -0
- data/examples/gdbus/gdbus +11 -5
- data/examples/no-introspect/nm-test.rb +2 -0
- data/examples/no-introspect/tracker-test.rb +3 -1
- data/examples/rhythmbox/playpause.rb +2 -1
- data/examples/service/call_service.rb +1 -0
- data/examples/service/complex-property.rb +21 -0
- data/examples/service/service_newapi.rb +1 -1
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +2 -1
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +1 -0
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +12 -7
- data/lib/dbus/bus.rb +114 -70
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/data.rb +744 -0
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +30 -18
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +229 -293
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +44 -37
- data/lib/dbus/message_queue.rb +10 -5
- data/lib/dbus/object.rb +36 -15
- data/lib/dbus/object_path.rb +11 -6
- data/lib/dbus/proxy_object.rb +18 -4
- data/lib/dbus/proxy_object_factory.rb +11 -7
- data/lib/dbus/proxy_object_interface.rb +26 -22
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +164 -80
- data/lib/dbus/xml.rb +28 -17
- data/lib/dbus.rb +13 -7
- data/ruby-dbus.gemspec +4 -2
- data/spec/async_spec.rb +2 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +2 -0
- data/spec/bus_driver_spec.rb +2 -0
- data/spec/bus_name_spec.rb +3 -1
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +4 -2
- data/spec/data/marshall.yaml +1639 -0
- data/spec/data_spec.rb +353 -0
- data/spec/err_msg_spec.rb +2 -0
- data/spec/introspect_xml_parser_spec.rb +2 -0
- data/spec/introspection_spec.rb +2 -0
- data/spec/main_loop_spec.rb +2 -0
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +3 -0
- data/spec/packet_marshaller_spec.rb +34 -0
- data/spec/packet_unmarshaller_spec.rb +262 -0
- data/spec/property_spec.rb +60 -2
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/server_robustness_spec.rb +2 -0
- data/spec/server_spec.rb +2 -0
- data/spec/service_newapi.rb +37 -4
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +2 -0
- data/spec/spec_helper.rb +19 -3
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/type_spec.rb +69 -6
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- data/spec/zzz_quit_spec.rb +16 -0
- metadata +16 -7
data/lib/dbus/message.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# dbus.rb - Module containing the low-level D-Bus implementation
|
2
4
|
#
|
3
5
|
# This file is part of the ruby-dbus project
|
@@ -27,7 +29,7 @@ module DBus
|
|
27
29
|
# Mutex that protects updates on the serial number.
|
28
30
|
@@serial_mutex = Mutex.new
|
29
31
|
# Type of a message (by specification).
|
30
|
-
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
32
|
+
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
31
33
|
|
32
34
|
# FIXME: following message type constants should be under Message::Type IMO
|
33
35
|
# well, yeah sure
|
@@ -43,6 +45,9 @@ module DBus
|
|
43
45
|
# Signal message type.
|
44
46
|
SIGNAL = 4
|
45
47
|
|
48
|
+
# Names used by signal match rules
|
49
|
+
TYPE_NAMES = ["invalid", "method_call", "method_return", "error", "signal"].freeze
|
50
|
+
|
46
51
|
# Message flag signyfing that no reply is expected.
|
47
52
|
NO_REPLY_EXPECTED = 0x1
|
48
53
|
# Message flag signifying that no automatic start is required/must be
|
@@ -66,11 +71,13 @@ module DBus
|
|
66
71
|
attr_accessor :sender
|
67
72
|
# The signature of the message contents.
|
68
73
|
attr_accessor :signature
|
69
|
-
#
|
74
|
+
# @return [Integer] (u32)
|
75
|
+
# The serial number of the message this message is a reply for.
|
70
76
|
attr_accessor :reply_serial
|
71
77
|
# The protocol.
|
72
78
|
attr_reader :protocol
|
73
|
-
#
|
79
|
+
# @return [Integer] (u32)
|
80
|
+
# The serial of the message.
|
74
81
|
attr_reader :serial
|
75
82
|
# The parameters of the message.
|
76
83
|
attr_reader :params
|
@@ -105,22 +112,28 @@ module DBus
|
|
105
112
|
"error_name=#{error_name}"
|
106
113
|
end
|
107
114
|
|
108
|
-
#
|
109
|
-
|
110
|
-
|
115
|
+
# @return [String] name of message type, as used in match rules:
|
116
|
+
# "method_call", "method_return", "signal", "error"
|
117
|
+
def message_type_s
|
118
|
+
TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
|
111
119
|
end
|
112
120
|
|
113
|
-
# Create
|
114
|
-
def self.
|
115
|
-
|
121
|
+
# Create a regular reply to a message _msg_.
|
122
|
+
def self.method_return(msg)
|
123
|
+
MethodReturnMessage.new.reply_to(msg)
|
116
124
|
end
|
117
125
|
|
118
|
-
#
|
119
|
-
|
126
|
+
# Create an error reply to a message _msg_.
|
127
|
+
def self.error(msg, error_name, description = nil)
|
128
|
+
ErrorMessage.new(error_name, description).reply_to(msg)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Mark this message as a reply to a another message _msg_, taking
|
132
|
+
# the serial number of _msg_ as reply serial and the sender of _msg_ as
|
120
133
|
# destination.
|
121
|
-
def reply_to(
|
122
|
-
@reply_serial =
|
123
|
-
@destination =
|
134
|
+
def reply_to(msg)
|
135
|
+
@reply_serial = msg.serial
|
136
|
+
@destination = msg.sender
|
124
137
|
self
|
125
138
|
end
|
126
139
|
|
@@ -159,7 +172,7 @@ module DBus
|
|
159
172
|
@body_length = params.packet.bytesize
|
160
173
|
|
161
174
|
marshaller = PacketMarshaller.new
|
162
|
-
marshaller.append(Type::BYTE, HOST_END)
|
175
|
+
marshaller.append(Type::BYTE, HOST_END.ord)
|
163
176
|
marshaller.append(Type::BYTE, @message_type)
|
164
177
|
marshaller.append(Type::BYTE, @flags)
|
165
178
|
marshaller.append(Type::BYTE, @protocol)
|
@@ -191,13 +204,7 @@ module DBus
|
|
191
204
|
# the detected message (self) and
|
192
205
|
# the index pointer of the buffer where the message data ended.
|
193
206
|
def unmarshall_buffer(buf)
|
194
|
-
|
195
|
-
endianness = if buf[0] == "l"
|
196
|
-
LIL_END
|
197
|
-
else
|
198
|
-
BIG_END
|
199
|
-
end
|
200
|
-
pu = PacketUnmarshaller.new(buf, endianness)
|
207
|
+
pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
|
201
208
|
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
202
209
|
_, @message_type, @flags, @protocol, @body_length, @serial,
|
203
210
|
headers = mdata
|
@@ -222,21 +229,21 @@ module DBus
|
|
222
229
|
@signature = struct[1]
|
223
230
|
end
|
224
231
|
end
|
225
|
-
pu.
|
226
|
-
if @body_length
|
232
|
+
pu.align_body
|
233
|
+
if @body_length.positive? && @signature
|
227
234
|
@params = pu.unmarshall(@signature, @body_length)
|
228
235
|
end
|
229
|
-
[self, pu.
|
236
|
+
[self, pu.consumed_size]
|
230
237
|
end
|
231
238
|
|
232
239
|
# Make a new exception from ex, mark it as being caused by this message
|
233
240
|
# @api private
|
234
|
-
def annotate_exception(
|
235
|
-
|
236
|
-
|
237
|
-
|
241
|
+
def annotate_exception(exc)
|
242
|
+
new_exc = exc.exception("#{exc}; caused by #{self}")
|
243
|
+
new_exc.set_backtrace(exc.backtrace)
|
244
|
+
new_exc
|
238
245
|
end
|
239
|
-
end
|
246
|
+
end
|
240
247
|
|
241
248
|
class MethodReturnMessage < Message
|
242
249
|
def initialize
|
@@ -251,17 +258,17 @@ module DBus
|
|
251
258
|
add_param(Type::STRING, description) unless description.nil?
|
252
259
|
end
|
253
260
|
|
254
|
-
def self.from_exception(
|
255
|
-
name = if
|
256
|
-
|
261
|
+
def self.from_exception(exc)
|
262
|
+
name = if exc.is_a? DBus::Error
|
263
|
+
exc.name
|
257
264
|
else
|
258
265
|
"org.freedesktop.DBus.Error.Failed"
|
259
|
-
#
|
266
|
+
# exc.class.to_s # RuntimeError is not a valid name, has no dot
|
260
267
|
end
|
261
|
-
description =
|
268
|
+
description = exc.message
|
262
269
|
msg = new(name, description)
|
263
|
-
msg.add_param(DBus.type("as"),
|
270
|
+
msg.add_param(DBus.type("as"), exc.backtrace)
|
264
271
|
msg
|
265
272
|
end
|
266
273
|
end
|
267
|
-
end
|
274
|
+
end
|
data/lib/dbus/message_queue.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -23,14 +25,16 @@ module DBus
|
|
23
25
|
connect
|
24
26
|
end
|
25
27
|
|
26
|
-
# @param
|
28
|
+
# @param blocking [Boolean]
|
29
|
+
# true: wait to return a {Message};
|
30
|
+
# false: may return `nil`
|
27
31
|
# @return [Message,nil] one message or nil if unavailable
|
28
32
|
# @raise EOFError
|
29
33
|
# @todo failure modes
|
30
|
-
def pop(
|
34
|
+
def pop(blocking: true)
|
31
35
|
buffer_from_socket_nonblock
|
32
36
|
message = message_from_buffer_nonblock
|
33
|
-
|
37
|
+
if blocking
|
34
38
|
# we can block
|
35
39
|
while message.nil?
|
36
40
|
r, _d, _d = IO.select([@socket])
|
@@ -54,7 +58,7 @@ module DBus
|
|
54
58
|
def connect
|
55
59
|
addresses = @address.split ";"
|
56
60
|
# connect to first one that succeeds
|
57
|
-
|
61
|
+
addresses.find do |a|
|
58
62
|
transport, keyvaluestring = a.split ":"
|
59
63
|
kv_list = keyvaluestring.split ","
|
60
64
|
kv_hash = {}
|
@@ -74,7 +78,6 @@ module DBus
|
|
74
78
|
# ignore, report?
|
75
79
|
end
|
76
80
|
end
|
77
|
-
worked
|
78
81
|
# returns the address that worked or nil.
|
79
82
|
# how to report failure?
|
80
83
|
end
|
@@ -136,6 +139,7 @@ module DBus
|
|
136
139
|
# @return [Message,nil] the message or nil if unavailable
|
137
140
|
def message_from_buffer_nonblock
|
138
141
|
return nil if @buffer.empty?
|
142
|
+
|
139
143
|
ret = nil
|
140
144
|
begin
|
141
145
|
ret, size = Message.new.unmarshall_buffer(@buffer)
|
@@ -162,6 +166,7 @@ module DBus
|
|
162
166
|
rescue Exception => e
|
163
167
|
puts "Oops:", e
|
164
168
|
raise if @is_tcp # why?
|
169
|
+
|
165
170
|
puts "WARNING: read_nonblock failed, falling back to .recv"
|
166
171
|
@buffer += @socket.recv(MSG_BUF_SIZE)
|
167
172
|
end
|
data/lib/dbus/object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
#
|
@@ -6,11 +8,10 @@
|
|
6
8
|
# License, version 2.1 as published by the Free Software Foundation.
|
7
9
|
# See the file "COPYING" for the exact licensing terms.
|
8
10
|
|
9
|
-
require "thread"
|
10
11
|
require_relative "core_ext/class/attribute"
|
11
12
|
|
12
13
|
module DBus
|
13
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
14
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
14
15
|
|
15
16
|
# Exported object type
|
16
17
|
# = Exportable D-Bus object class
|
@@ -20,6 +21,7 @@ module DBus
|
|
20
21
|
class Object
|
21
22
|
# The path of the object.
|
22
23
|
attr_reader :path
|
24
|
+
|
23
25
|
# The interfaces that the object supports. Hash: String => Interface
|
24
26
|
my_class_attribute :intfs
|
25
27
|
self.intfs = {}
|
@@ -43,11 +45,13 @@ module DBus
|
|
43
45
|
when Message::METHOD_CALL
|
44
46
|
reply = nil
|
45
47
|
begin
|
46
|
-
|
48
|
+
iface = intfs[msg.interface]
|
49
|
+
if !iface
|
47
50
|
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
48
51
|
"Interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
49
52
|
end
|
50
|
-
|
53
|
+
member_sym = msg.member.to_sym
|
54
|
+
meth = iface.methods[member_sym]
|
51
55
|
if !meth
|
52
56
|
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
53
57
|
"Method \"#{msg.member}\" on interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
@@ -57,11 +61,12 @@ module DBus
|
|
57
61
|
retdata = [*retdata]
|
58
62
|
|
59
63
|
reply = Message.method_return(msg)
|
60
|
-
meth.rets.
|
61
|
-
|
64
|
+
rsigs = meth.rets.map(&:type)
|
65
|
+
rsigs.zip(retdata).each do |rsig, rdata|
|
66
|
+
reply.add_param(rsig, rdata)
|
62
67
|
end
|
63
|
-
rescue StandardError =>
|
64
|
-
dbus_msg_exc = msg.annotate_exception(
|
68
|
+
rescue StandardError => e
|
69
|
+
dbus_msg_exc = msg.annotate_exception(e)
|
65
70
|
reply = ErrorMessage.from_exception(dbus_msg_exc).reply_to(msg)
|
66
71
|
end
|
67
72
|
@service.bus.message_queue.push(reply)
|
@@ -70,17 +75,19 @@ module DBus
|
|
70
75
|
|
71
76
|
# Select (and create) the interface that the following defined methods
|
72
77
|
# belong to.
|
73
|
-
|
78
|
+
# @param name [String] interface name like "org.example.ManagerManager"
|
79
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-interface
|
80
|
+
def self.dbus_interface(name)
|
74
81
|
@@intfs_mutex.synchronize do
|
75
|
-
@@cur_intf = intfs[
|
82
|
+
@@cur_intf = intfs[name]
|
76
83
|
if !@@cur_intf
|
77
|
-
@@cur_intf = Interface.new(
|
84
|
+
@@cur_intf = Interface.new(name) # validates the name
|
78
85
|
# As this is a mutable class_attr, we cannot use
|
79
|
-
# self.intfs[
|
86
|
+
# self.intfs[name] = @@cur_intf # Hash#[]=
|
80
87
|
# as that would modify parent class attr in place.
|
81
88
|
# Using the setter lets a subclass have the new value
|
82
89
|
# while the superclass keeps the old one.
|
83
|
-
self.intfs = intfs.merge(
|
90
|
+
self.intfs = intfs.merge(name => @@cur_intf)
|
84
91
|
end
|
85
92
|
yield
|
86
93
|
@@cur_intf = nil
|
@@ -110,6 +117,7 @@ module DBus
|
|
110
117
|
# @return [void]
|
111
118
|
def self.dbus_attr_accessor(ruby_name, type, dbus_name: nil)
|
112
119
|
attr_accessor(ruby_name)
|
120
|
+
|
113
121
|
dbus_accessor(ruby_name, type, dbus_name: dbus_name)
|
114
122
|
end
|
115
123
|
|
@@ -129,6 +137,7 @@ module DBus
|
|
129
137
|
# @return (see .dbus_attr_accessor)
|
130
138
|
def self.dbus_attr_reader(ruby_name, type, dbus_name: nil)
|
131
139
|
attr_reader(ruby_name)
|
140
|
+
|
132
141
|
dbus_reader(ruby_name, type, dbus_name: dbus_name)
|
133
142
|
end
|
134
143
|
|
@@ -139,6 +148,7 @@ module DBus
|
|
139
148
|
# @return (see .dbus_attr_accessor)
|
140
149
|
def self.dbus_attr_writer(ruby_name, type, dbus_name: nil)
|
141
150
|
attr_writer(ruby_name)
|
151
|
+
|
142
152
|
dbus_writer(ruby_name, type, dbus_name: dbus_name)
|
143
153
|
end
|
144
154
|
|
@@ -211,6 +221,7 @@ module DBus
|
|
211
221
|
# @return [void]
|
212
222
|
def self.dbus_watcher(ruby_name, dbus_name: nil)
|
213
223
|
raise UndefinedInterface, ruby_name if @@cur_intf.nil?
|
224
|
+
|
214
225
|
cur_intf = @@cur_intf
|
215
226
|
|
216
227
|
ruby_name = ruby_name.to_s.sub(/=$/, "").to_sym
|
@@ -235,6 +246,7 @@ module DBus
|
|
235
246
|
# @param prototype [Prototype]
|
236
247
|
def self.dbus_method(sym, prototype = "", &block)
|
237
248
|
raise UndefinedInterface, sym if @@cur_intf.nil?
|
249
|
+
|
238
250
|
@@cur_intf.define(Method.new(sym.to_s).from_prototype(prototype))
|
239
251
|
|
240
252
|
ruby_name = Object.make_method_name(@@cur_intf.name, sym.to_s)
|
@@ -254,6 +266,7 @@ module DBus
|
|
254
266
|
# Defines a signal for the object with a given name _sym_ and _prototype_.
|
255
267
|
def self.dbus_signal(sym, prototype = "")
|
256
268
|
raise UndefinedInterface, sym if @@cur_intf.nil?
|
269
|
+
|
257
270
|
cur_intf = @@cur_intf
|
258
271
|
signal = Signal.new(sym.to_s).from_prototype(prototype)
|
259
272
|
cur_intf.define(Signal.new(sym.to_s).from_prototype(prototype))
|
@@ -324,7 +337,9 @@ module DBus
|
|
324
337
|
if property.readable?
|
325
338
|
ruby_name = property.ruby_name
|
326
339
|
value = public_send(ruby_name)
|
327
|
-
|
340
|
+
# may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
|
341
|
+
typed_value = Data.make_typed(property.type, value)
|
342
|
+
[typed_value]
|
328
343
|
else
|
329
344
|
raise DBus.error("org.freedesktop.DBus.Error.PropertyWriteOnly"),
|
330
345
|
"Property '#{interface_name}.#{property_name}' (on object '#{@path}') is not readable"
|
@@ -336,6 +351,9 @@ module DBus
|
|
336
351
|
|
337
352
|
if property.writable?
|
338
353
|
ruby_name_eq = "#{property.ruby_name}="
|
354
|
+
# TODO: declare dbus_method :Set to take :exact argument
|
355
|
+
# and type check it here before passing its :plain value
|
356
|
+
# to the implementation
|
339
357
|
public_send(ruby_name_eq, value)
|
340
358
|
else
|
341
359
|
raise DBus.error("org.freedesktop.DBus.Error.PropertyReadOnly"),
|
@@ -364,7 +382,10 @@ module DBus
|
|
364
382
|
# > array.
|
365
383
|
# so we will silently omit properties that fail to read.
|
366
384
|
# Get'ting them individually will send DBus.Error
|
367
|
-
|
385
|
+
value = public_send(ruby_name)
|
386
|
+
# may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
|
387
|
+
typed_value = Data.make_typed(property.type, value)
|
388
|
+
p_hash[p_name.to_s] = typed_value
|
368
389
|
rescue StandardError
|
369
390
|
DBus.logger.debug "Property '#{interface_name}.#{p_name}' (on object '#{@path}')" \
|
370
391
|
" has raised during GetAll, omitting it"
|
data/lib/dbus/object_path.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2019 Martin Vidner
|
3
5
|
#
|
@@ -7,18 +9,21 @@
|
|
7
9
|
# See the file "COPYING" for the exact licensing terms.
|
8
10
|
|
9
11
|
module DBus
|
10
|
-
# A {::String} that validates at initialization time
|
12
|
+
# A {::String} that validates at initialization time.
|
13
|
+
# See also {DBus::Data::ObjectPath}
|
14
|
+
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
|
11
15
|
class ObjectPath < String
|
12
16
|
# @raise Error if not a valid object path
|
13
|
-
def initialize(
|
14
|
-
unless self.class.valid?(
|
15
|
-
raise DBus::Error, "Invalid object path #{
|
17
|
+
def initialize(str)
|
18
|
+
unless self.class.valid?(str)
|
19
|
+
raise DBus::Error, "Invalid object path #{str.inspect}"
|
16
20
|
end
|
21
|
+
|
17
22
|
super
|
18
23
|
end
|
19
24
|
|
20
|
-
def self.valid?(
|
21
|
-
|
25
|
+
def self.valid?(str)
|
26
|
+
str == "/" || str =~ %r{\A(/[A-Za-z0-9_]+)+\z}
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
data/lib/dbus/proxy_object.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -57,6 +59,7 @@ module DBus
|
|
57
59
|
introspect unless introspected
|
58
60
|
ifc = @interfaces[intfname]
|
59
61
|
raise DBus::Error, "no such interface `#{intfname}' on object `#{@path}'" unless ifc
|
62
|
+
|
60
63
|
ifc
|
61
64
|
end
|
62
65
|
|
@@ -93,6 +96,7 @@ module DBus
|
|
93
96
|
# don't overwrite instance methods!
|
94
97
|
next if dup_meths.include?(name)
|
95
98
|
next if self.class.instance_methods.include?(name)
|
99
|
+
|
96
100
|
if univocal_meths.include? name
|
97
101
|
univocal_meths.delete name
|
98
102
|
dup_meths << name
|
@@ -124,14 +128,17 @@ module DBus
|
|
124
128
|
def on_signal(name, &block)
|
125
129
|
# TODO: improve
|
126
130
|
raise NoMethodError unless @default_iface && has_iface?(@default_iface)
|
131
|
+
|
127
132
|
@interfaces[@default_iface].on_signal(name, &block)
|
128
133
|
end
|
129
134
|
|
130
135
|
####################################################
|
131
136
|
private
|
132
137
|
|
133
|
-
# rubocop:disable
|
134
|
-
#
|
138
|
+
# rubocop:disable Lint/MissingSuper
|
139
|
+
# as this should forward everything
|
140
|
+
#
|
141
|
+
# https://github.com/rubocop-hq/ruby-style-guide#no-method-missing
|
135
142
|
# and http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/
|
136
143
|
# have a point to be investigated
|
137
144
|
|
@@ -152,10 +159,17 @@ module DBus
|
|
152
159
|
# interesting, foo.method("unknown")
|
153
160
|
# raises NameError, not NoMethodError
|
154
161
|
raise unless e.to_s =~ /undefined method `#{name}'/
|
162
|
+
|
155
163
|
# BTW e.exception("...") would preserve the class.
|
156
164
|
raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
|
157
165
|
end
|
158
166
|
end
|
159
|
-
# rubocop:enable
|
160
|
-
|
167
|
+
# rubocop:enable Lint/MissingSuper
|
168
|
+
|
169
|
+
def respond_to_missing?(name, _include_private = false)
|
170
|
+
@default_iface &&
|
171
|
+
has_iface?(@default_iface) &&
|
172
|
+
@interfaces[@default_iface].methods.key?(name) or super
|
173
|
+
end
|
174
|
+
end
|
161
175
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -22,17 +24,19 @@ module DBus
|
|
22
24
|
@api = api
|
23
25
|
end
|
24
26
|
|
25
|
-
# Investigates the sub-nodes of the proxy object
|
27
|
+
# Investigates the sub-nodes of the proxy object _pobj_ based on the
|
26
28
|
# introspection XML data _xml_ and sets them up recursively.
|
27
|
-
|
28
|
-
|
29
|
+
# @param pobj [ProxyObject]
|
30
|
+
# @param xml [String]
|
31
|
+
def self.introspect_into(pobj, xml)
|
32
|
+
intfs, pobj.subnodes = IntrospectXMLParser.new(xml).parse
|
29
33
|
intfs.each do |i|
|
30
|
-
poi = ProxyObjectInterface.new(
|
34
|
+
poi = ProxyObjectInterface.new(pobj, i.name)
|
31
35
|
i.methods.each_value { |m| poi.define(m) }
|
32
36
|
i.signals.each_value { |s| poi.define(s) }
|
33
|
-
|
37
|
+
pobj[i.name] = poi
|
34
38
|
end
|
35
|
-
|
39
|
+
pobj.introspected = true
|
36
40
|
end
|
37
41
|
|
38
42
|
# Generates, sets up and returns the proxy object.
|
@@ -41,5 +45,5 @@ module DBus
|
|
41
45
|
ProxyObjectFactory.introspect_into(po, @xml)
|
42
46
|
po
|
43
47
|
end
|
44
|
-
end
|
48
|
+
end
|
45
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of the ruby-dbus project
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
@@ -36,27 +38,28 @@ module DBus
|
|
36
38
|
@name
|
37
39
|
end
|
38
40
|
|
39
|
-
# Defines a method on the interface from the Method descriptor
|
40
|
-
|
41
|
-
|
41
|
+
# Defines a method on the interface from the Method descriptor _method_.
|
42
|
+
# @param method [Method]
|
43
|
+
def define_method_from_descriptor(method)
|
44
|
+
method.params.each do |fpar|
|
42
45
|
par = fpar.type
|
43
46
|
# This is the signature validity check
|
44
47
|
Type::Parser.new(par).parse
|
45
48
|
end
|
46
49
|
|
47
50
|
singleton_class.class_eval do
|
48
|
-
define_method
|
49
|
-
if
|
50
|
-
raise ArgumentError, "wrong number of arguments (#{args.size} for #{
|
51
|
+
define_method method.name do |*args, &reply_handler|
|
52
|
+
if method.params.size != args.size
|
53
|
+
raise ArgumentError, "wrong number of arguments (#{args.size} for #{method.params.size})"
|
51
54
|
end
|
52
55
|
|
53
56
|
msg = Message.new(Message::METHOD_CALL)
|
54
57
|
msg.path = @object.path
|
55
58
|
msg.interface = @name
|
56
59
|
msg.destination = @object.destination
|
57
|
-
msg.member =
|
60
|
+
msg.member = method.name
|
58
61
|
msg.sender = @object.bus.unique_name
|
59
|
-
|
62
|
+
method.params.each do |fpar|
|
60
63
|
par = fpar.type
|
61
64
|
msg.add_param(par, args.shift)
|
62
65
|
end
|
@@ -64,30 +67,31 @@ module DBus
|
|
64
67
|
if ret.nil? || @object.api.proxy_method_returns_array
|
65
68
|
ret
|
66
69
|
else
|
67
|
-
|
70
|
+
method.rets.size == 1 ? ret.first : ret
|
68
71
|
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
|
72
|
-
@methods[
|
75
|
+
@methods[method.name] = method
|
73
76
|
end
|
74
77
|
|
75
|
-
# Defines a signal from the descriptor
|
76
|
-
|
77
|
-
|
78
|
+
# Defines a signal from the descriptor _sig_.
|
79
|
+
# @param sig [Signal]
|
80
|
+
def define_signal_from_descriptor(sig)
|
81
|
+
@signals[sig.name] = sig
|
78
82
|
end
|
79
83
|
|
80
|
-
# Defines a signal or method based on the descriptor
|
81
|
-
def define(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
84
|
+
# Defines a signal or method based on the descriptor _ifc_el_.
|
85
|
+
def define(ifc_el)
|
86
|
+
case ifc_el
|
87
|
+
when Method
|
88
|
+
define_method_from_descriptor(ifc_el)
|
89
|
+
when Signal
|
90
|
+
define_signal_from_descriptor(ifc_el)
|
86
91
|
end
|
87
92
|
end
|
88
93
|
|
89
94
|
# Defines a proxied method on the interface.
|
90
|
-
# Better name: declare_method
|
91
95
|
def define_method(methodname, prototype)
|
92
96
|
m = Method.new(methodname)
|
93
97
|
m.from_prototype(prototype)
|
@@ -110,7 +114,7 @@ module DBus
|
|
110
114
|
end
|
111
115
|
end
|
112
116
|
|
113
|
-
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
117
|
+
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
114
118
|
|
115
119
|
# Read a property.
|
116
120
|
# @param propname [String]
|
@@ -142,5 +146,5 @@ module DBus
|
|
142
146
|
ret
|
143
147
|
end
|
144
148
|
end
|
145
|
-
end
|
149
|
+
end
|
146
150
|
end
|