A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 227 lines 5.5 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Miscellaneous helper API definitions 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#include "plugin.h" 24#include "mpegplayer.h" 25 26/** Streams **/ 27 28/* Initializes the cursor */ 29void stream_scan_init(struct stream_scan *sk) 30{ 31 dbuf_l2_init(&sk->l2); 32} 33 34/* Ensures direction is -1 or 1 and margin is properly initialized */ 35void stream_scan_normalize(struct stream_scan *sk) 36{ 37 if (sk->dir >= 0) 38 { 39 sk->dir = SSCAN_FORWARD; 40 sk->margin = sk->len; 41 } 42 else if (sk->dir < 0) 43 { 44 sk->dir = SSCAN_REVERSE; 45 sk->margin = 0; 46 } 47} 48 49/* Moves a scan cursor. If amount is positive, the increment is in the scan 50 * direction, otherwise opposite the scan direction */ 51void stream_scan_offset(struct stream_scan *sk, off_t by) 52{ 53 off_t bydir = by*sk->dir; 54 sk->pos += bydir; 55 sk->margin -= bydir; 56 sk->len -= by; 57} 58 59/** Time helpers **/ 60void ts_to_hms(uint32_t pts, struct hms *hms) 61{ 62 hms->frac = pts % TS_SECOND; 63 hms->sec = pts / TS_SECOND; 64 hms->min = hms->sec / 60; 65 hms->hrs = hms->min / 60; 66 hms->sec %= 60; 67 hms->min %= 60; 68} 69 70void hms_format(char *buf, size_t bufsize, struct hms *hms) 71{ 72 /* Only display hours if nonzero */ 73 if (hms->hrs != 0) 74 { 75 rb->snprintf(buf, bufsize, "%u:%02u:%02u", 76 hms->hrs, hms->min, hms->sec); 77 } 78 else 79 { 80 rb->snprintf(buf, bufsize, "%u:%02u", 81 hms->min, hms->sec); 82 } 83} 84 85/** Maths **/ 86uint32_t muldiv_uint32(uint32_t multiplicand, 87 uint32_t multiplier, 88 uint32_t divisor) 89{ 90 if (divisor != 0) 91 { 92 uint64_t prod = (uint64_t)multiplier*multiplicand + divisor/2; 93 94 if ((uint32_t)(prod >> 32) < divisor) 95 return (uint32_t)(prod / divisor); 96 } 97 else if (multiplicand == 0 || multiplier == 0) 98 { 99 return 0; /* 0/0 = 0 : yaya */ 100 } 101 /* else (> 0) / 0 = UINT32_MAX */ 102 103 return UINT32_MAX; /* Saturate */ 104} 105 106 107/** Lists **/ 108 109/* Does the list have any members? */ 110bool list_is_empty(void **list) 111{ 112 return *list == NULL; 113} 114 115/* Is the item inserted into a particular list? */ 116bool list_is_member(void **list, void *item) 117{ 118 return *rb->find_array_ptr(list, item) != NULL; 119} 120 121/* Removes an item from a list - returns true if item was found 122 * and thus removed. */ 123bool list_remove_item(void **list, void *item) 124{ 125 return rb->remove_array_ptr(list, item) != -1; 126} 127 128/* Adds a list item, insert last, if not already present. */ 129void list_add_item(void **list, void *item) 130{ 131 void **item_p = rb->find_array_ptr(list, item); 132 if (*item_p == NULL) 133 *item_p = item; 134} 135 136/* Clears the entire list. */ 137void list_clear_all(void **list) 138{ 139 while (*list != NULL) 140 *list++ = NULL; 141} 142 143/* Enumerate all items in the array, passing each item in turn to the 144 * callback as well as the data value. The current item may be safely 145 * removed. Other changes during enumeration are undefined. The callback 146 * may return 'false' to stop the enumeration early. */ 147void list_enum_items(void **list, 148 list_enum_callback_t callback, 149 void* data) 150{ 151 for (;;) 152 { 153 void *item = *list; 154 155 if (item == NULL) 156 break; 157 158 if (callback != NULL && !callback(item, data)) 159 break; 160 161 if (*list == item) 162 list++; /* Item still there */ 163 } 164} 165 166 167/** System events **/ 168static long mpeg_sysevent_id; 169 170void mpeg_sysevent_clear(void) 171{ 172 mpeg_sysevent_id = 0; 173} 174 175void mpeg_sysevent_set(void) 176{ 177 /* Nonzero and won't invoke anything in default event handler */ 178 mpeg_sysevent_id = ACTION_STD_CANCEL; 179} 180 181long mpeg_sysevent(void) 182{ 183 return mpeg_sysevent_id; 184} 185 186int mpeg_sysevent_callback(int btn, 187 const struct menu_item_ex *menu, 188 struct gui_synclist *this_list) 189{ 190 (void) this_list; 191 switch (btn) 192 { 193 case SYS_USB_CONNECTED: 194 case SYS_POWEROFF: 195 case SYS_REBOOT: 196 mpeg_sysevent_id = btn; 197 return ACTION_STD_CANCEL; 198 } 199 200 return btn; 201 (void)menu; 202} 203 204void mpeg_sysevent_handle(void) 205{ 206 long id = mpeg_sysevent(); 207 if (id != 0) 208 rb->default_event_handler(id); 209} 210 211 212/** Buttons **/ 213 214int mpeg_button_get(int timeout) 215{ 216 int button; 217 218 mpeg_sysevent_clear(); 219 button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) : 220 rb->button_get_w_tmo(timeout); 221 222 /* Produce keyclick */ 223 rb->keyclick_click(true, button); 224 225 return mpeg_sysevent_callback(button, NULL, NULL); 226} 227