This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
tuto_icestream [2020/02/26 20:59] – [IceStream v2.1-2 : cooking - installation et utilisation] 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 ! | ||
+ | |||