Durvald
Player de música local-first com núcleo Rust compartilhado e interfaces nativas
Produto e estágio atual
Desenvolvo o Durvald como um player de música local-first em evolução de uma interface SolidJS/Tauri para aplicações nativas com núcleo compartilhado em Rust. Meu objetivo é organizar e reproduzir a coleção do usuário no próprio dispositivo.
Avancei mais na implementação macOS. Windows faz parte da migração para interfaces nativas e Linux tem uma implementação GTK4 iniciada. Essas frentes estão em estágios diferentes; ainda não ofereço paridade de funcionalidades entre as plataformas.
Versão nativa macOS: detalhe de álbum, lista de faixas e player persistente.
Autoria e aprendizado
Desenvolvi todo o projeto, do logotipo e da identidade visual às interfaces e ao núcleo Rust, com auxílio de diferentes modelos de inteligência artificial. Durvald é um projeto pessoal de desenvolvimento e aprendizado.
Da versão Tauri às interfaces nativas
A versão Tauri ainda estava incompleta, aproximadamente na metade do desenvolvimento, quando decidi privilegiar interfaces nativas como oportunidade de aprender SwiftUI e GTK4. Boa parte do núcleo Rust já era utilizada no Tauri; esse reaproveitamento limitou o impacto da mudança. A migração aconteceu durante a construção do produto, sem representar a substituição de um sistema consolidado em produção.
Na primeira implementação, combinei SolidJS na apresentação, comandos e eventos Tauri na comunicação e Rust no processamento. Mantenho seu código público em durvald-tauri, como referência da etapa anterior do mesmo produto.
Na arquitetura atual, concentro as responsabilidades compartilhadas em durvald-core, independente de interface. A mudança preserva o objetivo do produto, mas substitui a camada de apresentação compartilhada por clientes nativos. Essa escolha exige manter integrações e comportamentos de interface por plataforma. A seção de memória registra uma observação local das duas versões; benchmarks controlados estão fora do escopo atual.
Captura da versão SolidJS/Tauri; não representa a interface nativa atual.
Consistência visual entre sistemas
A busca por interfaces próprias de cada sistema também respondeu a um problema que observei no Windows: efeitos de transparência e desfoque com backdrop-filter falhavam em componentes sobrepostos da interface Tauri. Relacionei esse comportamento à issue Chromium #40835530, que usei como referência técnica na investigação.
Essa experiência aumentava o trabalho de compatibilidade visual da interface compartilhada e contribuiu para minha decisão de adotar clientes nativos. A referência registra o problema investigado; não confirmei o estado atual de resolução da issue nesta revisão.
Registrei esse defeito no Windows. Não observei o mesmo problema no Linux.
Distribuição Linux e custo de manutenção
Além da busca por interfaces nativas, meu fluxo de desenvolvimento Linux dependia de um ambiente Ubuntu. Relatos externos contextualizam esse custo: a discussão #12960 registra uma falha de linuxdeploy no Arch após a compilação, com incompatibilidade da ferramenta strip e observações do mantenedor sobre portabilidade de glibc. As issues #15106 e #11701 também relatam falhas na geração de AppImage no Arch.
Esses relatos reforçam a necessidade de controlar o ambiente de empacotamento e as dependências de distribuição. Não demonstram uma exigência universal de Ubuntu nem uma comparação controlada entre distribuições. A migração para GTK4 retira a WebView do cliente Linux, mas não elimina a necessidade de validar bibliotecas de sistema, empacotamento e compatibilidade entre distribuições.
Núcleo compartilhado e contratos
Concentrei no núcleo Rust indexação da biblioteca, persistência SQLite, reprodução local, histórico, configurações e integração Last.fm. Clientes SwiftUI e outros consumidores FFI usam a superfície UniFFI; o cliente GTK4, também escrito em Rust, consome diretamente a API pública do núcleo, sem bindings UniFFI.
A separação mantém as regras compartilhadas fora das interfaces. A documentação define contratos para caminhos e capas gerenciadas, varredura e cancelamento, formatos de áudio e erros públicos. Os clientes devem reagir às variantes de CoreError, sem interpretar mensagens de diagnóstico como contratos.
Consistência e operações demoradas
Somente uma varredura da biblioteca pode ocorrer por vez. O cancelamento é cooperativo: o trabalho para nos pontos seguros e os resultados cancelados não são persistidos. Uma varredura completa reconcilia arquivos removidos; uma varredura parcial ou cancelada preserva os registros existentes.
No cliente GTK4, os widgets permanecem na thread GTK/GLib e as operações do núcleo são encaminhadas para um runtime Tokio. Essa divisão evita executar trabalho bloqueante na thread da interface e exige coordenar resultados assíncronos com o ciclo de vida da janela.
Implementação por plataforma
- macOS: cliente nativo SwiftUI com integração ao núcleo pela superfície UniFFI; frente mais avançada do desenvolvimento.
- Windows: frente em desenvolvimento na transição para uma implementação nativa. Ainda não disponibilizei neste case uma demonstração nem uma lista validada de funcionalidades dessa versão.
- Linux: base Rust/GTK4 que abre uma janela, inicializa o núcleo e consulta a quantidade de músicas persistidas. Importação, lista de faixas e controles de reprodução ainda são próximos passos. “Atualizar biblioteca” relê o banco; não inicia uma varredura.
Memória observada em idle
Transcrevi os valores abaixo de uma observação local no Activity Monitor, com as duas versões em idle. Identifiquei o processo Durvald como a versão nativa e os outros quatro como a versão Tauri.
| Implementação | Processo ou comparação | Memória exibida |
|---|---|---|
| Nativa macOS | Durvald | 73,5 MB |
| Tauri | http://localhost:1420 | 95,7 MB |
| Tauri | durvald | 53,2 MB |
| Tauri | durvald Graphics and Media | 17,3 MB |
| Tauri | durvald Networking | 10,7 MB |
| Total Tauri | Soma dos quatro processos | 176,9 MB |
| Diferença observada | Tauri menos nativa | 103,4 MB (aproximadamente 58% menor na nativa) |
Nesta comparação, usei a soma dos valores exibidos pelo Activity Monitor, não memória física exclusiva. É uma observação pontual: não registrei neste case a máquina, a versão do macOS, os commits, o modo de build, o tamanho da biblioteca e o tempo em idle. O endereço localhost indica conteúdo servido localmente na versão Tauri. Os valores não comprovam uma redução geral de memória, consumo de CPU ou tempo de inicialização; uma comparação reproduzível requer condições equivalentes e múltiplas execuções.
Evidências e limites
Neste case, reúno código público, capturas da interface e uma observação local de memória. Meu foco é documentar o aprendizado em interfaces nativas e o reaproveitamento do núcleo Rust durante o desenvolvimento. Benchmarks comparativos não fazem parte do escopo atual; mantenho os valores de memória como registro pontual, sem promessa de desempenho geral.