A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 315 lines 9.8 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2014 by Michael Sevakis 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#ifndef _DIRCACHE_REDIRECT_H_ 22 23#include "rbpaths.h" 24#include "pathfuncs.h" 25#include "dir.h" 26#include "dircache.h" 27#include "file.h" 28 29#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) 30#include "rb-loader.h" 31#include "multiboot.h" 32#include "bootdata.h" 33#endif 34 35#ifndef RB_ROOT_VOL_HIDDEN 36#define RB_ROOT_VOL_HIDDEN(v) (0 == 0) 37#endif 38#ifndef RB_ROOT_CONTENTS_DIR 39#define RB_ROOT_CONTENTS_DIR "/" 40#endif 41/*** 42 ** Internal redirects that depend upon whether or not dircache is made 43 ** 44 ** Some stuff deals with it, some doesn't right now. This is a nexus point.. 45 **/ 46 47/** File binding **/ 48 49static inline void get_rootinfo_internal(struct file_base_info *infop) 50{ 51#ifdef HAVE_DIRCACHE 52 dircache_get_rootinfo(infop); 53#else 54 (void)infop; 55#endif 56} 57 58static inline void fileobj_bind_file(struct file_base_binding *bindp) 59{ 60#ifdef HAVE_DIRCACHE 61 dircache_bind_file(bindp); 62#else 63 file_binding_insert_last(bindp); 64#endif 65} 66 67static inline void fileobj_unbind_file(struct file_base_binding *bindp) 68{ 69#ifdef HAVE_DIRCACHE 70 dircache_unbind_file(bindp); 71#else 72 file_binding_remove(bindp); 73#endif 74} 75 76 77/** File event handlers **/ 78 79static inline void fileop_onopen_internal(struct filestr_base *stream, 80 struct file_base_info *srcinfop, 81 unsigned int callflags) 82{ 83 fileobj_fileop_open(stream, srcinfop, callflags); 84} 85 86static inline void fileop_onclose_internal(struct filestr_base *stream) 87{ 88 fileobj_fileop_close(stream); 89} 90 91static inline void fileop_oncreate_internal(struct filestr_base *stream, 92 struct file_base_info *srcinfop, 93 unsigned int callflags, 94 struct file_base_info *dirinfop, 95 const char *basename) 96{ 97#ifdef HAVE_DIRCACHE 98 dircache_dcfile_init(&srcinfop->dcfile); 99#endif 100 fileobj_fileop_create(stream, srcinfop, callflags); 101#ifdef HAVE_DIRCACHE 102 struct dirinfo_native din; 103 fill_dirinfo_native(&din); 104 dircache_fileop_create(dirinfop, stream->bindp, basename, &din); 105#endif 106 (void)dirinfop; (void)basename; 107} 108 109static inline void fileop_onremove_internal(struct filestr_base *stream, 110 struct file_base_info *oldinfop) 111{ 112 fileobj_fileop_remove(stream, oldinfop); 113#ifdef HAVE_DIRCACHE 114 dircache_fileop_remove(stream->bindp); 115#endif 116} 117 118static inline void fileop_onrename_internal(struct filestr_base *stream, 119 struct file_base_info *oldinfop, 120 struct file_base_info *dirinfop, 121 const char *basename) 122{ 123 fileobj_fileop_rename(stream, oldinfop); 124#ifdef HAVE_DIRCACHE 125 dircache_fileop_rename(dirinfop, stream->bindp, basename); 126#endif 127 (void)dirinfop; (void)basename; 128} 129 130static inline void fileop_onsync_internal(struct filestr_base *stream) 131{ 132 fileobj_fileop_sync(stream); 133#ifdef HAVE_DIRCACHE 134 struct dirinfo_native din; 135 fill_dirinfo_native(&din); 136 dircache_fileop_sync(stream->bindp, &din); 137#endif 138} 139 140#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) 141static inline bool multiboot_is_boot_volume(int volume) 142{ 143 if (boot_data.version == 0) 144 { 145 /* 146 * Version 0 bootloaders just pass the volume number, but that's 147 * dynamically assigned and sometimes differs by the time we get 148 * into the firmware. So we can't rely on the volume passed by 149 * the bootloader. 150 */ 151#if CONFIG_CPU == X1000 152 /* The affected X1000 players only have one drive to begin with */ 153 return volume_drive(volume) == 0; 154#else 155 /* FIXME: Anything else that can get here is a Sansa. */ 156 return volume_drive(volume) == boot_data._boot_volume || 157 volume == boot_data._boot_volume; 158#endif 159 } 160 161 if (boot_data.version == 1) 162 { 163 /* 164 * Since version 1 the bootloader passes drive and partition 165 * number which unambiguously identifies the boot volume. 166 */ 167 return volume_drive(volume) == boot_data.boot_drive && 168 volume_partition(volume) == boot_data.boot_partition; 169 } 170 171 return false; 172} 173#endif 174 175static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) 176{ 177#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER) 178 char path[VOL_MAX_LEN+2]; 179 char rtpath[MAX_PATH / 2]; 180 make_volume_root(volume, path); 181 182 if (boot_data_valid) 183 { 184 /* we need to mount the drive before we can access it */ 185 root_mount_path(path, 0); /* root could be different folder don't hide */ 186 187 if (multiboot_is_boot_volume(IF_MV_VOL(volume))) 188 { 189 /* get the full path to the BOOTFILE 190 ie. /<0>/redirectdir/.rockbox/rockbox.ext */ 191 int rtlen = get_redirect_dir(rtpath, sizeof(rtpath), 192 volume, BOOTDIR, BOOTFILE); 193 194 if (rtlen <= 0 || rtlen >= (int) sizeof(rtpath)) 195 rtlen = 0; /* path too long or sprintf error */ 196 else if (file_exists(rtpath)) 197 { 198 rtlen = get_redirect_dir(rtpath, sizeof(rtpath), volume, "", ""); 199 while (rtlen > 0 && rtpath[--rtlen] == PATH_SEPCH) 200 rtpath[rtlen] = '\0'; /* remove separators */ 201 } 202 else 203 rtlen = 0; /* No BOOTFILE found */ 204 205#if 0 /*removed, causes issues with playback for now?*/ 206 if (rtlen <= 0 || rtpath[rtlen] == VOL_END_TOK) 207 root_unmount_volume(volume); /* unmount so root can be hidden*/ 208#endif 209 if (rtlen <= 0 || root_mount_path(rtpath, NSITEM_CONTENTS) != 0) 210 { /* Error occurred, card removed? Set root to default */ 211 boot_data_valid = false; 212 root_unmount_volume(volume); /* unmount so root can be hidden*/ 213 goto standard_redirect; 214 } 215 } 216 } 217 else 218 { 219standard_redirect: 220 root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); 221 if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) 222 root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); 223 } 224#elif defined(HAVE_MULTIVOLUME) 225 char path[VOL_MAX_LEN+2]; 226 make_volume_root(volume, path); 227 root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); 228 if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false)) 229 root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); 230#else 231 const char *path = PATH_ROOTSTR; 232 root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0); 233 root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS); 234#endif /* HAVE_MULTIBOOT */ 235 236#ifdef HAVE_DIRCACHE 237 dircache_mount(); 238#endif 239} 240 241static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) 242{ 243#ifdef HAVE_DIRCACHE 244 /* First, to avoid update of something about to be destroyed anyway */ 245 dircache_unmount(IF_MV(volume)); 246#endif 247 root_unmount_volume(IF_MV(volume)); 248 fileobj_mgr_unmount(IF_MV(volume)); 249} 250 251static inline void fileop_onunmount_internal(struct filestr_base *stream) 252{ 253 254 if (stream->flags & FD_WRITE) 255 force_close_writer_internal(stream); /* try to save stuff */ 256 else 257 fileop_onclose_internal(stream); /* just readers, bye */ 258} 259 260 261/** Directory reading **/ 262 263static inline int readdir_dirent(struct filestr_base *stream, 264 struct dirscan_info *scanp, 265 struct DIRENT *entry) 266{ 267#ifdef HAVE_DIRCACHE 268 return dircache_readdir_dirent(stream, scanp, entry); 269#else 270 return uncached_readdir_dirent(stream, scanp, entry); 271#endif 272} 273 274static inline void rewinddir_dirent(struct dirscan_info *scanp) 275{ 276#ifdef HAVE_DIRCACHE 277 dircache_rewinddir_dirent(scanp); 278#else 279 uncached_rewinddir_dirent(scanp); 280#endif 281} 282 283static inline int readdir_internal(struct filestr_base *stream, 284 struct file_base_info *infop, 285 struct fat_direntry *fatent) 286{ 287#ifdef HAVE_DIRCACHE 288 return dircache_readdir_internal(stream, infop, fatent); 289#else 290 return uncached_readdir_internal(stream, infop, fatent); 291#endif 292} 293 294static inline void rewinddir_internal(struct file_base_info *infop) 295{ 296#ifdef HAVE_DIRCACHE 297 dircache_rewinddir_internal(infop); 298#else 299 uncached_rewinddir_internal(infop); 300#endif 301} 302 303 304/** Misc. stuff **/ 305 306static inline struct fat_direntry *get_dir_fatent_dircache(void) 307{ 308#ifdef HAVE_DIRCACHE 309 return get_dir_fatent(); 310#else 311 return NULL; 312#endif 313} 314 315#endif /* _DIRCACHE_REDIRECT_H_ */