int avfilter_graph_send_command(AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags) { int i, r = AVERROR(ENOSYS); if(!graph) return r; if((flags & AVFILTER_CMD_FLAG_ONE) && !(flags & AVFILTER_CMD_FLAG_FAST)) { r=avfilter_graph_send_command(graph, target, cmd, arg, res, res_len, flags | AVFILTER_CMD_FLAG_FAST); if(r != AVERROR(ENOSYS)) return r; } if(res_len && res) res[0]= 0; for (i = 0; i < graph->filter_count; i++) { AVFilterContext *filter = graph->filters[i]; if(!strcmp(target, "all") || (filter->name && !strcmp(target, filter->name)) || !strcmp(target, filter->filter->name)){ r = avfilter_process_command(filter, cmd, arg, res, res_len, flags); if(r != AVERROR(ENOSYS)) { if((flags & AVFILTER_CMD_FLAG_ONE) || r<0) return r; } } } return r; }
/* Update volume filter */ void BarPlayerSetVolume (player_t * const player) { assert (player != NULL); if (player->mode != PLAYER_PLAYING) { return; } int ret; #ifdef HAVE_AVFILTER_GRAPH_SEND_COMMAND /* ffmpeg and libav disagree on the type of this option (string vs. double) * -> print to string and let them parse it again */ char strbuf[16]; snprintf (strbuf, sizeof (strbuf), "%fdB", player->settings->volume + player->gain); assert (player->fgraph != NULL); if ((ret = avfilter_graph_send_command (player->fgraph, "volume", "volume", strbuf, NULL, 0, 0)) < 0) { #else /* convert from decibel */ const double volume = pow (10, (player->settings->volume + player->gain) / 20); /* libav does not provide other means to set this right now. it might not * even work everywhere. */ assert (player->fvolume != NULL); if ((ret = av_opt_set_double (player->fvolume->priv, "volume", volume, 0)) != 0) { #endif printError (player->settings, "Cannot set volume", ret); } } #define softfail(msg) \ printError (player->settings, msg, ret); \ return false; /* ffmpeg callback for blocking functions, returns 1 to abort function */ static int intCb (void * const data) { player_t * const player = data; assert (player != NULL); if (player->interrupted > 1) { /* got a sigint multiple times, quit pianobar (handled by main.c). */ player->doQuit = true; return 1; } else if (player->interrupted != 0) { /* the request is retried with the same player context */ player->interrupted = 0; return 1; } else { return 0; } }
/* Update volume filter */ void BarPlayerSetVolume (player_t * const player) { assert (player != NULL); if (player->mode != PLAYER_PLAYING) { return; } int ret; #ifdef HAVE_AVFILTER_GRAPH_SEND_COMMAND /* ffmpeg and libav disagree on the type of this option (string vs. double) * -> print to string and let them parse it again */ char strbuf[16]; snprintf (strbuf, sizeof (strbuf), "%fdB", player->settings->volume + player->gain); assert (player->fgraph != NULL); if ((ret = avfilter_graph_send_command (player->fgraph, "volume", "volume", strbuf, NULL, 0, 0)) < 0) { #else /* convert from decibel */ const double volume = pow (10, (player->settings->volume + player->gain) / 20); /* libav does not provide other means to set this right now. it might not * even work everywhere. */ assert (player->fvolume != NULL); if ((ret = av_opt_set_double (player->fvolume->priv, "volume", volume, 0)) != 0) { #endif printError (player->settings, "Cannot set volume", ret); } } #define softfail(msg) \ printError (player->settings, msg, ret); \ return false; #ifndef HAVE_AV_TIMEOUT /* interrupt callback for libav, which lacks a timeout option * * obviously calling ping() a lot of times and then calling av_gettime here * again is rather inefficient. */ static int intCb (void * const data) { player_t * const player = data; assert (player != NULL); /* 10 seconds timeout (usec) */ return (av_gettime () - player->ping) > 10*1000000; }