FSO
De openmoko-fr.
Avant de détailler un peu plus, un petit avertissement s'impose. FSO n'est PAS une distribution dans le sens où elle n'as pas pour but de fournir une suite logicielle complète a destination d'un utilisateur final.
FSO est un Framework qui a pour but de fournir aux développeurs d'une distribution une interface unifiée et simplifiée de gestion du périphérique. Il a pour but de permettre à une distribution FSO-compatible de pouvoir fonctionner sur tous les périphériques supportés par FSO.
Des images FSO sont fournies avec une application de test, [Zhone], qui permet de valider le fonctionnement du Frramework est qui est utilisable par un utilisateur final. Cependant, Zhone n'a pour but que de permettre le test et le débugguage de FSO
Sommaire |
Framework
Une compilation de quelques liens pour faciliter la compréhension du framework de FSO.
FSO est utilisé entre autres dans les distributions suivantes:
FSO respecte la modélisation suivante:
DBus
C'est une des première choses qu'on apprend dès qu'on cherche un peu d'infos sur FSO : le framework s'appuie massivement sur DBus. Mais qu'est-ce que DBus ?
En incontournable point de départ, l'introduction à DBus de http://www.freedesktop.org.
mdbus permet d'explorer cette interface afin de découvrir comment l'utiliser. La page mdbus détaille l'utilisation de celui-ci.
DBus via Python
Deuxième élément : FSO est développé en Python.
Voici donc le non-moins incontournable tutoriel dbus-python. En plus de l'API dbus implémentée dans python, on y découvre que la réception de signaux dbus s'appuie sur la boucle de traitement d'événements (event loop) de glib disponible via python-gobject. Et si on creuse un peu on s'aperçoit que GObject est à la base d'un nouveau langage nommé Vala que je me rappelle avoir vu cité récemment dans les posts sur FSO... Mais là je commence à être hors-sujet...
Et pour ceux qui se demandent ce qu'un serpent vient faire dans FSO, voici l'excellent Dive Into Python.
Zhone
Zhone, également développé en Python s'appuie principalement sur les modules Enlightenment :
- e_dbus
- evas
- edje
Les événements de l'IHM ainsi que les signaux DBus sont cablés via la méthode signal_callback de edje.decorators.
Ma première application - Activation / désactivation de l'économiseur d'écran via une applet
J'aime bien jouer au Sudoku dans le train avec mon FR. Ce qui est ennuyeux c'est qu'il faut sans cesse solliciter l'écran pendant qu'on réfléchit afin d'éviter qu'il ne soit obscurci par la mise en veille. L'idée est de créer une applet qui se loge dans le SysTray afin de :
- connaitre le statut de la mise en veille (activée / désactivée)
- activer la mise en veille (icône = lune)
- désactiver la mise en veille (icône = soleil)
Les icônes utilisés sont téléchargeables sur http://iconfinder.net/ :
En Python
Voici un premier essai ci-dessous. L'appli installe un icône dans le SysTray. Lorsque la mise en veille est bloquée, l'icône est un soleil. Sinon c'est une lune. Pour basculer on clique sur l'icône. Rien de plus simple. Le seul souci c'est que avec python, cette appli occupe 10,7% de la RAM :(
debian-gta02:~# cat bin/IdleBlocker.py
#! /usr/bin/python
import dbus
from framework.config import config
import gtk
gtk.init_check()
class IdleBlocker():
def __init__(self):
self.idleNotifier = dbus.Interface(dbus.SystemBus().get_object('org.freesmartphone.odeviced', '/org/freesmartphone/Device/IdleNotifier/0'), 'org.freesmartphone.Device.IdleNotifier')
# Timeout par defaut en dur car config retourne la valeur courante du timeout
self.default_idle_timeout = 10
# print config.getInt( 'odeviced.idlenotifier', 'idle', 10 )
self.init_mode()
self.icon = gtk.StatusIcon()
self.icon_file = { 'actif' : '/root/sunny.png', 'veille' : '/root/sunny_night.png' }
self.icon.set_from_file(self.icon_file[self.mode])
self.icon.connect("activate", self.activate)
def get_idle_timeout(self):
return self.idleNotifier.GetTimeouts()['idle']
def set_idle_timeout(self, timeout):
self.idleNotifier.SetTimeout('idle', timeout)
def set_state(self, state):
self.idleNotifier.SetState(state)
def init_mode(self):
if self.get_idle_timeout() == self.default_idle_timeout:
self.mode = 'veille'
else:
self.mode = 'actif'
def set_mode(self, new_mode):
if new_mode == self.mode:
return
if new_mode == 'actif':
self.set_idle_timeout(-1)
else:
self.set_idle_timeout(self.default_idle_timeout)
# On force le changement d'etat afin que le nouveau timeout soit correctement pris en compte
self.set_state('busy')
self.set_state('idle')
self.set_state('busy')
self.mode = new_mode
self.icon.set_from_file(self.icon_file[self.mode])
# Callback active sur clic de l'ione
def activate(self, widget, data=None):
if self.mode == 'actif':
self.set_mode('veille')
else:
self.set_mode('actif')
if __name__ == "__main__":
applet = IdleBlocker()
gtk.main()
En Vala
Vu la gourmandise de Python en terme de mémoire, j'ai voulu essayer Vala. J'ai beaucoup galéré avant de me rendre compte que Vala est très jeune, en plein développement, et qu'il me fallait une version plus récente que celle distribuée actuellement avec Debian unstable (0.3.4). J'ai donc installé à la main Vala-0.5.1, et mon appli fonctionne correctement avec deux fois moins de RAM que la version Python, et une réactivité sensiblement améliorée : plus aucun lag perceptible entre le clic de l'icône et son changement d'affichage.
using Gtk;
using GLib;
using DBus;
public class IdleBlocker : GLib.Object {
private DBus.Connection conn;
private dynamic DBus.Object idleNotifier;
public GLib.MainLoop loop;
private int default_idle_timeout = 10;
private Gtk.StatusIcon icon;
private string mode;
construct {
loop = new MainLoop (null, false);
}
public void init () {
conn = DBus.Bus.get(DBus.BusType.SYSTEM);
idleNotifier = conn.get_object("org.freesmartphone.odeviced", "/org/freesmartphone/Device/IdleNotifier/0", "org.freesmartphone.Device.IdleNotifier");
idleNotifier.GetTimeouts(_cb_get_timeouts);
loop.run();
}
private void _cb_get_timeouts(GLib.HashTable<string, int>? timeouts, GLib.Error? err) {
if (err != null) {
error (err.message);
loop.quit();
return;
}
if (timeouts == null) {
error ("GetTimeouts: resultat vide.");
loop.quit();
return;
}
int idle_timeout = timeouts.lookup("idle");
if (idle_timeout == -1) {
mode = "actif";
icon = new Gtk.StatusIcon.from_file("/root/sunny.png");
}
else {
mode = "veille";
icon = new Gtk.StatusIcon.from_file("/root/sunny_night.png");
}
icon.activate += cb_activate;
}
private void set_idle_timeout(int timeout) {
idleNotifier.SetTimeout("idle", timeout);
}
private void set_state(string state) {
idleNotifier.SetState(state);
}
private void set_mode(string new_mode) {
if (new_mode == mode) {
return;
}
if (new_mode == "actif") {
set_idle_timeout(-1);
}
else {
set_idle_timeout(default_idle_timeout);
}
set_state("busy");
set_state("idle");
set_state("busy");
mode = new_mode;
if (mode == "actif") {
icon.set_from_file("/root/sunny.png");
}
else {
icon.set_from_file("/root/sunny_night.png");
}
}
public void cb_activate(Gtk.StatusIcon object) {
if (mode == "actif") {
set_mode("veille");
}
else {
set_mode("actif");
}
}
public static void main(string[] args) {
Gtk.init(ref args);
var applet = new IdleBlocker();
applet.init();
Gtk.main();
}
}


