最近更新: 2010-03-14

Write a D-Bus service by Ruby

Install Ruby DBus

前往 ruby-dbus ,下載壓縮包 (tarball) 並解壓。

詳細安裝方式請閱讀壓縮包內的 README ,基本上只需要執行下列三個動作:

  1. ruby setup.rb config
  2. ruby setup.rb setup
  3. sudo ruby setup.rb install

Test:


irb> require 'dbus'
true

Write a D-Bus service

#!/usr/bin/ruby
# coding: utf-8
=begin rdoc
= Ruby DBus example

Ruby D-Bus Tutorial:
http://trac.luon.net/data/ruby-dbus/tutorial/index.html

Ruby D-Bus implementation:
https://trac.luon.net/ruby-dbus/

查詢 Hello service:
dbus-send --session --print-reply \
    --dest=blog.rock.hello \
    /blog/rock/hello \
    org.freedesktop.DBus.Introspectable.Introspect

調用 say method:
dbus-send --session --print-reply --dest=blog.rock.hello \
    /blog/rock/hello \
    blog.rock.hello.say \
    string:"Hello" boolean:true

調用 stop method:
dbus-send --session --print-reply --dest=blog.rock.hello \
    /blog/rock/hello \
    blog.rock.hello.stop

觸發 event_say signal:
dbus-send --session --print-reply --dest=blog.rock.hello \
    --type=signal /blog/rock/hello \
    blog.rock.hello.event_say \
    string:"Signal hello"

=end

require 'dbus'

=begin rdoc

Hello service

Inheriting from DBus::Object

DBus Service name: blog.rock.hello

=end
class Hello < DBus::Object
    @@name = 'blog.rock.hello'
    @@path = '/' + @@name.tr('.', '/')

    # Service name
    def self.name
        @@name
    end

    # Service object path
    def self.path
        @@path
    end

    # Export interface, *blog.rock.hello*, in this service.
    # One DBus service could have many interfaces.
    dbus_interface 'blog.rock.hello' do

        # Export *say* method in this interface.
        # say(message, timeout)
        #
        # in: input arguments
        # out: output
        # s: type string
        # b: type boolean
        # http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures
        dbus_method :say, "in message:s, in timeout:b, out reply:s" do |message, timeout|
            puts "[INFO] message: #{message}, timeout: #{timeout}"

            notify 'Say', message, timeout

            return "I say #{message}"
        end

        # Export *stop* method in this interface.
        # stop()
        dbus_method :stop do
            main_quit
        end

        # Export *event_say* signal in this interface.
        # yield message
        #
        # Signal only accepts input arguments.
        dbus_signal :event_say, "message:s"

    end

    attr_reader :bus

    def initialize
        # @bus = DBus::SessionBus.instance
        #  or
        @bus = DBus.session_bus

        super(@@path)

        service = bus.request_service(@@name)
        service.export(self)

        init_notifier
    end

  private
    def init_notifier  #:nodoc:
        notifications_service = 'org.freedesktop.Notifications'
        notifications_object = '/' + notifications_service.tr('.', '/')
        notifications_interface = notifications_service

        @notifier = bus.service(notifications_service).object(notifications_object)
        # This is a proxy object.

        # We need to do this before invoke any dbus method.
        # This fills in instance.
        @notifier.introspect

        # Set default interface.
        @notifier.default_iface = notifications_interface
    end

    def notify(title='', message='', timeout=false, icon='icon')  #:nodoc:
        @notifier.Notify('Hello', 0, icon, title, message, [], {}, timeout ? 1 : 0)
    end
end

=begin rdoc
Signal Recipient

Listen to *event_say* of blog.rock.hello.

=end
class SignalRecipient
    def initialize
        bus = DBus.session_bus

        hello_service = Hello.name
        hello_path = Hello.path
        hello_interface = Hello.name

        hello_object = bus.service(hello_service).object(hello_path)
        # This is a proxy object.

        # We need to do this before invoke any method.
        # This fills in instance.
        hello_object.introspect

        # Waiting for a signal
        # 指定介面與訊號名稱
        # event_say pass a string:message.
        hello_interface_object = hello_object[hello_interface]
        hello_interface_object.on_signal(bus, 'event_say') do |message|
            puts "I get signal(#{message})"
        end
    end
end

def main_quit
    $main.quit
end

service = Hello.new
recipient = SignalRecipient.new

puts "Working..."

$main = DBus::Main.new
$main << service.bus
$main.run
D-Bus signal

有 2 種方式綁定 D-Bus signal。

第一種方式: bind with interface。interface.on_signal(bus, signal_name, &block)

    hello_interface_object = hello_object[hello_interface]
    hello_interface_object.on_signal(bus, 'event_say') do |message|
        puts "I get signal(#{message})"
    end

第二種方式: bind with proxy object。object.on_signal(signal_name, &block)

    # You must set default_iface before bind the signal.
    hello_object.default_iface = hello_interface
    hello_object.on_signal('event_say') do |message|
        puts "I get signal(#{message})"
    end
相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/11949071.html