A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 262 lines 8.3 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Miscellaneous helper API declarations 11 * 12 * Copyright (c) 2007 Michael Sevakis 13 * 14 * This program is free software; you can redistribute it and/or 15 * modify it under the terms of the GNU General Public License 16 * as published by the Free Software Foundation; either version 2 17 * of the License, or (at your option) any later version. 18 * 19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 20 * KIND, either express or implied. 21 * 22 ****************************************************************************/ 23#ifndef MPEG_MISC_H 24#define MPEG_MISC_H 25 26/* Miscellaneous helpers */ 27#ifndef ALIGNED_ATTR 28#define ALIGNED_ATTR(x) __attribute__((aligned(x))) 29#endif 30 31#include "disk_buf.h" 32 33/* Generic states for when things are too simple to care about naming them */ 34enum state_enum 35{ 36 STATE0 = 0, 37 STATE1, 38 STATE2, 39 STATE3, 40 STATE4, 41 STATE5, 42 STATE6, 43 STATE7, 44 STATE8, 45 STATE9, 46}; 47 48/* Macros for comparing memory bytes to a series of constant bytes in an 49 efficient manner - evaluate to true if corresponding bytes match */ 50#if defined (CPU_ARM) 51/* ARM must load 32-bit values at addres % 4 == 0 offsets but this data 52 isn't aligned nescessarily, so just byte compare */ 53#define CMP_3_CONST(_a, _b) \ 54 ({ int _x; \ 55 asm volatile ( \ 56 BEGIN_ARM_ASM_SYNTAX_UNIFIED \ 57 "ldrb %[x], [%[a], #0] \n" \ 58 "eors %[x], %[x], %[b0] \n" \ 59 "ldrbeq %[x], [%[a], #1] \n" \ 60 "eorseq %[x], %[x], %[b1] \n" \ 61 "ldrbeq %[x], [%[a], #2] \n" \ 62 "eorseq %[x], %[x], %[b2] \n" \ 63 END_ARM_ASM_SYNTAX_UNIFIED \ 64 : [x]"=&r"(_x) \ 65 : [a]"r"(_a), \ 66 [b0]"i"(((_b) >> 24) & 0xff), \ 67 [b1]"i"(((_b) >> 16) & 0xff), \ 68 [b2]"i"(((_b) >> 8) & 0xff) \ 69 ); \ 70 _x == 0; }) 71 72#define CMP_4_CONST(_a, _b) \ 73 ({ int _x; \ 74 asm volatile ( \ 75 BEGIN_ARM_ASM_SYNTAX_UNIFIED \ 76 "ldrb %[x], [%[a], #0] \n" \ 77 "eors %[x], %[x], %[b0] \n" \ 78 "ldrbeq %[x], [%[a], #1] \n" \ 79 "eorseq %[x], %[x], %[b1] \n" \ 80 "ldrbeq %[x], [%[a], #2] \n" \ 81 "eorseq %[x], %[x], %[b2] \n" \ 82 "ldrbeq %[x], [%[a], #3] \n" \ 83 "eorseq %[x], %[x], %[b3] \n" \ 84 END_ARM_ASM_SYNTAX_UNIFIED \ 85 : [x]"=&r"(_x) \ 86 : [a]"r"(_a), \ 87 [b0]"i"(((_b) >> 24) & 0xff), \ 88 [b1]"i"(((_b) >> 16) & 0xff), \ 89 [b2]"i"(((_b) >> 8) & 0xff), \ 90 [b3]"i"(((_b) ) & 0xff) \ 91 ); \ 92 _x == 0; }) 93 94#elif defined (CPU_COLDFIRE) 95/* Coldfire can just load a 32 bit value at any offset but ASM is not the 96 best way to integrate this with the C code */ 97#define CMP_3_CONST(a, b) \ 98 (((*(uint32_t *)(a) >> 8) == ((uint32_t)(b) >> 8))) 99 100#define CMP_4_CONST(a, b) \ 101 ((*(uint32_t *)(a) == (b))) 102 103#else 104/* Don't know what this is - use bytewise comparisons */ 105#define CMP_3_CONST(a, b) \ 106 (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \ 107 ((a)[1] ^ (((b) >> 16) & 0xff)) | \ 108 ((a)[2] ^ (((b) >> 8) & 0xff)) ) == 0) 109 110#define CMP_4_CONST(a, b) \ 111 (( ((a)[0] ^ (((b) >> 24) & 0xff)) | \ 112 ((a)[1] ^ (((b) >> 16) & 0xff)) | \ 113 ((a)[2] ^ (((b) >> 8) & 0xff)) | \ 114 ((a)[3] ^ (((b) ) & 0xff)) ) == 0) 115#endif /* CPU_* */ 116 117 118/** Streams **/ 119 120/* Convert PTS/DTS ticks to our clock ticks */ 121#define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / TS_SECOND) 122/* Convert our clock ticks to PTS/DTS ticks */ 123#define TICKS_TO_TS(ts) ((uint64_t)TS_SECOND*(ts) / CLOCK_RATE) 124/* Convert timecode ticks to our clock ticks */ 125#define TC_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / TC_SECOND) 126/* Convert our clock ticks to timecode ticks */ 127#define TICKS_TO_TC(stamp) ((uint64_t)TC_SECOND*(stamp) / CLOCK_RATE) 128/* Convert timecode ticks to timestamp ticks */ 129#define TC_TO_TS(stamp) ((stamp) / 600) 130 131/* 132 * S = start position, E = end position 133 * 134 * pos: 135 * initialize to search start position (S) 136 * 137 * len: 138 * initialize to = ABS(S-E) 139 * scanning = remaining bytes in scan direction 140 * 141 * dir: 142 * scan direction; >= 0 == forward, < 0 == reverse 143 * 144 * margin: 145 * amount of data to right of cursor - initialize by stream_scan_normalize 146 * 147 * data: 148 * Extra data used/returned by the function implemented 149 * 150 * Forward scan: 151 * S pos E 152 * | *<-margin->| dir-> 153 * | |<--len--->| 154 * 155 * Reverse scan: 156 * E pos S 157 * |<-len->*<-margin->| <-dir 158 * | | | 159 */ 160struct stream_scan 161{ 162 off_t pos; /* Initial scan position (file offset) */ 163 ssize_t len; /* Maximum length of scan */ 164 off_t dir; /* Direction - >= 0; forward, < 0 backward */ 165 ssize_t margin; /* Used by function to track margin between position and data end */ 166 intptr_t data; /* */ 167 struct dbuf_l2_cache l2; 168}; 169 170#define SSCAN_REVERSE (-1) 171#define SSCAN_FORWARD 1 172 173/* Initializes the cursor */ 174void stream_scan_init(struct stream_scan *sk); 175 176/* Ensures direction is -1 or 1 and margin is properly initialized */ 177void stream_scan_normalize(struct stream_scan *sk); 178 179/* Moves a scan cursor. If amount is positive, the increment is in the scan 180 * direction, otherwise opposite the scan direction */ 181void stream_scan_offset(struct stream_scan *sk, off_t by); 182 183/** Time helpers **/ 184struct hms 185{ 186 unsigned int hrs; 187 unsigned int min; 188 unsigned int sec; 189 unsigned int frac; 190}; 191 192void ts_to_hms(uint32_t ts, struct hms *hms); 193void hms_format(char *buf, size_t bufsize, struct hms *hms); 194 195/** Maths **/ 196 197/* Moving average */ 198#define AVERAGE(var, x, count) \ 199 ({ typeof (count) _c = (count); \ 200 ((var) * (_c-1) + (x)) / (_c); }) 201 202/* Multiply two unsigned 32-bit integers yielding a 64-bit result and 203 * divide by another unsigned 32-bit integer to yield a 32-bit result. 204 * Rounds to nearest with saturation. */ 205uint32_t muldiv_uint32(uint32_t multiplicand, 206 uint32_t multiplier, 207 uint32_t divisor); 208 209 210/** Lists **/ 211 212/* Does the list have any members? */ 213bool list_is_empty(void **list); 214 215/* Is the item inserted into a particular list? */ 216bool list_is_member(void **list, void *item); 217 218/* Removes an item from a list - returns true if item was found 219 * and thus removed. */ 220bool list_remove_item(void **list, void *item); 221 222/* Adds a list item, insert last, if not already present. */ 223void list_add_item(void **list, void *item); 224 225/* Clears the entire list. */ 226void list_clear_all(void **list); 227 228/* Enumerate all items in the array. */ 229typedef bool (*list_enum_callback_t)(void *item, void* data); 230 231void list_enum_items(void **list, 232 list_enum_callback_t callback, 233 void *data); 234 235 236/** System events **/ 237 238/* Clear event */ 239void mpeg_sysevent_clear(void); 240 241/* Set to ACTION_STD_CANCEL */ 242void mpeg_sysevent_set(void); 243 244/* Get event code */ 245long mpeg_sysevent(void); 246 247/* Call with a system event code and used as menu callback */ 248int mpeg_sysevent_callback(int btn, const struct menu_item_ex *menu, 249 struct gui_synclist *this_list); 250 251/* Handle recorded event */ 252void mpeg_sysevent_handle(void); 253 254 255/** Buttons **/ 256 257/* Get button codes while remembering important events for later 258 * processing; return of ACTION_STD_CANCEL means plugin should 259 * abort and handle the event */ 260int mpeg_button_get(int timeout); 261 262#endif /* MPEG_MISC_H */