前兩天,我在觀看 PHP Manual 中新增的 Gearman 和 mqseries 兩個擴充元件的內容。我一邊想著 PHP 連 IBM WebSphere MQ Series 這種 Message bus 都支援了,真是不錯;另一邊又想起好一陣子沒留意 PHP 的 D-Bus 相關消息了。於是搜尋了一下,這次找到了兩個 php-dbus 擴充元件,版本都還在 0.1.x ,文件也非常匱乏。不過我還是看了它們的源碼文件,安裝並撰寫一些 D-Bus 應用。就結果而言,現在已經可以使用 PHP 撰寫基本的 D-Bus 客戶端應用工具了。
目前有兩套 php-dbus 擴充元件:
- GREE Labs's php-dbus
GREE 這套的實作內容有限,你無法用它補捉 D-Bus signal 。也無法用它撰寫 D-Bus 服務。
- Derick's php-dbus
Derick 這套已經被列入 PECL 之中,而且大部分的 D-Bus 內容皆已實作,可用度最高。但是文件相當匱乏,我實際上是看著它的源碼中的範例程式碼摸索它的使用方式。
這兩套我都測試過了,以 Derick's php-dbus 完成度較高。儘管 Derick's php-dbus 目前版本 (ver 0.1.0) 在撰寫 D-Bus 服務與客戶端程式時,仍然要避開某些情況才不會觸發記憶體錯誤。但它功能齊全,假以時日,等它修正錯誤後,相信它就會是 PHP 官方的 php-dbus 擴充元件。
本文接下來就會採用 Derick's php-dbus 示範如何用 PHP 撰寫一個簡單的 D-Bus 客戶端工具。
Install Derick's php-dbus
因為 Windows 平台基本上沒有 D-Bus 服務,所以以下內容,都假設你是在 Linux/FreeBSD 平台下操作。
首先前往 PECL 的 DBus 網頁下載源碼壓縮檔。因為這是源碼文件,必須經過編譯才能安裝。所以接著準備 D-Bus library, header files ,以及 PHP header files, phpize (PECL tool)。或是使用我修改過的版本: php dbus extension with ByteArray。
Ubuntu requied packages: libdbus-1-dev, libxml2-dev, php5-dev (include phpize)
你下載回來的 php-dbus 是一套符合 PHP 標準擴充元件撰寫規範的源碼,故而解開壓縮檔後,僅需要執行四個標準動作,就可以完成編譯與安裝動作。假設我將 php-dbus 源碼壓縮檔的內容解開於 php-dbus 的目錄內,我只需要執行下列動作即可完成安裝。
$ cd php-dbus
$ phpize #PHP標準擴充元件源碼組態工具
$ ./configure
$ make #執行成功後就會得到 dbus.so
$ sudo make install
最後的 make install 只是將 dbus.so 複製到 PHP 搜尋擴充元件的目錄內。我們仍然要編輯 php.ini 的 extensions 區段,加入 extension=dbus.so
的設定,才能啟用 php-dbus 擴充元件。
DBus class
Derick's php-dbus 目前缺乏說明文件,我是參考源碼中的 Examples 了解它的用法。
php-dbus 實作了一個 DBus 類別。我們通常用到以下幾個方法:
- new DBus($type)
type: BUS_SESSION, BUS_SYSTEM
- DBus::createProxy($service, $object, $interface)
配置一個 proxy 個體指向我們想要使用的 D-Bus 服務實體。
- DBus::addWatch($interface)
傾聽指定介面的 D-Bus signal (訊號)。屬於這個介面的訊號(signal) 都會回報給我們的 PHP 程式。我們要自己過濾目前的訊號事件是哪一個訊號。
- DBus::waitLoop($timeout)
配合 DBus::addWatch()
,用於等待訊號事件。若有訊號事件發生,則它會回傳一個 DBusSignal 實體,否則回傳 NULL。
- DBusSignal::matches($interface, $signal)
配合 DBus::waitLoop()
使用。用於過濾目前的訊號事件為何?
- DBusSignal::getData()
取得此訊號事件的回應資料。
顯示 Rhythmbox 目前播放曲目
我將以 Rhythmbox 這套 Ubuntu 預設安裝的媒體播放工具為例,以 PHP 透過 D-Bus 服務取得 Rhythmbox 目前播放的音樂檔名。
watch_rhythmbox_playing.php
我只用 Rhythmbox D-Bus 服務的 org.gnome.Rhythmbox.Player.getPlayingUri() 方法,以及傾聽 org.gnome.Rhythmbox.Player.playingUriChanged() 訊號。
DBus2 class
我覺得目前 php-dbus 過濾訊號的模式很難看,所以我參考了 Python dbus 模組,另外定義了一個 DBus2 類別,它實作了一個新方法 addSignalReceiver()
,以及內含迴圈的 mainLoop()
。並覆寫了 waitLoop()
的行為方式
new_watch_rhythmbox_playing.php
我看過 php-dbus 的源碼後,發覺它目前實作的方法有點少,所以我們才需要特別處理 waitLoop()
的模式。如果我們使用 dbus library 中的 dbus_message_get_interface()
和 dbus_message_get_member()
方法,就可以提高過濾訊號的效率。
等我改天找個空閒時間,跟作者聯絡一下,把我這 DBus2 class 的內容,用 C 語言寫進 php-dbus。
相關文章
樂多舊網址: http://blog.roodo.com/rocksaying/archives/12193781.html