Journal Écouter la radio

Posté par  . Licence CC By‑SA.
27
12
avr.
2016

Salut,

Je me suis fait un petit script pour écouter la radio par internet sur mon laptop.
Ça s'utilise dans un terminal ou on peut l'appeler par un raccourci clavier par exemple.

Il faut mettre le script dans le path de l'utilisateur et lui donner les droits d'execution (chmod u+x fichier).

Ensuite on choisit ses radios préférées et on récupère l'adresse des flux par exemple ici : Liste de flux radio. Il faut les renseigner dans le script.

Et voilà. Pour l'utiliser, 2 méthodes :

  • Depuis un terminal.
    • Sans arguments, il renvoie la liste des stations connues
    • Avec le numéro ou le nom de la station, il lance la lecture
  • Avec un raccourci clavier
    • Votre gestionnaire de bureau doit vous permettre de configurer des raccourcis claviers. Assignez une combinaison de touches à l'execution du script, avec l'option -g (mode graphique).
    • Le script affiche un menu présentant les stations possibles. Sélectionner la station désirée et appuyer sur entrée
    • Si une lecture est déjà en cours, le script l'arrête plutôt que de lancer une autre lecture.

C'est vachement plus accessible que de retourner sur les interfaces webs divers et variés des différentes radios. En espérant que ça puisse vous être utile !

#!/bin/bash
# Émile Decorsière <al@md2t.eu>
# ----------------------------------------------------------------------
#         DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
#                    Version 2, December 2004 
# Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> 
# Everyone is permitted to copy and distribute verbatim or modified 
# copies of this license document, and changing it is allowed as long 
# as the name is changed. 
#
#            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 
#   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
#
#  0. You just DO WHAT THE FUCK YOU WANT TO.
# ----------------------------------------------------------------------
# used softwares:
#   mpv
#   dmenu (provided in suckless-tools debian package)
# ----------------------------------------------------------------------

# Audio player command
PLAYER=mpv

### Liste des stations
#sta[n]="nom de la station à appeller"
#stan[n]="url à lancer dans mpv"

sta[0]="wwoz"
stau[0]="http://wwoz-sc.streamguys.com/wwoz-hi.mp3.m3u"

sta[1]="fip"
stau[1]="http://audio.scdn.arkena.com/11016/fip-midfi128.mp3"

sta[2]="classique"
stau[2]="http://players.creacast.com/creacast/classique/playlist.pls"

sta[3]="inter"
stau[3]="http://www.listenlive.eu/franceinter128.m3u"

sta[4]="nostalgie"
stau[4]="http://www.listenlive.eu/nostalgie_fr.m3u"

sta[5]="larzac"
stau[5]="http://www.radiolarzac.org:8000/radiolarzac.m3u"

sta[6]=""
stau[6]=""

