A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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 */