MusicPod es un reproductor local de música, radio, televisión y podcasts para Linux Desktop, MacOS y Windows. (Android está planeado pero aún no hay ETA cuando sucederá).
SO | Cómo instalar |
---|---|
linux | o |
ventanas | Página de lanzamiento |
Mac OS | Página de lanzamiento |
Androide | WIP |
Características | Linux oscuro | Linux ligero | Mac OS oscuro | Mac OS ligero |
---|---|---|---|---|
Reproducir audio local | ||||
Encuentra audios locales ordenados por metadatos | ||||
¡Reproduzca estaciones de radio con etiquetas heladas y obras de arte buscadas! | ||||
¡Reproduce y descarga podcasts, progresa de forma segura, ordena episodios y más! | ||||
¡Soporte para podcasts de vídeo! | ||||
Descubre podcasts, filtrados a tu gusto | ||||
Descubre emisoras de radio, filtradas a tu gusto | ||||
Diferentes modos de visualización |
El icono de la aplicación ha sido creado por Stuart Jaggers, ¡muchas gracias Stuart!
¡Gracias TheShadowOfHassen por empaquetar MusicPod como Flatpak!
¡Gracias a todos los contribuyentes de MPV!
¡Gracias @amugofjava por crear podcast_search confiable y fácil de usar!
¡Gracias @alexmercerind por la biblioteca Mediakit de excelente rendimiento y la implementación de mpris_service dart!
Gracias @KRTirtho por el paquete smtc_windows y Flutter Discord RPC, muy fáciles de usar.
¡Gracias @tomassasovsky por la implementación de dart de radiobrowser-api!
¡Gracias @ClementBeal por el lector de metadatos de audio súper rápido y puro!
¡Gracias @escamoteur por crear get_it y watch_it, lo que hizo que mi aplicación fuera más rápida y el código fuente más limpio!
Las contribuciones son muy bienvenidas. Especialmente las traducciones. Bifurque MusicPod en su espacio de nombres de GitHub, clónelo en su computadora, cree una rama nombrada por usted mismo, confirme sus cambios en su rama local, envíelos a su bifurcación y luego realice una solicitud de extracción desde su bifurcación a este repositorio. Recomiendo la extensión vscode GitHub Pull Requests, especialmente para personas nuevas en Git y GitHub.
Para traducciones a su idioma, cambie el archivo app_xx.arb
correspondiente donde xx
es el código de idioma de su idioma en minúsculas. Si el archivo aún no existe, créelo y copie whole
el contenido de app_en.arb en él y cambie solo los valores de su traducción, pero deje las claves intactas. Se recomienda encarecidamente el editor arb de extensión vscode de Google para evitar errores de sintaxis arb. También se recomienda la extensión Google Translate.
Si encuentra algún error, no dude en informarlo como un problema y describirlo lo mejor que pueda. Si desea contribuir con código, primero cree un problema.
Los simulacros de prueba se generan con Mockito. Debe ejecutar el comando build_runner
para volver a generar simulacros, en caso de que haya cambiado las firmas de los métodos de servicio.
dart run build_runner build
¡MusicPod es básicamente una elegante interfaz para MPV! Sin él, todavía se vería bien, pero no reproduciría ningún medio :D.
MusicPod utiliza el patrón arquitectónico MVVM, que se adapta mejor a las necesidades de esta aplicación reactiva y mantiene todas las capas separadas para que podamos intercambiar la implementación de una capa si es necesario. Flutter también recomienda MVVM.
La aplicación, el reproductor, el buscador y cada página principal tienen su propio conjunto de widgets, uno o más modelos de vista, que dependen de uno o más servicios.
Todos los servicios y ViewModels se registran de forma diferida a través de get_it, lo que significa que no se crean instancias de ellos hasta que se ubican por primera vez a través di
o di
.
diagrama de flujo LR
relleno de vista classDef:#0e84207d
relleno del modelo de vista classDef:#e9542080
relleno del modelo classDef:#77216f80
Ver["`
**Vista**
(Aparatos)
`"]:::vista--watchProperty-->ViewModel["`
**Ver modelo**
(Notificador de cambios)
`"]:::viewmodel--escuchar/obtener propiedades-->Modelo["`
**Modelo (dominio)**
(Servicio)
`"]:::modelo
ViewModel--notificar-->Ver
Modelo--changedProperties.add(true)-->ViewModel
Los ViewModels tienen dependencias de los servicios que se brindan a través de su constructor, donde se ubican a través del localizador de servicios get_it. Esto hace que sean fáciles de probar, ya que puede reemplazar los servicios con servicios simulados.
Los ViewModels son ChangeNotifiers. Pueden usar el método notifyListener
que hace que los oyentes (concretos: clases de UI) reaccionen (es decir, reconstruyan).
Los ViewModels tienen (una) StreamSubscription(s) para (los) servicios de los que dependen. Si las propiedades son solo un estado de interfaz de usuario no persistente, se mantienen dentro de ViewModel. Si son más que eso, simplemente son captadores de propiedades de servicio. Entonces, si una propiedad de un servicio cambia, los ViewModels serán notificados a través de la secuencia propertiesChanged, y si queremos que la UI se dé cuenta, dentro de la devolución de llamada listen
, notificaremos a la UI (oyentes).
En cuanto a los paquetes para implementar esta arquitectura, he tenido un gran recorrido desde el proveedor hasta el Riverpod.
Encontré mi solución favorita con get_it más su extensión watch_it porque se adapta mejor a las necesidades de esta aplicación y a la arquitectura MVVM sin ser demasiado invasivo en la API del árbol de widgets de flutter.
De esta manera, todas las capas están claramente separadas, son fáciles de volver a implementar y de seguir, incluso si esto implica un poco de código repetitivo.
Si los widgets quieren reconstruirse una vez que cambian las propiedades de ViewModels, usamos el método watchPropertyValue
del paquete watch_it:
final audio = watchPropertyValue (( PlayerModel m) => m.audio);
Esto lo hace más fácil, aunque también podríamos usar flutters integrados en ListenableBuilder.
Tanto las portadas locales como las remotas se almacenan en caché en CoverStore
y UrlStore
después de haber sido cargadas/obtenidas.
La lectura de las portadas locales y la búsqueda de portadas remotas para datos de radio se realizan dentro de aislados de segundo dardo adicionales.
Las preferencias se almacenan con preferencias_compartidas.