# Script
# Help if no args or -h or --help
if [ $# -eq 0 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]
  then echo "usage $0 [nom_radio|num_radio]"
  echo "-g option for non interactive mode - dmenu required"
  # Print sta list
  for ((i=0; i<${#sta[@]}; i++))
  do
    echo $i . ${sta[$i]}
  done
  exit 1
fi

# If graphical mode
if [ "$1" = "-g" ]
then
  if ps aux | grep -v grep | grep "mpv"
  then 
    pkill mpv
    exit 0
  else
    stname=$(for i in ${sta[@]}; do echo $i; done | dmenu)
    for ((i=0; i<${#sta[@]}; i++))
    do
      if [ "$stname" = "${sta[$i]}" ]
        then stream=${stau[$i]}
      fi
    done
  fi
else
  # If sta number given
  if [ "$1" -eq "$1" ] 2>/dev/null
  then stream=${stau[${1}]}
  # If sta name given
  else
    for ((i=0; i<${#sta[@]}; i++))
    do
      if [ "$1" = "${sta[$i]}" ]
      then stream=${stau[$i]}
      fi
    done
  fi
fi
# Test if arg given is valid
if [ -n "$stream" ]
  then 
  # Detect if stream is in playlist format to give playlist opt to mplayer...
  if [ ${stream: -4} == ".pls" ] || [ ${stream: -4} == ".m3u" ]
  then
    $PLAYER -playlist $stream
  # Or not
  else
    $PLAYER $stream
  fi
else
  exit 2
fi
  • # comme toujours : pensez à weboob !

    Posté par  (Mastodon) . Évalué à 10.

    Pour info, pour écouter la radio en ligne de commande, il y a aussi radioob, un module de weboob.

    http://weboob.org/applications/radioob.html

    En théorie, la théorie et la pratique c'est pareil. En pratique c'est pas vrai.

  • # Player

    Posté par  . Évalué à 5.

    Si vous avez une vieille machine, ça vaut le coup d'essayer mpg123 comme lecteur : suivant le processeur, il peut être 50% moins gourmand en temps processeur. C'est ce que je constate sur un Celeron 900 d'EeePc avec la commande time.

    Il y a aussi le problème du reéchantillonage en passant par pulseaudio, comme c'est expliqué dans la FAQ.

    ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

    • [^] # Re: Player

      Posté par  . Évalué à 5.

      Enfin radiotray fait aussi le job en graphique. Ou dans F-droid : radiodroid est une tuerie en utilisant un annuaire ouvert.

      ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

  • # Avec votre langage préféré...

    Posté par  . Évalué à -3.

    … Ça donnerait quoi ?

    Avec vlc plutôt que mpv, de gros doutes sur l'utilisation de dmenu, et à l'arrache

    #!/usr/bin/env node
    
    if (process.argv.length<3) {
      var path = require('path')
      console.error('Usage: %s %s [nom_radio|num_radio]',
                path.basename(process.argv[0]), path.relative(".", process.argv[1]));
      process.exit(1)
    }
    
    var radios = {
      wwoz: "http://wwoz-sc.streamguys.com/wwoz-hi.mp3.m3u",
      fip: "http://audio.scdn.arkena.com/11016/fip-midfi128.mp3",
      classique: "http://players.creacast.com/creacast/classique/playlist.pls",
      inter: "http://www.listenlive.eu/franceinter128.m3u",
      nostalgie: "http://www.listenlive.eu/nostalgie_fr.m3u",
      larzac: "http://www.radiolarzac.org:8000/radiolarzac.m3u",
    }
    
    var argRadio = process.argv[2];
    
    if (argRadio.match(/^[0-9]+$/)) argRadio = Object.keys(radios)[argRadio]
    
    if (!radios[argRadio]) {
      console.error('Unknown radio %s\nChoose one of\n%s', process.argv[2], Object.keys(radios))
      process.exit(1)
    }
    
    var player = 'vlc'
    
    var dmenu = process.argv[3];
    
    if (!dmenu) return invokePlayer(player, radios[argRadio])
    
    var child = require('child_process').spawn('demnu', [], {stdio: 'pipe'})
    Object.keys(radios).forEach(function (k, i) {
      child.stdin.write(i + '\n')
    })
    var selected = null;
    child.stdout.on('data', function (d) {
      selected = d.toString().replace(/^\s*|\s*$/, '')
    })
    child.on('close', function () {
      if (selected!==null) return invokePlayer(player, radios[Object.keys(radios)[selected]])
      console.error('Oh no !...')
    })
    child.on('error', console.error.bind(console))
    
    function invokePlayer(player, url){
      var args = [];
      (player.match(/mpv/) && url.match(/[.](pls|m3u)$/)) && args.push('-playlist');
      args.push(url)
    
      var child = require('child_process').spawn(player, args, {stdio: 'inherit'})
    
      process.on('SIGINT', function () {
        child.kill('SIGINT')
      })
    }

    Je ne suis pas certain de cette partie au sujet de dmenu

        stname=$(for i in ${sta[@]}; do echo $i; done | dmenu) // envoie les options à dmenu ? une par ligne ? bloque jusqu'à la fermeture de dmenu ? sauvegarde la réponse de dmenu dans stname ?
        for ((i=0; i<${#sta[@]}; i++))
        do
          if [ "$stname" = "${sta[$i]}" ]
            then stream=${stau[$i]}
          fi
        done
    • [^] # Re: Avec votre langage préféré...

      Posté par  . Évalué à 1.

      Merci de la réponse.
      Je suis pas sûr de suivre ton code, comme tu as pu le remarquer, le mien est fait avec mes pieds d'autodidacte acharné…

      Pour la ligne dmenu, ça envoie effectivement les options à dmenu, séparées par des changements de lignes. Ensuite dmenu renvoie l'option que l'on selectionne.

      • [^] # Re: Avec votre langage préféré...

        Posté par  . Évalué à -6.

        Je suis pas sûr de suivre ton code, comme tu as pu le remarquer, le mien est fait avec mes pieds d'autodidacte acharné…

        oui c'est un peu l'idée, sans prétention, se contenter de partager, d'avoir plusieurs versions de la même chose. Après à chacun d'aller dans la direction qu'il souhaite. Et/ou de poser les questions dont il a besoin.

        Mais bon rassurons nous, cela n'est pas arrivé ; )

  • # Revue de code

    Posté par  . Évalué à 10.

    ps aux | grep -v grep | grep "mpv"

    Tu peux utiliser pgrep à la place (surtout que tu utilise pkill juste derrière).
    AMHA il y a une coquille tu devrais utiliser $PLAYER à la place de mpv.

    for i in ${sta[@]}; do echo $i; done

    Il y a une astuce super sympa pour ça :

    printf "%s\n" "${sta[@]}"; done

    Pour le paramétrage comme tu utilise bash j'aurais plutôt utilisé un tableau associatif :

    sta[wwoz]="http://wwoz-sc.streamguys.com/wwoz-hi.mp3.m3u"
    sta[fip]="http://audio.scdn.arkena.com/11016/fip-midfi128.mp3"
    #...

    Ça simplifie pas mal ton code en remplaçant :

    stname=$(for i in ${sta[@]}; do echo $i; done | dmenu)
    for ((i=0; i<${#sta[@]}; i++))
    do
        if [ "$stname" = "${sta[$i]}" ]
            then stream=${stau[$i]}
        fi
    done

    Par :

    stname=$(printf "%s\n" "${!sta[@]}" | dmenu)
    stream="${sta[$stname]}"

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Revue de code

      Posté par  . Évalué à 1. Dernière modification le 12 avril 2016 à 20:35.

      Merci des conseils, j'ai corrigé la coquille ! Comme tu as pu le voir mes compétences en programmation sont limitées. Tu peux expliquer, le coup du :

      printf "%s\n" "${sta[@]}"

      Pour le coup du tableau associatif… J'y avais pensé, mais j'aimais bien lancer une radio avec son numéro (plus court à taper). Donc j'ai laissé les numéros.

      • [^] # Re: Revue de code

        Posté par  . Évalué à 4. Dernière modification le 12 avril 2016 à 23:07.

        man printf ! ;)

        M’enfin ouai, une basherie… :

        stef@medusa:~/test$ toto=('pim' 'pam' 'pooooooom!')
        stef@medusa:~/test$ printf "%s hello ! \n" "${toto[@]}"
        pim hello ! 
        pam hello ! 
        pooooooom! hello !
        

        Je vois pas comment expliquer plus…

        Note que je viens de découvrir cette construction ^^

        • [^] # Re: Revue de code

          Posté par  . Évalué à 3.

          stef@medusa:~/test$ echo ${toto[@]}
          pim pam pooooooom!
          

          Rho putain… je viens de découvrir une belle fôte sur le strip « autosatisfaction récursive ? »

          que je l’avais écris

          écrit :/

          • [^] # Re: Revue de code

            Posté par  . Évalué à 3.

            stef@medusa:~/test$ echo ${toto[@]}
            pim pam pooooooom!
            

            Euh… dmenu a besoin (du moins par défaut d'une option par ligne (après oui il y a pleins de manière de faire).

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Revue de code

              Posté par  . Évalué à 2.

              Oui. C’est pour ça que dans mon message précédent je faisais un printf "%s\n" "${toto[@]}" (comme quelqu’un d’autre l’avait déjà montrer)

              Le simple echo c’était pour montrer à quoi correspondait ${toto[@]} car on avait demandé :

              Tu peux expliquer, le coup du : printf "%s\n" "${sta[@]}"

              Sinon pour :

              du moins par défaut d'une option par ligne (après oui il y a pleins de manière de faire

              Je suppose qu’en changeant IFS on doit pouvoir faire ça, mais le printf "%s\n" … est plus propre sans aucun doute.

      • [^] # Re: Revue de code

        Posté par  . Évalué à 3.

        Pour le coup du tableau associatif… J'y avais pensé, mais j'aimais bien lancer une radio avec son numéro (plus court à taper). Donc j'ai laissé les numéros.

        Ça n'empêche pas. C'est juste que ça te demande un peu plus de travail.

        keys=( "${!sta[@]}" )
        stream="${sta[${keys[1]]}"

        (je ne connais pas de moyen avec bash de se passer de la variables keys)

        Pour la gestion des extensions tu peux aussi faire :

        if [[ "${stream##*.}" =~ ^(mu3|pls)$ ]]; then
            #....

        Les notations #, ##, % et %% retire les préfixes et suffixes. Donc là j'enlève tout jusqu'au dernier '.'
        Ensuite pour simplifier l'écriture j'utilise un expression régulière. En soit il vaudrait mieux mettre les extensions dans un tableau et tester si l'extension fait partie du tableau, mais il n'y a pas de bonne manière de tester si quelque chose existe dans un tableau en bash, l'un des moins pire pourrait être :

        playlist_ext=( 'mu3' 'pls')
        
        #...
        
        if printf "${playlist_ext[@]}\n" | grep -q "^${stream##*.}$" ; then

        C'est comme tu préfère :)

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # tant qu'on y est

    Posté par  (site web personnel, Mastodon) . Évalué à 5.

    je file mon vieux script, qui se contente de lancer la station (radio [nom_station]):

    #!/bin/sh
    cd ~/radios
    if [ $# != 1 ]; then
            echo "syntaxe: radio nom_radio"
            echo "liste:"
            echo "--"
            ls -1
            echo "--"
            echo
            exit 1
    fi 
    mpv --playlist "$1"

    et dans ~/radios y'a des listes de lecture avec les noms des radios

    % cat lat
    http://vdl.stream-lat.org:8000/voixdulat_mp3
    

    Pendant que j'y suis pour sauvegarder le prochain bulletin france info :

    % cat sauve_prochaines_infos 
    #!/bin/zsh
    STREAM='http://audio.scdn.arkena.com/11006/franceinfo-midfi128.mp3'
    
    sleep $((1800-(`date +%s`%(60*30)))); mplayer -dumpfile ~/dump/dernieres_infos.mp3 -dumpstream "$STREAM" & sleep $((60*15)); pkill -f "dumpfile.*dernieres_infos.mp3"
    • [^] # Re: tant qu'on y est

      Posté par  . Évalué à -8.

      ce serait pas mal du tout si il existait un genre de bash package manager à la manière de npm pour partager ce genre de script.

      • [^] # Re: tant qu'on y est

        Posté par  . Évalué à 10.

        Ouai ! Comme ça on pourrait créer des packages d'une ligne genre :

        file_exist.sh

        test -f "$1"

        Je plaisante, mais il est très difficile de faire quelque chose vraiment réutilisable en shell. Il faut se mettre d'accord sur les conventions d'appel par exemple comme les fonction n'ont pas de valeur de retour des fois on modifie une variable globale (ouai) des fois on récupère la sortie standard (ouai).

        Le niveau de portabilité est souvent assez faible (pas de vérification des programmes installés - voir de leur version GNU/BSD), pas d'utilisation de XDG,… Ce n'est pas une critique un script c'est fait pour servir son utilisateur si ça fonctionne ainsi tant mieux :)

        La communauté zsh a tout de même créé un truc pour faire via un système de module, mais ça utilise des trucs qu'on ne trouve que dans zsh et qui permettent d'être portable sans sortir de zsh.

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: tant qu'on y est

          Posté par  . Évalué à -8.

          oui. Ce serait mieux un Bash script installer. Des package en bash c'est comme invité le diable dans son shell.

          Quelque chose sans prétention qui fasse juste le job d'interroger, télécharger, extraire et installer les deux trois petites choses qui ferait ce genre de script (les deux) plus aisément partageable.

  • # mpd

    Posté par  (site web personnel) . Évalué à 6.

    Dans mon arborescence de musique, j'ai un répertoire avec des fichiers m3u très bien compris par mpd (comme playlist).

    Et avec mpd on a l’embarra du choix côté client, en ligne de commande : mpc, ncmpcpp, etc.

    Exemple de fichier m3u:

    $ cat pbb.m3u 
    #EXTM3U
    #EXTINF:Pedro's Broadcasting Basement
    http://pbb.laurentgarnier.com:8000/pbb128
    

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.