MusicPod est un lecteur local de musique, de radio, de télévision et de podcast pour Linux Desktop, MacOS et Windows. (Android est prévu mais pas encore d'ETA quand cela se produira.)
Système d'exploitation | Comment installer |
---|---|
Linux | ou |
Fenêtres | Page de sortie |
Mac OS | Page de sortie |
Androïde | En-cours |
Caractéristiques | Linux sombre | Linux léger | MacOS sombre | MacOS léger |
---|---|---|---|---|
Lire de l'audio local | ||||
Rechercher des audios locaux triés par métadonnées | ||||
Écoutez des stations de radio, avec des icytags et des illustrations recherchées ! | ||||
Jouez et téléchargez des podcasts, progressez en toute sécurité, triez les épisodes et bien plus encore ! | ||||
Prise en charge des podcasts vidéo ! | ||||
Découvrez des podcasts, filtrés à votre guise | ||||
Découvrez les stations de radio, filtrées à votre guise | ||||
Différents modes d'affichage |
L'icône de l'application a été réalisée par Stuart Jaggers, merci beaucoup Stuart !
Merci à TheShadowOfHassen d'avoir emballé MusicPod sous forme de Flatpak !
Merci à tous les contributeurs MPV !
Merci @amugofjava d'avoir créé le podcast_search très simple à utiliser et fiable !
Merci @alexmercerind pour la bibliothèque Mediakit super performante et l'implémentation de mpris_service dart !
Merci @KRTirtho pour le package smtc_windows très facile à utiliser et Flutter Discord RPC
Merci @tomassasovsky pour l'implémentation Dart de radiobrowser-api !
Merci @ClementBeal pour le lecteur de métadonnées audio Dart ultra rapide et pur !
Merci @escamoteur d'avoir créé get_it et watch_it, qui ont rendu mon application plus rapide et plus propre le code source !
Les contributions sont les bienvenues. Surtout les traductions. Veuillez transférer MusicPod vers votre espace de noms GitHub, clonez-le sur votre ordinateur, créez une branche nommée par vous-même, validez vos modifications dans votre branche locale, transférez-les vers votre fork, puis effectuez une demande d'extraction de votre fork vers ce référentiel. Je recommande l'extension vscode GitHub Pull Requests en particulier pour les personnes qui découvrent Git et GitHub.
Pour les traductions dans votre langue, modifiez le fichier app_xx.arb
correspondant où xx
est le code de langue de votre langue en minuscules. Si le fichier n'existe pas encore, créez-le et copiez-y whole
le contenu de app_en.arb et modifiez uniquement les valeurs de votre traduction, mais laissez les clés intactes. L'éditeur arb d'extension vscode de Google est fortement recommandé pour éviter les erreurs de syntaxe arb. L'extension Google Translate est également recommandée.
Si vous trouvez une erreur, n'hésitez pas à la signaler comme un problème et à la décrire aussi bien que possible. Si vous souhaitez contribuer au code, veuillez d'abord créer un problème.
Les simulations de tests sont générées avec Mockito. Vous devez exécuter la commande build_runner
afin de régénérer les simulations, au cas où vous auriez modifié les signatures des méthodes de service.
dart run build_runner build
MusicPod est fondamentalement une interface sophistiquée pour MPV ! Sans cela, il aurait toujours l'air sympa, mais il ne lirait aucun média :D !
MusicPod utilise le modèle architectural MVVM, qui répond le mieux aux besoins de cette application réactive, et maintient toutes les couches séparées afin que nous puissions échanger l'implémentation d'une couche si nécessaire. MVVM est également recommandé par Flutter lui-même.
L'application, le lecteur, la recherche et chaque page principale ont leur propre ensemble de widgets, un ou plusieurs modèles de vue, qui dépendent d'un ou plusieurs services.
Tous les services et ViewModels sont enregistrés paresseusement via get_it, ce qui signifie qu'ils ne sont pas instanciés jusqu'à ce qu'ils soient localisés pour la première fois via di
ou di
.
organigramme LR
remplissage de la vue classDef :#0e84207d
remplissage du modèle de vue classDef : #e9542080
Remplissage du modèle classDef : #77216f80
Vue["`
**Voir**
(Widgets)
`"]:::view--watchProperty-->ViewModel["`
**Modèle de vue**
(ChangeNotifier)
`"]:::viewmodel--écouter/obtenir les propriétés-->Modèle["`
**Modèle (de domaine)**
(Service)
`"]:::modèle
ViewModel--notify-->View
Modèle--changedProperties.add(true)-->ViewModel
Les ViewModels ont des dépendances aux services qui sont données via leur constructeur, où ils sont localisés via le localisateur de services get_it. Cela les rend faciles à tester puisque vous pouvez remplacer les services par des services simulés.
Les ViewModels sont des ChangeNotifiers. Ils peuvent utiliser la méthode notifyListener
qui fait réagir les auditeurs (concrets : classes d'interface utilisateur) (c'est-à-dire reconstruire).
Les ViewModels détiennent (un) StreamSubscription (s) au (aux) service (s) dont ils dépendent. Si les propriétés sont uniquement un état d’interface utilisateur non persistant, elles sont conservées dans le ViewModel. S’ils sont plus que cela, ils ne font que s’occuper des propriétés. Ainsi, si une propriété d'un service change, les ViewModels seront notifiés via le flux PropertiesChanged, et si nous voulons que l'interface utilisateur en prenne note, dans le rappel listen
nous en informerons l'interface utilisateur (auditeurs).
En ce qui concerne les packages permettant d'implémenter cette architecture, j'ai parcouru tout un parcours, du fournisseur au riverpod.
J'ai trouvé ma solution préférée avec get_it plus son extension watch_it car cela répond le mieux aux besoins de cette application et à l'architecture MVVM sans être trop invasif dans l'API de l'arborescence des widgets Flutter.
De cette façon, toutes les couches sont clairement séparées, faciles à réimplémenter et faciles à suivre, même si cela apporte un peu de code passe-partout.
Si les Widgets veulent être reconstruits une fois les propriétés des ViewModels modifiées, nous utilisons la méthode watchPropertyValue
du package watch_it :
final audio = watchPropertyValue (( PlayerModel m) => m.audio);
Cela rend les choses plus faciles, même si nous pourrions également simplement utiliser des flutters intégrés dans ListenableBuilder.
Les couvertures locales et distantes sont mises en cache dans un CoverStore
et un UrlStore
après avoir été chargées/récupérées.
La lecture des couvertures locales et la récupération des couvertures distantes pour les données radio se produisent à l'intérieur d'isolats de deuxième fléchette supplémentaires.
Les préférences sont stockées avec shared_preferences.