Durvald

Reproductor de música local-first con núcleo Rust compartido e interfaces nativas

2025

Producto y estado actual

Desarrollo Durvald como un reproductor de música local-first en evolución desde una interfaz SolidJS/Tauri hacia aplicaciones nativas con un núcleo compartido en Rust. Mi objetivo es organizar y reproducir la colección del usuario en su propio dispositivo.

He avanzado más en la implementación macOS. Windows forma parte de la migración a interfaces nativas y Linux cuenta con una implementación GTK4 inicial. Los clientes están en etapas distintas; todavía no ofrezco paridad de funciones entre plataformas.

Interfaz nativa de Durvald en macOS, con navegación de biblioteca, el álbum Switched-On Bach y controles de reproducción.Versión nativa macOS: detalle del álbum, lista de canciones y reproductor persistente.

Autoría y aprendizaje

Desarrollé todo el proyecto, desde el logotipo y la identidad visual hasta las interfaces y el núcleo Rust, con ayuda de distintos modelos de inteligencia artificial. Durvald es un proyecto personal de desarrollo y aprendizaje.

De Tauri a interfaces nativas

La versión Tauri todavía estaba incompleta, aproximadamente a mitad del desarrollo, cuando elegí las interfaces nativas como oportunidad para aprender SwiftUI y GTK4. Buena parte del núcleo Rust ya se utilizaba en Tauri; su reutilización limitó el impacto del cambio. La migración ocurrió durante la construcción del producto, sin sustituir un sistema consolidado en producción.

En la primera implementación, combiné SolidJS para la presentación, comandos y eventos Tauri para la comunicación y Rust para el procesamiento. Mantengo su código público en durvald-tauri, como referencia de la etapa anterior del mismo producto.

En la arquitectura actual, concentro las responsabilidades compartidas en durvald-core, independiente de la interfaz. El objetivo del producto se mantiene, mientras clientes nativos reemplazan la capa de presentación compartida. Esta decisión exige mantener integraciones y comportamientos específicos por plataforma. La sección de memoria registra una observación local de ambas versiones; los benchmarks controlados quedan fuera del alcance actual.

Interfaz de la implementación anterior de Durvald con SolidJS y Tauri.Captura de la versión SolidJS/Tauri; no representa la interfaz nativa actual.

Consistencia visual entre sistemas

La búsqueda de interfaces propias de cada sistema también respondió a un problema que observé en Windows: los efectos de transparencia y desenfoque con backdrop-filter fallaban en componentes superpuestos de la interfaz Tauri. Relacioné este comportamiento con la issue Chromium #40835530, que utilicé como referencia técnica de la investigación.

Esta experiencia aumentaba el trabajo de compatibilidad visual de la interfaz compartida y contribuyó a mi decisión de adoptar clientes nativos. La referencia identifica el problema investigado; no he confirmado su estado actual de resolución en esta revisión.

Menú contextual de la versión Tauri en Windows, con un fondo rectangular que sobresale de las esquinas redondeadas.Registré este defecto en Windows. No observé el mismo problema en Linux.

Distribución Linux y coste de mantenimiento

Además de buscar interfaces nativas, mi flujo de desarrollo Linux dependía de un entorno Ubuntu. Los informes externos aportan contexto: la discusión #12960 registra un fallo de linuxdeploy en Arch después de compilar, con una herramienta strip incompatible y comentarios del mantenedor sobre portabilidad de glibc. Las issues #15106 y #11701 también describen fallos al generar AppImage en Arch.

Estos informes refuerzan la necesidad de controlar el entorno de empaquetado y las dependencias de distribución. No demuestran un requisito universal de Ubuntu ni una comparación controlada entre distribuciones. La migración a GTK4 elimina la WebView del cliente Linux, pero las bibliotecas del sistema, el empaquetado y la compatibilidad entre distribuciones siguen requiriendo validación.

Núcleo compartido y contratos

Concentré en el núcleo Rust indexación, persistencia SQLite, reproducción local, historial, configuración e integración Last.fm. SwiftUI y otros clientes FFI usan la superficie UniFFI; el cliente GTK4, también escrito en Rust, consume directamente la API pública Rust sin bindings UniFFI.

Esta separación mantiene las reglas compartidas fuera de las interfaces. La documentación define contratos para rutas y portadas gestionadas, escaneo y cancelación, formatos de audio y errores públicos. Los clientes deben reaccionar a las variantes de CoreError, sin interpretar mensajes de diagnóstico como contratos.

Consistencia y operaciones prolongadas

Solo puede ejecutarse un escaneo de biblioteca a la vez. La cancelación es cooperativa: el trabajo se detiene en puntos seguros y los resultados cancelados no se guardan. Un escaneo completo reconcilia archivos eliminados; uno parcial o cancelado conserva los registros existentes.

En GTK4, los widgets permanecen en el hilo GTK/GLib y las operaciones del núcleo se envían a un runtime Tokio. Esto separa el trabajo bloqueante del hilo de interfaz y exige coordinar los resultados asíncronos con el ciclo de vida de la ventana.

Implementación por plataforma

  • macOS: cliente nativo SwiftUI integrado mediante UniFFI; la línea de desarrollo más avanzada.
  • Windows: en desarrollo dentro de la transición a una implementación nativa. Todavía no he incluido en este caso una demostración ni una lista validada de funciones de esta versión.
  • Linux: base Rust/GTK4 que abre una ventana, inicializa el núcleo y consulta la cantidad de canciones persistidas. Importación, listas y controles de reproducción siguen pendientes. Actualizar la biblioteca relee la base; no inicia un escaneo.

Memoria observada en reposo

Transcribí los valores siguientes de una observación local en Activity Monitor, con ambas versiones en reposo. Identifiqué Durvald como la versión nativa y los otros cuatro procesos como la versión Tauri.

ImplementaciónProceso o comparaciónMemoria mostrada
Nativa macOSDurvald73,5 MB
Taurihttp://localhost:142095,7 MB
Tauridurvald53,2 MB
Tauridurvald Graphics and Media17,3 MB
Tauridurvald Networking10,7 MB
Total TauriSuma de los cuatro procesos176,9 MB
Diferencia observadaTauri menos nativa103,4 MB (aproximadamente un 58% menos en la nativa)

En esta comparación, sumé los valores mostrados por Activity Monitor, no memoria física exclusiva. Es una observación puntual: no registré el equipo, la versión de macOS, los commits, el modo de compilación, el tamaño de la biblioteca ni el tiempo en reposo. La dirección localhost indica contenido servido localmente en la versión Tauri. Estos valores no demuestran una reducción general de memoria, CPU o tiempo de inicio; una comparación reproducible requiere condiciones equivalentes y varias ejecuciones.

Evidencias y límites

En este caso, reúno código público, capturas de interfaz y una observación local de memoria. Mi enfoque es el aprendizaje de interfaces nativas y la reutilización del núcleo Rust durante el desarrollo. Los benchmarks comparativos quedan fuera del alcance actual; mantengo los valores de memoria como observación puntual, sin prometer mejoras generales de rendimiento.

Código actual

Versión anterior — Tauri

Contratos del núcleo Rust

Estado y ejecución del cliente Linux