File: service_newapi.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 (231 lines) | stat: -rwxr-xr-x 7,009 bytes parent folder | download | duplicates (2)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require_relative "spec_helper"
SimpleCov.command_name "Service Tests" if Object.const_defined? "SimpleCov"
# find the library without external help
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)

require "dbus"

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

class Test < DBus::Object
  INTERFACE = "org.ruby.SampleInterface".freeze
  def initialize(path)
    super path
    @read_me = "READ ME"
    @read_or_write_me = "READ OR WRITE ME"
  end

  # Create an interface aggregating all upcoming dbus_method defines.
  dbus_interface INTERFACE do
    dbus_method :hello, "in name:s, in name2:s" do |name, name2|
      puts "hello(#{name}, #{name2})"
    end

    dbus_method :test_variant, "in stuff:v" do |variant|
      DBus.logger.debug variant.inspect
    end

    dbus_method :bounce_variant, "in stuff:v, out chaff:v" do |variant|
      [variant]
    end

    dbus_method :variant_size, "in stuff:v, out size:u" do |variant|
      [variant.size]
    end

    dbus_method :the_answer, "out answer:i" do
      42
    end

    dbus_method :will_raise, "" do
      raise "Handle this"
    end

    dbus_method :will_raise_error_failed, "" do
      raise DBus.error, "failed as designed"
    end

    dbus_method :will_raise_name_error, "" do
      "foo".frobnicate
    end

    dbus_method :Error, "in name:s, in description:s" do |name, description|
      raise DBus.error(name), description
    end

    dbus_method :mirror_byte_array, "in bytes:ay, out mirrored:ay" do |bytes|
      [bytes]
    end
  end

  # closing and reopening the same interface
  dbus_interface INTERFACE do
    dbus_method :multibyte_string, "out string:s" do
      "あいうえお"
    end

    dbus_method :i16_plus, "in a:n, in b:n, out result:n" do |a, b|
      a + b
    end

    dbus_signal :SomethingJustHappened, "toto:s, tutu:u"
  end

  dbus_interface "org.ruby.AnotherInterface" do
    dbus_method :ThatsALongMethodNameIThink do
      puts "ThatsALongMethodNameIThink"
    end
    dbus_method :Reverse, "in instr:s, out outstr:s" do |instr|
      outstr = instr.split(//).reverse.join
      [outstr]
    end
  end

  dbus_interface "org.ruby.Ticket30" do
    dbus_method :Sybilla, "in choices:av, out advice:s" do |choices|
      ["Do #{choices[0]}"]
    end
  end

  dbus_interface "org.ruby.Duplicates" do
    dbus_method :the_answer, "out answer:i" do
      [0]
    end
    dbus_method :interfaces, "out answer:i" do
      raise "This DBus method is currently shadowed by ProxyObject#interfaces"
    end
  end

  dbus_interface "org.ruby.Loop" do
    # starts doing something long, but returns immediately
    # and sends a signal when done
    dbus_method :LongTaskBegin, "in delay:i" do |delay|
      # FIXME: did not complain about mismatch between signature and block args
      self.LongTaskStart
      DBus.logger.debug "Long task began"
      task = Thread.new do
        DBus.logger.debug "Long task thread started (#{delay}s)"
        sleep delay
        DBus.logger.debug "Long task will signal end"
        self.LongTaskEnd
      end
      task.abort_on_exception = true # protect from test case bugs
    end

    dbus_signal :LongTaskStart
    dbus_signal :LongTaskEnd
  end

  # Properties:
  # ReadMe:string, returns "READ ME" at first, then what WriteMe received
  # WriteMe:string
  # ReadOrWriteMe:string, returns "READ OR WRITE ME" at first
  dbus_interface PROPERTY_INTERFACE do
    dbus_method :Get, "in interface:s, in propname:s, out value:v" do |interface, propname|
      unless interface == INTERFACE
        raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
              "Interface '#{interface}' not found on object '#{@path}'"
      end

      case propname
      when "ReadMe"
        [@read_me]
      when "ReadOrWriteMe"
        [@read_or_write_me]
      when "WriteMe"
        raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
              "Property '#{interface}.#{propname}' (on object '#{@path}') is not readable"
      else
        # what should happen for unknown properties
        # plasma: InvalidArgs (propname), UnknownInterface (interface)
        raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
              "Property '#{interface}.#{propname}' not found on object '#{@path}'"
      end
    end

    dbus_method :Set, "in interface:s, in propname:s, in  value:v" do |interface, propname, value|
      unless interface == INTERFACE
        raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
              "Interface '#{interface}' not found on object '#{@path}'"
      end

      case propname
      when "ReadMe"
        raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
              "Property '#{interface}.#{propname}' (on object '#{@path}') is not writable"
      when "ReadOrWriteMe"
        @read_or_write_me = value
        self.PropertiesChanged(interface, { propname => value }, [])
      when "WriteMe"
        @read_me = value
        self.PropertiesChanged(interface, { "ReadMe" => value }, [])
      else
        raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
              "Property '#{interface}.#{propname}' not found on object '#{@path}'"
      end
    end

    dbus_method :GetAll, "in interface:s, out value:a{sv}" do |interface|
      unless interface == INTERFACE
        raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
              "Interface '#{interface}' not found on object '#{@path}'"
      end

      [
        {
          "ReadMe" => @read_me,
          "ReadOrWriteMe" => @read_or_write_me
        }
      ]
    end

    dbus_signal :PropertiesChanged, "interface:s, changed_properties:a{sv}, invalidated_properties:as"
  end
end

class Derived < Test
end

class Test2 < DBus::Object
  dbus_interface "org.ruby.Test2" do
    dbus_method :hi, "in name:s, out greeting:s" do |name|
      "Hi, #{name}!"
    end
  end
end

bus = DBus::SessionBus.instance
service = bus.request_service("org.ruby.service")
myobj = Test.new("/org/ruby/MyInstance")
service.export(myobj)
derived = Derived.new "/org/ruby/MyDerivedInstance"
service.export derived
test2 = Test2.new "/org/ruby/MyInstance2"
service.export test2

# introspect every other connection, Ticket #34
#  (except the one that activates us - it has already emitted
#  NOC by the time we run this. Therefore the test for #34 will not work
#  by running t2.rb alone, one has to run t1 before it; 'rake' does it)
mr = DBus::MatchRule.new.from_s "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'"
bus.add_match(mr) do |msg|
  new_unique_name = msg.params[2]
  unless new_unique_name.empty?
    DBus.logger.debug "RRRING #{new_unique_name}"
    bus.introspect_data(new_unique_name, "/") do
      # ignore the result
    end
  end
end

puts "listening, with ruby-#{RUBY_VERSION}"
main = DBus::Main.new
main << bus
begin
  main.run
rescue SystemCallError
  # the test driver will kill the bus, that's OK
end