A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 238 lines 7.6 kB view raw
1#include "plugin.h" 2 3#include "fixedpoint.h" 4#include "lib/helper.h" 5#include "lib/pluginlib_exit.h" 6 7 8#include "SDL.h" 9#include "SDL_video.h" 10 11#ifdef COMBINED_SDL 12#error deprecated 13#endif 14 15/* SDL program */ 16extern int my_main(int argc, char *argv[]); 17 18void *audiobuf = NULL; 19 20unsigned int sdl_thread_id, main_thread_id; 21 22bool printf_enabled = true; 23 24static void (*exit_cb)(void) = NULL; 25 26/* sets the exit handler presented to the program */ 27void rbsdl_atexit(void (*cb)(void)) 28{ 29 if(exit_cb) 30 { 31 rb->splash(HZ, "WARNING: multiple exit handlers!"); 32 } 33 exit_cb = cb; 34} 35 36/* called by program */ 37void rb_exit(int rc) 38{ 39 if(rb->thread_self() == main_thread_id) /* rockbox main thread */ 40 exit(rc); 41 else 42 rb->thread_exit(); 43} 44 45/* exit handler, called by rockbox */ 46void cleanup(void) 47{ 48 if(exit_cb) 49 exit_cb(); 50 51 if(exit_cb != SDL_Quit) 52 SDL_Quit(); 53 54#if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR) && !defined(RB_PROFILE) 55#define USE_TIMER 56#endif 57 58#ifdef USE_TIMER 59 /* stop timer callback if there is one, since the memory it 60 * resides in could be overwritten */ 61 rb->timer_unregister(); 62#endif 63 64 if(audiobuf) 65 memset(audiobuf, 0, 4); /* clear */ 66 67 backlight_use_settings(); 68 69#ifdef HAVE_ADJUSTABLE_CPU_FREQ 70 rb->cpu_boost(false); 71#endif 72} 73 74static long main_stack[1024 * 1024 / 4]; /* ie 1 MB */ 75 76int (*main_fn)(int argc, char *argv[]); 77int prog_idx; 78static void main_thread(void) 79{ 80 char *fallback[] = { "/blah", NULL }; 81 82#ifdef COMBINED_SDL 83 char **argv = programs[prog_idx].argv ? programs[prog_idx].argv : fallback; 84 int argc = programs[prog_idx].argv ? programs[prog_idx].argc : 1; 85#else 86 char **argv = fallback; 87 int argc = 1; 88#endif 89 90 int rc = main_fn(argc, argv); 91 if(rc != 0) 92 rb->splash(HZ * 2, SDL_GetError()); 93 94 rb->thread_exit(); 95} 96 97#if defined(CPU_ARM) && !defined(SIMULATOR) 98#define CR_M (1 << 0) /* MMU enable */ 99#define CR_A (1 << 1) /* Alignment abort enable */ 100#define CR_C (1 << 2) /* Dcache enable */ 101#define CR_W (1 << 3) /* Write buffer enable */ 102#define CR_P (1 << 4) /* 32-bit exception handler */ 103#define CR_D (1 << 5) /* 32-bit data address range */ 104#define CR_L (1 << 6) /* Implementation defined */ 105#define CR_B (1 << 7) /* Big endian */ 106#define CR_S (1 << 8) /* System MMU protection */ 107#define CR_R (1 << 9) /* ROM MMU protection */ 108#define CR_F (1 << 10) /* Implementation defined */ 109#define CR_Z (1 << 11) /* Implementation defined */ 110#define CR_I (1 << 12) /* Icache enable */ 111#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */ 112#define CR_RR (1 << 14) /* Round Robin cache replacement */ 113#define CR_L4 (1 << 15) /* LDR pc can set T bit */ 114#define CR_DT (1 << 16) 115#ifdef CONFIG_MMU 116#define CR_HA (1 << 17) /* Hardware management of Access Flag */ 117#else 118#define CR_BR (1 << 17) /* MPU Background region enable (PMSA) */ 119#endif 120#define CR_IT (1 << 18) 121#define CR_ST (1 << 19) 122#define CR_FI (1 << 21) /* Fast interrupt (lower latency mode) */ 123#define CR_U (1 << 22) /* Unaligned access operation */ 124#define CR_XP (1 << 23) /* Extended page tables */ 125#define CR_VE (1 << 24) /* Vectored interrupts */ 126#define CR_EE (1 << 25) /* Exception (Big) Endian */ 127#define CR_TRE (1 << 28) /* TEX remap enable */ 128#define CR_AFE (1 << 29) /* Access flag enable */ 129#define CR_TE (1 << 30) /* Thumb exception enable */ 130 131#define __LINUX_ARM_ARCH__ ARM_ARCH 132 133#if __LINUX_ARM_ARCH__ >= 7 134#define isb(option) __asm__ __volatile__ ("isb " #option : : : "memory") 135#define dsb(option) __asm__ __volatile__ ("dsb " #option : : : "memory") 136#define dmb(option) __asm__ __volatile__ ("dmb " #option : : : "memory") 137#elif defined(CONFIG_CPU_XSC3) || __LINUX_ARM_ARCH__ == 6 138#define isb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \ 139 : : "r" (0) : "memory") 140#define dsb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ 141 : : "r" (0) : "memory") 142#define dmb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \ 143 : : "r" (0) : "memory") 144#elif defined(CONFIG_CPU_FA526) 145#define isb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \ 146 : : "r" (0) : "memory") 147#define dsb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ 148 : : "r" (0) : "memory") 149#define dmb(x) __asm__ __volatile__ ("" : : : "memory") 150#else 151#define isb(x) __asm__ __volatile__ ("" : : : "memory") 152#define dsb(x) __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \ 153 : : "r" (0) : "memory") 154#define dmb(x) __asm__ __volatile__ ("" : : : "memory") 155#endif 156 157static inline unsigned long get_cr(void) 158{ 159 unsigned long val; 160 asm("mrc p15, 0, %0, c1, c0, 0 @ get CR" : "=r" (val) : : "cc"); 161 return val; 162} 163 164static inline void set_cr(unsigned long val) 165{ 166 asm volatile("mcr p15, 0, %0, c1, c0, 0 @ set CR" 167 : : "r" (val) : "cc"); 168 isb(); 169} 170#endif 171 172enum plugin_status plugin_start(const void *param) 173{ 174 (void) param; 175 176#if defined(CPU_ARM) && !defined(SIMULATOR) && (ARM_ARCH >= 5) 177 /* (don't) set alignment trap. Will generate a data abort 178 * exception on ARM. */ 179// set_cr(get_cr() | CR_A); 180#endif 181 182#if 0 183 char c = *((char*)NULL); 184 185 /* test alignment trap */ 186 unsigned int x = 0x12345678; 187 char *p = ((char*)&x) + 1; 188 unsigned short *p2 = (unsigned short*)p; 189 rb->splashf(HZ, "%04x, %02x%02x", *p2, *(p+1), *p); 190#endif 191 192 /* don't confuse this with the main SDL thread! */ 193 main_thread_id = rb->thread_self(); 194 195 /* we always use the audio buffer */ 196 size_t sz; 197 audiobuf = rb->plugin_get_audio_buffer(&sz); 198#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 199 /* We are loaded as an overlay towards the end of the audio 200 * buffer. We must take care not to overwrite ourselves. */ 201 if ((uintptr_t)audiobuf < (uintptr_t)plugin_start_addr) 202 { 203 uint32_t tmp_size = (uintptr_t)plugin_start_addr - (uintptr_t)audiobuf; 204 sz = MIN(sz, tmp_size); 205 } 206#endif 207 208 /* wipe sig */ 209 rb->memset(audiobuf, 0, sz); 210 if(init_memory_pool(sz, audiobuf) == (size_t) -1) 211 { 212 rb->splashf(HZ*2, "TLSF init failed!"); 213 return PLUGIN_ERROR; 214 } 215 216 main_fn = my_main; 217 218#ifdef HAVE_ADJUSTABLE_CPU_FREQ 219 rb->cpu_boost(true); 220#endif 221 222 backlight_ignore_timeout(); 223 224 /* set the real exit handler */ 225#undef rb_atexit 226 rb_atexit(cleanup); 227 228 /* make a new thread to use a bigger stack and higher priority than otherwise accessible */ 229 sdl_thread_id = rb->create_thread(main_thread, main_stack, 230 sizeof(main_stack), 0, "sdl_main" 231 IF_PRIO(, PRIORITY_USER_INTERFACE) // we need other threads still 232 IF_COP(, CPU)); 233 rb->thread_wait(sdl_thread_id); 234 235 rb->sleep(HZ); /* wait a second in case there's an error message on screen */ 236 237 return PLUGIN_OK; 238}