Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Integrate Typesense server and update Zig build (zig 0.16)

Add rockbox-typesense integration and wire it into the CLI. Add dirs
and uuid workspace dependencies. Spawn a background thread to set up and
run typesense-server, set RB_TYPESENSE_API_KEY/PORT, and use
~/.config/rockbox.org/typesense as the data directory.

Make the typesense crate create the data directory and check for an
existing typesense-server in PATH.

Migrate Zig build and executable entry to updated Zig APIs: use
root_module for
addLibraryPath/addObjectFile/linkSystemLibrary/linkFramework,
set link_libc, and update main to use std.process.Init.Minimal with new
args handling.

+76 -28
+4
Cargo.lock
··· 8923 8923 dependencies = [ 8924 8924 "anyhow", 8925 8925 "clap", 8926 + "dirs 6.0.0", 8926 8927 "owo-colors 4.1.0", 8927 8928 "rockbox-library", 8928 8929 "rockbox-rocksky", 8929 8930 "rockbox-search", 8930 8931 "rockbox-settings", 8932 + "rockbox-typesense", 8931 8933 "tokio", 8934 + "uuid", 8932 8935 ] 8933 8936 8934 8937 [[package]] ··· 9218 9221 version = "0.1.0" 9219 9222 dependencies = [ 9220 9223 "anyhow", 9224 + "dirs 6.0.0", 9221 9225 ] 9222 9226 9223 9227 [[package]]
+3
crates/cli/Cargo.toml
··· 14 14 rockbox-search = {path = "../search"} 15 15 rockbox-settings = {path = "../settings"} 16 16 rockbox-rocksky = {path = "../rocksky"} 17 + rockbox-typesense = {path = "../typesense"} 17 18 tokio = {version = "1.36.0", features = ["full"]} 19 + dirs = "6.0.0" 20 + uuid.workspace = true
+34
crates/cli/src/lib.rs
··· 7 7 use rockbox_search::artist::Artist; 8 8 use rockbox_search::track::Track; 9 9 use rockbox_search::{create_indexes, delete_all_documents, index_entity}; 10 + use std::process::Stdio; 10 11 use std::thread::sleep; 11 12 use std::time::Duration; 12 13 use std::{env, ffi::CStr}; ··· 170 171 ); 171 172 }); 172 173 174 + thread::spawn(move || { 175 + rockbox_typesense::setup()?; 176 + 177 + let api_key = uuid::Uuid::new_v4().to_string(); 178 + let api_key = std::env::var("RB_TYPESENSE_API_KEY").unwrap_or(api_key); 179 + std::env::set_var("RB_TYPESENSE_API_KEY", &api_key); 180 + println!("Using Typesense API key: {}", api_key); 181 + 182 + let port = std::env::var("RB_TYPESENSE_PORT").unwrap_or_else(|_| "8109".to_string()); 183 + std::env::set_var("RB_TYPESENSE_PORT", &port); 184 + 185 + let homedir = dirs::home_dir() 186 + .ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?; 187 + let data_dir = homedir.join(".config/rockbox.org/typesense"); 188 + 189 + let path = format!( 190 + "{}:{}", 191 + std::env::var("PATH").unwrap_or_default(), 192 + "~/.rockbox/bin" 193 + ); 194 + 195 + std::process::Command::new("sh") 196 + .arg("-c") 197 + .arg(&format!("typesense-server --enable-cors --port {port}")) 198 + .env("PATH", &path) 199 + .env("TYPESENSE_API_KEY", &api_key) 200 + .env("TYPESENSE_DATA_DIR", &data_dir) 201 + .stdout(Stdio::inherit()) 202 + .stderr(Stdio::inherit()) 203 + .status()?; 204 + 205 + Ok::<(), Error>(()) 206 + }); 173 207 return 0; 174 208 } 175 209
+1
crates/typesense/Cargo.toml
··· 8 8 9 9 [dependencies] 10 10 anyhow.workspace = true 11 + dirs = "6.0.0"
+16 -9
crates/typesense/src/lib.rs
··· 1 - use std::process::{Command, Stdio}; 1 + use std::{ 2 + fs, 3 + process::{Command, Stdio}, 4 + }; 2 5 3 6 pub fn setup() -> Result<(), anyhow::Error> { 7 + let path = format!( 8 + "{}:{}", 9 + std::env::var("PATH").unwrap_or_default(), 10 + "~/.rockbox/bin" 11 + ); 4 12 let mut cmd = Command::new("command") 5 13 .arg("-v") 6 14 .arg("typesense-server") 7 - .env( 8 - "PATH", 9 - format!( 10 - "{}:{}", 11 - std::env::var("PATH").unwrap_or_default(), 12 - "~/.rockbox/bin" 13 - ), 14 - ) 15 + .env("PATH", &path) 15 16 .stderr(std::process::Stdio::null()) 16 17 .stdout(std::process::Stdio::null()) 17 18 .spawn()?; 18 19 20 + let homedir = 21 + dirs::home_dir().ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?; 22 + let data_dir = homedir.join(".config/rockbox.org/typesense"); 23 + fs::create_dir_all(&data_dir)?; 24 + 19 25 if cmd.wait()?.success() { 26 + println!("Typesense server is already installed and available in PATH."); 20 27 return Ok(()); 21 28 } 22 29
+15 -15
zig/build.zig
··· 83 83 }), 84 84 }); 85 85 86 - exe.addLibraryPath(.{ 86 + exe.root_module.addLibraryPath(.{ 87 87 .cwd_relative = "../target/release", 88 88 }); 89 89 90 90 if (target.result.os.tag == .macos) { 91 - exe.addLibraryPath(.{ .cwd_relative = "/opt/homebrew/lib" }); 92 - exe.linkFramework("CoreFoundation"); 91 + exe.root_module.addLibraryPath(.{ .cwd_relative = "/opt/homebrew/lib" }); 92 + exe.root_module.linkFramework("CoreFoundation", .{}); 93 93 } 94 94 95 95 if (target.result.os.tag == .linux) { 96 - exe.linkSystemLibrary("unwind"); 96 + exe.root_module.linkSystemLibrary("unwind", .{}); 97 97 } 98 98 99 99 const librockbox = b.path("../build-lib/librockbox.a"); ··· 105 105 const libspeex_voice = b.path("../build-lib/lib/rbcodec/codecs/libspeex-voice.a"); 106 106 const librockbox_cli = b.path("../target/release/librockbox_cli.a"); 107 107 const librockbox_server = b.path("../target/release/librockbox_server.a"); 108 - exe.addObjectFile(librockbox); 109 - exe.addObjectFile(libfirmware); 110 - exe.addObjectFile(libfixedpoint); 111 - exe.addObjectFile(libskin_parser); 112 - exe.addObjectFile(librbcodec); 113 - exe.addObjectFile(libtlsf); 114 - exe.addObjectFile(libspeex_voice); 115 - exe.addObjectFile(librockbox_cli); 116 - exe.addObjectFile(librockbox_server); 117 - exe.linkSystemLibrary("SDL2"); 118 - exe.linkLibC(); 108 + exe.root_module.addObjectFile(librockbox); 109 + exe.root_module.addObjectFile(libfirmware); 110 + exe.root_module.addObjectFile(libfixedpoint); 111 + exe.root_module.addObjectFile(libskin_parser); 112 + exe.root_module.addObjectFile(librbcodec); 113 + exe.root_module.addObjectFile(libtlsf); 114 + exe.root_module.addObjectFile(libspeex_voice); 115 + exe.root_module.addObjectFile(librockbox_cli); 116 + exe.root_module.addObjectFile(librockbox_server); 117 + exe.root_module.linkSystemLibrary("SDL2", .{}); 118 + exe.root_module.link_libc = true; 119 119 120 120 // This declares intent for the executable to be installed into the 121 121 // install prefix when running `zig build` (i.e. when executing the default
+3 -4
zig/src/main.zig
··· 7 7 extern fn main_c() c_int; 8 8 extern fn parse_args(argc: usize, argv: [*]const [*]const u8) c_int; 9 9 10 - pub fn main() !void { 11 - const args = try std.process.argsAlloc(std.heap.page_allocator); 12 - defer std.process.argsFree(std.heap.page_allocator, args); 10 + pub fn main(init: std.process.Init.Minimal) !void { 11 + const args = init.args.vector; 13 12 14 13 var argv: [10][*]const u8 = undefined; 15 14 ··· 21 20 } 22 21 23 22 for (args) |arg| { 24 - argv[argc] = @ptrCast(arg.ptr); 23 + argv[argc] = @ptrCast(arg); 25 24 argc += 1; 26 25 } 27 26