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.

Link librockbox in Zig build and add bindings

Add Zig wrappers and C APIs for metadata, playlist, settings, tree
Update build to include library sources and link required static libs

+870 -35
+5 -2
apps/apps.make
··· 9 9 10 10 INCLUDES += -I$(APPSDIR) $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA))) 11 11 SRC += $(call preprocess, $(APPSDIR)/SOURCES) 12 + LIB_SRC += $(call preprocess, $(APPSDIR)/SOURCES) 13 + LIB_SRC += $(BUILDDIR)/lang/lang_core.c 14 + LIB_SRC += $(BUILDDIR)/apps/bitmaps/mono/*.c 15 + LIB_SRC += $(BUILDDIR)/apps/bitmaps/native/*.c 12 16 13 17 # apps/features.txt is a file that (is preprocessed and) lists named features 14 18 # based on defines in the config-*.h files. The named features will be passed ··· 39 43 40 44 ROCKBOXLIB = $(BUILDDIR)/librockbox.a 41 45 42 - ROCKBOXLIB_OBJ := $(call c2obj, $(SRC)) 46 + ROCKBOXLIB_OBJ := $(call c2obj, $(LIB_SRC)) 43 47 44 48 $(ROCKBOXLIB): $(ROCKBOXLIB_OBJ) 45 49 $(SILENT)$(shell rm -f $@) 46 50 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null 47 -
+1 -1
tools/root.make
··· 191 191 OBJ := $(call full_path_subst,$(ROOTDIR)/%,$(BUILDDIR)/%,$(OBJ)) 192 192 193 193 build: $(TOOLS) $(BUILDDIR)/$(BINARY) $(CODECS) $(ROCKS) $(RBINFO) 194 - lib: $(DEPFILE) $(ROCKBOXLIB) $(TOOLS) $(CODECS) $(ROCKS) 194 + lib: $(DEPFILE) $(ROCKBOXLIB) $(FIRMLIB) $(RBCODECLIB) $(CORE_LIBS) $(VOICESPEEXLIB) $(TOOLS) $(CODECS) $(ROCKS) 195 195 196 196 $(RBINFO): $(BUILDDIR)/$(BINARY) 197 197 $(SILENT)echo Creating $(@F)
+30 -13
zig/build.zig
··· 83 83 }), 84 84 }); 85 85 86 + exe.addLibraryPath(.{ 87 + .cwd_relative = "../target/release", 88 + }); 89 + 90 + if (target.result.os.tag == .macos) { 91 + exe.addLibraryPath(.{ .cwd_relative = "/opt/homebrew/lib" }); 92 + exe.linkFramework("CoreFoundation"); 93 + } 94 + 95 + const librockbox = b.path("../build-lib/librockbox.a"); 96 + const libfirmware = b.path("../build-lib/firmware/libfirmware.a"); 97 + const libfixedpoint = b.path("../build-lib/lib/libfixedpoint.a"); 98 + const librbcodec = b.path("../build-lib/lib/librbcodec.a"); 99 + const libskin_parser = b.path("../build-lib/lib/libskin_parser.a"); 100 + const libtlsf = b.path("../build-lib/lib/libtlsf.a"); 101 + const libspeex_voice = b.path("../build-lib/lib/rbcodec/codecs/libspeex-voice.a"); 102 + const librockbox_cli = b.path("../target/release/librockbox_cli.a"); 103 + const librockbox_server = b.path("../target/release/librockbox_server.a"); 104 + exe.addObjectFile(librockbox); 105 + exe.addObjectFile(libfirmware); 106 + exe.addObjectFile(libfixedpoint); 107 + exe.addObjectFile(libskin_parser); 108 + exe.addObjectFile(librbcodec); 109 + exe.addObjectFile(libtlsf); 110 + exe.addObjectFile(libspeex_voice); 111 + exe.addObjectFile(librockbox_cli); 112 + exe.addObjectFile(librockbox_server); 113 + exe.linkSystemLibrary("SDL2"); 114 + exe.linkLibC(); 115 + 86 116 // This declares intent for the executable to be installed into the 87 117 // install prefix when running `zig build` (i.e. when executing the default 88 118 // step). By default the install prefix is `zig-out/` but can be overridden ··· 141 171 const test_step = b.step("test", "Run tests"); 142 172 test_step.dependOn(&run_mod_tests.step); 143 173 test_step.dependOn(&run_exe_tests.step); 144 - 145 - exe.addLibraryPath(.{ 146 - .cwd_relative = "../target/release", 147 - }); 148 - 149 - const librockbox = b.path("../build-lib/librockbox.a"); 150 - exe.addObjectFile(librockbox); 151 - 152 - //exe.linkSystemLibrary("rockbox_cli"); 153 - //exe.linkSystemLibrary("rockbox_server"); 154 - //exe.linkSystemLibrary("unwind"); 155 - exe.linkSystemLibrary("SDL2"); 156 - exe.linkLibC(); 157 174 158 175 // Just like flags, top level steps are also listed in the `--help` menu. 159 176 //
+101 -19
zig/src/main.zig
··· 1 1 const std = @import("std"); 2 - const rockboxd = @import("rockboxd"); 2 + const playlist = @import("rockbox/playlist.zig"); 3 + const metadata = @import("rockbox/metadata.zig"); 4 + const tree = @import("rockbox/tree.zig"); 5 + const settings = @import("rockbox/settings.zig"); 6 + 7 + extern fn main_c() c_int; 8 + extern fn parse_args(argc: usize, argv: [*]const [*]const u8) c_int; 3 9 4 10 pub fn main() !void { 5 - // Prints to stderr, ignoring potential errors. 6 - std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); 7 - try rockboxd.bufferedPrint(); 11 + const args = try std.process.argsAlloc(std.heap.page_allocator); 12 + defer std.process.argsFree(std.heap.page_allocator, args); 13 + 14 + var argv: [10][*]const u8 = undefined; 15 + 16 + var argc: usize = 0; 17 + 18 + if (args.len > 10) { 19 + std.debug.print("Too many arguments, max 10", .{}); 20 + std.process.exit(1); 21 + } 22 + 23 + for (args) |arg| { 24 + argv[argc] = @ptrCast(arg.ptr); 25 + argc += 1; 26 + } 27 + 28 + _ = parse_args(argc, &argv); 29 + _ = main_c(); 8 30 } 9 31 10 - test "simple test" { 11 - const gpa = std.testing.allocator; 12 - var list: std.ArrayList(i32) = .empty; 13 - defer list.deinit(gpa); // Try commenting this out and see if zig detects the memory leak! 14 - try list.append(gpa, 42); 15 - try std.testing.expectEqual(@as(i32, 42), list.pop()); 32 + // metadata functions 33 + export fn rb_get_metadata(fd: c_int, trackname: [*]const u8) metadata.mp3entry { 34 + return metadata._get_metadata(fd, trackname); 16 35 } 17 36 18 - test "fuzz example" { 19 - const Context = struct { 20 - fn testOne(context: @This(), input: []const u8) anyerror!void { 21 - _ = context; 22 - // Try passing `--fuzz` to `zig build test` and see if it manages to fail this test case! 23 - try std.testing.expect(!std.mem.eql(u8, "canyoufindme", input)); 24 - } 25 - }; 26 - try std.testing.fuzz(Context{}, Context.testOne, .{}); 37 + // browsing functions 38 + export fn rb_rockbox_browse() c_int { 39 + return tree._rockbox_browse(); 40 + } 41 + 42 + export fn rb_tree_get_context() tree.tree_context { 43 + return tree._tree_get_context(); 44 + } 45 + 46 + export fn rb_tree_get_entries() *tree.entry { 47 + return tree._tree_get_entries(); 48 + } 49 + 50 + export fn rb_tree_get_entry_at(index: c_int) tree.entry { 51 + return tree._tree_get_entry_at(index); 52 + } 53 + 54 + // playlist functions 55 + export fn rb_get_track_info_from_current_playlist(index: c_int) playlist.PlaylistTrackInfo { 56 + return playlist._get_track_info_from_current_playlist(index); 57 + } 58 + 59 + export fn rb_build_playlist(files: [*]const [*]const u8, start_index: c_int, size: c_int) c_int { 60 + return playlist.build_playlist(files, start_index, size); 61 + } 62 + 63 + export fn rb_playlist_insert_tracks(files: [*]const [*]const u8, position: c_int, size: c_int) c_int { 64 + return playlist.insert_tracks(files, position, size); 65 + } 66 + 67 + export fn rb_playlist_insert_track(filename: [*]const u8, position: c_int, queue: bool, sync: bool) c_int { 68 + return playlist.insert_track(filename, position, queue, sync); 69 + } 70 + 71 + export fn rb_playlist_delete_track(index: c_int) c_int { 72 + return playlist.delete_track(index); 73 + } 74 + 75 + export fn rb_playlist_insert_directory(dir: [*]const u8, position: c_int, queue: bool, recurse: bool) c_int { 76 + return playlist.insert_directory(dir, position, queue, recurse); 77 + } 78 + 79 + export fn rb_playlist_remove_all_tracks() c_int { 80 + return playlist.remove_all_tracks(); 81 + } 82 + 83 + export fn rb_playlist_index() c_int { 84 + return playlist.playlist_index(); 85 + } 86 + 87 + export fn rb_playlist_first_index() c_int { 88 + return playlist.playlist_first_index(); 89 + } 90 + 91 + export fn rb_playlist_last_insert_pos() c_int { 92 + return playlist.playlist_last_insert_pos(); 93 + } 94 + 95 + export fn rb_playlist_seed() c_int { 96 + return playlist.playlist_seed(); 97 + } 98 + 99 + export fn rb_playlist_last_shuffled_start() c_int { 100 + return playlist.playlist_last_shuffled_start(); 101 + } 102 + 103 + export fn rb_max_playlist_size() c_int { 104 + return playlist.max_playlist_size(); 105 + } 106 + 107 + export fn rb_get_crossfade_mode() c_int { 108 + return settings.get_crossfade_mode(); 27 109 }
+85
zig/src/rockbox/metadata.zig
··· 1 + pub const MAX_PATH = 260; 2 + pub const ID3V2_BUF_SIZE = 1800; 3 + 4 + const mp3_aa_type = enum(c_int) { 5 + AA_TYPE_UNSYNC = -1, 6 + AA_TYPE_UNKNOWN = 0, 7 + AA_TYPE_BMP, 8 + AA_TYPE_PNG, 9 + AA_TYPE_JPG, 10 + }; 11 + 12 + const mp3_albumart = extern struct { 13 + type: mp3_aa_type, 14 + size: c_int, 15 + pos: c_long, // Use c_long to match the typical size of off_t, but adjust as necessary 16 + }; 17 + 18 + pub const mp3entry = extern struct { 19 + path: [MAX_PATH]u8, 20 + title: ?*[*c]u8, 21 + artist: ?*[*c]u8, 22 + album: ?*[*c]u8, 23 + genre_string: ?*[*c]u8, 24 + disc_string: ?*[*c]u8, 25 + track_string: ?*[*c]u8, 26 + year_string: ?*[*c]u8, 27 + composer: ?*[*c]u8, 28 + comment: ?*[*c]u8, 29 + albumartist: ?*[*c]u8, 30 + grouping: ?*[*c]u8, 31 + discnum: c_int, 32 + tracknum: c_int, 33 + layer: c_int, 34 + year: c_int, 35 + id3version: u8, 36 + codectype: u32, 37 + bitrate: u32, 38 + frequency: u32, 39 + id3v2len: u32, 40 + id3v1len: u32, 41 + first_frame_offset: u32, 42 + filesize: u32, 43 + length: u32, 44 + elapsed: u32, 45 + lead_trim: c_int, 46 + tail_trim: c_int, 47 + samples: u64, 48 + frame_count: u32, 49 + bytesperframe: u32, 50 + vbr: bool, 51 + has_toc: bool, 52 + toc: [100]u8, 53 + needs_upsampling_correction: bool, 54 + id3v2buf: [ID3V2_BUF_SIZE]u8, 55 + id3v1buf: [4][92]u8, 56 + offset: u32, 57 + index: c_int, 58 + skip_resume_adjustments: bool, 59 + autoresumable: u8, 60 + tagcache_idx: c_long, 61 + rating: c_int, 62 + score: c_int, 63 + playcount: c_long, 64 + lastplayed: c_long, 65 + playtime: c_long, 66 + track_level: c_long, 67 + album_level: c_long, 68 + track_gain: c_long, 69 + album_gain: c_long, 70 + track_peak: c_long, 71 + album_peak: c_long, 72 + has_embedded_albumart: bool, 73 + albumart: mp3_albumart, 74 + has_embedded_cuesheet: bool, 75 + mb_track_id: ?*[*c]u8, 76 + is_asf_stream: bool, 77 + }; 78 + 79 + extern fn get_metadata(id3: *mp3entry, fd: c_int, trackname: [*]const u8) bool; 80 + 81 + pub fn _get_metadata(fd: c_int, trackname: [*]const u8) mp3entry { 82 + var id3: mp3entry = undefined; 83 + _ = get_metadata(&id3, fd, trackname); 84 + return id3; 85 + }
+160
zig/src/rockbox/playlist.zig
··· 1 + const MAX_PATH = 260; 2 + const PLAYLIST_CONTROL_FILE_SIZE = 256; 3 + 4 + const PLAYLIST_PREPEND = -1; 5 + const PLAYLIST_INSERT = -2; 6 + const PLAYLIST_INSERT_LAST = -3; 7 + const PLAYLIST_INSERT_FIRST = -4; 8 + const PLAYLIST_INSERT_SHUFFLED = -5; 9 + const PLAYLIST_REPLACE = -6; 10 + const PLAYLIST_INSERT_LAST_SHUFFLED = -7; 11 + const PLAYLIST_INSERT_LAST_ROTATED = -8; 12 + 13 + pub const PlaylistInfo = extern struct { 14 + utf8: bool, 15 + control_created: bool, 16 + flags: c_uint, 17 + fd: c_int, 18 + control_fd: c_int, 19 + max_playlist_size: c_int, 20 + indices: ?*c_ulong, 21 + index: c_int, 22 + first_index: c_int, 23 + amount: c_int, 24 + last_insert_pos: c_int, 25 + started: bool, 26 + last_shuffled_start: c_int, 27 + seed: c_int, 28 + dcfrefs_handle: c_int, 29 + dirlen: c_int, 30 + filename: [MAX_PATH]u8, 31 + control_filename: [PLAYLIST_CONTROL_FILE_SIZE + 8]u8, 32 + }; 33 + 34 + pub const PlaylistTrackInfo = extern struct { 35 + filename: [260]u8, 36 + attr: c_int, 37 + index: c_int, 38 + display_index: c_int, 39 + }; 40 + 41 + pub const PlaylistInsertContext = extern struct { 42 + playlist: *PlaylistInfo, 43 + position: c_int, 44 + queue: bool, 45 + progress: bool, 46 + initialized: bool, 47 + count: c_int, 48 + count_langid: c_int, 49 + }; 50 + 51 + extern fn playlist_get_current() *PlaylistInfo; 52 + extern fn playlist_get_track_info(playlist: *PlaylistInfo, index: c_int, info: *PlaylistTrackInfo) c_int; 53 + extern fn playlist_create(dir: [*]const u8, file: [*]const u8) c_int; 54 + extern fn playlist_insert_context_create(playlist: *PlaylistInfo, context: *PlaylistInsertContext, position: c_int, queue: bool, progress: bool) c_int; 55 + extern fn playlist_insert_context_release(context: *PlaylistInsertContext) void; 56 + extern fn playlist_insert_context_add(context: *PlaylistInsertContext, filename: [*]const u8) c_int; 57 + extern fn playlist_delete(playlist: *PlaylistInfo, index: c_int) c_int; 58 + extern fn playlist_insert_track(playlist: *PlaylistInfo, filename: [*]const u8, position: c_int, queue: bool, sync: bool) c_int; 59 + extern fn playlist_insert_directory(playlist: *PlaylistInfo, dir: [*]const u8, position: c_int, queue: bool, recurse: bool) c_int; 60 + extern fn playlist_remove_all_tracks(playlist: *PlaylistInfo) c_int; 61 + 62 + pub fn _get_track_info_from_current_playlist(index: c_int) PlaylistTrackInfo { 63 + const playlist = playlist_get_current(); 64 + var info: PlaylistTrackInfo = undefined; 65 + _ = playlist_get_track_info(playlist, index, &info); 66 + return info; 67 + } 68 + 69 + pub fn build_playlist(files: [*]const [*]const u8, start_index: c_int, size: c_int) c_int { 70 + const start = start_index; 71 + const playlist = playlist_get_current(); 72 + var context: PlaylistInsertContext = undefined; 73 + 74 + if (playlist_insert_context_create(playlist, &context, PLAYLIST_REPLACE, false, false) < 0) { 75 + return -1; 76 + } 77 + 78 + var i: usize = 0; 79 + while (i < size) { 80 + const res = playlist_insert_context_add(&context, files[i]); 81 + if (res < 0) { 82 + break; 83 + } 84 + i += 1; 85 + } 86 + 87 + playlist_insert_context_release(&context); 88 + return start; 89 + } 90 + 91 + pub fn insert_tracks(files: [*]const [*]const u8, position: c_int, size: c_int) c_int { 92 + const playlist = playlist_get_current(); 93 + var context: PlaylistInsertContext = undefined; 94 + 95 + if (playlist_insert_context_create(playlist, &context, position, false, false) < 0) { 96 + return -1; 97 + } 98 + 99 + var i: usize = 0; 100 + while (i < size) { 101 + const res = playlist_insert_context_add(&context, files[i]); 102 + if (res < 0) { 103 + break; 104 + } 105 + i += 1; 106 + } 107 + 108 + playlist_insert_context_release(&context); 109 + return position; 110 + } 111 + 112 + pub fn insert_track(filename: [*]const u8, position: c_int, queue: bool, sync: bool) c_int { 113 + const playlist = playlist_get_current(); 114 + return playlist_insert_track(playlist, filename, position, queue, sync); 115 + } 116 + 117 + pub fn delete_track(index: c_int) c_int { 118 + const playlist = playlist_get_current(); 119 + return playlist_delete(playlist, index); 120 + } 121 + 122 + pub fn insert_directory(dir: [*]const u8, position: c_int, queue: bool, recurse: bool) c_int { 123 + const playlist = playlist_get_current(); 124 + return playlist_insert_directory(playlist, dir, position, queue, recurse); 125 + } 126 + 127 + pub fn remove_all_tracks() c_int { 128 + const playlist = playlist_get_current(); 129 + return playlist_remove_all_tracks(playlist); 130 + } 131 + 132 + pub fn playlist_index() c_int { 133 + const playlist = playlist_get_current(); 134 + return playlist.index; 135 + } 136 + 137 + pub fn playlist_first_index() c_int { 138 + const playlist = playlist_get_current(); 139 + return playlist.first_index; 140 + } 141 + 142 + pub fn playlist_last_insert_pos() c_int { 143 + const playlist = playlist_get_current(); 144 + return playlist.last_insert_pos; 145 + } 146 + 147 + pub fn playlist_seed() c_int { 148 + const playlist = playlist_get_current(); 149 + return playlist.seed; 150 + } 151 + 152 + pub fn playlist_last_shuffled_start() c_int { 153 + const playlist = playlist_get_current(); 154 + return playlist.last_shuffled_start; 155 + } 156 + 157 + pub fn max_playlist_size() c_int { 158 + const playlist = playlist_get_current(); 159 + return playlist.max_playlist_size; 160 + }
+361
zig/src/rockbox/settings.zig
··· 1 + pub const std = @import("std"); 2 + 3 + pub const EQ_NUM_BANDS = 10; 4 + pub const QUICKSCREEN_ITEM_COUNT = 4; 5 + pub const MAX_FILENAME = 32; 6 + pub const MAX_PATHNAME = 256; 7 + 8 + pub const ReplaygainSettings = extern struct { 9 + noclip: bool, 10 + type: c_int, 11 + preamp: c_int, 12 + }; 13 + 14 + pub const EqBandSetting = extern struct { 15 + cutoff: c_int, 16 + gain: c_int, 17 + q: c_int, 18 + }; 19 + 20 + pub const StorageType = extern union { int_val: c_int }; 21 + 22 + pub const SoundSetting = extern struct { setting: c_int }; 23 + 24 + pub const BoolSetting = extern struct { lang_yes: c_int, lang_no: c_int }; 25 + 26 + pub const FilenameSetting = extern struct { 27 + prefix: [*]const u8, 28 + suffix: [*]const u8, 29 + max_len: c_int, 30 + }; 31 + 32 + pub const IntSetting = extern struct { 33 + unit: c_int, 34 + step: c_int, 35 + min: c_int, 36 + max: c_int, 37 + }; 38 + 39 + pub const ChoiceSettingData = extern struct { 40 + desc: [*]const [*]const u8, 41 + talks: [*]const c_int, 42 + }; 43 + 44 + pub const ChoiceSetting = extern struct { 45 + count: c_int, 46 + data: ChoiceSettingData, 47 + }; 48 + 49 + pub const TableSetting = extern struct { 50 + unit: c_int, 51 + count: c_int, 52 + values: [*]const c_int, 53 + }; 54 + 55 + pub const CustomSetting = extern struct { 56 + unit: c_int, 57 + count: c_int, 58 + values: [*]const c_int, 59 + }; 60 + 61 + pub const SettingsTypeUnion = extern union { 62 + sound_setting: SoundSetting, 63 + bool_setting: BoolSetting, 64 + filename_setting: FilenameSetting, 65 + int_setting: IntSetting, 66 + choice_setting: ChoiceSetting, 67 + table_setting: TableSetting, 68 + custom_setting: CustomSetting, 69 + }; 70 + 71 + pub const SettingsList = extern struct { 72 + flags: c_uint, 73 + lang_id: c_int, 74 + default_val: StorageType, 75 + cfg_name: [*]const u8, 76 + cfg_vals: [*]const u8, 77 + settings_type: SettingsTypeUnion, 78 + }; 79 + 80 + pub const TouchscreenParameter = extern struct { 81 + A: c_int, 82 + B: c_int, 83 + C: c_int, 84 + D: c_int, 85 + E: c_int, 86 + F: c_int, 87 + divider: c_int, 88 + }; 89 + 90 + pub const CompressorSettings = extern struct { 91 + threshold: c_int, 92 + makeup_gain: c_int, 93 + ratio: c_int, 94 + knee: c_int, 95 + release_time: c_int, 96 + attack_time: c_int, 97 + }; 98 + 99 + pub const UserSettings = extern struct { 100 + // Audio settings 101 + volume: c_int, 102 + balance: c_int, 103 + bass: c_int, 104 + treble: c_int, 105 + channel_config: c_int, 106 + stereo_width: c_int, 107 + 108 + bass_cutoff: c_int, 109 + treble_cutoff: c_int, 110 + 111 + crossfade: c_int, 112 + crossfade_fade_in_delay: c_int, 113 + crossfade_fade_out_delay: c_int, 114 + crossfade_fade_in_duration: c_int, 115 + crossfade_fade_out_duration: c_int, 116 + crossfade_fade_out_mixmode: c_int, 117 + 118 + // Replaygain 119 + replaygain_settings: ReplaygainSettings, 120 + 121 + // Crossfeed 122 + crossfeed: c_int, 123 + crossfeed_direct_gain: c_uint, 124 + crossfeed_cross_gain: c_uint, 125 + crossfeed_hf_attenuation: c_uint, 126 + crossfeed_hf_cutoff: c_uint, 127 + 128 + // EQ 129 + eq_enabled: u8, 130 + eq_precut: c_uint, 131 + eq_band_settings: [EQ_NUM_BANDS]EqBandSetting, 132 + 133 + // Misc. swcodec 134 + beep: c_int, 135 + keyclick: c_int, 136 + keyclick_repeats: c_int, 137 + dithering_enabled: u8, 138 + timestretch_enabled: u8, 139 + 140 + // Misc options 141 + list_accel_start_delay: c_int, 142 + list_accel_wait: c_int, 143 + 144 + touchpad_sensitivity: c_int, 145 + touchpad_deadzone: c_int, 146 + 147 + pause_rewind: c_int, 148 + unplug_mode: c_int, 149 + unplug_autoresume: u8, 150 + 151 + qs_items: [QUICKSCREEN_ITEM_COUNT]SettingsList, 152 + 153 + timeformat: c_int, 154 + disk_spindown: c_int, 155 + buffer_margin: c_int, 156 + 157 + dirfilter: c_int, 158 + show_filename_ext: c_int, 159 + default_codepage: c_int, 160 + hold_lr_for_scroll_in_list: u8, 161 + play_selected: u8, 162 + single_mode: c_int, 163 + party_mode: u8, 164 + cuesheet: u8, 165 + car_adapter_mode: u8, 166 + car_adapter_mode_delay: c_int, 167 + start_in_screen: c_int, 168 + ff_rewind_min_step: c_int, 169 + ff_rewind_accel: c_int, 170 + 171 + peak_meter_release: c_int, 172 + peak_meter_hold: c_int, 173 + peak_meter_clip_hold: c_int, 174 + peak_meter_dbfs: u8, 175 + peak_meter_min: c_int, 176 + peak_meter_max: c_int, 177 + 178 + wps_file: [MAX_FILENAME + 1]u8, 179 + sbs_file: [MAX_FILENAME + 1]u8, 180 + lang_file: [MAX_FILENAME + 1]u8, 181 + playlist_catalog_dir: [MAX_PATHNAME + 1]u8, 182 + skip_length: c_int, 183 + max_files_in_dir: c_int, 184 + max_files_in_playlist: c_int, 185 + volume_type: c_int, 186 + battery_display: c_int, 187 + show_icons: u8, 188 + statusbar: c_int, 189 + 190 + scrollbar: c_int, 191 + scrollbar_width: c_int, 192 + 193 + list_line_padding: c_int, 194 + list_separator_height: c_int, 195 + list_separator_color: c_int, 196 + 197 + browse_current: u8, 198 + scroll_paginated: u8, 199 + list_wraparound: u8, 200 + list_order: c_int, 201 + scroll_speed: c_int, 202 + bidir_limit: c_int, 203 + scroll_delay: c_int, 204 + scroll_step: c_int, 205 + 206 + autoloadbookmark: c_int, 207 + autocreatebookmark: c_int, 208 + autoupdatebookmark: u8, 209 + usemrb: c_int, 210 + 211 + dircache: u8, 212 + tagcache_ram: c_int, 213 + tagcache_autoupdate: u8, 214 + autoresume_enable: u8, 215 + autoresume_automatic: c_int, 216 + autoresume_paths: [MAX_PATHNAME + 1]u8, 217 + runtimedb: u8, 218 + tagcache_scan_paths: [MAX_PATHNAME + 1]u8, 219 + tagcache_db_path: [MAX_PATHNAME + 1]u8, 220 + backdrop_file: [MAX_PATHNAME + 1]u8, 221 + 222 + bg_color: c_int, 223 + fg_color: c_int, 224 + lss_color: c_int, 225 + lse_color: c_int, 226 + lst_color: c_int, 227 + colors_file: [MAX_FILENAME + 1]u8, 228 + 229 + browser_default: c_int, 230 + 231 + repeat_mode: c_int, 232 + next_folder: c_int, 233 + constrain_next_folder: u8, 234 + recursive_dir_insert: c_int, 235 + fade_on_stop: u8, 236 + playlist_shuffle: u8, 237 + warnon_erase_dynplaylist: u8, 238 + keep_current_track_on_replace_playlist: u8, 239 + show_shuffled_adding_options: u8, 240 + show_queue_options: c_int, 241 + album_art: c_int, 242 + rewind_across_tracks: u8, 243 + 244 + playlist_viewer_icons: u8, 245 + playlist_viewer_indices: u8, 246 + playlist_viewer_track_display: c_int, 247 + 248 + talk_menu: u8, 249 + talk_dir: c_int, 250 + talk_dir_clip: u8, 251 + talk_file: c_int, 252 + talk_file_clip: u8, 253 + talk_filetype: u8, 254 + talk_battery_level: u8, 255 + talk_mixer_amp: c_int, 256 + 257 + sort_case: u8, 258 + sort_dir: c_int, 259 + sort_file: c_int, 260 + interpret_numbers: c_int, 261 + 262 + poweroff: c_int, 263 + battery_capacity: c_int, 264 + battery_type: c_int, 265 + spdif_enable: u8, 266 + usb_charging: c_int, 267 + 268 + contrast: c_int, 269 + invert: u8, 270 + flip_display: u8, 271 + cursor_style: c_int, 272 + screen_scroll_step: c_int, 273 + show_path_in_browser: c_int, 274 + offset_out_of_view: u8, 275 + disable_mainmenu_scrolling: u8, 276 + icon_file: [MAX_FILENAME + 1]u8, 277 + viewers_icon_file: [MAX_FILENAME + 1]u8, 278 + font_file: [MAX_FILENAME + 1]u8, 279 + glyphs_to_cache: c_int, 280 + kbd_file: [MAX_FILENAME + 1]u8, 281 + backlight_timeout: c_int, 282 + caption_backlight: u8, 283 + bl_filter_first_keypress: u8, 284 + backlight_timeout_plugged: c_int, 285 + bt_selective_softlock_actions: u8, 286 + bt_selective_softlock_actions_mask: c_int, 287 + bl_selective_actions: u8, 288 + bl_selective_actions_mask: c_int, 289 + backlight_on_button_hold: c_int, 290 + lcd_sleep_after_backlight_off: c_int, 291 + brightness: c_int, 292 + 293 + speaker_mode: c_int, 294 + prevent_skip: u8, 295 + 296 + touch_mode: c_int, 297 + ts_calibration_data: TouchscreenParameter, 298 + 299 + pitch_mode_semitone: u8, 300 + pitch_mode_timestretch: u8, 301 + 302 + usb_hid: u8, 303 + usb_keypad_mode: c_int, 304 + 305 + usb_skip_first_drive: u8, 306 + 307 + ui_vp_config: [64]u8, 308 + player_name: [64]u8, 309 + 310 + compressor_settings: CompressorSettings, 311 + 312 + sleeptimer_duration: c_int, 313 + sleeptimer_on_startup: u8, 314 + keypress_restarts_sleeptimer: u8, 315 + 316 + show_shutdown_message: u8, 317 + 318 + hotkey_wps: c_int, 319 + hotkey_tree: c_int, 320 + 321 + resume_rewind: c_int, 322 + 323 + depth_3d: c_int, 324 + 325 + roll_off: c_int, 326 + 327 + power_mode: c_int, 328 + 329 + keyclick_hardware: u8, 330 + 331 + start_directory: [MAX_PATHNAME + 1]u8, 332 + root_menu_customized: u8, 333 + shortcuts_replaces_qs: u8, 334 + 335 + play_frequency: c_int, 336 + volume_limit: c_int, 337 + 338 + volume_adjust_mode: c_int, 339 + volume_adjust_norm_steps: c_int, 340 + 341 + surround_enabled: c_int, 342 + surround_balance: c_int, 343 + surround_fx1: c_int, 344 + surround_fx2: u8, 345 + surround_method2: u8, 346 + surround_mix: c_int, 347 + 348 + pbe: c_int, 349 + pbe_precut: c_int, 350 + 351 + afr_enabled: c_int, 352 + 353 + governor: c_int, 354 + stereosw_mode: c_int, 355 + }; 356 + 357 + extern var global_settings: UserSettings; 358 + 359 + pub fn get_crossfade_mode() c_int { 360 + return global_settings.crossfade; 361 + }
+127
zig/src/rockbox/tree.zig
··· 1 + const std = @import("std"); 2 + 3 + pub const MAX_PATH = 260; 4 + pub const MAX_DIR_LEVELS = 10; 5 + 6 + const themable_icons = enum(c_int) { 7 + NOICON = -2, 8 + Icon_NOICON = -1, 9 + Icon_Audio, 10 + Icon_Folder, 11 + Icon_Playlist, 12 + Icon_Cursor, 13 + Icon_Wps, 14 + Icon_Firmware, 15 + Icon_Font, 16 + Icon_Language, 17 + Icon_Config, 18 + Icon_Plugin, 19 + Icon_Bookmark, 20 + Icon_Preset, 21 + Icon_Queued, 22 + Icon_Moving, 23 + Icon_Keyboard, 24 + Icon_Reverse_Cursor, 25 + Icon_Questionmark, 26 + Icon_Menu_setting, 27 + Icon_Menu_functioncall, 28 + Icon_Submenu, 29 + Icon_Submenu_Entered, 30 + Icon_Recording, 31 + Icon_Voice, 32 + Icon_General_settings_menu, 33 + Icon_System_menu, 34 + Icon_Playback_menu, 35 + Icon_Display_menu, 36 + Icon_Remote_Display_menu, 37 + Icon_Radio_screen, 38 + Icon_file_view_menu, 39 + Icon_EQ, 40 + Icon_Rockbox, 41 + Icon_Last_Themeable, 42 + }; 43 + 44 + pub const browse_context = extern struct { 45 + dirfilter: c_int, 46 + flags: c_uint, // 'unsigned' is translated to 'c_uint' 47 + title: [*c]const u8, // Nullable C string for the title 48 + icon: themable_icons, // Enum 'themable_icons', assumed to be defined elsewhere 49 + root: [*c]const u8, // Const C string for root directory path 50 + selected: [*c]const u8, // Const C string for selected file name 51 + buf: [*c]u8, // Buffer for the selected file 52 + bufsize: usize, // Size of the buffer (translated to 'usize' for portability) 53 + }; 54 + 55 + const tree_cache = extern struct { 56 + entries_handle: c_int, // Handle to the entry cache 57 + name_buffer_handle: c_int, // Handle to the name cache 58 + max_entries: c_int, // Maximum number of entries in the cache 59 + name_buffer_size: c_int, // Size of the name buffer (in bytes) 60 + }; 61 + 62 + pub const tree_context = extern struct { 63 + currdir: [MAX_PATH]u8, // Fixed-size array for the current directory 64 + dirlevel: i32, // int in C is c_int in Zig 65 + selected_item: i32, // Selected file/id3dbitem index 66 + selected_item_history: [MAX_DIR_LEVELS]c_int, // History of selected items, fixed-size array 67 + 68 + dirfilter: ?*c_int, // Nullable pointer to an int for file use 69 + filesindir: i32, // Number of files in the directory cache 70 + dirsindir: i32, // Directory use 71 + dirlength: i32, // Total number of entries in directory 72 + 73 + currtable: i32, 74 + currextra: i32, 75 + 76 + sort_dir: i32, // Directory sort order 77 + out_of_tree: i32, // Shortcut from elsewhere 78 + cache: tree_cache, // Struct tree_cache, defined elsewhere 79 + 80 + dirfull: bool, 81 + is_browsing: bool, 82 + 83 + browse: ?*browse_context, // Pointer to browse_context, nullable 84 + }; 85 + pub const entry = extern struct { 86 + name: ?*c_char, // Pointer to the name (nullable) 87 + attr: c_int, // FAT attributes + file type flags 88 + time_write: c_uint, // Last write time (unsigned) 89 + customaction: c_int, // Custom action (for database use) 90 + }; 91 + 92 + extern fn tree_init() void; 93 + extern fn rockbox_browse(browse: ?*browse_context) c_int; 94 + extern fn rockbox_browse_at(path: [*]const u8) c_int; 95 + extern fn tree_get_context() *tree_context; 96 + extern fn tree_get_entries(t: *tree_context) *entry; 97 + extern fn tree_get_entry_at(t: *tree_context, index: c_int) *entry; 98 + 99 + pub fn _rockbox_browse() c_int { 100 + var browse: browse_context = .{ 101 + .dirfilter = 0, 102 + .flags = 0, 103 + .title = "demo", 104 + .icon = themable_icons.Icon_NOICON, 105 + .root = "/", 106 + .selected = null, 107 + .buf = null, 108 + .bufsize = 0, 109 + }; 110 + return rockbox_browse(&browse); 111 + } 112 + 113 + pub fn _tree_get_context() tree_context { 114 + const tc = tree_get_context(); 115 + return tc.*; 116 + } 117 + 118 + pub fn _tree_get_entries() *entry { 119 + const tc = tree_get_context(); 120 + return tree_get_entries(tc); 121 + } 122 + 123 + pub fn _tree_get_entry_at(index: c_int) entry { 124 + const tc = tree_get_context(); 125 + const e = tree_get_entry_at(tc, index); 126 + return e.*; 127 + }