const char * pl_find_meta (playItem_t *it, const char *key) { pl_lock (); DB_metaInfo_t *m = it->meta; if (key && key[0] == ':') { // try to find an override while (m) { if (m->key[0] == '!' && !strcasecmp (key+1, m->key+1)) { pl_unlock (); return m->value; } m = m->next; } } m = it->meta; while (m) { if (!strcasecmp (key, m->key)) { pl_unlock (); return m->value; } m = m->next; } pl_unlock (); return NULL; }
playItem_t * playqueue_getnext (void) { pl_lock (); if (playqueue_count > 0) { playItem_t *val = playqueue[0]; pl_item_ref (val); pl_unlock (); return val; } pl_unlock (); return NULL; }
int playqueue_test (playItem_t *it) { pl_lock (); for (int i = 0; i < playqueue_count; i++) { if (playqueue[i] == it) { pl_unlock (); return i; } } pl_unlock (); return -1; }
int pl_get_meta_raw (playItem_t *it, const char *key, char *val, int size) { *val = 0; pl_lock (); const char *v = pl_find_meta_raw (it, key); if (!v) { pl_unlock (); return 0; } strncpy (val, v, size); pl_unlock (); return 1; }
const char * pl_find_meta_raw (playItem_t *it, const char *key) { pl_lock (); DB_metaInfo_t *m = it->meta; while (m) { if (!strcasecmp (key, m->key)) { pl_unlock (); return m->value; } m = m->next; } pl_unlock (); return NULL; }
void playqueue_remove (playItem_t *it) { pl_lock (); for (;;) { int i; for (i = 0; i < playqueue_count; i++) { if (playqueue[i] == it) { if (i < playqueue_count-1) { memmove (&playqueue[i], &playqueue[i+1], (playqueue_count-i) * sizeof (playItem_t*)); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); } else { playqueue_send_trackinfochanged (it); } pl_item_unref (it); playqueue_count--; break; } } if (i == playqueue_count) { break; } } pl_unlock (); }
int pl_meta_exists (playItem_t *it, const char *key) { pl_lock (); const char *v = pl_find_meta (it, key); pl_unlock (); return v ? 1 : 0; }
float pl_find_meta_float (playItem_t *it, const char *key, float def) { pl_lock (); const char *val = pl_find_meta (it, key); float res = val ? atof (val) : def; pl_unlock (); return res; }
int pl_find_meta_int (playItem_t *it, const char *key, int def) { pl_lock (); const char *val = pl_find_meta (it, key); int res = val ? atoi (val) : def; pl_unlock (); return res; }
playItem_t * playqueue_get_item (int i) { pl_lock (); playItem_t *it = playqueue[i]; pl_item_ref (it); pl_unlock (); return it; }
void pl_append_meta (playItem_t *it, const char *key, const char *value) { pl_lock (); const char *old = pl_find_meta_raw (it, key); if (old && (!strcasecmp (key, "cuesheet") || !strcasecmp (key, "log"))) { pl_unlock (); return; } size_t newlen = strlen (value); if (!old) { pl_add_meta (it, key, value); } else { // check for duplicate data const char *str = old; int len; while (str) { char *next = strchr (str, '\n'); if (next) { len = next - str; next++; } else { len = strlen (str); } if (len == newlen && !memcmp (str, value, len)) { pl_unlock (); return; } str = next; } int sz = strlen (old) + newlen + 2; char out[sz]; snprintf (out, sz, "%s\n%s", old, value); pl_replace_meta (it, key, out); } pl_unlock (); }
void playqueue_insert_at (int n, playItem_t *it) { if (playqueue_count == PLAYQUEUE_SIZE) { trace ("playqueue is full\n"); return; } pl_lock (); if (n == playqueue_count) { playqueue_push(it); pl_unlock (); return; } memmove (playqueue+n+1, playqueue+n, (playqueue_count - n) * sizeof (playItem_t *)); playqueue[n] = it; pl_item_ref (it); playqueue_count++; pl_unlock (); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); }
void playqueue_pop (void) { if (!playqueue_count) { return; } pl_lock (); if (playqueue_count == 1) { playqueue_count = 0; playqueue_send_trackinfochanged (playqueue[0]); pl_item_unref (playqueue[0]); pl_unlock (); return; } playItem_t *it = playqueue[0]; memmove (&playqueue[0], &playqueue[1], (playqueue_count-1) * sizeof (playItem_t*)); playqueue_count--; pl_item_unref (it); pl_unlock (); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); }
void playqueue_clear (void) { pl_lock (); for (int i = 0; i < playqueue_count; i++) { pl_item_unref (playqueue[i]); playqueue[i] = NULL; } playqueue_count = 0; pl_unlock (); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); }
void playqueue_remove_nth (int n) { pl_lock (); playItem_t *it = playqueue[n]; if (n < playqueue_count-1) { memmove (playqueue + n, playqueue + n + 1, (playqueue_count-n) * sizeof (playItem_t*)); } playqueue_count--; pl_item_unref (it); pl_unlock (); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_PLAYQUEUE, 0); }
int playqueue_push (playItem_t *it) { if (playqueue_count == PLAYQUEUE_SIZE) { trace ("playqueue is full\n"); return -1; } pl_lock (); pl_item_ref (it); playqueue[playqueue_count++] = it; pl_unlock (); playqueue_send_trackinfochanged (it); return 0; }
void plt_sort_random (playlist_t *playlist, int iter) { if (!playlist->head[iter] || !playlist->head[iter]->next[iter]) { return; } pl_lock (); const int playlist_count = playlist->count[iter]; playItem_t **array = malloc (playlist_count * sizeof (playItem_t *)); int idx = 0; for (playItem_t *it = playlist->head[iter]; it; it = it->next[iter], idx++) { array[idx] = it; } //randomize array for (int swap_a = 0; swap_a < playlist_count - 1; swap_a++) { //select random item above swap_a-1 const int swap_b = swap_a + (rand() / (float)RAND_MAX * (playlist_count - swap_a)); //swap a with b playItem_t* const swap_temp = array[swap_a]; array[swap_a] = array[swap_b]; array[swap_b] = swap_temp; } playItem_t *prev = NULL; playlist->head[iter] = 0; for (idx = 0; idx < playlist->count[iter]; idx++) { playItem_t *it = array[idx]; it->prev[iter] = prev; it->next[iter] = NULL; if (!prev) { playlist->head[iter] = it; } else { prev->next[iter] = it; } prev = it; } playlist->tail[iter] = array[playlist->count[iter]-1]; free (array); plt_modified (playlist); pl_unlock (); }
void pl_delete_metadata (playItem_t *it, DB_metaInfo_t *meta) { pl_lock (); DB_metaInfo_t *prev = NULL; DB_metaInfo_t *m = it->meta; while (m) { if (m == meta) { if (prev) { prev->next = m->next; } else { it->meta = m->next; } metacache_remove_string (m->key); metacache_remove_string (m->value); free (m); break; } prev = m; m = m->next; } pl_unlock (); }
void pl_delete_meta (playItem_t *it, const char *key) { pl_lock (); DB_metaInfo_t *prev = NULL; DB_metaInfo_t *m = it->meta; while (m) { if (!strcasecmp (key, m->key)) { if (prev) { prev->next = m->next; } else { it->meta = m->next; } metacache_remove_string (m->key); metacache_remove_string (m->value); free (m); break; } prev = m; m = m->next; } pl_unlock (); }
// version 0: title formatting v1 // version 1: title formatting v2 void plt_sort_internal (playlist_t *playlist, int iter, int id, const char *format, int order, int version) { if (order == DDB_SORT_RANDOM) { plt_sort_random (playlist, iter); return; } int ascending = order == DDB_SORT_DESCENDING ? 0 : 1; if (format == NULL || id == DB_COLUMN_FILENUMBER || !playlist->head[iter] || !playlist->head[iter]->next[iter]) { return; } pl_lock (); struct timeval tm1; gettimeofday (&tm1, NULL); pl_sort_ascending = ascending; trace ("ascending: %d\n", ascending); pl_sort_id = id; pl_sort_version = version; if (version == 0) { pl_sort_format = format; pl_sort_tf_bytecode = NULL; } else { pl_sort_format = NULL; pl_sort_tf_bytecode = tf_compile (format); pl_sort_tf_ctx._size = sizeof (pl_sort_tf_ctx); pl_sort_tf_ctx.it = NULL; pl_sort_tf_ctx.plt = (ddb_playlist_t *)playlist; pl_sort_tf_ctx.idx = -1; pl_sort_tf_ctx.id = id; } if (format && id == -1 && ((version == 0 && !strcmp (format, "%l")) || (version == 1 && !strcmp (format, "%length%"))) ) { pl_sort_is_duration = 1; } else { pl_sort_is_duration = 0; } if (format && id == -1 && ((version == 0 && !strcmp (format, "%n")) || (version == 1 && (!strcmp (format, "%track number%") || !strcmp (format, "%tracknumber%")))) ) { pl_sort_is_track = 1; } else { pl_sort_is_track = 0; } playItem_t **array = malloc (playlist->count[iter] * sizeof (playItem_t *)); int idx = 0; for (playItem_t *it = playlist->head[iter]; it; it = it->next[iter], idx++) { array[idx] = it; } qsort (array, playlist->count[iter], sizeof (playItem_t *), qsort_cmp_func); playItem_t *prev = NULL; playlist->head[iter] = 0; for (idx = 0; idx < playlist->count[iter]; idx++) { playItem_t *it = array[idx]; it->prev[iter] = prev; it->next[iter] = NULL; if (!prev) { playlist->head[iter] = it; } else { prev->next[iter] = it; } prev = it; } playlist->tail[iter] = array[playlist->count[iter]-1]; free (array); struct timeval tm2; gettimeofday (&tm2, NULL); int ms = (tm2.tv_sec*1000+tm2.tv_usec/1000) - (tm1.tv_sec*1000+tm1.tv_usec/1000); trace ("sort time: %f seconds\n", ms / 1000.f); plt_modified (playlist); if (version == 0) { pl_sort_format = NULL; } if (version == 1) { tf_free (pl_sort_tf_bytecode); pl_sort_tf_bytecode = NULL; memset (&pl_sort_tf_ctx, 0, sizeof (pl_sort_tf_ctx)); } pl_unlock (); }