static int pl_sort_compare_str (playItem_t *a, playItem_t *b) { if (pl_sort_is_duration) { float dur_a = a->_duration * 100000; float dur_b = b->_duration * 100000; return !pl_sort_ascending ? dur_b - dur_a : dur_a - dur_b; } else if (pl_sort_is_track) { int t1; int t2; const char *t; t = pl_find_meta_raw (a, "track"); if (t && !isdigit (*t)) { t1 = 999999; } else { t1 = t ? atoi (t) : -1; } t = pl_find_meta_raw (b, "track"); if (t && !isdigit (*t)) { t2 = 999999; } else { t2 = t ? atoi (t) : -1; } return !pl_sort_ascending ? t2 - t1 : t1 - t2; } else { char tmp1[1024]; char tmp2[1024]; if (pl_sort_version == 0) { pl_format_title (a, -1, tmp1, sizeof (tmp1), pl_sort_id, pl_sort_format); pl_format_title (b, -1, tmp2, sizeof (tmp2), pl_sort_id, pl_sort_format); } else { pl_sort_tf_ctx.id = pl_sort_id; pl_sort_tf_ctx.it = (ddb_playItem_t *)a; tf_eval(&pl_sort_tf_ctx, pl_sort_tf_bytecode, tmp1, sizeof(tmp1)); pl_sort_tf_ctx.it = (ddb_playItem_t *)b; tf_eval(&pl_sort_tf_ctx, pl_sort_tf_bytecode, tmp2, sizeof(tmp2)); } int res = strcasecmp_numeric (tmp1, tmp2); if (!pl_sort_ascending) { res = -res; } return res; } }
// 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")) {
// 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 uint8_t *parg = (const uint8_t *)cmdline; const uint8_t *pend = cmdline + len; int queue = 0; while (parg < pend) { const char *parg_c = parg; 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) { if (sendback) { snprintf (sendback, sbsize, "error --nowplaying expects format argument\n"); return 0; } else { fprintf (stderr, "--nowplaying expects format argument\n"); return -1; } } if (sendback) { playItem_t *curr = streamer_get_playing_track (); DB_fileinfo_t *dec = streamer_get_current_fileinfo (); if (curr && dec) { const char np[] = "nowplaying "; memcpy (sendback, np, sizeof (np)-1); pl_format_title (curr, -1, sendback+sizeof(np)-1, sbsize-sizeof(np)+1, -1, parg); } else { strcpy (sendback, "nowplaying nothing"); } if (curr) { pl_item_unref (curr); } } else { char out[2048]; playItem_t *curr = streamer_get_playing_track (); DB_fileinfo_t *dec = streamer_get_current_fileinfo(); if (curr && dec) { pl_format_title (curr, -1, out, sizeof (out), -1, parg); } else { strcpy (out, "nothing"); } if (curr) { pl_item_unref (curr); } fwrite (out, 1, strlen (out), stdout); return 1; // exit } } else if (!strcmp (parg, "--next")) { messagepump_push (DB_EV_NEXT, 0, 0, 0); return 0; } else if (!strcmp (parg, "--prev")) { messagepump_push (DB_EV_PREV, 0, 0, 0); return 0; } else if (!strcmp (parg, "--play")) { messagepump_push (DB_EV_PLAY_CURRENT, 0, 0, 0); return 0; } else if (!strcmp (parg, "--stop")) { messagepump_push (DB_EV_STOP, 0, 0, 0); return 0; } else if (!strcmp (parg, "--pause")) { messagepump_push (DB_EV_PAUSE, 0, 0, 0); return 0; } else if (!strcmp (parg, "--toggle-pause")) { messagepump_push (DB_EV_TOGGLE_PAUSE, 0, 0, 0); return 0; } else if (!strcmp (parg, "--play-pause")) { int state = deadbeef->get_output ()->state (); if (state == OUTPUT_STATE_PLAYING) { deadbeef->sendmessage (DB_EV_PAUSE, 0, 0, 0); } else { deadbeef->sendmessage (DB_EV_PLAY_CURRENT, 0, 0, 0); } return 0; } else if (!strcmp (parg, "--random")) { messagepump_push (DB_EV_PLAY_RANDOM, 0, 0, 0); return 0; } else if (!strcmp (parg, "--queue")) { queue = 1; } else if (!strcmp (parg, "--quit")) { messagepump_push (DB_EV_TERMINATE, 0, 0, 0); } else if (!strcmp (parg, "--sm-client-id")) { parg += strlen (parg); parg++; if (parg < pend) { parg += strlen (parg); parg++; } continue; } else if (!strcmp (parg, "--gui")) { // need to skip --gui here, it is handled in the client cmdline parg += strlen (parg); parg++; if (parg >= pend) { break; } parg += strlen (parg); parg++; continue; } else if (parg[0] != '-') { break; // unknown option is filename } parg += strlen (parg); parg++; } if (parg < pend) { if (conf_get_int ("cli_add_to_specific_playlist", 1)) { char str[200]; conf_get_str ("cli_add_playlist_name", "Default", str, sizeof (str)); int idx = plt_find (str); if (idx < 0) { idx = plt_add (plt_get_count (), str); } if (idx >= 0) { plt_set_curr_idx (idx); } } playlist_t *curr_plt = plt_get_curr (); if (plt_add_files_begin (curr_plt, 0) != 0) { plt_unref (curr_plt); snprintf (sendback, sbsize, "it's not allowed to add files to playlist right now, because another file adding operation is in progress. please try again later."); return 0; } // add files if (!queue) { plt_clear (curr_plt); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, 0, 0); plt_reset_cursor (curr_plt); } while (parg < pend) { char resolved[PATH_MAX]; const char *pname; if (realpath (parg, resolved)) { pname = resolved; } else { pname = parg; } if (deadbeef->plt_add_dir2 (0, (ddb_playlist_t*)curr_plt, pname, NULL, NULL) < 0) { if (deadbeef->plt_add_file2 (0, (ddb_playlist_t*)curr_plt, pname, NULL, NULL) < 0) { int ab = 0; playItem_t *it = plt_load2 (0, curr_plt, NULL, pname, &ab, NULL, NULL); if (!it) { fprintf (stderr, "failed to add file or folder %s\n", pname); } } } parg += strlen (parg); parg++; } messagepump_push (DB_EV_PLAYLIST_REFRESH, 0, 0, 0); plt_add_files_end (curr_plt, 0); plt_unref (curr_plt); if (!queue) { messagepump_push (DB_EV_PLAY_NUM, 0, 0, 0); return 2; // don't reload playlist at startup } } return 0; }