ruby-dbus-openplacos 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|