Rendez-vous sur Arrakis

C'est lorsque nous croyons savoir quelque chose qu'il faut justement réfléchir un peu plus profondément. F. Herbert

Openbox et ses pipemenus

Cette page n'a pas pour objectif d'écrire un autre tutoriel pour openbox, puisqu'il en existe déjà d'excellents.

Ici, on va parler de pipemenus, cette fonctionnalité qui permet d'avoir des menus dynamiques et donc accès à à peu près n'importe quoi.

Les scripts décrits ci-dessous sont pour la plupart présents ici.

Généralités

Pour insérer un pipemenu, il faudra mettre une ligne qui ressemble à celle ci-dessous dans le fichier ~/.config/openbox/menu.xml :

<menu execute="~/.config/openbox/pipemenus/mescripts.sh" id="scripts" label="Scripts"/>

À chaque fois, il faudra modifier :

Météo

On peut avoir la météo dans le menu d'Openbox avec le script weather.py. Dans le fichier menu.xml, ajoutez et adaptez:

<menu execute="~/.config/openbox/pipemenus/weather.py Paris fr" id="weather" label="Meteo"/>

Ça ressemble à ça :

Le script :

#!/usr/bin/python3
# -*- coding:Utf-8 -*-

"""

Auteur :      thuban (thuban@yeuxdelibad.net)
licence :     GNU General Public Licence

Description : get weather forecast in openbox pipemenu

"""

import sys
import os
import json
from urllib import request as urllibrequest
import urllib

icon_dir = os.path.join(os.path.dirname(sys.argv[0]),"weathericons")

def help():
    print("usage : {} city language".format(sys.argv[0]))
    sys.exit(1)

def main():
    if len(sys.argv) != 3:
        help()
    else:
        if not os.path.isdir(icon_dir):
            os.mkdir(icon_dir)
        city = sys.argv[1]
        lang = sys.argv[2]
        apiurl="http://api.openweathermap.org/data/2.5/forecast?q={0},{1}&amp;mode=json&amp;units=metric&amp;lang={1}".format(city,lang)

    a = urllibrequest.urlopen(apiurl)
    j = json.loads(a.read().decode('utf-8'))

    print("<openbox_pipe_menu>")
    print('<separator label="{}"></separator>'.format(city))

    for i in j['list']:
        t = i['main']['temp']
        t_min = i['main']['temp_min']
        t_max = i['main']['temp_max']
        humidity = i['main']['humidity']
        pressure = i['main']['pressure']
        temps = i['weather'][0]['main']
        description = i['weather'][0]['description']
        heure = i['dt_txt']
        icon_id = i['weather'][0]['icon']

        # Download the file from `url` and save it locally under `file_name`:
        icon=os.path.join(os.path.dirname(sys.argv[0]),"weathericons", icon_id + ".png")
        if not os.path.isfile(icon):
            with urllibrequest.urlopen("http://openweathermap.org/img/w/{}.png".format(icon_id))\
                    as response, open(icon, 'wb') as out_file:
                data = response.read() # a `bytes` object
                out_file.write(data)
        print('<separator label="{}"></separator>'.format(heure))
        print("<item icon=\"{}\" label=\"{} \"><action name=\"execute\">\
                <execute>x-www-browser \"http://openweathermap.org/find?q={}\"</execute>\
                </action></item>".format(icon, description, city.replace(' ', '+')))
        print("<item label=\"{}°C   max: {}°C - min: {}°C\"><action name=\"execute\">\
                <execute>x-www-browser \"http://openweathermap.org/find?q={}\"</execute>\
                </action></item>".format(t, t_min, t_max,city.replace(' ', '+')))
        print("<item label=\"Humidité : {}% - Pression : {} hPa\"><action name=\"execute\">\
                <execute>x-www-browser \"http://openweathermap.org/find?q={}\"</execute>\
                </action></item>".format(humidity, pressure, city.replace(' ', '+')))

    print("</openbox_pipe_menu>")
    return 0

if __name__ == '__main__':
    main()

Gestion de mpd

On peut gérer mpd et avoir accès à sa liste de lecture. À mettre dans menu.xml :

<menu execute="~/.config/openbox/pipemenus/mpdob.py" id="mpd" label="Liste de lecture"/>

L'aperçu :

