ruby-dbus-openplacos 0.6.0
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.
- data/COPYING +504 -0
- data/NEWS +146 -0
- data/README +42 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/doc/tutorial/index.markdown +480 -0
- data/examples/gdbus/gdbus +255 -0
- data/examples/gdbus/gdbus.glade +184 -0
- data/examples/gdbus/launch.sh +4 -0
- data/examples/no-introspect/nm-test.rb +21 -0
- data/examples/no-introspect/tracker-test.rb +16 -0
- data/examples/rhythmbox/playpause.rb +25 -0
- data/examples/service/call_service.rb +25 -0
- data/examples/service/service_newapi.rb +51 -0
- data/examples/simple/call_introspect.rb +34 -0
- data/examples/simple/properties.rb +19 -0
- data/examples/utils/listnames.rb +11 -0
- data/examples/utils/notify.rb +19 -0
- data/lib/dbus/auth.rb +258 -0
- data/lib/dbus/bus.rb +947 -0
- data/lib/dbus/core_ext/class/attribute.rb +91 -0
- data/lib/dbus/core_ext/kernel/singleton_class.rb +14 -0
- data/lib/dbus/core_ext/module/remove_method.rb +12 -0
- data/lib/dbus/error.rb +44 -0
- data/lib/dbus/export.rb +124 -0
- data/lib/dbus/introspect.rb +570 -0
- data/lib/dbus/marshall.rb +443 -0
- data/lib/dbus/matchrule.rb +100 -0
- data/lib/dbus/message.rb +310 -0
- data/lib/dbus/type.rb +222 -0
- data/lib/dbus.rb +83 -0
- data/ruby-dbus-openplacos.gemspec +17 -0
- data/test/binding_test.rb +56 -0
- data/test/bus_driver_test.rb +22 -0
- data/test/dbus-launch-simple +35 -0
- data/test/dbus-limited-session.conf +28 -0
- data/test/property_test.rb +55 -0
- data/test/server_robustness_test.rb +72 -0
- data/test/server_test.rb +53 -0
- data/test/service_newapi.rb +197 -0
- data/test/session_bus_test_manual.rb +20 -0
- data/test/signal_test.rb +64 -0
- data/test/t1 +4 -0
- data/test/t2.rb +66 -0
- data/test/t3-ticket27.rb +18 -0
- data/test/t5-report-dbus-interface.rb +58 -0
- data/test/t6-loop.rb +82 -0
- data/test/test_env +13 -0
- data/test/test_server +39 -0
- data/test/variant_test.rb +66 -0
- metadata +118 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
# copied from activesupport/core_ext from Rails, MIT license
|
2
|
+
require 'dbus/core_ext/kernel/singleton_class'
|
3
|
+
require 'dbus/core_ext/module/remove_method'
|
4
|
+
|
5
|
+
class Class
|
6
|
+
# Declare a class-level attribute whose value is inheritable by subclasses.
|
7
|
+
# Subclasses can change their own value and it will not impact parent class.
|
8
|
+
#
|
9
|
+
# class Base
|
10
|
+
# class_attribute :setting
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class Subclass < Base
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# Base.setting = true
|
17
|
+
# Subclass.setting # => true
|
18
|
+
# Subclass.setting = false
|
19
|
+
# Subclass.setting # => false
|
20
|
+
# Base.setting # => true
|
21
|
+
#
|
22
|
+
# In the above case as long as Subclass does not assign a value to setting
|
23
|
+
# by performing <tt>Subclass.setting = _something_ </tt>, <tt>Subclass.setting</tt>
|
24
|
+
# would read value assigned to parent class. Once Subclass assigns a value then
|
25
|
+
# the value assigned by Subclass would be returned.
|
26
|
+
#
|
27
|
+
# This matches normal Ruby method inheritance: think of writing an attribute
|
28
|
+
# on a subclass as overriding the reader method. However, you need to be aware
|
29
|
+
# when using +class_attribute+ with mutable structures as +Array+ or +Hash+.
|
30
|
+
# In such cases, you don't want to do changes in places but use setters:
|
31
|
+
#
|
32
|
+
# Base.setting = []
|
33
|
+
# Base.setting # => []
|
34
|
+
# Subclass.setting # => []
|
35
|
+
#
|
36
|
+
# # Appending in child changes both parent and child because it is the same object:
|
37
|
+
# Subclass.setting << :foo
|
38
|
+
# Base.setting # => [:foo]
|
39
|
+
# Subclass.setting # => [:foo]
|
40
|
+
#
|
41
|
+
# # Use setters to not propagate changes:
|
42
|
+
# Base.setting = []
|
43
|
+
# Subclass.setting += [:foo]
|
44
|
+
# Base.setting # => []
|
45
|
+
# Subclass.setting # => [:foo]
|
46
|
+
#
|
47
|
+
# For convenience, a query method is defined as well:
|
48
|
+
#
|
49
|
+
# Subclass.setting? # => false
|
50
|
+
#
|
51
|
+
# Instances may overwrite the class value in the same way:
|
52
|
+
#
|
53
|
+
# Base.setting = true
|
54
|
+
# object = Base.new
|
55
|
+
# object.setting # => true
|
56
|
+
# object.setting = false
|
57
|
+
# object.setting # => false
|
58
|
+
# Base.setting # => true
|
59
|
+
#
|
60
|
+
# To opt out of the instance writer method, pass :instance_writer => false.
|
61
|
+
#
|
62
|
+
# object.setting = false # => NoMethodError
|
63
|
+
def class_attribute(*attrs)
|
64
|
+
instance_writer = !attrs.last.is_a?(Hash) || attrs.pop[:instance_writer]
|
65
|
+
|
66
|
+
attrs.each do |name|
|
67
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
68
|
+
def self.#{name}() nil end
|
69
|
+
def self.#{name}?() !!#{name} end
|
70
|
+
|
71
|
+
def self.#{name}=(val)
|
72
|
+
singleton_class.class_eval do
|
73
|
+
remove_possible_method(:#{name})
|
74
|
+
define_method(:#{name}) { val }
|
75
|
+
end
|
76
|
+
val
|
77
|
+
end
|
78
|
+
|
79
|
+
def #{name}
|
80
|
+
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
81
|
+
end
|
82
|
+
|
83
|
+
def #{name}?
|
84
|
+
!!#{name}
|
85
|
+
end
|
86
|
+
RUBY
|
87
|
+
|
88
|
+
attr_writer name if instance_writer
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# copied from activesupport/core_ext from Rails, MIT license
|
2
|
+
module Kernel
|
3
|
+
# Returns the object's singleton class.
|
4
|
+
def singleton_class
|
5
|
+
class << self
|
6
|
+
self
|
7
|
+
end
|
8
|
+
end unless respond_to?(:singleton_class) # exists in 1.9.2
|
9
|
+
|
10
|
+
# class_eval on an object acts like singleton_class.class_eval.
|
11
|
+
def class_eval(*args, &block)
|
12
|
+
singleton_class.class_eval(*args, &block)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# copied from activesupport/core_ext from Rails, MIT license
|
2
|
+
class Module
|
3
|
+
def remove_possible_method(method)
|
4
|
+
remove_method(method)
|
5
|
+
rescue NameError
|
6
|
+
end
|
7
|
+
|
8
|
+
def redefine_method(method, &block)
|
9
|
+
remove_possible_method(method)
|
10
|
+
define_method(method, &block)
|
11
|
+
end
|
12
|
+
end
|
data/lib/dbus/error.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# error.rb
|
2
|
+
#
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
9
|
+
# See the file "COPYING" for the exact licensing terms.
|
10
|
+
|
11
|
+
module DBus
|
12
|
+
# Represents a D-Bus Error, both on the client and server side.
|
13
|
+
class Error < StandardError
|
14
|
+
# error_name. +message+ is inherited from +Exception+
|
15
|
+
attr_reader :name
|
16
|
+
# for received errors, the raw D-Bus message
|
17
|
+
attr_reader :dbus_message
|
18
|
+
|
19
|
+
# If +msg+ is a +DBus::Message+, its contents is used for initialization.
|
20
|
+
# Otherwise, +msg+ is taken as a string and +name+ is used.
|
21
|
+
def initialize(msg, name = "org.freedesktop.DBus.Error.Failed")
|
22
|
+
if msg.is_a? DBus::Message
|
23
|
+
@dbus_message = msg
|
24
|
+
@name = msg.error_name
|
25
|
+
super(msg.params[0]) # or nil
|
26
|
+
if msg.params[1].is_a? Array
|
27
|
+
set_backtrace msg.params[1]
|
28
|
+
end
|
29
|
+
else
|
30
|
+
@name = name
|
31
|
+
super(msg)
|
32
|
+
end
|
33
|
+
# TODO validate error name
|
34
|
+
end
|
35
|
+
end # class Error
|
36
|
+
|
37
|
+
# raise DBus.error, "message"
|
38
|
+
# raise DBus.error("org.example.Error.SeatOccupied"), "Seat #{n} is occupied"
|
39
|
+
def error(name = "org.freedesktop.DBus.Error.Failed")
|
40
|
+
# message will be set by Kernel.raise
|
41
|
+
DBus::Error.new(nil, name)
|
42
|
+
end
|
43
|
+
module_function :error
|
44
|
+
end # module DBus
|
data/lib/dbus/export.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# dbus/introspection.rb - module containing a low-level D-Bus introspection implementation
|
2
|
+
#
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
9
|
+
# See the file "COPYING" for the exact licensing terms.
|
10
|
+
|
11
|
+
require 'thread'
|
12
|
+
|
13
|
+
module DBus
|
14
|
+
# Exported object type
|
15
|
+
# = Exportable D-Bus object class
|
16
|
+
#
|
17
|
+
# Objects that are going to be exported by a D-Bus service
|
18
|
+
# should inherit from this class.
|
19
|
+
class Object
|
20
|
+
# The path of the object.
|
21
|
+
attr_reader :path
|
22
|
+
# The interfaces that the object supports.
|
23
|
+
class_attribute :intfs
|
24
|
+
# The service that the object is exported by.
|
25
|
+
attr_writer :service
|
26
|
+
|
27
|
+
@@cur_intf = nil
|
28
|
+
@@intfs_mutex = Mutex.new
|
29
|
+
|
30
|
+
# Create a new object with a given _path_.
|
31
|
+
def initialize(path)
|
32
|
+
@path = path
|
33
|
+
@service = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# State that the object implements the given _intf_.
|
37
|
+
def implements(intf)
|
38
|
+
# use a setter
|
39
|
+
self.intfs = (self.intfs || {}).merge({intf.name => intf})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Dispatch a message _msg_.
|
43
|
+
def dispatch(msg)
|
44
|
+
case msg.message_type
|
45
|
+
when Message::METHOD_CALL
|
46
|
+
reply = nil
|
47
|
+
begin
|
48
|
+
if not self.intfs[msg.interface]
|
49
|
+
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
50
|
+
"Interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
51
|
+
end
|
52
|
+
meth = self.intfs[msg.interface].methods[msg.member.to_sym]
|
53
|
+
if not meth
|
54
|
+
raise DBus.error("org.freedesktop.DBus.Error.UnknownMethod"),
|
55
|
+
"Method \"#{msg.member}\" on interface \"#{msg.interface}\" of object \"#{msg.path}\" doesn't exist"
|
56
|
+
end
|
57
|
+
methname = Object.make_method_name(msg.interface, msg.member)
|
58
|
+
retdata = method(methname).call(*msg.params)
|
59
|
+
retdata = [*retdata]
|
60
|
+
|
61
|
+
reply = Message.method_return(msg)
|
62
|
+
meth.rets.zip(retdata).each do |rsig, rdata|
|
63
|
+
reply.add_param(rsig.type, rdata)
|
64
|
+
end
|
65
|
+
rescue => ex
|
66
|
+
reply = ErrorMessage.from_exception(ex).reply_to(msg)
|
67
|
+
end
|
68
|
+
@service.bus.send(reply.marshall)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Select (and create) the interface that the following defined methods
|
73
|
+
# belong to.
|
74
|
+
def self.dbus_interface(s)
|
75
|
+
@@intfs_mutex.synchronize do
|
76
|
+
@@cur_intf = Interface.new(s)
|
77
|
+
self.intfs = (self.intfs || {}).merge({s => @@cur_intf})
|
78
|
+
yield
|
79
|
+
@@cur_intf = nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Dummy undefined interface class.
|
84
|
+
class UndefinedInterface < ScriptError
|
85
|
+
def initialize(sym)
|
86
|
+
super "No interface specified for #{sym}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Defines an exportable method on the object with the given name _sym_,
|
91
|
+
# _prototype_ and the code in a block.
|
92
|
+
def self.dbus_method(sym, protoype = "", &block)
|
93
|
+
raise UndefinedInterface, sym if @@cur_intf.nil?
|
94
|
+
@@cur_intf.define(Method.new(sym.to_s).from_prototype(protoype))
|
95
|
+
define_method(Object.make_method_name(@@cur_intf.name, sym.to_s), &block)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Emits a signal from the object with the given _interface_, signal
|
99
|
+
# _sig_ and arguments _args_.
|
100
|
+
def emit(intf, sig, *args)
|
101
|
+
@service.bus.emit(@service, self, intf, sig, *args)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Defines a signal for the object with a given name _sym_ and _prototype_.
|
105
|
+
def self.dbus_signal(sym, protoype = "")
|
106
|
+
raise UndefinedInterface, sym if @@cur_intf.nil?
|
107
|
+
cur_intf = @@cur_intf
|
108
|
+
signal = Signal.new(sym.to_s).from_prototype(protoype)
|
109
|
+
cur_intf.define(Signal.new(sym.to_s).from_prototype(protoype))
|
110
|
+
define_method(sym.to_s) do |*args|
|
111
|
+
emit(cur_intf, signal, *args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
####################################################################
|
116
|
+
private
|
117
|
+
|
118
|
+
# Helper method that returns a method name generated from the interface
|
119
|
+
# name _intfname_ and method name _methname_.
|
120
|
+
def self.make_method_name(intfname, methname)
|
121
|
+
"#{intfname}%%#{methname}"
|
122
|
+
end
|
123
|
+
end # class Object
|
124
|
+
end # module DBus
|