Je me suis récemment découvert une nouvelle passion pour Emacs et sa configuration. J’essaye de commencer à l’utiliser au quotidien. Et je viens de l’utiliser pour télécharger des fichiers mp3.

Ma fille a eu un baladeur mp3 pour son anniversaire et elle m’a demandé si je pouvais lui mettre les épisodes d’un podcast qu’elle aime bien Merci Rémi !. J’ai commencé à regarder sur la page, essayer de scripter la récupération des liens des fichiers. Puis j’ai vu l’icône du flux rss et je me suis souvenu que j’avais commencé à configurer elfeed dans Emacs. Et comme Emacs est réputé adaptable à toutes les situations et que j’avais quelques heures à passer j’ai essayé d’adapter elfeed à mon besoin.

Premier problème j’ai configuré le protocole fever pour récupérer mes flux rss sur une instance freshrss. Et les entrées récupérées par elfeed ne contiennent pas d’entrée enclosure avec le lien vers le fichier mp3 de l’épisode. La solution est de configurer la variable elfeed-feeds pour des flux locaux qui auront l’entrée closure en plus de la variable elfeed-fever-feeds pour l’entrée vers freshrss. Et enfin de concaténer le tout dans elfeed-feeds qui est la variable utilisée. Ce qui donne :

  (setq elfeed-fever-feeds '(("fever+http://toto@freshrss.example.org"
				 :api-url "http://toto@freshrss.example.org/api/fever.php"
				 :password "mot_de_passe")))

  (setq elfeed-feeds
        '(("https://feed.ausha.co/Kw9GDtDjwkRX" podcast)))
		
  (setq elfeed-feeds (append elfeed-fever-feeds elfeed-feeds))

Ensuite j’ai commencé à écrire directement depuis le buffer *scratch* une fonction pour récupérer le lien sous mon curseur. C’est un plaisir de modifier le comportement d’Emacs tout en l’utilisant. La fonction a évolué pour télécharger l’enclosure de l’entrée elfeed sous le cluster. Voici la version finale. Elle récupère l’enclosure (il n’y en a qu’une occurrence dans les entrées du podcast) ainsi que le titre du flux et le nom de l’entrée. La fonction marque l’entrée comme lue et passe à la suivante. J’ai récupéré l’exemple de la boucle.

(defun elfeed-download-podcast (&optional use-generic-p)
    "Download podcast"
    (interactive "P")
    (let ((entries (elfeed-search-selected)))
      (cl-loop for entry in entries
       do (elfeed-untag entry 'unread)
       when (elfeed-entry-link entry) 
       ;; On récupère la première enclosure, le titre du flux et le nom de l'entrée
       do (my/id3v2 (car (elt (elfeed-entry-enclosures entry) 0 )) (elfeed-feed-title (elfeed-entry-feed entry)) (elfeed-entry-title entry) )
       )
     (mapc #'elfeed-search-update-entry entries)
     (unless (use-region-p) (forward-line))))

Les 3 paramètres récupérés sont passés à la fonction my/id3v2. Cette fonction va télécharger le lien passé en paramètre (l’enclosure) et ajouter le tag nom de l’artiste avec le nom du flux et le tag titre avec le nom de l’entrée du flux.

  (defun my/id3v2 (my/url artist file)
    (url-copy-file my/url (format "/tmp/%s.mp3" file))
    (shell-command (format "mid3v2 -a \"%s\" -t \"%s\" /tmp/\"%s\".mp3" artist file file))
    (shell-command (format "mid3v2 /tmp/\"%s\".mp3" file))
  )

Le téléchargement se fait avec url-copy-file qui est livré avec Emacs. Pour ajouter les tags et vérifier que tout est correct je lance un process avec l’outil en ligne de commande mid3v2 qu’il faut avoir installé au préalable.

Enfin l’appel est mappé à la touche v dans le keymap de elfeed.

  (define-key elfeed-search-mode-map (kbd "v") 'elfeed-download-podcast)

On peut bien sûr améliorer tout ça, ne serait-ce que pour ajouter une variable pour le répertoire de téléchargement.

Mais en l’état cela fonctionne, cela m’a permis de télécharger rapidement les 98 épisodes du podcast et qu’ils aient des tags pour être triés sur le lecteur mp3. Et pour les prochains épisodes cela sera suffisant.

Je suis content du résultat. Cela m’a pris 2h de ma soirée et j’ai tout écrit directement dans Emacs sans quitter l’éditeur. Je pense que je vais continuer à utiliser Emacs et à faire plus de choses avec.