Le script :

#!/usr/bin/env python
# -*- coding:Utf-8 -*-
# Fichier: mpdob.py
# Cree le 15 nov. 2011 08:15:43

"""

Auteur :      thuban (thuban@yeuxdelibad.net)
licence :     GNU General Public Licence

Description :
    Create an openbox menu to control mpd.
    requires python-mpd and mpc
    Ajouter dans le menu.xml :
            <menu id="mpd" label="♫ MPD ♫" execute="~/Documents/Scripts/Openbox/mpdob.py" />

"""

try:
        import sys
        import mpd

except ImportError as err:
        print ("Couldn't load module. {0}".format(err))
        sys.exit(2)

def makeListe(x, y, playlist):
    liste = []
    for i in range(x,y):
        liste.append((i+1 ,playlist[i].replace('&amp;', '').split('/')[-1]))
    return(liste)

step = 20
scriptname=sys.argv[0]
client = mpd.MPDClient()
client.connect('localhost',6600)
playlist = client.playlist()
lp = len(playlist)
a,b = 0, step
if len(sys.argv) == 1:
    a, b = 0, step
else:
    a, b = int(sys.argv[1]), int(sys.argv[2])
if a < 0:
    a = 0
if b > lp:
    b = lp

liste = makeListe(a, b, playlist)
print('<openbox_pipe_menu>')

for item in liste:
    print('<item label="' + item[1] + '">')
    print('<action name="Execute"><execute>mpc play ' + str(item[0]) + '</execute></action></item>')

if b < lp:
    print('<menu execute="{0} {1} {2}" id="{3}{2}" label="+"/>'.format(\
                            scriptname,a+step,b+step, 'mpd'))
print('</openbox_pipe_menu>')

Un TODO

Ajouter des choses à faire, les modifier…

Dans le menu.xml :

    <menu execute="~/.config/openbox/pipemenus/obtodo.sh" id="todo" label="TODO"/>

L'aperçu :

Le script :

#!/bin/sh
#Todo menu for Openbox
#Copyright (c) 2010 Cameron Turner
#Released under a BSD license
SB="#000000"
SF="#00AFAF"
NB="#000000"
NF="#797979"

# La police de dmenu
FN="-*-fixed-medium-r-semicondensed-*-13-*-*-*-*-*-iso10646-*"
# Le prompt, ce que dmenu vous "dit"
P="Todo:"

OPTION="-fn $FN -nb $NB -nf $NF -sb $SB -sf $SF -i -p $P "

TODO_PATH=~/.todo
[ -z "$XDG_CONFIG_HOME" ] || TODO_PATH="$XDG_CONFIG_HOME/todo"

[ ! -f $TODO_PATH ] &amp;&amp; touch $TODO_PATH

if [ "$1" = "add" ]
then
TODO=`echo "" | dmenu $OPTION`
[ "$TODO" = "" ] &amp;&amp; exit
    echo $TODO >> $TODO_PATH
elif [ "$1" = "delete" ]
then
TEMP=`mktemp`
sed "$2 d" $TODO_PATH > $TEMP
mv -f $TEMP $TODO_PATH
elif [ "$1" = "edit" ]
then
TODO=`sed "$2 !d" < $TODO_PATH`
TODO=`echo "" | dmenu $OPTION`
[ "$TODO" = "" ] &amp;&amp; exit

TEMP=`mktemp`
TODO=`echo -n $TODO | sed -e "s/\&amp;/\&amp;/g" -e "s/</\</g" -e "s/>/\>/g"`
sed "$2 c$TODO" $TODO_PATH > $TEMP
mv -f $TEMP $TODO_PATH
else
echo "<openbox_pipe_menu>"
i=1
while read LINE
do
    echo "<menu id=\"todo-$i\" label=\"$LINE\">"
    echo "<item label=\"Editer\">"
    echo "<action name=\"Execute\"><execute>$0 edit $i</execute></action>"
    echo "</item>"
    echo "<item label=\"Supprimer\">"
    echo "<action name=\"Execute\"><execute>$0 delete $i</execute></action>"
    echo "</item>"
    echo "</menu>"
    i=$(($i+1))
done < $TODO_PATH
echo "<separator />"
echo "<item label=\"+ todo\">"
echo "<action name=\"execute\"><execute>$0 add</execute></action>"
echo "</item>"
echo "</openbox_pipe_menu>"
fi

Marque-pages de firefox

On peut lancer les marques-pages de firefox/iceweasel.

Dans le menu.xml :

    <menu execute="~/.config/openbox/pipemenus/obbookmark.py" id="bmk" label="Marque-pages"/>

L'aperçu :

Le code :

#!/usr/bin/env python
# add this line to menu.xml
# /usr/bin/python ~/Documents/Scripts/Openbox/obbookmark.py

import sqlite3
from xml.sax.saxutils import quoteattr

import shutil
import tempfile
import os

browser = 'iceweasel'
ffoxdirlist = os.listdir(os.path.expanduser('~/.mozilla/firefox'))
for i in ffoxdirlist:
    if i.endswith(".default"):
        ffsqlite = os.path.join(os.path.expanduser('~/.mozilla/firefox'),i,"places.sqlite")

def print_label(title, url):
    print '<item label=%s>' % (quoteattr(title.encode('utf-8')))
    print '<action name="Execute">'
    print '<command>%s %s</command>'  % (browser, quoteattr(url.encode('utf-8')))
    print '</action>'
    print '</item>'

def rbuild_tree(id, title, conn, first_run=False):
        if first_run:
            print '<openbox_pipe_menu>'
        else:
            print '<menu id="%s" label=%s>' % (id, quoteattr(title.encode('utf-8')))

        c2 = conn.cursor()
        c2.execute('select id, title, type from moz_bookmarks b where parent=? and type=2;', (id, ))
        for sid, stitle, type in c2:
            rbuild_tree(sid, stitle, conn)
        c2.execute('select b.title, p.title, p.url from moz_bookmarks b, moz_places p where b.fk = p.id and b.type=1 and parent=?;', (id, ))
        for btitle, ptitle, url in c2:
            if url == None or url.startswith('place'):
                continue
            if btitle != None:
                print_label(btitle, url)
            else:
                print_label(btitle, url)

        if first_run:
            print '</openbox_pipe_menu>'
        else:
            print '</menu>'

def main():

    tf = tempfile.NamedTemporaryFile('r', suffix='.sqlite')

    shutil.copyfile(ffsqlite, tf.name)
    conn = sqlite3.connect(tf.name)

    rbuild_tree(2, '', conn, True)

    conn.close()
    tf.close()

if __name__ == '__main__':
    main()

Ouvrir ses fichiers

Dans le menu.xml :

    <menu execute="~/.config/openbox/pipemenus/obfile.py" id="files" label="Fichiers"/>

L'aperçu :

Le code :

#!/usr/bin/python
# add this to menu.xml
#       <menu execute="~/Documents/Scripts/Openbox/obfile.py" id="Fichiers" label="Fichiers"/>

import os
import random
from sys import argv

mediaplayer="vlc"
editor="geany"

mypath = argv[0]

def ext_resolver(filename):
    ext = filename.split('.')[-1].lower()
    ext_list = {'smc':'zsnes','bin':'dgen','gen':'dgen',
                'ogm':mediaplayer,'ogv':mediaplayer, 'avi':mediaplayer,'mkv':mediaplayer,'ogg':mediaplayer,'mp4':mediaplayer,'dv':mediaplayer,
                'mpeg':mediaplayer,'mov':mediaplayer,'wma':mediaplayer,'mp3':mediaplayer,'flv':mediaplayer, 'webm':mediaplayer,
                'sh' :editor,'c' :editor, 'py':editor,
                'pdf' :'mupdf',
                'doc' :'libreoffice',
                'txt' :'libreoffice',
                'odp' :'libreoffice',
                'xls' :'libreoffice',
                'xslx' :'libreoffice',
                'odt' :'libreoffice',
                'ods' :'libreoffice',
                'pps' :'libreoffice',
                'ods' :'libreoffice',
                'ppt' :'libreoffice',
                'opt' :'libreoffice',
                'pps' :'libreoffice',
                'docx':'libreoffice',
                'obt' :'libreoffice',
                'png':'gpicview','jpg':'gpicview','bmp':'gpicview','gif':'gpicview',
                'svg':'inkscape'}
    if ext in ext_list:
        return ext_list[ext]
    else:
        return 'xdg-open'

def dir_list(dircontent):
    dirs = []
    files = []
    for item in dircontent:
        if os.path.isdir(os.path.join(currentpath,item)):
            dirs.append(item)
        else:
            files.append(item)
    dirs.sort(key=str.lower)
    files.sort(key=str.lower)
    return dirs, files

def replacer(string):
    return string.replace('&amp;', '&amp;amp;').replace('<', '&amp;lt;').replace('>', '&amp;gt;').replace('"', '&amp;quot;').replace("'", '&amp;apos;')

def gen_menu(dirs, files):
    curpath = replacer(currentpath)
    print('<openbox_pipe_menu>')

    print('<item label="Ouvrir"><action name="execute"><execute>thunar "' + curpath + '"</execute></action></item>')
    print('<item label="Terminal ici..."><action name="execute"><execute>sh -c "cd ' + curpath + ' &amp;amp;&amp;amp; x-terminal-emulator "</execute></action></item>')
    print('<separator />')

    for thisdir in dirs:
        thisdir = replacer(thisdir)
        menuid = str(random.randrange(1,99,1)).zfill(2)
        print('  <menu execute="' + mypath + ' ' + curpath + '/' + thisdir + '" id="' + thisdir + "-" + menuid + '" label="' + thisdir + '"/>')

    for thisfile in files:
        thisfile = replacer(thisfile)
        print('  <item label="' + thisfile + '">')
        print('    <action name="execute">')
        print('      <execute>')
        print('        ' + ext_resolver(thisfile) + ' "' + curpath + '/' + thisfile + '"')
        print('      </execute>')
        print('    </action>')
        print('  </item>')
    print('</openbox_pipe_menu>')

if len(argv) > 1:
    currentpath = ' '.join(argv[1:])
else:
    currentpath = os.path.expanduser('~')

try:
    content = [x for x in os.listdir(currentpath) if x[0] != '.']
    parts = dir_list(content)
    gen_menu(parts[0], parts[1])
except OSError:
    print('<openbox_pipe_menu>')
    print('<separator label="No access" />')
    print('</openbox_pipe_menu>')

Changer de fond d'écran

Le script est par là, mais il en existe d'autres sur la toile.

Calendrier

Consulter le calendrier et ouvrir orage au clic :

Le script :

#! /bin/sh
CAL=orage

calRow() {
    cal -h | sed -n "$1p" |dos2unix
}

echo "<openbox_pipe_menu>";
echo "<separator label=\"$(date +%A\ \ %H\:%M\ %p)\"></separator>";
echo "<item label=\"$(calRow 2)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 3)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 4)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 5)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 6)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 7)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "<item label=\"$(calRow 8)\"><action name=\"execute\"><execute> $CAL</execute></action></item>"
echo "</openbox_pipe_menu>";
exit 0

Mon fichier menu.xml

Si vous voulez comparer avec le votre :

<?xml version="1.0" encoding="utf-8"?>
<openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/                 file:///usr/share/openbox/menu.xsd">
    <menu id="root-menu" label="Openbox 3">
        <menu execute="~/.config/openbox/pipemenus/obbookmark.py" id="bmk" label="Marque-pages"/>
        <menu id="root-menu-874936" label="Web">
            <item label="Navigateur web">
                <action name="Execute">
                    <execute>iceweasel</execute>
                </action>
            </item>
            <item label="Gajim">
                <action name="Execute">
                    <execute>gajim</execute>
                </action>
            </item>
        </menu>
        <menu id="root-menu-574945" label="Multimedia">
            <item label="VLC">
                <action name="Execute">
                    <execute>vlc</execute>
                </action>
            </item>
            <item label="Openshot">
                <action name="Execute">
                    <execute>openshot</execute>
                </action>
            </item>
            <item label="Screencast">
                <action name="Execute">
                    <execute>istanbul</execute>
                </action>
            </item>
        </menu>
        <menu id="root-menu-584941" label="Graphisme">
            <item label="Inkscape">
                <action name="Execute">
                    <execute>inkscape</execute>
                </action>
            </item>
            <item label="Gimp">
                <action name="Execute">
                    <execute>gimp</execute>
                </action>
            </item>
        </menu>
        <menu execute="~/.config/openbox/pipemenus/obfile.py" id="files" label="Fichiers"/>
        <item label="Terminal">
            <action name="Execute">
                <execute>x-terminal-emulator</execute>
            </action>
        </item>
        <separator/>
        <menu id="root-menu-601229" label="MPD ♩♪♫">
            <menu execute="~/.config/openbox/pipemenus/mpdob.py" id="mpd" label="Liste de lecture"/>
            <item label="Sonata">
                <action name="Execute">
                    <execute>sonata</execute>
                </action>
            </item>
            <separator/>
            <item label="♬ Suivant ">
                <action name="Execute">
                    <execute>mpc next</execute>
                </action>
            </item>
            <item label="♫ Précédent">
                <action name="Execute">
                    <execute>mpc prev</execute>
                </action>
            </item>
            <item label="♩ Play/pause">
                <action name="Execute">
                    <execute>mpc toggle</execute>
                </action>
            </item>
        </menu>
        <menu id="root-menu-504454" label="Outils">
            <menu execute="~/.config/openbox/pipemenus/process.pl" id="procs" label="Processus"/>
            <menu execute="~/.config/openbox/pipemenus/weather.py Coueron fr" id="weather" label="Meteo"/>
            <menu execute="~/.config/openbox/pipemenus/mescripts.sh" id="scripts" label="Scripts"/>
            <item label="Redshift on/off">
                <action name="Execute">
                    <execute>pkill -USR1 redshif</execute>
                </action>
            </item>
            <item label="Capture d'écran">
                <action name="Execute">
                    <execute>/home/xavier/bin/bin/scrotup.sh</execute>
                </action>
            </item>
            <item label="Capture dans 3s">
                <action name="Execute">
                    <execute>/home/xavier/bin/bin/scrotups3.sh</execute>
                </action>
            </item>
            <menu id="root-menu-504454-71436" label="Luminosité">
                <item label="+50%">
                    <action name="Execute">
                        <execute>xbacklight -inc 50</execute>
                    </action>
                </item>
                <item label="+25%">
                    <action name="Execute">
                        <execute>xbacklight -inc 25</execute>
                    </action>
                </item>
                <item label="+10%">
                    <action name="Execute">
                        <execute>xbacklight -inc 10</execute>
                    </action>
                </item>
                <item label="-50%">
                    <action name="Execute">
                        <execute>xbacklight -dec 50</execute>
                    </action>
                </item>
                <item label="-25%">
                    <action name="Execute">
                        <execute>xbacklight -dec 25</execute>
                    </action>
                </item>
                <item label="-10%">
                    <action name="Execute">
                        <execute>xbacklight -dec 10</execute>
                    </action>
                </item>
            </menu>
            <menu id="root-menu-504454-831051" label="Écran">
                <item label="Cloner sur HDMI">
                    <action name="Execute">
                        <execute>xrandr --output HDMI1</execute>
                    </action>
                </item>
                <item label="Cloner sur VGA">
                    <action name="Execute">
                        <execute>xrandr --output VGA1</execute>
                    </action>
                </item>
                <item label="800x600">
                    <action name="Execute">
                        <execute>xrandr -s 640x480</execute>
                    </action>
                </item>
                <item label="1366x768">
                    <action name="Execute">
                        <execute>xrandr -s 1366x768</execute>
                    </action>
                </item>
            </menu>
            <menu execute="~/.config/openbox/pipemenus/wallmenu.py" id="walls" label="Fonds d'écran"/>
        </menu>
        <menu execute="~/.config/openbox/pipemenus/obtodo.sh" id="todo" label="TODO"/>
        <separator/>
        <!-- This requires the presence of the 'menu' package to work -->
        <menu id="/Debian"/>
        <separator/>
        <menu id="client-list-menu"/>
        <separator/>
        <menu id="root-menu-681941" label="Quitter">
            <item label="Reconfigurer">
                <action name="Reconfigure"/>
            </item>
            <item label="Fermer la session">
                <action name="Exit"/>
            </item>
            <separator/>
            <item label="Redémarrer">
                <action name="Execute">
                    <execute>systemctl reboot</execute>
                </action>
            </item>
            <item label="Éteindre">
                <action name="Execute">
                    <execute>systemctl poweroff</execute>
                </action>
            </item>
        </menu>
    </menu>
</openbox_menu>