Ecrire un plugin Cairo-Dock avec D-bus en Python

Si vous utilisez Cairo-Dock, vous avez sûrement eu envie d’écrire vous même un plugin. Mais vous ne connaissez pas le langage C (Cairo-Dock est développé en C) ou vous ne voulez pas vous lancer dans la compilation des sources ? Qu’à cela ne tienne, depuis la version 2.1.3 vous pouvez écrire facilement un plugin dans un langage de script, Python par exemple, grâce au démon de communication inter-processus D-bus.

Introduction

Sans entrer dans les détails, D-bus est un systême assez simple qui permet à vos programmes de communiquer entre eux. On récupère des « objets », on s’enregistre à des services et on s’envoit des messages. Nous allons écrire facilement grâce à lui, un plugin en python pour Cairo-Dock. Ce plugin, basique, affichera l’espace disque disponible quand on cliquera sur son icône. Je l’appelerai DiskFree.
Avant de commencer, assurez vous que les paquets python-dbus et python-gobject sont présents sur votre système . Le paquet python-dbus-doc pourrait aussi vous intéresser.

Vous pouvez télécharger les sources du plugin sur cette page.

Structure d’un plugin

Pour créer un plugin Cairo-Dock, il faut créer 4 fichiers qu’on place dans un dossier du même nom que le plugin. Dans mon cas, je dois donc créer le dossier DiskFree et y placer :

  1. auto-load.conf, qui contiendra la description du plugin
  2. DiskFree, le script Python du même nom que le plugin et sans extension
  3. DiskFree.conf, le fichier de configuration du même nom que le plugin
  4. icon, l’icône du plugin, sans extension
Structure d'un plugin Cairo-Dock

Structure d'un plugin Cairo-Dock

Vous pouvez télécharger les plugins D-bus existants pour Cairo-Dock ici : cairo-dock-plug-ins-extras. Vous y trouverez des exemples de plugins programmés en Python, Bash, Ruby, etc.

Fichier auto-load.conf

[Register]
author = Xavier Nayrac
description = Affiche l'espace disque libre.
category = 6
version = 0.1.0

La seule clé à expliquer est category. Cairo-Dock range les plugins selon des catégories dans son interface de configuration. Le numéro 6 correspond à la catégorie « system ». Le reste parle de lui-même.

DiskFree, le script Python

#!/usr/bin/python
# -*- coding: utf-8 -*-

# DiskFree, applet pour Cairo-Dock.
# Copyright 2010 Xavier Nayrac
# Adapté de demo_bash, par Nochka85, modifié par matttbe, basé sur
# demo.py by Fabounet.
#
# Ce programme est un logiciel libre ; vous pouvez le redistribuer ou le
# modifier suivant les termes de la “GNU General Public License” telle que
# publiée par la Free Software Foundation : soit la version 3 de cette
# licence, soit (à votre gré) toute version ultérieure.
#
# Ce programme est distribué dans l’espoir qu’il vous sera utile, mais SANS
# AUCUNE GARANTIE : sans même la garantie implicite de COMMERCIALISABILITÉ
# ni d’ADÉQUATION À UN OBJECTIF PARTICULIER. Consultez la Licence Générale
# Publique GNU pour plus de détails.
#
# Vous devriez avoir reçu une copie de la Licence Générale Publique GNU avec
# ce programme ; si ce n’est pas le cas, consultez :
# <http://www.gnu.org/licenses/>.

import sys
import gobject
import dbus
import os
import os.path
from dbus.mainloop.glib import DBusGMainLoop

CAIRO_SERVICE = 'org.cairodock.CairoDock'
CAIRO_APPLET = 'org.cairodock.CairoDock.applet'
CAIRO_PATH = '/org/cairodock/CairoDock/'

Les trois définitions ci-dessus serviront à communiquer avec le dock par l’intermédiaire de D-bus.

def getFreeSpace():
  """
  Je retourne l'espace disque disponible (le nombre d'octets) à la
  racine du système de fichier.
  """
  stats = os.statvfs('/')
  return stats.f_bsize * stats.f_bavail

C’est cette petite fonction, getFreeSpace(), qu’il faudra appeler quand on cliquera sur le plugin.

def actionOnClick(iState):
  """
  Je réagis au clic gauche de la souris sur mon icône, en modifiant
  mon label pour qu'il reflète le nombre de Go libres du disque.
  """
  gigaOctets = getFreeSpace() / (1024.0 * 1024 * 1024)
  label = "%.1f Go" % (gigaOctets)
  myPlugin.SetLabel(label)

La fonction actionOnClick() sera appelé automatiquement par le dock, une fois qu’on l’aura enregistrée. Elle calcule le nombre de giga-octets libres sur le disque et inscrit le résultat dans le label de l’icône du plugin.

