A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 231 lines 6.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2006 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 22#include <stdio.h> 23#include "kernel.h" 24#include "general.h" 25#include "file.h" 26#include "dir.h" 27#include "rbpaths.h" 28#include "limits.h" 29#include "stdlib.h" 30#include "string-extra.h" 31#include "time.h" 32#include "timefuncs.h" 33 34int round_value_to_list32(unsigned long value, 35 const unsigned long list[], 36 int count, 37 bool signd) 38{ 39 unsigned long dmin = ULONG_MAX; 40 int idmin = -1, i; 41 42 for (i = 0; i < count; i++) 43 { 44 unsigned long diff; 45 46 if (list[i] == value) 47 { 48 idmin = i; 49 break; 50 } 51 52 if (signd ? ((long)list[i] < (long)value) : (list[i] < value)) 53 diff = value - list[i]; 54 else 55 diff = list[i] - value; 56 57 if (diff < dmin) 58 { 59 dmin = diff; 60 idmin = i; 61 } 62 } 63 64 return idmin; 65} /* round_value_to_list32 */ 66 67/* Number of bits set in src_mask should equal src_list length */ 68int make_list_from_caps32(unsigned long src_mask, 69 const unsigned long *src_list, 70 unsigned long caps_mask, 71 unsigned long *caps_list) 72{ 73 int i, count; 74 unsigned long mask; 75 76 for (mask = src_mask, count = 0, i = 0; 77 mask != 0; 78 src_mask = mask, i++) 79 { 80 unsigned long test_bit; 81 mask &= mask - 1; /* Zero lowest bit set */ 82 test_bit = mask ^ src_mask; /* Isolate the bit */ 83 if (test_bit & caps_mask) /* Add item if caps has test bit set */ 84 caps_list[count++] = src_list ? src_list[i] : (unsigned long)i; 85 } 86 87 return count; 88} /* make_list_from_caps32 */ 89 90/* Create a filename with a number part in a way that the number is 1 91 * higher than the highest numbered file matching the same pattern. 92 * It is allowed that buffer and path point to the same memory location, 93 * saving a strcpy(). Path must always be given without trailing slash. 94 * "num" can point to an int specifying the number to use or NULL or a value 95 * less than zero to number automatically. The final number used will also 96 * be returned in *num. If *num is >= 0 then *num will be incremented by 97 * one. */ 98char *create_numbered_filename(char *buffer, const char *path, 99 const char *prefix, const char *suffix, 100 int numberlen IF_CNFN_NUM_(, int *num)) 101{ 102 DIR *dir; 103 struct dirent *entry; 104 int max_num; 105 int pathlen; 106 int prefixlen = strlen(prefix); 107 int suffixlen = strlen(suffix); 108 109 if (buffer != path) 110 strmemccpy(buffer, path, MAX_PATH); 111 112 pathlen = strlen(buffer); 113 114#ifdef IF_CNFN_NUM 115 if (num && *num >= 0) 116 { 117 /* number specified */ 118 max_num = *num; 119 } 120 else 121#endif 122 { 123 /* automatic numbering */ 124 max_num = 0; 125 126 dir = opendir(pathlen ? buffer : HOME_DIR); 127 if (!dir) 128 return NULL; 129 130 while ((entry = readdir(dir))) 131 { 132 int curr_num, namelen; 133 134 if (strncasecmp((char *)entry->d_name, prefix, prefixlen)) 135 continue; 136 137 namelen = strlen((char *)entry->d_name); 138 if ((namelen <= prefixlen + suffixlen) 139 || strcasecmp((char *)entry->d_name + namelen - suffixlen, suffix)) 140 continue; 141 142 curr_num = atoi((char *)entry->d_name + prefixlen); 143 if (curr_num > max_num) 144 max_num = curr_num; 145 } 146 147 closedir(dir); 148 } 149 150 max_num++; 151 152 snprintf(buffer + pathlen, MAX_PATH - pathlen, "/%s%0*d%s", prefix, 153 numberlen, max_num, suffix); 154 155#ifdef IF_CNFN_NUM 156 if (num) 157 *num = max_num; 158#endif 159 160 return buffer; 161} 162 163 164#if CONFIG_RTC 165/* Create a filename with a date+time part. 166 It is allowed that buffer and path point to the same memory location, 167 saving a strcpy(). Path must always be given without trailing slash. 168 unique_time as true makes the function wait until the current time has 169 changed. */ 170char *create_datetime_filename(char *buffer, const char *path, 171 const char *prefix, const char *suffix, 172 bool unique_time) 173{ 174 struct tm *tm = get_time(); 175 static struct tm last_tm; 176 int pathlen; 177 178 while (unique_time && !memcmp(get_time(), &last_tm, sizeof (struct tm))) 179 sleep(HZ/10); 180 181 last_tm = *tm; 182 183 if (buffer != path) 184 strmemccpy(buffer, path, MAX_PATH); 185 186 pathlen = strlen(buffer); 187 snprintf(buffer + pathlen, MAX_PATH - pathlen, 188 "/%s%02d%02d%02d-%02d%02d%02d%s", prefix, 189 tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, 190 tm->tm_hour, tm->tm_min, tm->tm_sec, suffix); 191 192 return buffer; 193} 194#endif /* CONFIG_RTC */ 195 196/*** 197 ** Compacted pointer lists 198 ** 199 ** N-length list requires N+1 elements to ensure NULL-termination. 200 **/ 201 202/* Find a pointer in a pointer array. Returns the addess of the element if 203 * found or the address of the terminating NULL otherwise. This can be used 204 * to bounds check and add items. */ 205void ** find_array_ptr(void **arr, void *ptr) 206{ 207 void *curr; 208 for (curr = *arr; curr != NULL && curr != ptr; curr = *(++arr)); 209 return arr; 210} 211 212/* Remove a pointer from a pointer array if it exists. Compacts it so that 213 * no gaps exist. Returns 0 on success and -1 if the element wasn't found. */ 214int remove_array_ptr(void **arr, void *ptr) 215{ 216 void *curr; 217 arr = find_array_ptr(arr, ptr); 218 219 if (*arr == NULL) 220 return -1; 221 222 /* Found. Slide up following items. */ 223 do 224 { 225 void **arr1 = arr + 1; 226 *arr++ = curr = *arr1; 227 } 228 while (curr != NULL); 229 230 return 0; 231}