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.
Files changed (51) hide show
  1. data/COPYING +504 -0
  2. data/NEWS +146 -0
  3. data/README +42 -0
  4. data/Rakefile +54 -0
  5. data/VERSION +1 -0
  6. data/doc/tutorial/index.markdown +480 -0
  7. data/examples/gdbus/gdbus +255 -0
  8. data/examples/gdbus/gdbus.glade +184 -0
  9. data/examples/gdbus/launch.sh +4 -0
  10. data/examples/no-introspect/nm-test.rb +21 -0
  11. data/examples/no-introspect/tracker-test.rb +16 -0
  12. data/examples/rhythmbox/playpause.rb +25 -0
  13. data/examples/service/call_service.rb +25 -0
  14. data/examples/service/service_newapi.rb +51 -0
  15. data/examples/simple/call_introspect.rb +34 -0
  16. data/examples/simple/properties.rb +19 -0
  17. data/examples/utils/listnames.rb +11 -0
  18. data/examples/utils/notify.rb +19 -0
  19. data/lib/dbus/auth.rb +258 -0
  20. data/lib/dbus/bus.rb +947 -0
  21. data/lib/dbus/core_ext/class/attribute.rb +91 -0
  22. data/lib/dbus/core_ext/kernel/singleton_class.rb +14 -0
  23. data/lib/dbus/core_ext/module/remove_method.rb +12 -0
  24. data/lib/dbus/error.rb +44 -0
  25. data/lib/dbus/export.rb +124 -0
  26. data/lib/dbus/introspect.rb +570 -0
  27. data/lib/dbus/marshall.rb +443 -0
  28. data/lib/dbus/matchrule.rb +100 -0
  29. data/lib/dbus/message.rb +310 -0
  30. data/lib/dbus/type.rb +222 -0
  31. data/lib/dbus.rb +83 -0
  32. data/ruby-dbus-openplacos.gemspec +17 -0
  33. data/test/binding_test.rb +56 -0
  34. data/test/bus_driver_test.rb +22 -0
  35. data/test/dbus-launch-simple +35 -0
  36. data/test/dbus-limited-session.conf +28 -0
  37. data/test/property_test.rb +55 -0
  38. data/test/server_robustness_test.rb +72 -0
  39. data/test/server_test.rb +53 -0
  40. data/test/service_newapi.rb +197 -0
  41. data/test/session_bus_test_manual.rb +20 -0
  42. data/test/signal_test.rb +64 -0
  43. data/test/t1 +4 -0
  44. data/test/t2.rb +66 -0
  45. data/test/t3-ticket27.rb +18 -0
  46. data/test/t5-report-dbus-interface.rb +58 -0
  47. data/test/t6-loop.rb +82 -0
  48. data/test/test_env +13 -0
  49. data/test/test_server +39 -0
  50. data/test/variant_test.rb +66 -0
  51. 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
@@ -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