def actionOnStop():
  loop.quit()

La fonction actionOnStop(), qui devra aussi être enregistrée, sera appelée quand le plugin est supprimé. Il faudra alors quitter la boucle principale.

if __name__ == '__main__':
  pluginName = os.path.basename(os.path.abspath("."))

On profite du fait que le nom du plugin doit être identique au nom du dossier pour le récupérer « en live ».

  pluginPath = CAIRO_PATH + pluginName

Le chemin du plugin, selon le point de vue de D-bus.

  DBusGMainLoop(set_as_default=True)
  bus = dbus.SessionBus()

Le wrapper D-bus pour python possède sa propre boucle d’événement par défaut. Pour profiter de celle de Glib, on le signale avec DBusGMainLoop(set_as_default=true). On peut après ça se connecter à D-bus avec la méthode SessionBus().

  try:
    pluginObject = bus.get_object(CAIRO_SERVICE, pluginPath)
  except dbus.DBusException:
    print ">>> <%s> can't be found on the bus, exit." % (pluginName)
    sys.exit(1)

On tente de récupérer l’objet qui servira de pont de communication entre le dock et notre plugin. Si ça ne fonctionne pas, on écrit un message et on met fin au script. Pour voir ce message, il faudra que vous lanciez Cairo-Dock depuis un terminal. C’est la façon la plus simple de déboguer vos plugins.

  myPlugin = dbus.Interface(pluginObject, CAIRO_APPLET)

On récupère l’interface de notre objet avec dbus.Inerface(), ce qui permettra d’utiliser les méthodes de l’interface.

  myPlugin.connect_to_signal("on_click", actionOnClick)
  myPlugin.connect_to_signal("on_stop_module", actionOnStop)

C’est à l’aide de la méthode connect_to_signal() de l’interface que nos fonctions actionOnClick() et actionOnStop() vont maintenant devenir des fonctions callbacks. C’est-à-dire qu’elle seront appelées de l’extérieur de notre script, par Cairo-Dock et par l’intermédiaire de D-bus.

  loop = gobject.MainLoop()
  loop.run()
  sys.exit(0)

Nous voici à la fin du programme. On crée la boucle d’évenement de notre script et on la lance.

Les autres fichiers

Les deux autres fichiers, DiskFree.conf et icon n’ont pas vraiment d’importance pour cet exemple. J’ai simplement copié/collé ceux trouvés dans un autre plugin (au hasard : demo_python). Faites en autant, sans oublier de renommer nomDuPlugin.conf en DiskFree.conf.

Installation

Copiez le dossier DiskFree et son contenu dans ~/.config/cairo-dock/third-party. Si le dossier third-party n’existe pas, créez le. Il ne vous reste plus qu’à faire un clic droit sur votre dock et à sélectionner le menu « Cairo-Dock>Configurer ». Dans l’interface de configuration, désactivez le plugin Dbus puis réactivez le. Vous pouvez maintenant activer le plugin DiskFree.

DiskFree en action

Le plugin DiskFree en action

Conclusion

L’écriture d’un plugin pour Cairo-Dock à l’aide de D-bus est relativement simple. Une fois que vous aurez consulté le code des plugins existants et lu un peu les documentations que je fournis en référence, vous devriez rapidement pouvoir mettre en oeuvre le votre.

En ce qui concerne DiskFree, le plugin que j’ai présenté ici, vous devriez pouvoir aisément l’améliorer. Vous pourriez utiliser un timer pour déclencher la lecture de l’espace disque disponible, évitant ainsi d’avoir à cliquer sur l’icône pour rafraîchir l’information. Grâce à l’interface de configuration du plugin, qui est fournie par Cairo-Dock, vous pourriez laisser l’utilisateur choisir le format de l’information (mega-octet, giga-octet, etc).

Références

Source du plugin DiskFree 0.1 http://sources.xavier.free.fr/python.php#diskfree-0.1

Site de Cairo-Dock http://www.glx-dock.org

Control your dock with D-bus http://www.glx-dock.org/ww_page.php?p=Control_your_dock_with_DBus&lang=en

D-bus sur wikipédia http://fr.wikipedia.org/wiki/D-Bus

Introduction to D-bus http://www.freedesktop.org/wiki/IntroductionToDBus

D-bus python tutorial http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html

La classe gobject.MainLoop http://hosting.1command.com/fbsd/doc/pygobject/class-gobjectmainloop.html

Plugins Cairo-Dock https://code.launchpad.net/cairo-dock-plug-ins-extras

Articles en relation

DiskFree 1.0, plugin pour Cairo-Dock
Un notificateur de mail en python

Publicités

, , , , , ,

  1. Poster un commentaire

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :