Rolinh

Rolinh' release

Un Widget / Contrôleur Pour Le Lecteur Audio Cmus Pour Awesome WM

Je vous parlais hier de ma découverte de cmus. Et bien ce petit bout d’application m’a tellement emballé que je l’ai adopté et, pour une intégration parfaite avec mon environnement AwesomeWM, je lui ai écrit un widget et un contrôleur. L’idée était de remplacer celui que j’avais pour contrôler moc et je dois dire qu’il remplit son boulot à la perfection.

En image, c’est toujours plus parlant alors voici:

Cette première image montre la barre d’awesome en entier et on peut y voir le widget, qui signale que cmus n’est pas lancé (not running).

Une fois que l’on lance cmus, le widget affiche ceci:

Évidemment, lorsque l’on joue une chanson, le widget l’affiche ainsi que le temps écoulé:

Et l’on sait évidemment aussi quand la chanson est en pause:

Tout cela n’aurait que peu d’intérêt si on ne pouvait pas contrôler les fonctions “play/pause/stop/chanson suivante/chanson précédente” depuis son environnement Awesome. Heureusement, les développeurs de cmus ont eu la bonne idée d’intégrer un système permettant de le contrôler via la ligne de commande (cmus-remote). Par conséquent, j’ai sauté sur l’occasion pour intégrer tout ça à Awesome. Ainsi, il est possible de réaliser toutes ces fonctions sans même aller sur la fenêtre où cmus est lancé.

Pour pouvoir bénéficier de tout cela, il vous suffit de rajouter les quelques lignes de codes que j’ai écris dans votre rc.lua (le fichier de configuration d’Awesome).

Il faut d’abord une fonction qui vérifie si cmus est bien lancé. Pour cela, il suffit de vérifier le pid associé:

1
2
3
4
5
6
7
-- Get cmus PID to check if it is running
function getCmusPid()
  local fpid = io.popen("pgrep cmus")
  local pid = fpid:read("*n")
  fpid:close()
  return pid
end

Maintenant que nous avons cela, on a besoin d’un contrôleur qui associe des combinaisons de touche au fonctions souhaitées:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- Enable cmus control
function cmus_control (action)
  local cmus_info, cmus_state
  local cmus_run = getCmusPid()
  if cmus_run then
      cmus_info = io.popen("cmus-remote -Q"):read("*all")
      cmus_state = string.gsub(string.match(cmus_info, "status %a*"),"status ","")
      if cmus_state ~= "stopped" then
          if action == "next" then
              io.popen("cmus-remote -n")
          elseif action == "previous" then
              io.popen("cmus-remote -r")
          elseif action == "stop" then
              io.popen("cmus-remote -s")
          end
      end
      if action == "play_pause" then
          if cmus_state == "playing" or cmus_state == "paused" then
              io.popen("cmus-remote -u")
          elseif cmus_state == "stopped" then
              io.popen("cmus-remote -p")
          end
      end
  end
end

Et pour l’affichage, il faut le widget:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
-- Cmus Widget
tb_cmus = widget({ type = "textbox", align = "right" })
function hook_cmus()
  -- check if cmus is running
  local cmus_run = getCmusPid()
  if cmus_run then
      cmus_info = io.popen("cmus-remote -Q"):read("*all")
      cmus_state = string.gsub(string.match(cmus_info, "status %a*"),"status ","")
      if cmus_state == "playing" or cmus_state == "paused" then
          cmus_artist = string.gsub(string.match(cmus_info, "tag artist %C*"), "tag artist ","")
          cmus_title = string.gsub(string.match(cmus_info, "tag title %C*"), "tag title ","")
          cmus_curtime = string.gsub(string.match(cmus_info, "position %d*"), "position ","")
          cmus_curtime_formated = math.floor(cmus_curtime/60) .. ':' .. string.format("%02d",cmus_curtime % 60)
          cmus_totaltime = string.gsub(string.match(cmus_info, "duration %d*"), "duration ","")
          cmus_totaltime_formated = math.floor(cmus_totaltime/60) .. ':' .. string.format("%02d",cmus_totaltime % 60)
          if cmus_artist == "" then
              cmus_artist = "unknown artist"
          end
          if cmus_title == "" then
              cmus_title = "unknown title"
          end
          -- cmus_title = string.format("%.5c", cmus_title)
          cmus_string = cmus_artist .. " - " .. cmus_title .. "(" .. cmus_curtime_formated .. "/" .. cmus_totaltime_formated .. ")"
          if cmus_state == "paused" then
              cmus_string = '|| ' .. cmus_string .. ''
          else
              cmus_string = '\> ' .. cmus_string .. ''
          end
      else
          cmus_string = '-- not playing --'
      end
      return cmus_string
  else
      return '-- not running --'
  end
end
-- refresh Cmus widget
cmus_timer = timer({timeout = 1})
cmus_timer:add_signal("timeout", function() tb_cmus.text = '| ' .. hook_cmus() .. ' ' end)
cmus_timer:start()

Comme pour tous les widgets, il faut évidemment l’ajouter dans la wibox. Pour cela, regardez où elle se trouve dans votre rc.lua et ajoutez-y celui pour cmus. Chez moi, cela se présente ainsi avec tous les widgets, le widget correspondant à cmus s’appelant tb_cmus(l’ordre à de l’importance):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    -- Add widgets to the wibox - order matters
    mywibox[s].widgets = {
        {
            mylauncher,
            mytaglist[s],
            mypromptbox[s],
            layout = awful.widget.layout.horizontal.leftright
        },
        mylayoutbox[s],
  mymail,
        s == 1 and mysystray or nil,
  tb_volume,
        mytextclock,
  batinfo,
  meminfo,
  cputemp,
  cpuinfo,
  gputemp,
  tb_cmus,
        mytasklist[s],
        layout = awful.widget.layout.horizontal.rightleft
    }

Afin de pouvoir le contrôler depuis Awesome, il faut encore ajouter la combinaison de touches qui permettent d’activer les différents signaux. Dans la section “keybindings”, ajoutez-y la combinaison de touches que vous voulez. Chez moi, j’ai choisis que ça soit les touches “Ctrl”+“droite/gauche/haut/bas” mais vous pouvez évidemment les remplacer par ce que vous voulez:

1
2
3
4
5
6
(...)
    awful.key({ "Control", }, "Right", function () cmus_control("next") end),
    awful.key({ "Control", }, "Left", function () cmus_control("previous") end),
    awful.key({ "Control", }, "Up", function () cmus_control("stop") end),
    awful.key({ "Control", }, "Down", function () cmus_control("play_pause") end),
(...)

Voilà, j’espère que cela sera utile à quelqu’un et si quelque chose n’est pas claire, n’hésitez pas à le signaler dans un commentaire ;). Et n’oubliez pas que vous pouvez toujours accéder à mon rc.lua si vous avez besoin d’inspiration.