This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tuto_icestream [2020/02/25 14:42] – raven14 | tuto_icestream [2020/03/03 09:12] (current) – raven14 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== IceStream ====== | ||
| + | |||
| + | Icestream est un logiciel de stream audio qui permet de mixer, recevoir ou envoyer des flux audio à travers un réseau local ou Internet. | ||
| + | |||
| + | |||
| + | ==== IceStream v2.1-2 : cooking - installation et utilisation ==== | ||
| + | |||
| + | === 1 - La mise à jour du logiciel === | ||
| + | |||
| + | Les nouvelles fonctionnalités et changements : | ||
| + | |||
| + | General | ||
| + | * Les paramètres peuvent désormais être sauvegardé et chargé, ainsi qu' | ||
| + | * Amélioration de la gestion des chemins | ||
| + | Lecteur | ||
| + | * Ajout d'un vu-Mètre rudimentaire | ||
| + | * Ajout d'une trackbar non interactive | ||
| + | * Fix du contrôle de volume | ||
| + | * Fix du comportement du lecteur | ||
| + | * Amélioration général de la lisibilité générale | ||
| + | Client | ||
| + | * Transition d'ices à Liquidsoap | ||
| + | * Ajout du support pour le format mp3 | ||
| + | * Ajout d'une supervision des logs et statut du client | ||
| + | * Ajout d'une option de sauvegarde du stream en local | ||
| + | * Ajout d'une option de duplication du stream en basse qualité | ||
| + | Server | ||
| + | * Mise à jour vers IceCast2 | ||
| + | * Ajout d'une vue Web vers le serveur | ||
| + | * Ajout d'une supervision des logs et statut du client | ||
| + | |||
| + | |||
| + | === 2 - Installation How-To === | ||
| + | |||
| + | == [RECOMMENDÉ] Par package : == | ||
| + | |||
| + | L' | ||
| + | |||
| + | Double-clicker (//ou click-droit -> Installer logiciel//) le fichier installera Icestream, ainsi que ces dépendances. | ||
| + | |||
| + | == [ALTERNATIVE] == | ||
| + | |||
| + | Vous pouvez également installer le package via dpkg, puis apt pour les dépendances : | ||
| + | < | ||
| + | dpkg -i ~/ | ||
| + | apt -f install | ||
| + | </ | ||
| + | |||
| + | == À partir des sources :== | ||
| + | |||
| + | Si vous souhaitez compiler directement IceStream, vous trouverez ce dont vous avez besoin [[https:// | ||
| + | N' | ||
| + | < | ||
| + | apt install debhelper-compat, | ||
| + | </ | ||
| + | |||
| + | === 3 - Comment utiliser Icestream === | ||
| + | |||
| + | L' | ||
| + | - Les lecteurs, pouvant jouer la majorité des formats audio et vidéo, que ce soit en local, ou en réseau.\\ | ||
| + | - Le client, permettant de transmettre le flux vers un serveur.\\ | ||
| + | - Le serveur, si vous souhaitez héberger votre propre serveur.\\ | ||
| + | |||
| + | |||
| + | Pour lire un fichier/ | ||
| + | |||
| + | Pour envoyé votre flux vers un serveur, il vous suffira d' | ||
| + | Il vous faudra ensuite, dans l' | ||
| + | |||
| + | Pour héberger votre serveur, il vous suffira de rentrer les paramètres demandés.\\ | ||
| + | Le mot de passe et port demandés sont bien ceux qu'il faudra transmettre au client.\\ | ||
| + | Une fois le serveur démarré, une fenêtre s' | ||
| + | |||
| + | |||
| + | == [ FAQ ] == | ||
| + | |||
| + | - Mon audio ne joue pas !\\ | ||
| + | -> Assurez vous d' | ||
| + | |||
| + | - J' | ||
| + | -> Assurez vous d' | ||
| + | Il est également possible qu' | ||
| + | < | ||
| + | |||
| + | |||
| + | ===4 - Détails=== | ||
| + | [**AVERTISSEMENT**]\\ | ||
| + | Les solutions présentées ci-dessous ne sont absolument pas les meilleures pratiques possible, mais les ébauches d'un débutant.\\ | ||
| + | Une grande partie des ces méthodes pourraient être améliorées.\\ | ||
| + | Veillez donc à rester critique, et à garder votre propre vision des choses. Merci.\\ | ||
| + | \\ | ||
| + | |||
| + | Cette section consiste à expliquer en plus de détails les changements effectué au code\\ | ||
| + | Note : IceStream à été conçu avec Qt Creator et Qt Designer, compilé sous qt4.8.\\ | ||
| + | |||
| + | ==Fichiers de configurations Client/ | ||
| + | |||
| + | __Serveur__\\ | ||
| + | Un guide des plus complet peut être trouvé [[https:// | ||
| + | __Client__\\ | ||
| + | La documentation du fichier de config Liquidsoap peut être trouvé [[https:// | ||
| + | Exemple : | ||
| + | < | ||
| + | set(" | ||
| + | set(" | ||
| + | set(" | ||
| + | set(" | ||
| + | set(" | ||
| + | full = input.jack(id=" | ||
| + | output.icecast(%vorbis(samplerate=96000, | ||
| + | host=" | ||
| + | port=XXXX, | ||
| + | password=" | ||
| + | mount=" | ||
| + | name=" | ||
| + | description=" | ||
| + | genre=" | ||
| + | full) | ||
| + | </ | ||
| + | |||
| + | __Creation d'un fichier de config Client/ | ||
| + | La création d'un fichier de config ce sont en utilisant [[https:// | ||
| + | La configuration d' | ||
| + | La configuration de Liquidsoap devant être en Plain Text, [[https:// | ||
| + | |||
| + | < | ||
| + | void CreateLiquidConfig() | ||
| + | { | ||
| + | QFile file(clientFilePath); | ||
| + | |||
| + | file.open(QFile:: | ||
| + | QTextStream stream(& | ||
| + | stream.setCodec(" | ||
| + | |||
| + | stream << " | ||
| + | ... | ||
| + | file.close(); | ||
| + | ---------------------------------------------------------------------- | ||
| + | QXmlStreamWriter writer(& | ||
| + | writer.setCodec(" | ||
| + | |||
| + | writer.setAutoFormatting(true); | ||
| + | writer.writeStartDocument(); | ||
| + | writer.writeStartElement(" | ||
| + | writer.writeEndElement(); | ||
| + | ... | ||
| + | file.close(); | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | == Mise à jour IceCast2 == | ||
| + | IceCast(1) étant obsolète, il a fallu passer à IceCast2.\\ | ||
| + | Au niveau code, il a simplement fallu remplacer un mot-clef. Le fichier de configuration est lui resté le même. | ||
| + | < | ||
| + | void launchIceCast() | ||
| + | { | ||
| + | [...] | ||
| + | serverStreamCommande = " | ||
| + | [...] | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==La vue Web== | ||
| + | Une vue Web (comme un explorateur internet) vers la page d' | ||
| + | |||
| + | Pour cela on utilise un objet [[https:// | ||
| + | À la confirmation du bon lancement du serveur, on ouvre la vue, en lui donnant l' | ||
| + | Ici un [[https:// | ||
| + | |||
| + | < | ||
| + | [ Après lancement ] | ||
| + | QTimer:: | ||
| + | |||
| + | void slotOpenAdminView(){ | ||
| + | ui-> | ||
| + | ui-> | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ==Supervision des logs et statut d'un QProcess== | ||
| + | Le but était d' | ||
| + | |||
| + | Les fichiers de logs se trouvent dans /tmp/ (voir configuration server/ | ||
| + | Un [[https:// | ||
| + | < | ||
| + | liquidsoap_watcher = new QFileSystemWatcher(this); | ||
| + | liquidsoap_watcher-> | ||
| + | connect(liquidsoap_watcher, | ||
| + | |||
| + | slotLiquidlog(QString filepath) | ||
| + | { | ||
| + | QString log = getLogs(filepath); | ||
| + | if((log != lastLiquidlog) && !(log.contains(lastLiquidlog))){ | ||
| + | ui-> | ||
| + | lastLiquidlog = log ; | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | Avec une fonction permettant de parser les nouvelles lignes ajoutées | ||
| + | < | ||
| + | getLogs(QString path){ | ||
| + | QFile file(path); | ||
| + | QString log; | ||
| + | QString lastlog[3]; | ||
| + | if (file.open(QIODevice:: | ||
| + | file.seek(file.size()-1); | ||
| + | for (int i=0; | ||
| + | QString token = file.read(1); | ||
| + | file.seek(file.pos()-2); | ||
| + | if (token == " | ||
| + | i++; | ||
| + | } | ||
| + | } | ||
| + | log = file.readAll(); | ||
| + | file.close(); | ||
| + | log.remove(0, | ||
| + | } return log; } | ||
| + | </ | ||
| + | **Note : Cette méthode complète est loin d' | ||
| + | |||
| + | Les applications étant lancées en tant que [[https:// | ||
| + | < | ||
| + | connect(streamProcess, | ||
| + | |||
| + | void slotstreamProcess_StateChanged(QProcess:: | ||
| + | { | ||
| + | if(i == 0){ ui-> | ||
| + | else { ui-> | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==Ajout d'un format audio (ici mp3)== | ||
| + | La documentation sur les formats audio se trouve [[https:// | ||
| + | La configuration ayant besoin d' | ||
| + | < | ||
| + | // Exemple avec ogg | ||
| + | output_setting = " | ||
| + | </ | ||
| + | La ligne correspondante au format doit pouvoir être interchangeable si l'on veut pouvoir utiliser plusieurs formats. | ||
| + | < | ||
| + | void audioFormatSettingsPicker(int i){ | ||
| + | QString output_setting; | ||
| + | switch (i) { | ||
| + | case 0: // ogg | ||
| + | output_setting = " | ||
| + | break; | ||
| + | case 1: // mp3 | ||
| + | output_setting = " | ||
| + | break; | ||
| + | </ | ||
| + | Il faut également que l' | ||
| + | C'est frame sont ensuite cachées et affichées selon le format sélectionné. | ||
| + | < | ||
| + | connect(ui-> | ||
| + | |||
| + | void audioFormatFrameHandler(int i){ | ||
| + | switch (i) { | ||
| + | case 0: | ||
| + | ui-> | ||
| + | ui-> | ||
| + | ui-> | ||
| + | ui-> | ||
| + | break; | ||
| + | case 1: | ||
| + | ui-> | ||
| + | ui-> | ||
| + | ui-> | ||
| + | ui-> | ||
| + | break; | ||
| + | </ | ||
| + | |||
| + | ==Ajout d'une option Liquidsoap== | ||
| + | Liquidsoap est un client puissant, offrant plus que la possibilité d' | ||
| + | Lors de la création du fichier de configuration, | ||
| + | < | ||
| + | void createLiquidConfig() | ||
| + | { | ||
| + | QFile file(clientFilePath); | ||
| + | // Ouverture du fichier en écriture et en texte. | ||
| + | file.open(QFile:: | ||
| + | QTextStream stream(& | ||
| + | [...] | ||
| + | if(ui-> | ||
| + | stream << " | ||
| + | stream << "' | ||
| + | stream << " | ||
| + | stream << " | ||
| + | stream << " | ||
| + | stream << " | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==Utilisation de QProcess== | ||
| + | Un [[https:// | ||
| + | L' | ||
| + | QProcess à besoin du nom de l' | ||
| + | < | ||
| + | void startVuMeter(){ | ||
| + | QStringList arguments; | ||
| + | QString output = " | ||
| + | arguments << " | ||
| + | vuMeterProcess-> | ||
| + | } | ||
| + | </ | ||
| + | Note : Ici est également démontré l' | ||
| + | |||
| + | |||
| + | ==Le stdin & stdout de MPlayer== | ||
| + | __Exemple : La trackbar__\\ | ||
| + | Elle consiste d'une simple [[https:// | ||
| + | Le snippet si dessous correspond à la stylesheet utilisé pour IceStream. La syntax est dans l' | ||
| + | |||
| + | < | ||
| + | QProgressBar:: | ||
| + | background-color: | ||
| + | margin-left: | ||
| + | margin-right: | ||
| + | border: 1px solid rgb(110, 95, 100); | ||
| + | border-radius: | ||
| + | } | ||
| + | </ | ||
| + | La position de la piste est obtenu en envoyant à MPlayer la commande " | ||
| + | < | ||
| + | poller = new QTimer(this); | ||
| + | poller-> | ||
| + | |||
| + | connect(poller, | ||
| + | </ | ||
| + | La réponse d' | ||
| + | < | ||
| + | connect(lecteurProcess, | ||
| + | |||
| + | void slotprocessMessage(){ | ||
| + | while (lecteurProcess-> | ||
| + | { | ||
| + | buffer.remove(0, | ||
| + | currentTime = buffer.toFloat(); | ||
| + | trackBar-> | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | __Exemple : Le volume__\\ | ||
| + | Le principe est le même que pour la trackbar, mais cet fois-ci pas besoin de lire le stdout.\\ | ||
| + | Le petit détail ennuyant avec MPlayer est qu'il est impossible de lui donner une valeur à affecter au volume.\\ | ||
| + | Il faut donc lui envoyer la commande " | ||
| + | Lorsque le volume est modifié par l' | ||
| + | |||
| + | < | ||
| + | void setVolume(int i) | ||
| + | { | ||
| + | int val = (i-volumeAncienneValeur); | ||
| + | QString lecteurVolume; | ||
| + | if((i-volAncienneValeur) >= 0){ | ||
| + | for (int n=0; | ||
| + | lecteurVolume= " | ||
| + | char *volumeProc=playerVolume.toAscii().data(); | ||
| + | lecteurProcess-> | ||
| + | } | ||
| + | } | ||
| + | else { | ||
| + | for (int n=0; | ||
| + | playerVolume = " | ||
| + | char *volumeProc=playerVolume.toAscii().data(); | ||
| + | lecteurProcess-> | ||
| + | } | ||
| + | } | ||
| + | volAncienneValeur=slider-> | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==La sauvegarde des paramètres de l'UI (save, load)== | ||
| + | Pour éviter que l' | ||
| + | \\ | ||
| + | Pour créer le fichier de config, on utilise le même principe que pour la config de Liquidsoap, c' | ||
| + | < | ||
| + | void makeConfig(QString chemin){ | ||
| + | QFile file(chemin); | ||
| + | file.open(QFile:: | ||
| + | QTextStream outStream(& | ||
| + | |||
| + | outStream << " | ||
| + | outStream << " | ||
| + | [...] | ||
| + | file.close; | ||
| + | </ | ||
| + | Cela produira un fichier contenant, ligne par ligne, les nom & valeurs que vous lui avez donné.\\ | ||
| + | Note: N' | ||
| + | \\ | ||
| + | Maintenant, il faut lire ces valeurs, et les réattribués à leurs champs respectifs.\\ | ||
| + | Ici, une [[https:// | ||
| + | Le but est de lire l' | ||
| + | Puis on finit par remplir les champs en utilisant " | ||
| + | < | ||
| + | QMap< | ||
| + | |||
| + | void getConfig(QString chemin) | ||
| + | { | ||
| + | QFile file(chemin); | ||
| + | QString current_line; | ||
| + | file.open(QFile:: | ||
| + | QTextStream outStream(& | ||
| + | |||
| + | while(!outStream.atEnd()){ | ||
| + | std::string a = outStream.readLine().toStdString(); | ||
| + | size_t pos = a.find(' | ||
| + | QString key = QString:: | ||
| + | QString value = QString:: | ||
| + | settingsMap[key] = value; | ||
| + | } | ||
| + | |||
| + | ui-> | ||
| + | ui-> | ||
| + | [...] | ||
| + | file.close; | ||
| + | |||
| + | </ | ||
| + | ==== Installation Icestream v1.2 : ==== | ||
| + | |||
| + | Pour l' | ||
| + | [[http:// | ||
| + | |||
| + | |||
| + | Les dépendances : | ||
| + | |||
| + | < | ||
| + | |||
| + | Puis les paquets en root : | ||
| + | |||
| + | < | ||
| + | sudo su | ||
| + | tar xvzf IceStream.tar.gz | ||
| + | cd IceStream/ | ||
| + | dpkg -i libshout_2.2-1_i386.deb | ||
| + | dpkg -i libtheora_1.2-1_i386.deb | ||
| + | dpkg -i icecast-2.3.2_3-1_i386.deb | ||
| + | dpkg -i ices-2.0_4-1_i386.deb | ||
| + | cd IHMB/ | ||
| + | qmake -project | ||
| + | qmake . | ||
| + | make | ||
| + | sudo cp IHMB / | ||
| + | </ | ||
| + | |||
| + | ==== Utilisation : ==== | ||
| + | Vous le lancer comme ceci en utilisateur ** simple** (id NOT sudo): | ||
| + | < | ||
| + | |||
| + | Pour l' | ||
| + | Enjoy ! | ||
| + | |||