Sommaire
- Résumé
- Introduction, Qui ?
- Quoi ?
- Qu’est-ce que Rust ?
- Pourquoi Rust ?
- Pourquoi devrait-on s’en préoccuper ?
- État, il y a un an
- Écrire des applications GStreamer avec Rust
- Écrire des extensions GStreamer en Rust
- À venir…
- Merci / Questions ?
Rustifiez votre multimédia !
Voici une traduction de la présentation « Oxidising GStreamer — Rust out your multimedia! » qui a eu lieu le 22 octobre 2017 à Prague dans le cadre de la Conférence GStreamer 2017.
Merci à Sebastian Dröge pour cette présentation et pour son autorisation de traduction.
Pour les planches au format PDF, rendez-vous ici.
Résumé
Dans la suite logique de ma présentation de l’année dernière, je vais vous tenir au courant de ce qu’il s’est passé depuis autour de GStreamer pour le développement d’applications et d’extensions en Rust.
C’est maintenant le bon moment pour utiliser Rust dans le cadre de vos développements GStreamer au lieu du C ou du C++ et même à la place de Python ou de C#. Vous bénéficierez ainsi de plus de sûreté, d’une meilleure productivité et pourquoi pas d’un certain plaisir à développer, tout en conservant un haut niveau de performance et un faible surcoût qui ne se rencontrent généralement qu’en utilisant le C ou le C++ et avec en plus la possibilité d’exécuter votre application sur des équipements embarqués.
Alors que l’apprentissage d’un nouveau langage peut sembler superflu et qu’il y a trop de langages de nos jours, je vais vous montrer pourquoi vous devriez vous en préoccuper et pourquoi le langage en question semble être un candidat parfait pour les applications multimédias et pour plein d’autres cas d’utilisation sur environnements embarqués. Je vais vous indiquer comment vous mettre le pied à l’étrier et vous présenter quelques courts exemples de code.
Sebastian Dröge est un développeur de Logiciels Libres et l’un des mainteneurs et développeurs principaux de GStreamer. Il est impliqué dans le projet depuis plus de 10 ans. Il contribue également à plusieurs autres projets tels que Debian, GNOME et WebKit. Après son master en sciences des Systèmes d’Information à l’Université de Paderborn en Allemagne, il commence à travailler en tant qu’entrepreneur autour de GStreamer et des technologies connexes. Sebastian est l’un des fondateurs de Centricular, une société proposant des services de conseil. Depuis son nouveau domicile en Grèce, il travaille à l’amélioration de GStreamer et de l’écosystème du Logiciel Libre en général.
En plus des sujets relatifs au multimédia, Sebastian s’intéresse au traitement numérique du signal, aux langages de programmation, à l’apprentissage automatique, aux protocoles réseau et aux systèmes distribués.
Introduction, Qui ?
Aujourd’hui, nous allons parler de l’oxydation de GStreamer ou comment rustifier votre multimédia. Je suis Sebastian Dröge, je participe au développement de GStreamer depuis 2006 environ. Actuellement, je suis en charge de la préparation des versions. J’ai touché à pratiquement tout dans GStreamer. Je suis aussi l’un des cofondateurs de Centricular. Nous proposons du conseil autour de GStreamer et des Logiciels Libres de cette catégorie. C’est tout ce que j’ai à dire à mon sujet, passons au contenu.
Quoi ?
Je vais vous parler de Rust et de GStreamer. Je suppose que certains d’entre vous ne connaissent pas Rust, je vais donc commencer par une courte introduction. Si vous souhaitez approfondir, rendez-vous sur le site web, la documentation est de très bonne qualité. Je ne vais pas vous expliquer ce qu’est GStreamer, je pense que vous le savez déjà.
J’ai déjà eu l’occasion de vous parler de ce sujet l’année dernière, je vais donc évoquer ce qu’il s’est passé depuis, puis entrer un peu plus dans les détails sur la manière de développer des applications et des extensions GStreamer avec Rust. Je vous montrerai aussi quelques exemples de code. Enfin, je vous parlerai de ce à quoi on peut s’attendre pour l’avenir.
Qu’est-ce que Rust ?
Définition
C’est « un langage de programmation système qui vise à garantir un typage sûr et une gestion sûre de la mémoire ». Les développements ont commencé chez Mozilla. Tout est open source. De nos jours, le langage bénéficie d’une large communauté et une bonne proportion des développeurs n’est plus employée par Mozilla. C’est une communauté assez diversifiée. La conception du langage suit les pratiques du développement open source. Ils utilisent un processus d’appel à commentaires (Request For Comments) pour toutes les modifications du langage. Chaque membre de la communauté peut apporter des éléments à la discussion, c’est très transparent… ça me plaît bien !
Qu’est-ce que ces mots signifient au juste et plus particulièrement « gestion sûre de la mémoire » ? En fait, c’est un peu l’argument de vente de Rust. On sait tous ce qui peut arriver en C, si on dé-référence le mauvais pointeur ou si on dépasse les limites d’un tableau : le truc part à veau-l’eau. Rust empêche cela. Le typage est aussi beaucoup plus sûr qu’en C. Le C apporte un peu de sécurité pour le typage, mais bon… passons !
Selon moi, la caractéristique la plus importante est qu’il s’agit d’un langage de programmation système. Il travaille vraiment près du matériel, il n’y a pas de gros environnement d’exécution. Tout ce que vous écrivez tourne vraiment sur le processeur. Toutes les abstractions que le langage propose sont sans surcoûts, du moins c’est la manière dont ils en font la pub, et je le crois aussi. Mais je dirais que c’est à vous de le vérifier par vous-même.
Une autre caractéristique importante est l’existence d’un système très puissant permettant l’interopérabilité avec des bibliothèques écrites en C. Quel que soit l’existant écrit en C dont vous disposez, vous pouvez l’utiliser depuis votre code écrit en Rust.
De la programmation bas-niveau avec un air de programmation haut-niveau
Si vous regardez le code, cela ressemble parfois à ce que vous écririez en Javascript ou en Python ou avec un autre langage d’orchestration (scripting). Ça peut sembler de plus haut niveau que ce que vous obtiendriez en C++. Néanmoins, on parle bien de programmation bas-niveau : vous conservez le contrôle sur tout si vous le souhaitez. Vous pouvez décider d’où allouer la mémoire — doit-on utiliser le tas ou la pile — de quand allouer, de quand désallouer. Mais l’important c’est que vous n’avez pas à vous en soucier. Vous pouvez le faire… vous pouvez aussi, dans une certaine mesure, l’ignorer. Ça n’implique pas une gestion manuelle de la mémoire, c’est le compilateur qui s’assure que vous n’êtes pas en train de faire quelque chose de stupide.
Comme je l’ai dit, Rust ressemble un peu à Python ou à d’autres langages d’orchestration. L’une de ses caractéristiques importantes est l’inférence de type : vous n’êtes pas obligés de préciser systématiquement le type des variables. Généralement, le compilateur se débrouille tout seul tout en vous garantissant un typage sûr. C’est quelque chose dont le C++ dispose aussi aujourd’hui. Vous avez également d’autres caractéristiques que l’on trouve plutôt dans les langages d’orchestration ou les langages fonctionnels, mais qui sont disponibles pour de la programmation système.
Domaines
Rust est actuellement utilisé pour :
- Du développement d’applications web. Qui essaierait de développer des applications web en C aujourd’hui ? Personne ? Par contre, vous pouvez en écrire en Rust.
- On l’utilise aussi pour le développement de jeux, la programmation de serveurs… en gros tous les domaines pour lesquels vous utiliseriez le C++.
- Des gens écrivent aussi des systèmes d’exploitation en Rust, il y en a actuellement deux ou trois en cours d’écriture.
- Certains l’utilisent pour des développements vraiment très proches du matériel comme de la programmation de micro-contrôleurs.
Rust couvre tout le spectre des cas d’utilisation pour lesquels vous utiliseriez un langage de programmation système.
Par ailleurs, Rust est désormais utilisé et poussé par des acteurs de l’Industrie. Vous pouvez consulter cette page pour découvrir les sociétés qui déclarent publiquement utiliser Rust. Il y a des noms tels que Dropbox, npm, Atlassian, Coursera, Canonical et bien d’autres.
Rust est ce que le C++ aurait dû être
Selon moi, Rust est ce que le C++ aurait dû être. Bon, un certain nombre d’années se sont écoulées, les gens ont appris de l’histoire. Aujourd’hui, je l’utiliserais pour n’importe quel projet pour lequel j’aurais utilisé le C++ ou même le C auparavant.
Pourquoi Rust ?
De la difficulté d’écrire du code sûr en C et en C++
Il est difficile d’écrire du code sûr en C et en C++. Toute personne pouvant dire qu’elle n’a pas subi d’erreur de segmentation durant l’année écoulée n’a probablement programmé ni en C, ni en C++. Vous pouvez facilement faire quelque chose qui fera planter votre système et permettra à un attaquant de prendre le contrôle de la machine de l’utilisateur, sans même vous rendre compte que ce que vous avez écrit n’est pas sûr.
La gestion des erreurs est plutôt compliquée avec ces deux langages. En C, on s’arrange généralement avec les valeurs de retour, vous pouvez facilement les ignorer et personne ne s’en offusquera ! Ça va juste échouer à l’exécution avec des symptômes bizarres. En C++, vous avez bien les exceptions, qui bénéficient de leur propre lot de problèmes. En général, ça entraîne une certaine verbosité qui finit par masquer ce que le programme fait vraiment et rend la tâche encore plus difficile pour faire en sorte que le code soit sûr.
Laissez le compilateur vous aider à écrire du code correct et rapide
Il y a un inconvénient à cela : le compilateur risque de beaucoup se plaindre ! Il vous dira des choses comme : « non, tu ne peux pas faire ça, ce n’est pas sûr ». Ça va vous prendre plus de temps avant de pouvoir exécuter votre code. Mais une fois qu’il s’exécute, vous savez qu’un gros paquet de problèmes ne vont pas se présenter parce que le compilateur vous aura déjà prévenu : « ici, ici et là, tu ne peux pas faire ça, tu devrais faire ça autrement ». Avec le C ou le C++, en général on fait cela à l’exécution et on sait tous combien il est pénible de déboguer des trucs à l’exécution.
Rust utilise un modèle très puissant de possession et de mutabilité. Il identifie en permanence le possesseur d’une variable et trace si celle-ci est accessible en lecture seule ou en lecture et en écriture. Par défaut, toute variable est accessible en lecture seule. C’est le contraire de ce que font les C et C++. Avec ces langages, vous pouvez préciser qu’une variable est constante, mais par défaut elle est visible en lecture et en écriture. Rien qu’avec cette approche (chaque variable en lecture seule par défaut) le code est déjà plus sûr et il est plus difficile d’introduire des bogues.
Par défaut avec Rust, le code doit respecter les contraintes de sûreté. Ce qui veut dire que si vous ne sortez pas du bac à sable, votre programme ne plantera pas… du moins il ne produira pas d’erreur de segmentation. Vous pouvez toujours introduire des erreurs de logique qui feront que votre programme ne fera pas ce qu’il était censé faire, mais au moins il ne plantera pas.
On bénéficie aussi d’une certaine sécurité pour les fils d’exécution. Vous indiquez si votre type de données est sûr pour le partage entre fils d’exécutions et/ou s’il peut être transféré d’un fil d’exécution à l’autre. Le compilateur se chargera ensuite de vérifier que ces contraintes sont bien respectées.
Comme je le disais dans la section relative aux erreurs, Rust vérifie la bonne prise en compte des erreurs. Vous ne pouvez pas ignorer les erreurs, vous devez les gérer. Mais la mécanique qui permet de le faire est telle que ça en devient sympa. Ça n’a rien à voir avec ce que l’on doit faire en C : « si ceci échoue, nettoie ceci et sors, si ceci échoue, nettoie cela et sors »… Dans le cas de Rust, c’est vraiment pratique à utiliser.
L’issue de secours : unsafe
Il y a une issue de secours : le mot clé unsafe. Dès qu’il introduit une section de code, vous pouvez faire ce que vous voulez dans cette section, comme vous le feriez en C. Vous pouvez dé-référencer des pointeurs, vous pouvez créer des pointeurs à partir de nombres, tout ce qui vous passe par la tête. L’idée principale est que c’est déclaratif. Vous savez alors que vous avez une petite partie de votre code qui n’est pas sûre. Si ensuite votre programme plante, ça viendra de là ! Et si vous voulez relire votre code, vous saurez que ce sera par là qu’il faudra commencer.
Un langage de haut niveau qui n’est pas juste une glorification de l’assembleur
… comme c’est le cas pour le C
Une autre différence notable par rapport au C est que Rust dispose d’une bonne bibliothèque standard. Elle contient tout un tas de structures de données. On sait tous qu’en C, la bibliothèque standard ne comporte aucune structure de données. Chacun développe ses propres listes chaînées, ses propres tableaux associatifs. La bibliothèque standard de Rust fournit des implémentations très efficaces de toutes les structures de données, d’algorithmes, etc.
Avec tous les langages d’orchestration récents, on trouve des petits outils pour récupérer les dépendances. Pour node vous avez npm
, pour Python il y a pip
. Rust propose la même chose, vous pouvez facilement dire : « je veux telle et telle bibliothèques » et l’outil ira chercher les versions dont vous avez besoin, les compilera et les inclura lors de la construction de votre propre logiciel. Cet outil facilite vraiment l’utilisation des dépendances externes. Ça ne tourne pas au cauchemar comme en C ou en C++ où chaque chose fonctionne à sa manière et où il est très difficile de dépendre de quoi que ce soit. En fin de comptes, ça a poussé pas mal de bibliothèques en C et en C++ à ré-implémenter plein d’algorithmes qui existaient déjà partout ailleurs… mais bon, c’est tellement compliqué de tirer ces dépendances que l’on ré-implémente les fonctions nous-mêmes.
Pourquoi devrait-on s’en préoccuper ?
L’analyse syntaxique de formats de médias
… venant de sources non sûres
Je passerai assez vite sur le sujet, nous sommes déjà tous au courant des problèmes. L’analyse syntaxique (parsing) des formats multimédias n’est pas chose facile, particulièrement en C ou en C++. Par ailleurs, les données en entrée viennent rarement de sources de confiance. Certaines sources peuvent même proposer des médias qui contiennent intentionnellement quelque chose qui peut nuire à votre machine en exploitant des problèmes dans les logiciels que vous utilisez. C’est pour cela que je pense que pour nous, Rust serait un bon langage. Il permet d’éviter beaucoup de problèmes de sécurité courants. Tous les problèmes de sécurité que nous avons rencontrés dans GStreamer les années passées auraient pu être évités en utilisant Rust. Je pense que c’est déjà assez éloquent.
Et donc, l’analyse syntaxique est compliquée en C. Il n’y a pas beaucoup de moyens d’abstraction, alors qu’avec Rust on dispose de tout un tas de possibilités pour représenter des abstractions. Il est même possible d’écrire des grammaires formelles, du moins quelque chose qui ressemble à de la grammaire formelle. Le code correspondant est ensuite généré automatiquement, ce qui rend la compréhension de ce que fait ce code vraiment aisée en comparaison à du code écrit à la main.
La maîtrise des fils d’exécution concurrents est difficile
… surtout en C !
Rust dispose de tout un tas de fonctionnalités pour nous aider lorsque l’on développe dans un environnement à plusieurs fils d’exécution. GStreamer exploite massivement les fils d’exécution concurrents, ça pourrait donc être une bonne idée…
Programmer comme si on était en 2017
Et par-dessus tout, nous programmerions comme si nous étions en 2017 et non dans les années 60 du siècle dernier :
- Les langages modernes offrent toute une variété de fonctionnalités et d’outils.
- Nous ne sommes plus obligés de réinventer des ustensiles de base comme
GObject
. - Nous pourrions attirer de nouveaux développeurs. Plus personne n’a vraiment envie d’apprendre le C de nos jours et encore moins des choses comme
GObject
qui entraîne plein de copié-collés partout. C’est plutôt difficile à prendre en main pour les nouveaux contributeurs.
Cependant, ce n’est pas la panacée
Tout code non trivial comporte des bogues. Mais au moins, une importante classe de bogues peut être évitée.
État, il y a un an
Les bindings GStreamer
L’année dernière, nous disposions d’un ensemble de bindings Rust pour GStreamer. Cet ensemble était écrit à la main et ne s’intégrait pas très bien avec le reste du code Rust. Par ailleurs, il imposait aux utilisateurs d’utiliser des sections avec le mot clé unsafe, ce qui est tout simplement rédhibitoire. Il divergeait aussi vis-à-vis de certains concepts de GStreamer, ce qui le rendait difficile à appréhender et il était incomplet. Pas mal de gens utilisaient ces bindings, mais ce n’était vraiment pas idéal.
Nous avions aussi ce dont je vous parlais la dernière fois : une manière expérimentale d’écrire des extensions GStreamer. Ce projet était également écrit à la main, il était très incomplet et difficile à faire évoluer. Oublions tout cela, nous sommes en 2017 maintenant !
Écrire des applications GStreamer avec Rust
Les nouveaux bindings GStreamer
Comparaison par rapport aux anciens bindings
Les nouveaux bindings Rust pour GStreamer sont en grande partie générés à partir des informations d’introspection de GObject
. Malheureusement, certaines choses ne peuvent pas être générées automatiquement. Mais globalement, ça facilite bien l’évolutivité. Ils remplacent complètement les anciens bindings. Ils ne sont pas compatibles au niveau interface de programmation, mais ça ne devrait pas être difficile de modifier un projet basé sur les anciens bindings pour qu’il utilise les nouveaux.
Une évolution importante du point de vue des applications est qu’il n’est plus nécessaire de passer par du code marqué unsafe… Sauf si le développeur le veut bien sûr, ou s’il veut s’intégrer avec X11, qui n’est pas sûr par conception, mais c’est un autre problème !
Les nouveaux bindings couvrent pratiquement tous les composants du cœur de GStreamer ainsi que ceux des autres bibliothèques. Ils s’intègrent bien avec les bibliothèques des infrastructures GLib et GTK, ce qui les rend sympas à utiliser ensemble.
Un style idiomatique rustien (en grande partie)
Les bindings sont écrits dans un style idiomatique rustien. Ils devraient être faciles à prendre en main par des développeurs habitués à Rust. Ils auront l’impression qu’il s’agit d’une vraie interface de programmation Rust. Et à la fois, les concepts des bindings correspondent pratiquement trait pour trait aux concepts de GStreamer. Ce qui signifie que vous, en tant que développeurs GStreamer, aurez seulement à apprendre un nouveau langage. Par contre, tous les concepts de GStreamer, c’est-à-dire comment l’interface de programmation fonctionne, restent les mêmes.
Les objets
Regardons rapidement quelques-uns des points d’entrée des bindings. Dans GStreamer, nous avons tout un tas d’objets : les Element
s, les Pad
s, le Pipeline
, l’objet Clock
, etc. La manière dont ils sont représentés dans les bindings est telle que vous retrouvez précisément les mêmes objets. Ils disposent d’une sorte de mécanisme semi-automatique et sûr de comptage de références. Vous contrôlez toujours quand le compteur d’une référence est incrémenté, mais le compilateur se charge de vérifier que vous l’incrémentez bien quand c’est nécessaire. Ceci vous permet d’être alertés si vous faites des choses bizarres que vous n’auriez pas voulu faire. Donc, ce n’est pas complètement automatique, mais d’un autre côté, vous ne pouvez pas oublier de dé-référencer quoi que ce soit. Quand un objet n’est plus dans la portée courante, quand il n’est plus nécessaire, il est automatiquement dé-référencé et détruit au moment voulu.
Dans GStreamer, nous utilisons l’héritage. Rust ne gère pas l’héritage : il n’y a pas de classes, ni de vraie notion d’héritage. À la place, on peut utiliser des traits. Cela peut sembler un peu compliqué, un peu bizarre, mais si vous utilisez l’interface Rust, vous allez vous rendre compte qu’elle fonctionne de la même façon que si vous utilisiez, par exemple, les bindings C++ de GStreamer. Ça donne une sensation de quelque chose de naturel.
Comme je l’ai déjà dit, il y a une sorte de sûreté des fils d’exécution (thread safety) et elle est contrôlée à la compilation. Par exemple, on sait tous que les Element
s de GStreamer sont censés être thread safe, on peut donc les échanger entre fils d’exécution et on peut les partager entre plusieurs fils d’exécution. Le compilateur n’ira pas se plaindre de tels agissements. En revanche, quelque chose comme GstAdapter
n’est pas thread safe. Donc si vous tentez de l’utiliser dans d’autres fils d’exécution, vous allez devoir le migrer, car vous ne pouvez pas en disposer depuis deux fils d’exécution différents. Si vous faites cela, le compilateur vous dira : « non, tu ne peux pas faire ça ». C’est une caractéristique plutôt sympa.
Vous disposez également de toute l’interface standard GObject
de GStreamer. Vous retouverez : les propriétés, les signaux, toutes les méthodes… tout ce dont vous avez besoin.
J’aurais dû mentionner ceci auparavant : tout est garanti contre l’utilisation inappropriée de pointeurs NULL
. Il n’y a aucun pointeur NULL
caché. Vous devez gérer explicitement tout ce qui peut être NULL
, vous ne pouvez pas ignorer ce genre de problèmes. Donc dans toute l’interface, lorsque quelque chose renvoie un Element
, il y aura bien un Element
derrière. Il est impossible qu’il ne soit pas disponible. Ça ne peut pas planter ensuite, vous ne pouvez pas vous retrouver face à un pointeur NULL
. Et bien sûr, si l’appel est susceptible d’échouer, vous devez gérer ce cas. Le compilateur ne vous laissera pas utiliser la valeur retournée sans avoir vérifié au préalable qu’elle est bien valide.
Les MiniObjects
Les MiniObject
s sont probablement le recoin le plus obscur de GStreamer. Ils sont générés automatiquement dans la plupart des autres bindings, ce qui les rend un peu inhabituels vis-à-vis du langage cible. Avec Rust c’est différent : la plupart des concepts autour des MiniObject
s correspondent à ce que l’on fait déjà en Rust. Par exemple, le concept de mutabilité des MiniObject
s est tel que vous ne pouvez modifier un MiniObject
que s’il n’est utilisé qu’à un seul endroit à un instant donné, sinon vous devez le copier. C’est quelque chose qui trouve un équivalent direct en Rust. Le compilateur vous empêchera de modifier des MiniObject
s qui ne sont pas en mode écriture. À titre de comparaison, en C on a pas mal de code qui modifie des MiniObject
s alors qu’ils ne sont pas en mode écriture. L’approche de Rust me semble présenter un avantage significatif.
Les types basés sur les MiniObject
s paraissent aussi typiquement rustiens. Ils comprennent les Caps
, les Structure
s, même quelque chose comme GstFraction
, qui semblait un peu bizarre à l’utilisation en Python par le passé, ressemble vraiment à quelque chose que vous auriez utilisé en Rust.
Qu’est-ce qui manque ?
J’ai dit que la plupart du cœur de GStreamer était déjà disponible. Il manque encore :
-
GstMemory
,GstAllocator
,GstMeta
etGstCapsFeatures
. Non pas parce qu’ils présentent une difficulté, mais plutôt parce que je n’en ai pas encore eu l’utilité et apparemment personne n’en a eu besoin pour le moment. Donc, si quelqu’un rencontre un problème pour lequel le besoin se fait sentir, criez, on pourra les ajouter à ce moment-là. - Il manque aussi des trucs mineurs comme les
TypeFinder
s. Ils sont du même acabit : faciles à ajouter en cas de besoin. - Les objets dans la catégorie des
GstControlBinding
s. - A part pour celles du cœur, les bibliothèques des autres modules ne sont pas entièrement couvertes. Mais par exemple, pour la bibliothèque
Audio
,GstAudioInfo
est disponible, pour la bibliothèqueVideo
vous avez déjàVideoInfo
etVideoFrame
. Il y aussiGstAdapter
,AppSrc
etAppSink
.
Tout ce dont vous avez habituellement besoin est donc disponible et pour le reste, criez et on l’ajoutera !
Est-ce utilisable ? Oui !
Selon moi, tout est déjà très utilisable. Je l’utilise moi-même pour pas mal d’applications de test afin de m’assurer que tout fonctionne correctement ou pour écrire des cas de test quand quelque chose ne marche pas. De part mon expérience, je peux dire que c’est facile et généralement plus rapide à écrire que l’équivalent en C. C’est facile à déboguer, ou du moins aussi facile à déboguer que le C. Vous pouvez toujours utiliser gdb
, obtenir la pile d’appels, scruter les variables, etc. Ça marche de la même manière qu’avec du C. Et généralement, ça donne plus ou moins le même code machine que ce que vous obtiendriez avec du C. Si vous lisez ce que le compilateur produit, il est assez facile de savoir ce qui se passe, comment les correspondances avec le C se concrétisent. Donc c’est prêt à être utilisé !
Quelques exemples de code
Création d’Element
s
Voici un exemple de création d’Element
s. Ça ne devrait pas être trop difficile à lire :
let pipeline = gst::Pipeline::new(None); // 1
let src = gst::ElementFactory::make("filesrc", None)
.ok_or(MyError::ElementNotFound("filesrc"))?; // 2
let dbin = gst::ElementFactory::make("decodebin", None)
.ok_or(MyError::ElementNotFound("decodebin"))?;
- En 1, on génère un nouveau
Pipeline
. Ici, on ne lui donne pas de nom particulier. En C, on passeraitNULL
, en Rust on indiqueNone
. On récupère toujours unPipeline
. Si vous regardez l’interface en C, vous verrez que ça ne renvoie jamaisNULL
, donc on récupère vraiment unPipeline
. - En 2, on veut construire une variable
src
. On utilise doncgst::ElementFactory::make
, ce qui est très similaire à ce que vous feriez en C. L’objectif est de créer une source sur un fichier avec l’extensionfilesrc
. Bien sûr, il peut arriver que l’extensionfilesrc
ne soit pas disponible sur votre machine, cette fonction est donc susceptible d’échouer en renvoyantNone
. Vous pouvez indiquer comment gérer les différents cas avec la fonctionok_or
: « si tout estok
, alors renvoie ce que la fonctiongst::ElementFactory::make
a généré, sinon renvoie un type d’erreur dédié ». Pour cela, vous pouvez créer une sorte d’énumération d’erreurs et préciser les différents cas tels queElementNotFound
, à quoi vous pouvez ajouter une variable. Dans notre cas, on a indiqué le nom de l’Element
. À la fin de la ligne, on trouve un point d’interrogation. Il est là pour indiquer ceci : « en cas d’échec, sors de la fonction et renvoie l’erreur en question ». L’appelant peut donc gérer l’erreur et prendre les mesures appropriées, mais dans la fonction en question on s’arrêtera là en cas d’erreur. Bien sûr, il n’y aura pas de fuite mémoire, tout ce qui doit être dé-référencé et détruit le sera automatiquement.
Création de Caps
Voici maintenant un exemple de création d’un objet Caps
:
let caps = gst::Caps::new_simple( // 1
"video/x-raw", // 2
&[ // 3
("format", "BGRA"), // 4
("width", &(1080i32), // 5
("height", &(720i32)), // 6
("framerate", &gst::Fraction::new(30, 1)), // 7
],
);
- En 1, vous utilisez
gst::Caps::new_simple
exactement comme en C. - En 2, vous indiquez le nom, rien de spécial à signaler ici.
- En 3, vous fournissez un tableau de propriétés qui sont en fait des tuples.
- En 5, je pense que ce qu’il faut retenir, c’est que vous n’indiquez pas seulement la valeur pour la propriété, vous devez aussi préciser son type. Assez souvent, c’est quelque chose qui tourne mal en C : les gens fournissent un entier non signé ou un entier sur 64bits pour une propriété donnée et ça ne fonctionne pas comme prévu ensuite. Ici, vous devez être explicite. En interne, ça ne va pas créer d’objet
GValue
, si vous lisez le code généré, il sera très similaire à ce que vous auriez obtenu avec du C.
Question d’un membre du public :
— L’esperluette est nécessaire dans ce cas ?
— En fait, l’esperluette n’est pas indispensable ici. L’esperluette crée une référence, c’est comme un pointeur dont la valeur ne peut pas êtreNULL
.
— Et donc, elle indique si ta constante est statique ou non ?
— En fait… Bon, parlons-en après, cela nécessiterait d’entrer un peu plus dans les détails. En bref, l’esperluette introduit une référence et les références ne peuvent jamais êtreNULL
. Le compilateur s’assure que cette valeur est toujours valide au moment où tu l’utilises. Donc, tu ne peux pas libérer ce qui en dépend, sinon ça ne sera pas accepté à la compilation. Mais, la raison exacte pour laquelle nous avons besoin d’une esperluette ici nécessiterait une explication dans laquelle je ne souhaite pas m’engager maintenant. Ça a un rapport avec le fait que chacun des éléments présente un type différent : en 4 il s’agit d’une chaîne de caractères, en 5 et 6 ce sont des entiers signés, en 7 on trouve une fraction.
NDLT : à ce stade de la présentation, Sebastian commence à être à court de temps. Il décide donc de passer quelques exemples. Vous pouvez les retrouver dans les planches au format PDF.
Le signal pad-added
Le signal pad-added
fait partie des choses utilisées fréquemment. Voici un court exemple utilisant ce signal :
let pipeline = _; // 1
decodebin.connect_pad_added(move |dbin, src_pad| { // 2
let sink = gst::ElementFactory::make( // 3
"fakesink", // 4
None // 5
).unwrap(); // 6
pipeline.add(&sink); // 7
let sink_pad = sink.get_static_pad("sink").unwrap(); // 8
src_pad.link(&sink_pad); // 9
sink.sync_state_with_parent(); // 10
});
- En 2, on utilise un decodebin qui a été créé auparavant. On le connecte au signal
pad-added
en lui passant une fermeture (closure). En C, vous auriez à définir une nouvelle fonction, sa déclaration, tout cette verbosité… Ici, vous pouvez écrire la fonction directement avec la connexion au signal. Tout ce qui est disponible en amont peut être capturé dans la fermeture. Par exemple, lepipeline
défini en ligne 1 est utilisé à l’intérieur de la fermeture à la ligne 7. Rust s’assure que tout ce qui est capturé est utilisé en respectant les règles de sûreté. Vous pouvez être amenés à devoir copier les objets pour les utiliser à l’intérieur d’une fermeture parce qu’il peut y avoir des cas pour lesquels l’utilisation du même objet ne serait pas sûre. Mais généralement, c’est très pratique à utiliser et vous pouvez simplement écrire vos gestionnaires de signaux directement sans code superflu. Vous vous demandez peut-être à quoi correspond ce truc avec les|
en ligne 2. C’est la façon dont on définit une fermeture : vous retrouvez les argumentsdecodebin
etsrc_pad
qui correspondent à ceux passés lors de l’invocation du signalpad-added
. - À l’intérieur de la fermeture, on crée un
fakesink
(lignes 3 à 6), - que l’on ajoute au
pipeline
(ligne 7). - On récupère ensuite le
pad
«sink
» (ligne 8), que l’on relie aupad
«src
» dudecodebin
(ligne 9). - Finalement en 10, on lance la synchronisation.
Toute personne ayant déjà utilisé GStreamer devrait être en mesure de lire cet exemple et de comprendre exactement tout ce qu’il s’y passe.
Réaction d’un membre du public :
— inaudible
— Ce n’est pas ton cas ?
— Est-ce que Rust permet àgst_element_sync_state_with_parent
de devenir thread safe ? (rires)
— Bien sûr que non parce que l’implémentation est en C et que cette fonction est défectueuse par conception. Il faut que l’on trouve une meilleure solution à cela. La fermeture que tu passes ici est marquée comme devant respecter des contraintes de sûreté pour l’exécution en environnement à plusieurs fils d’exécution. Donc, tu ne peux pas simplement utiliser une autre référence vers unGstAdapter
là-dedans par exemple, parce queGstAdapter
ne respecte pas ces contraintes. Tu ne peux rien utiliser qui ne soit pas thread safe dans cette fermeture, à moins de migrer la variable à l’intérieur, ou dis autrement : à moins que l’unique référence restante sur cet objet se trouve à l’intérieur de la fermeture au final.
Mapping de Buffer
En Python le mapping de buffer est un peu étrange. En Rust, on peut le faire de façon assez élégante :
let mut buffer = gst::Buffer::with_size(320 * 240 * 4).unwrap(); // 1
{ // 2
let buffer = buffer.get_mut().unwrap(); // 3
let mut data = buffer.map_writable().unwrap(); // 4
for p in data.as_mut_slice().chunks_mut(4) { // 5
p[0] = b; p[1] = g; // 6
p[2] = r; p[3] = 0; // 7
} // 8
} // 9
- En 1, on crée un nouveau
Buffer
. On a besoin d’unBuffer
mutable pour pouvoir écrire dedans. - Ensuite de 2 à 9, on est obligé d’écrire un truc un peu moche. Il s’agit d’un nouveau bloc qui limite la validité des variables qu’il contient. Elles seront libérées à la fin du bloc et le destructeur sera exécuté.
- En 4, on mappe le
Buffer
en écriture. À la fin du bloc, la fonctionunmap
est exécutée automatiquement. - On peut aussi mentionner que le
Buffer
doit être récupéré sous une forme mutable (ligne 3) avant de pouvoir en extraire une map en écriture. Toutes ces fonctions peuvent échouer, c’est pour cela qu’on utiliseunwrap
. En cas d’échec, cette fonction termine l’application. Bien sûr, il y a des façons plus élégantes de gérer cela. Je ne les ai pas indiquées parce que ça surchargerait la planche. Il faudrait un peu de code pour gérer le cas d’erreur. - De 5 à 8, on itère sur la zone mémoire et on renseigne les valeurs des composantes R, G et B. On peut simplement utiliser les itérateurs de Rust pour parcourir le
Buffer
par tronçons de 4 octets, c’est ce que l’on peut lire en ligne 5.
Une fois compilé, ça ressemble pratiquement à ce que vous auriez obtenu si vous l’aviez écrit en C.
Quelques liens
- Les bindings sont actuellement sur mon dépôt github. J’ai l’intention de les déplacer vers freedesktop à un moment donné, mais j’aimerais qu’on migre d’abord vers github. Je n’ai pas envie de les déplacer deux fois, donc pour le moment ils restent sur github.
- Vous pouvez trouver plein d’exemples de code ici.
- La plupart des tutoriels de GStreamer ont aussi été portés ici. Je n’en ai écrit qu’un, les autres ont été portés par des contributeurs, donc grâce à eux, vous disposez des tutoriels.
Écrire des extensions GStreamer en Rust
Je vais vous parler rapidement de la manière d’écrire des extensions GStreamer en Rust. Comme je l’ai dit plus haut, l’année dernière nous disposions d’une infrastructure écrite à la main. La plupart de l’infrastructure pour les extensions est toujours écrite à la main, mais ce qui est important c’est qu’elle s’appuie désormais sur les nouveaux bindings Rust de GStreamer. Toute l’infrastructure hors sous-classes est générée automatiquement et prise en charge par les bindings. Évidemment, toute l’infrastructure pour les sous-classes, la surcharge des méthodes virtuelles et l’installation des propriétés sont encore écrites à la main.
La différence par rapport à l’année dernière, c’est que vous pouvez maintenant utiliser des méthodes virtuelles et vous pouvez définir des propriétés. Par ailleurs, les gens qui implémentent des Element
s ne sont plus obligés d’écrire du code Rust non sûr (déclaré unsafe), ils peuvent le faire, mais ils n’y sont plus contraints.
Le but de tout cela est de pouvoir écrire des extensions GStreamer en implémentant simplement des traits Rust, sans utiliser quoi que ce soit qui ne fasse pas partie du langage, de façon à ce que cela soit très facile pour des gens connaissant Rust d’écrire des extensions GStreamer.
Comme je l’ai dit, une partie du code est encore écrite à la main. Tout cela va être amélioré. Les gens de GNOME travaillent actuellement sur des solutions à base de macros qui font en gros la même chose que les GST_DEFINE_…
s, mais d’une manière plus sympa. À l’avenir vous pourrez écrire du code qui ressemblera à du Vala ou du C#, et les macros convertiront cela en quelque chose de similaire à ce que j’ai écrit à la main. Ceci dit, c’est pour plus tard, cela va prendre un peu de temps avant d’en arriver là.
Classes de base disponibles
Actuellement, des classes de base sont disponibles pour :
- Les
Element
s. - BaseSrc, BasSink et BaseTransform.
- Thibault, qui est peut-être parmi nous, travaille actuellement sur le binding VideoDecoder et il a aussi l’intention d’écrire un décodeur d’images GIF.
- Il y a une chose que je voudrais souligner ici. Chaque fois que vous faites quelque chose que vous n’êtes pas autorisé à faire, par exemple ce que je faisais tout à l’heure avec
unwrap
(la création d’unElement
pouvant échouer, car il peut ne pas être disponible), et donc si vous utilisezunwrap
, en cas d’erreur, Rust va paniquer. Ce que l’on entend par là, c’est que la pile va être déroulée et…
NDLT : l’organisation informe Sabastian qu’il ne lui reste plus beaucoup de temps.
Element
s disponibles
Nous disposons des Element
s suivants :
- Démultiplexeur FLV.
- Source HTTP.
- Source et « dissipateur » (
sink
) depuis / vers un fichier. - Source et « dissipateur » (
sink
) depuis / vers Amazon S3. - Il y a quelques jours, j’ai ré-écrit en Rust l’
Element
AudioEcho
qui existait déjà en C. - Et bientôt, si tout va bien, on aura aussi un décodeur d’images GIF (animées).
Une anecdote intéressante : lorsque j’ai écrit l’Element
AudioEcho
en Rust, il était environ 1,7 fois plus rapide que l’implémentation en C. Ce n’est pas parce que Rust est plus rapide mais plutôt parce qu’il était plus difficile de faire en sorte que l’équivalent en C soit rapide. J’ai trouvé l’expérience intéressante. Ce n’était pas exactement l’objectif initial lorsque j’ai entrepris la ré-écriture de cet Element
, mais ça montre bien que l’on n’a pas affaire à un langage de haut niveau qui ralentirait les choses, c’est vraiment un langage que l’on peut utiliser pour ce genre de développements.
État actuel
- Les bindings sont encore assez jeunes.
- Ils sont utilisables pour une implémentation nécessitant les classes de base que je mentionnais plus haut.
- Les fonctionnalités manquantes seront ajoutées le moment venu.
Si vous voulez écrire des extensions GStreamer en Rust maintenant, lancez-vous, dites-moi s’il manque des choses et je les ajouterai ou je vous aiderai à les ajouter. Jusqu’à présent, j’ai pris beaucoup de plaisir à écrire des extensions GStreamer en Rust, j’ai beaucoup plus apprécié cela que d’en écrire en C. Donc, essayez et voyez si c’est le cas pour vous aussi !
NDLT : Sebastian passe les exemples de code par manque de temps. Vous pouvez les retrouver dans les planches au format PDF.
Quelques liens
Si vous voulez voir à quoi cela ressemble, c’est sur mon dépôt github. Les extensions sont également dans le dépôt.
À venir…
Encore quelques mots à propos de l’avenir : mon objectif est que l’on écrive de plus en plus de code en Rust plutôt qu’en C. Commençons d’abord par les extensions externes. Plus tard, on pourra aussi envisager de remplacer le code du cœur. Mais ça, c’est pour l’avenir. Il n’y a pas de raison de se faire du souci pour le moment. Nous pouvons faire tout cela de façon itérative en remplaçant des petites portions de code grâce au système FFI de Rust qui rend les choses vraiment faciles pour s’intégrer dans du code C existant. Vous pouvez remplacer un simple module ou même une simple fonction si vous le souhaitez.
Globalement, je voudrais faire en sorte que les bindings soient mieux finis. Que l’infrastructure pour écrire des extensions soit mieux finie aussi, plus complète, mais bon, je suppose que c’est assez évident.
Et le plus important, c’est que j’aimerais faire en sorte que plus de personnes s’intéressent et s’impliquent dans l’utilisation de Rust, ce qui était le but principal de cette présentation. J’espère avoir atteint mon objectif. Jetez-y un œil, essayez-le, j’espère que vous ne le regretterez pas. Moi je ne le regrette pas ! Plus généralement, je dirais : n’écrivez plus de projets en C, c’est une mauvaise idée. Regardez tous les CVE des projets à base de C… ce n’est pas une bonne idée !
Merci / Questions ?
On n’a plus le temps pour des questions, donc passez me voir après. Voici encore quelques liens. Il y a pas mal d’informations sur le site web de Rust, la documentation est de très bonne qualité, vous y trouverez probablement toutes les réponses aux questions que vous vous posez.
- https://www.rust-lang.org/
- https://github.com/sdroege/gstreamer-rs
- https://github.com/sdroege/gst-plugin-rs/
Merci !
# Rust vs. unsafe Rust
Posté par Perthmâd (site web personnel) . Évalué à 10.
Bien que fervent soutien de Rust (et même actuellement membre de RustBelt), je me permets de réagir à cette remarque. Je souhaiterais faire remarquer que ceci est une croyance assez répandue, mais complètement foireuse.
La programmation à coup d'unsafe en Rust a des répercussions non-locales qui sont dues au fait que la sémantique d'une structure de donnée est décrite par son API, qui constitue un tout, et non pas par chaque fonction une par une. En gros, ça veut dire que la validité d'un code unsafe dépend de l'ensemble des interfaces transparentes qui en dépendent, ce qui peut être nettement plus vaste que le code dans un bloc unsafe. Il y a un très bon post de blog par Ralf Jung à ce sujet pour les gens intéressés.
[^] # Re: Rust vs. unsafe Rust
Posté par fengalin (site web personnel) . Évalué à 2.
Merci pour les liens. Je ne connaissais pas RustBelt, l'approche semble très intéressante.
J'ai prévu de rédiger un résumé des commentaires à l'attention de Sebastian, bien sûr ta remarque en fera partie.
[^] # Re: Rust vs. unsafe Rust
Posté par fengalin (site web personnel) . Évalué à 6.
Voici la réponse Sebastian dont je vous propose une traduction à la suite.
Je suis complètement d'accord avec toi, mais il est parfois nécessaire de passer par des simplifications. Je pourrais faire toute une présentation sur le sujet que tu évoques.
Le public [de la conférence GStreamer] est constitué de plein de développeurs C et tous ceux qui ont écrit du code C savent qu'une utilisation non sûre de la mémoire à un endroit donné peut ré-apparaître à un endroit totalement différent. Néanmoins, en fin de compte, le problème est bien provoqué par un bloc non sûr donné.
De la même façon, en Rust, si tes abstractions sûres basées sur du code non sûr fuient ou sont boguées, quelque chose de complètement différent risque d'exploser plus tard. Mais, le bug en lui-même se trouvera dans un bloc non sûr.
Donc selon moi, ce que j'ai dit est exact (mis à parts les bugs du compilateur ou du langage), c'est une grosse simplification que tous ceux qui écrivent du code dans un langage à gestion de la mémoire non sûre devraient comprendre.
[^] # Re: Rust vs. unsafe Rust
Posté par karchnu . Évalué à 1.
Donc en résumé : ça peut casser partout dans ton code, mais le bug viendra de la partie "unsafe" (modulo les bugs dans le langage ou compilateur).
# Une ode à Rust sur un sujet assez pointu
Posté par karchnu . Évalué à 5.
Je trouve ton article intéressant. Tu expliques comment on arrive à Rust et quels sont certains de ses avantages par rapport à C, et bien que d'autres articles existent sur le sujet tu l'appliques sur ton sujet de prédilection : GStreamer. Et c'est un peu là que j'ai du mal.
GStreamer est un code conséquent, les références que tu fais sont parfois floues et le code que tu montres ne m'a pas permis de comprendre intuitivement ce que tu faisais. Et ce n'est pas vraiment un reproche que je ferai à ton article, tu n'as sans doute pas le temps de présenter tous les concepts derrière GStreamer en détail. De ce fait, dès qu'on rentre dans "Écrire des applications GStreamer avec Rust" il devient difficile de suivre sans ouvrir une dizaine d'onglets… ça me rebute un peu. Du coup, je ne sais pas si l'article est trop grand ou pas assez.
En tout cas merci, tu donnes de la visibilité à Rust et à GStreamer. Si en tant que développeur d'outils assez poussés et gourmands en ressources tu considères ce langage, cela lui donne encore plus de crédibilité.
[^] # Re: Une ode à Rust sur un sujet assez pointu
Posté par fengalin (site web personnel) . Évalué à 2.
En effet, c'est le risque avec la traduction d'une présentation destinée à une conférence spécialisée. Ton commentaire me suggère une dépêche sur le développement avec GStreamer du coup. Je n'en suis pas un spécialiste, donc une rédaction à plusieurs mains pourrait être vraiment adaptée.
Ta conclusion est précisément ce qui m'a donné envie de partager cette présentation avec vous. Merci pour Sebastian.
# VLC
Posté par claudex . Évalué à 6.
À noter que Rust est déjà utilisé dans VLC (http://dev.unhandledexpression.com/slides/rustconf-2016/vlc/).
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: VLC
Posté par fengalin (site web personnel) . Évalué à 2.
Commentaire de Sebastian, puis traduction:
À ma connaissance, ils l'« utilisent » autant que GStreamer pour le moment. Ça ne fait pas encore partie du tronc principal du projet, à moins que quelque chose ait changé.
Mais en effet, les gens de VLC et de ffmpeg regardent aussi du côté de Rust, ce qui est super et ce, aussi pour GStreamer :) Par exemple, l'un des membres du projet VLC a écrit un démultiplexeur FLV autour duquel j'ai écrit une extension GStreamer en Rust (il a également écrit mom, qui est utile plus globalement). En ce qui concerne ffmpeg, cela profitera directement à GStreamer sans nécessiter de travail supplémentaire (grâce à l'extension ffmpeg de GStreamer).
[^] # Re: VLC
Posté par claudex . Évalué à 5.
Merci d'avoir transmis ces réponses.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
# dans la durée
Posté par Le Gab . Évalué à 5.
Pourquoi la communauté Rust pense que leur langage doit s'affranchir d'applications conséquentes et d'évaluations dans le temps afin de démontrer sa supériorité effective?
Le lien avec les CVEs en C est juste inapproprié, pas la même base de code vivante, pas la même longévité et pas le même nombre d'yeux qui ont effectué toutes ces relectures de codes, d'audit etc…
Perso, je me fiche de savoir lequel est mieux, je trouve juste l'approche étrange et symptomatique de ce seul langage.
[^] # Re: dans la durée
Posté par fengalin (site web personnel) . Évalué à 6.
Je ne vais pas m'exprimer au nom de la communauté, mais il m'a semblé lire assez souvent que Rust permettait d'éviter un certain nombre de failles de sécurité sans toutefois garantir un logiciel infaillible. Je pense que l'avantage du langage sur ce sujet réside principalement dans les contraintes imposées au développeur dès la compilation. Ces contraintes imposent des pratiques éprouvées pour permettre d'éviter un grand nombre de failles de sécurité. Je trouve que c'est quelque chose que Sebastian détaille vraiment bien dans les premières sections de la présentation. Voir aussi l'échange avec Renault dans mon précédent journal.
Selon moi, Sebastian mentionne les CVE en C à la fin de l'article (le lien renvoie vers l'article Wikipedia, et non vers une liste de CVE lâchées en patûre ;-)) en écho à sa remarque en tant que développeur et mainteneur de GStreamer :
Rust doit faire ses preuves, comme les autres. Il est particulièrement prometteur et on sait déjà qu'il permet de faciliter la vie des développeurs.
[^] # Re: dans la durée
Posté par fengalin (site web personnel) . Évalué à 6.
Comme pour les autres commentaires ci-dessus, voici la réponse de Sebastian, puis une traduction :
Tous les problèmes de sécurité qui sont apparus l'année dernière dans GStreamer (ainsi que des centaines d'autres bogues) auraient été impossibles avec Rust. Ça aurait également été le cas en utilisant D, Go, Haskell, JavaScript, … à la différence que ces langages comportent d'autres inconvénients qui ne les rendent pas appropriés pour GStreamer (à part pour le développement d'applications).
[^] # Re: dans la durée
Posté par xcomcmdr . Évalué à 3.
Y'a eu des relectures de code et des audits ? Vraiment ?
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
# Commentaire supprimé
Posté par Anonyme . Évalué à 6.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: Super dépêche
Posté par fengalin (site web personnel) . Évalué à 4.
Merci yPhil et merci aussi pour l'explication et les exemples parlants ! J'ai hésité, mais d'ailleurs je préfère, et je dis « qu'est-ce qui manque » dans la vraie vie.
[^] # Re: Super dépêche
Posté par Benoît Sibaud (site web personnel) . Évalué à 3.
Corrigé, merci.
[^] # Commentaire supprimé
Posté par Anonyme . Évalué à 3. Dernière modification le 08 novembre 2017 à 07:27.
Ce commentaire a été supprimé par l’équipe de modération.
[^] # Re: Super dépêche
Posté par Benoît Sibaud (site web personnel) . Évalué à 7.
Corrigé, merci.
La question de la conversion journal -> dépêche est sur la table depuis un moment, non tranchée. On ne « déplace » un journal, on en envoie une copie en rédaction, le contenu y est souvent modifié, parfois enrichi (notamment d'un résumé des discussions déjà présentes sur le journal), il est potentiellement aussi modifié en modération et ensuite publié. On aurait donc des commentaires commentant la version du texte du journal, qui serait mélangé à des commentaires concernant la nouvelle version, plus ou moins entrelacés. Il y a aussi les questions de l'auteur (le texte peut devenir Collectif dans la dépêche, contrairement au journal), du karma gagné sur une dépêche et pas sur le journal, de la double notation (une fois sur le journal, une fois sur la dépêche), de la durée d'exposition d'un journal/d'une dépêche, du relais des dépêches sur d'autres médias (courriel, réseaux sociaux, etc.), de la différence de nature des commentaires due à la différence de public sur les journaux et les dépêches. Etc. La suite de la discussion dans l'entrée de suivi correspondante, où je vais d'ailleurs recopier ce commentaire.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.