// 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 (); }
// this function executes server-side commands only // must be called only from within server // -1 error, program must exit with error code -1 // 0 proceed normally as nothing happened // 1 no error, but program must exit with error code 0 // 2 don't load playlist on startup // when executed in remote server -- error code will be ignored int server_exec_command_line (const char *cmdline, int len, char *sendback, int sbsize) { if (sendback) { sendback[0] = 0; } const char *parg = cmdline; const char *pend = cmdline + len; int queue = 0; while (parg < pend) { if (strlen (parg) >= 2 && parg[0] == '-' && parg[1] != '-') { parg += strlen (parg); parg++; return 0; // running under osx debugger? } else if (!strcmp (parg, "--nowplaying")) { parg += strlen (parg); parg++; if (parg >= pend) { const char *errtext = "--nowplaying expects format argument"; if (sendback) { snprintf (sendback, sbsize, "error %s\n", errtext); return 0; } else { trace_err ("%s\n", errtext); return -1; } } char out[2048]; playItem_t *curr = streamer_get_playing_track (); if (curr) { pl_format_title (curr, -1, out, sizeof (out), -1, parg); pl_item_unref (curr); } else { strcpy (out, "nothing"); } if (sendback) { snprintf (sendback, sbsize, "nowplaying %s", out); } else { fwrite (out, 1, strlen (out), stdout); return 1; // exit } } else if (!strcmp (parg, "--nowplaying-tf")) { parg += strlen (parg); parg++; if (parg >= pend) { const char *errtext = "--nowplaying-tf expects format argument"; if (sendback) { snprintf (sendback, sbsize, "error %s\n", errtext); return 0; } else { trace_err ("%s\n", errtext); return -1; } } char out[2048]; playItem_t *curr = streamer_get_playing_track (); char *script = tf_compile (parg); if (script) { ddb_tf_context_t ctx = { ._size = sizeof (ddb_tf_context_t), .it = (DB_playItem_t *)curr, }; tf_eval (&ctx, script, out, sizeof (out)); tf_free (script); } else { *out = 0; } if (curr) { pl_item_unref (curr); } if (sendback) { snprintf (sendback, sbsize, "nowplaying %s", out); } else { fwrite (out, 1, strlen (out), stdout); return 1; // exit } } else if (!strcmp (parg, "--next")) {