我來教你 KDE 開發 --- KDE 後臺服務模組

喜歡程式設計嗎?想要一窺 KDE/Qt 程式設計的奧秘嗎?想要
學習 X Window 上的視窗程式設計嗎?歡迎各類關於 KDE/Qt、Qtopia、Qt/Embedded、QSA、PyQt 等各類心得討論。

版主: AceLan, Franklin

我來教你 KDE 開發 --- KDE 後臺服務模組

文章訪客 » 週四 4月 14, 2011 12:44 am

標題很長,原本打算再長一些的。專開了個“我來教你 KDE 開發”的分類。

KDE 後臺服務模組,學名叫做 kded 模組,kded 就是 kde daemon 的縮寫。
kded 是 kdelibs 的一部分,主要負責執行 KDE 的後臺服務。
這些服務包括內建服務、自啟動服務和按需裝入服務。
內建服務是 kded 自帶的服務,這種服務在每次啟動 KDE 的時候都會載入,沒有明顯的使用者介面來配置它們,但是可以改某些隱藏得很深的設定檔項來進行基本的配置。比如安裝程式後自動刷新主功能表,升級設定檔和監視主機名稱。
自啟動服務是每次啟動 KDE 的時候按照設置載入,載入與否可以通過 系統設置->開機和關機->服務管理器->啟動服務 來控制。
按需裝入服務可以推遲到需要時再載入,能不佔用啟動資源。載入與否可以通過 系統設置->開機和關機->服務管理器->按需裝入服務 查看。

為何要有 kded 後臺服務這個東西?
因為有些資訊是會話級別的,需要被 KDE 全域訪問,而且因為某種原因無法包含於某個特定進程中,所以專門設立 kded 來管理。
所 以只有迫不得已,實在沒有其它辦法的時候再考慮開發 kded 模組,比如改用自啟動進程等。因為 kded 模組越多,kded 本身的穩定性越不好,從而影響到 kded 其它模組的穩定性。如果 kded 異常退出了,KDE 桌面和應用程式也會出各種問題。再強調一次,只有萬不得已的時候再用這招。

實例教學 --- 開發後臺播放服務模組
文件列表:kmplayerserver.h kmplayerserver.cpp kmplayerserver.desktop org.kde.kmplayerserver.xml CMakeLists.txt

kmplayerserver.h
代碼: 選擇全部
#ifndef KMPLAYERSERVER_H
#define KMPLAYERSERVER_H

#include <KDE/KDEDModule>
#include <phonon/audiooutput.h>
#include <phonon/mediaobject.h>

/// 所有的 kded 模組都實現 KDEDModule
class KMPlayerServer : public KDEDModule
{
    Q_OBJECT
    public:
        /// parent 參數與 KDEDModule 的構造函數一致,args 參數是為了和 KPluginLoader 載入範本一致
        explicit KMPlayerServer( QObject* parent, const QVariantList& args );
    public Q_SLOTS:
        /// 播放音樂檔函數
        void play( const QString& file );
    private:
        Phonon::AudioOutput* audioOutput;/// 音訊輸出
        Phonon::MediaObject* media;/// 媒體
};

#endif // KMPLAYERSERVER_H


kmplayerserver.cpp
代碼: 選擇全部
#include "kmplayerserver.h"
#include <KDE/KPluginFactory>
#include <KDE/KPluginLoader>
#include "kmplayerserveradaptor.h"/// dbus 物件,自動生成的標頭檔

/// KDE 外掛程式註冊巨集
K_PLUGIN_FACTORY( KMPlayerServerFactory, registerPlugin<KMPlayerServer>(); )
K_EXPORT_PLUGIN( KMPlayerServerFactory( "kmplayerserver" ) )

KMPlayerServer::KMPlayerServer( QObject* parent, const QVariantList& args )
: KDEDModule(parent)
{
    Q_UNUSED(args)

    new KMPlayerServerAdaptor( this );/// 註冊 dbus 介面

    audioOutput = new Phonon::AudioOutput( Phonon::MusicCategory, this );
    media = new Phonon::MediaObject( this );
    Phonon::createPath( media, audioOutput );
}

void KMPlayerServer::play( const QString& file )
{
    media->setCurrentSource( file );
    media->play();
}


kmplayerserver.desktop
代碼: 選擇全部
[Desktop Entry]
Type=Service
Name=Media Player Server
Comment=Media player server
# 服務類型為 KDEDModule
X-KDE-ServiceTypes=KDEDModule
# 二進位外掛程式的名稱,比如 kded_kmplayerserver 就寫 kmplayerserver
X-KDE-Library=kmplayerserver
# dbus 介面的名稱 kmplayerserver
X-KDE-DBus-ModuleName=kmplayerserver
# 是否是自啟動服務
X-KDE-Kded-autoload=true
# 是否是按需裝入服務
# X-KDE-Kded-autoload 與 X-KDE-Kded-load-on-demand 同時為 true 或同時為 false 的時候將被視為無效模組而拒絕載入
X-KDE-Kded-load-on-demand=false
# 啟動情形,可以寫 0、1、2。不寫這行的話默認是 2。
# 0 表示模組每次都會隨著 kded 進程啟動而啟動,比如 gnome 裡啟動第一個 KDE 程式時也會啟動
# 1 表示模組每次在啟動 KDE 會話時啟動
# 2 表示模組會在 kded 進程啟動後按照自啟動/按需裝入分類和具體配置是否啟動而選擇啟動
X-KDE-Kded-phase=2


org.kde.kmplayerserver.xml,通過 qdbuscpp2xml kmplayerserver.h > org.kde.kmplayerserver.xml 生成,再修改下名稱

代碼: 選擇全部
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.kde.kmplayerserver">
    <method name="play">
      <arg name="file" type="s" direction="in"/>
    </method>
  </interface>
</node>


CMakeLists.txt
代碼: 選擇全部
project(kded_kmplayerserver)
cmake_minimum_required(VERSION 2.6)
find_package(KDE4 REQUIRED)

include(KDE4Defaults)

add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
include_directories(${QT_INCLUDES} ${KDE4_INCLUDES})

set(kded_kmplayerserver_SRCS
    kmplayerserver.cpp
)

qt4_add_dbus_adaptor(kded_kmplayerserver_SRCS
    org.kde.kmplayerserver.xml
    kmplayerserver.h
    KMPlayerServer
    kmplayerserveradaptor
    KMPlayerServerAdaptor
)

kde4_add_plugin(kded_kmplayerserver
    ${kded_kmplayerserver_SRCS}
)

target_link_libraries(kded_kmplayerserver
    ${KDE4_KDECORE_LIBS}
    ${PHONON_LIBRARY}
)

install(TARGETS kded_kmplayerserver DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES kmplayerserver.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded)
install(FILES org.kde.kmplayerserver.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})


編譯安裝完需要重啟一下 KDE 會話。
下次 KDE 會話進入後就會自動啟動這個播放模組,系統設置->開機和關機->服務管理器->啟動服務 裡面也能手工控制。

現在啟動 qt 自帶的 qdbusviewer,找到 Session Bus 裡的 org.kde.kded,然後在右側中找到 modules 的 kmplayerserver。
org.kde.kmplayerserver 中會有一個自訂的 Method: play。按兩下 play,填上檔路徑,OK。
如果聽到音樂了,那就說明播放模組已經能在後臺正常工作啦。
訪客
 

回到 KDE/Qt 程式設計

誰在線上

正在瀏覽這個版面的使用者:沒有註冊會員 和 1 位訪客