// 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; }
void player_mainloop (void) { for (;;) { uint32_t msg; uintptr_t ctx; uint32_t p1; uint32_t p2; int term = 0; while (messagepump_pop(&msg, &ctx, &p1, &p2) != -1) { // broadcast to all plugins DB_plugin_t **plugs = plug_get_list (); for (int n = 0; plugs[n]; n++) { if (plugs[n]->message) { plugs[n]->message (msg, ctx, p1, p2); } } DB_output_t *output = plug_get_output (); switch (msg) { case DB_EV_REINIT_SOUND: plug_reinit_sound (); streamer_reset (1); conf_save (); break; case DB_EV_TERMINATE: { save_resume_state (); pl_playqueue_clear (); // stop streaming and playback before unloading plugins DB_output_t *output = plug_get_output (); output->stop (); streamer_free (); output->free (); term = 1; } break; case DB_EV_PLAY_CURRENT: if (p1) { output->stop (); pl_playqueue_clear (); streamer_set_nextsong (0, 1); } else { streamer_play_current_track (); } break; case DB_EV_PLAY_NUM: output->stop (); pl_playqueue_clear (); streamer_set_nextsong (p1, 1); if (pl_get_order () == PLAYBACK_ORDER_SHUFFLE_ALBUMS) { int pl = streamer_get_current_playlist (); playlist_t *plt = plt_get_for_idx (pl); plt_init_shuffle_albums (plt, p1); plt_unref (plt); } break; case DB_EV_STOP: streamer_set_nextsong (-2, 0); break; case DB_EV_NEXT: output->stop (); streamer_move_to_nextsong (1); break; case DB_EV_PREV: output->stop (); streamer_move_to_prevsong (); break; case DB_EV_PAUSE: if (output->state () != OUTPUT_STATE_PAUSED) { output->pause (); messagepump_push (DB_EV_PAUSED, 0, 1, 0); } break; case DB_EV_TOGGLE_PAUSE: if (output->state () == OUTPUT_STATE_PAUSED) { output->unpause (); messagepump_push (DB_EV_PAUSED, 0, 0, 0); } else { output->pause (); messagepump_push (DB_EV_PAUSED, 0, 1, 0); } break; case DB_EV_PLAY_RANDOM: output->stop (); streamer_move_to_randomsong (); break; case DB_EV_PLAYLIST_REFRESH: pl_save_current (); messagepump_push (DB_EV_PLAYLISTCHANGED, 0, 0, 0); break; case DB_EV_CONFIGCHANGED: conf_save (); streamer_configchanged (); break; case DB_EV_SEEK: streamer_set_seek (p1 / 1000.f); break; } if (msg >= DB_EV_FIRST && ctx) { messagepump_event_free ((ddb_event_t *)ctx); } } if (term) { return; } messagepump_wait (); } }