diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index a3c1143e22..e8313fa4c2 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -48,7 +48,7 @@ #define INITIAL_PROBE_SIZE STREAM_BUFFER_SIZE #define SMALL_MAX_PROBE_SIZE (32 * 1024) -#define PROBE_BUF_SIZE (2*1024*1024) +#define PROBE_BUF_SIZE (2 * 1024 * 1024) const m_option_t lavfdopts_conf[] = { OPT_INTRANGE("probesize", lavfdopts.probesize, 0, 32, INT_MAX), @@ -79,40 +79,44 @@ typedef struct lavf_priv { bool use_dts; bool seek_by_bytes; int bitrate; -}lavf_priv_t; +} lavf_priv_t; -static int mp_read(void *opaque, uint8_t *buf, int size) { +static int mp_read(void *opaque, uint8_t *buf, int size) +{ struct demuxer *demuxer = opaque; struct stream *stream = demuxer->stream; int ret; - ret=stream_read(stream, buf, size); + ret = stream_read(stream, buf, size); - mp_msg(MSGT_HEADER,MSGL_DBG2,"%d=mp_read(%p, %p, %d), pos: %"PRId64", eof:%d\n", + mp_msg(MSGT_HEADER, MSGL_DBG2, + "%d=mp_read(%p, %p, %d), pos: %"PRId64", eof:%d\n", ret, stream, buf, size, stream_tell(stream), stream->eof); return ret; } -static int64_t mp_seek(void *opaque, int64_t pos, int whence) { +static int64_t mp_seek(void *opaque, int64_t pos, int whence) +{ struct demuxer *demuxer = opaque; struct stream *stream = demuxer->stream; int64_t current_pos; - mp_msg(MSGT_HEADER,MSGL_DBG2,"mp_seek(%p, %"PRId64", %d)\n", stream, pos, whence); - if(whence == SEEK_CUR) - pos +=stream_tell(stream); - else if(whence == SEEK_END && stream->end_pos > 0) + mp_msg(MSGT_HEADER, MSGL_DBG2, "mp_seek(%p, %"PRId64", %d)\n", + stream, pos, whence); + if (whence == SEEK_CUR) + pos += stream_tell(stream); + else if (whence == SEEK_END && stream->end_pos > 0) pos += stream->end_pos; - else if(whence == SEEK_SET) + else if (whence == SEEK_SET) pos += stream->start_pos; - else if(whence == AVSEEK_SIZE && stream->end_pos > 0) + else if (whence == AVSEEK_SIZE && stream->end_pos > 0) return stream->end_pos - stream->start_pos; else return -1; - if(pos<0) + if (pos < 0) return -1; current_pos = stream_tell(stream); - if(stream_seek(stream, pos)==0) { + if (stream_seek(stream, pos) == 0) { stream_reset(stream); stream_seek(stream, current_pos); return -1; @@ -135,14 +139,16 @@ static int64_t mp_read_seek(void *opaque, int stream_idx, int64_t ts, int flags) return ret; } -static void list_formats(void) { +static void list_formats(void) +{ mp_msg(MSGT_DEMUX, MSGL_INFO, "Available lavf input formats:\n"); AVInputFormat *fmt = NULL; while (fmt = av_iformat_next(fmt)) mp_msg(MSGT_DEMUX, MSGL_INFO, "%15s : %s\n", fmt->name, fmt->long_name); } -static int lavf_check_file(demuxer_t *demuxer){ +static int lavf_check_file(demuxer_t *demuxer) +{ struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; AVProbeData avpd; @@ -151,9 +157,9 @@ static int lavf_check_file(demuxer_t *demuxer){ int read_size = INITIAL_PROBE_SIZE; int score; - if(!demuxer->priv) - demuxer->priv=calloc(sizeof(lavf_priv_t),1); - priv= demuxer->priv; + if (!demuxer->priv) + demuxer->priv = calloc(sizeof(lavf_priv_t), 1); + priv = demuxer->priv; av_register_all(); @@ -162,39 +168,41 @@ static int lavf_check_file(demuxer_t *demuxer){ format = demuxer->stream->lavf_type; if (format) { if (strcmp(format, "help") == 0) { - list_formats(); - return 0; + list_formats(); + return 0; } priv->avif = av_find_input_format(format); if (!priv->avif) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "Unknown lavf format %s\n", format); return 0; } - mp_msg(MSGT_DEMUX,MSGL_INFO,"Forced lavf %s demuxer\n", priv->avif->long_name); + mp_msg(MSGT_DEMUX, MSGL_INFO, "Forced lavf %s demuxer\n", + priv->avif->long_name); return DEMUXER_TYPE_LAVF; } avpd.buf = av_mallocz(FFMAX(BIO_BUFFER_SIZE, PROBE_BUF_SIZE) + FF_INPUT_BUFFER_PADDING_SIZE); do { - read_size = stream_read(demuxer->stream, avpd.buf + probe_data_size, read_size); - if(read_size < 0) { + read_size = stream_read(demuxer->stream, avpd.buf + probe_data_size, + read_size); + if (read_size < 0) { av_free(avpd.buf); return 0; } probe_data_size += read_size; - avpd.filename= demuxer->stream->url; + avpd.filename = demuxer->stream->url; if (!avpd.filename) { mp_msg(MSGT_DEMUX, MSGL_WARN, "Stream url is not set!\n"); avpd.filename = ""; } if (!strncmp(avpd.filename, "ffmpeg://", 9)) avpd.filename += 9; - avpd.buf_size= probe_data_size; + avpd.buf_size = probe_data_size; score = 0; - priv->avif= av_probe_input_format2(&avpd, probe_data_size > 0, &score); - read_size = FFMIN(2*read_size, PROBE_BUF_SIZE - probe_data_size); + priv->avif = av_probe_input_format2(&avpd, probe_data_size > 0, &score); + read_size = FFMIN(2 * read_size, PROBE_BUF_SIZE - probe_data_size); } while ((demuxer->desc->type != DEMUXER_TYPE_LAVF_PREFERRED || probe_data_size < SMALL_MAX_PROBE_SIZE) && score <= AVPROBE_SCORE_MAX / 4 && @@ -202,10 +210,11 @@ static int lavf_check_file(demuxer_t *demuxer){ av_free(avpd.buf); if (!priv->avif || score <= AVPROBE_SCORE_MAX / 4) { - mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: no clue about this gibberish!\n"); + mp_msg(MSGT_HEADER, MSGL_V, + "LAVF_check: no clue about this gibberish!\n"); return 0; - }else - mp_msg(MSGT_HEADER,MSGL_V,"LAVF_check: %s\n", priv->avif->long_name); + } else + mp_msg(MSGT_HEADER, MSGL_V, "LAVF_check: %s\n", priv->avif->long_name); demuxer->filetype = priv->avif->long_name; if (!demuxer->filetype) @@ -245,7 +254,8 @@ static const char * const preferred_internal[] = { NULL }; -static int lavf_check_preferred_file(demuxer_t *demuxer){ +static int lavf_check_preferred_file(demuxer_t *demuxer) +{ if (lavf_check_file(demuxer)) { const char * const *p; lavf_priv_t *priv = demuxer->priv; @@ -257,14 +267,16 @@ static int lavf_check_preferred_file(demuxer_t *demuxer){ return 0; } -static uint8_t char2int(char c) { +static uint8_t char2int(char c) +{ if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return 0; } -static void parse_cryptokey(AVFormatContext *avfc, const char *str) { +static void parse_cryptokey(AVFormatContext *avfc, const char *str) +{ int len = strlen(str) / 2; uint8_t *key = av_mallocz(len); int i; @@ -274,246 +286,254 @@ static void parse_cryptokey(AVFormatContext *avfc, const char *str) { *key++ = (char2int(str[0]) << 4) | char2int(str[1]); } -static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { - lavf_priv_t *priv= demuxer->priv; - AVStream *st= avfc->streams[i]; - AVCodecContext *codec= st->codec; +static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) +{ + lavf_priv_t *priv = demuxer->priv; + AVStream *st = avfc->streams[i]; + AVCodecContext *codec = st->codec; char *stream_type = NULL; int stream_id; AVMetadataTag *lang = av_metadata_get(st->metadata, "language", NULL, 0); - AVMetadataTag *title= av_metadata_get(st->metadata, "title", NULL, 0); + AVMetadataTag *title = av_metadata_get(st->metadata, "title", NULL, 0); int g, override_tag = mp_av_codec_get_tag(mp_codecid_override_taglists, codec->codec_id); // For some formats (like PCM) always trust CODEC_ID_* more than codec_tag if (override_tag) codec->codec_tag = override_tag; - switch(codec->codec_type){ - case AVMEDIA_TYPE_AUDIO:{ - WAVEFORMATEX *wf; - sh_audio_t* sh_audio; - sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams); - if(!sh_audio) - break; - stream_type = "audio"; - priv->astreams[priv->audio_streams] = i; - wf= calloc(sizeof(*wf) + codec->extradata_size, 1); - // mp4a tag is used for all mp4 files no matter what they actually contain - if(codec->codec_tag == MKTAG('m', 'p', '4', 'a')) - codec->codec_tag= 0; - if(!codec->codec_tag) - codec->codec_tag= mp_av_codec_get_tag(mp_wav_taglists, codec->codec_id); - wf->wFormatTag= codec->codec_tag; - wf->nChannels= codec->channels; - wf->nSamplesPerSec= codec->sample_rate; - wf->nAvgBytesPerSec= codec->bit_rate/8; - wf->nBlockAlign= codec->block_align ? codec->block_align : 1; - wf->wBitsPerSample= codec->bits_per_coded_sample; - wf->cbSize= codec->extradata_size; - if(codec->extradata_size) - memcpy(wf + 1, codec->extradata, codec->extradata_size); - sh_audio->wf= wf; - sh_audio->audio.dwSampleSize= codec->block_align; - if(codec->frame_size && codec->sample_rate){ - sh_audio->audio.dwScale=codec->frame_size; - sh_audio->audio.dwRate= codec->sample_rate; - }else{ - sh_audio->audio.dwScale= codec->block_align ? codec->block_align*8 : 8; - sh_audio->audio.dwRate = codec->bit_rate; - } - g= av_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); - sh_audio->audio.dwScale /= g; - sh_audio->audio.dwRate /= g; + switch (codec->codec_type) { + case AVMEDIA_TYPE_AUDIO: { + WAVEFORMATEX *wf; + sh_audio_t *sh_audio; + sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams); + if (!sh_audio) + break; + stream_type = "audio"; + priv->astreams[priv->audio_streams] = i; + wf = calloc(sizeof(*wf) + codec->extradata_size, 1); + // mp4a tag is used for all mp4 files no matter what they actually contain + if (codec->codec_tag == MKTAG('m', 'p', '4', 'a')) + codec->codec_tag = 0; + if (!codec->codec_tag) + codec->codec_tag = mp_av_codec_get_tag(mp_wav_taglists, + codec->codec_id); + wf->wFormatTag = codec->codec_tag; + wf->nChannels = codec->channels; + wf->nSamplesPerSec = codec->sample_rate; + wf->nAvgBytesPerSec = codec->bit_rate / 8; + wf->nBlockAlign = codec->block_align ? codec->block_align : 1; + wf->wBitsPerSample = codec->bits_per_coded_sample; + wf->cbSize = codec->extradata_size; + if (codec->extradata_size) + memcpy(wf + 1, codec->extradata, codec->extradata_size); + sh_audio->wf = wf; + sh_audio->audio.dwSampleSize = codec->block_align; + if (codec->frame_size && codec->sample_rate) { + sh_audio->audio.dwScale = codec->frame_size; + sh_audio->audio.dwRate = codec->sample_rate; + } else { + sh_audio->audio.dwScale = codec->block_align ? codec->block_align * 8 : 8; + sh_audio->audio.dwRate = codec->bit_rate; + } + g = av_gcd(sh_audio->audio.dwScale, sh_audio->audio.dwRate); + sh_audio->audio.dwScale /= g; + sh_audio->audio.dwRate /= g; // printf("sca:%d rat:%d fs:%d sr:%d ba:%d\n", sh_audio->audio.dwScale, sh_audio->audio.dwRate, codec->frame_size, codec->sample_rate, codec->block_align); - sh_audio->ds= demuxer->audio; - sh_audio->format= codec->codec_tag; - sh_audio->channels= codec->channels; - sh_audio->samplerate= codec->sample_rate; - sh_audio->i_bps= codec->bit_rate/8; - switch (codec->codec_id) { - case CODEC_ID_PCM_S8: - case CODEC_ID_PCM_U8: - sh_audio->samplesize = 1; - break; - case CODEC_ID_PCM_S16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_U16BE: - sh_audio->samplesize = 2; - break; - case CODEC_ID_PCM_ALAW: - sh_audio->format = 0x6; - break; - case CODEC_ID_PCM_MULAW: - sh_audio->format = 0x7; - break; - } - if (title && title->value) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", priv->audio_streams, title->value); - if (lang && lang->value) { - sh_audio->lang = talloc_strdup(sh_audio, lang->value); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", priv->audio_streams, sh_audio->lang); - } - if (st->disposition & AV_DISPOSITION_DEFAULT) - sh_audio->default_track = 1; - if(mp_msg_test(MSGT_HEADER,MSGL_V) ) print_wave_header(sh_audio->wf, MSGL_V); - st->discard= AVDISCARD_ALL; - stream_id = priv->audio_streams++; + sh_audio->ds = demuxer->audio; + sh_audio->format = codec->codec_tag; + sh_audio->channels = codec->channels; + sh_audio->samplerate = codec->sample_rate; + sh_audio->i_bps = codec->bit_rate / 8; + switch (codec->codec_id) { + case CODEC_ID_PCM_S8: + case CODEC_ID_PCM_U8: + sh_audio->samplesize = 1; + break; + case CODEC_ID_PCM_S16LE: + case CODEC_ID_PCM_S16BE: + case CODEC_ID_PCM_U16LE: + case CODEC_ID_PCM_U16BE: + sh_audio->samplesize = 2; + break; + case CODEC_ID_PCM_ALAW: + sh_audio->format = 0x6; + break; + case CODEC_ID_PCM_MULAW: + sh_audio->format = 0x7; break; } - case AVMEDIA_TYPE_VIDEO:{ - sh_video_t* sh_video; - BITMAPINFOHEADER *bih; - sh_video=new_sh_video_vid(demuxer, i, priv->video_streams); - if(!sh_video) break; - stream_type = "video"; - priv->vstreams[priv->video_streams] = i; - bih=calloc(sizeof(*bih) + codec->extradata_size,1); + if (title && title->value) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_NAME=%s\n", + priv->audio_streams, title->value); + if (lang && lang->value) { + sh_audio->lang = talloc_strdup(sh_audio, lang->value); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AID_%d_LANG=%s\n", + priv->audio_streams, sh_audio->lang); + } + if (st->disposition & AV_DISPOSITION_DEFAULT) + sh_audio->default_track = 1; + if (mp_msg_test(MSGT_HEADER, MSGL_V)) + print_wave_header(sh_audio->wf, MSGL_V); + st->discard = AVDISCARD_ALL; + stream_id = priv->audio_streams++; + break; + } + case AVMEDIA_TYPE_VIDEO: { + sh_video_t *sh_video; + BITMAPINFOHEADER *bih; + sh_video = new_sh_video_vid(demuxer, i, priv->video_streams); + if (!sh_video) + break; + stream_type = "video"; + priv->vstreams[priv->video_streams] = i; + bih = calloc(sizeof(*bih) + codec->extradata_size, 1); - if(codec->codec_id == CODEC_ID_RAWVIDEO) { - switch (codec->pix_fmt) { - case PIX_FMT_RGB24: - codec->codec_tag= MKTAG(24, 'B', 'G', 'R'); - case PIX_FMT_BGR24: - codec->codec_tag= MKTAG(24, 'R', 'G', 'B'); - } + if (codec->codec_id == CODEC_ID_RAWVIDEO) { + switch (codec->pix_fmt) { + case PIX_FMT_RGB24: + codec->codec_tag = MKTAG(24, 'B', 'G', 'R'); + case PIX_FMT_BGR24: + codec->codec_tag = MKTAG(24, 'R', 'G', 'B'); } - if(!codec->codec_tag) - codec->codec_tag= mp_av_codec_get_tag(mp_bmp_taglists, codec->codec_id); - bih->biSize= sizeof(*bih) + codec->extradata_size; - bih->biWidth= codec->width; - bih->biHeight= codec->height; - bih->biBitCount= codec->bits_per_coded_sample; - bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount/8; - bih->biCompression= codec->codec_tag; - sh_video->bih= bih; - sh_video->disp_w= codec->width; - sh_video->disp_h= codec->height; - if (st->time_base.den) { /* if container has time_base, use that */ - sh_video->video.dwRate= st->time_base.den; - sh_video->video.dwScale= st->time_base.num; - } else { - sh_video->video.dwRate= codec->time_base.den; - sh_video->video.dwScale= codec->time_base.num; - } - sh_video->fps=av_q2d(st->r_frame_rate); - sh_video->frametime=1/av_q2d(st->r_frame_rate); - sh_video->format=bih->biCompression; - if(st->sample_aspect_ratio.num) - sh_video->aspect = codec->width * st->sample_aspect_ratio.num - / (float)(codec->height * st->sample_aspect_ratio.den); - else - sh_video->aspect=codec->width * codec->sample_aspect_ratio.num - / (float)(codec->height * codec->sample_aspect_ratio.den); - sh_video->i_bps=codec->bit_rate/8; - if (title && title->value) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", priv->video_streams, title->value); - mp_msg(MSGT_DEMUX,MSGL_DBG2,"aspect= %d*%d/(%d*%d)\n", - codec->width, codec->sample_aspect_ratio.num, - codec->height, codec->sample_aspect_ratio.den); + } + if (!codec->codec_tag) + codec->codec_tag = mp_av_codec_get_tag(mp_bmp_taglists, + codec->codec_id); + bih->biSize = sizeof(*bih) + codec->extradata_size; + bih->biWidth = codec->width; + bih->biHeight = codec->height; + bih->biBitCount = codec->bits_per_coded_sample; + bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount / 8; + bih->biCompression = codec->codec_tag; + sh_video->bih = bih; + sh_video->disp_w = codec->width; + sh_video->disp_h = codec->height; + if (st->time_base.den) { /* if container has time_base, use that */ + sh_video->video.dwRate = st->time_base.den; + sh_video->video.dwScale = st->time_base.num; + } else { + sh_video->video.dwRate = codec->time_base.den; + sh_video->video.dwScale = codec->time_base.num; + } + sh_video->fps = av_q2d(st->r_frame_rate); + sh_video->frametime = 1 / av_q2d(st->r_frame_rate); + sh_video->format = bih->biCompression; + if (st->sample_aspect_ratio.num) + sh_video->aspect = codec->width * st->sample_aspect_ratio.num + / (float)(codec->height * st->sample_aspect_ratio.den); + else + sh_video->aspect = codec->width * codec->sample_aspect_ratio.num + / (float)(codec->height * codec->sample_aspect_ratio.den); + sh_video->i_bps = codec->bit_rate / 8; + if (title && title->value) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VID_%d_NAME=%s\n", + priv->video_streams, title->value); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "aspect= %d*%d/(%d*%d)\n", + codec->width, codec->sample_aspect_ratio.num, + codec->height, codec->sample_aspect_ratio.den); - sh_video->ds= demuxer->video; - if(codec->extradata_size) - memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); - if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V); - /* - short biPlanes; - int biXPelsPerMeter; - int biYPelsPerMeter; - int biClrUsed; - int biClrImportant; - */ - if(demuxer->video->id != priv->video_streams - && demuxer->video->id != -1) - st->discard= AVDISCARD_ALL; - else{ - demuxer->video->id = i; - demuxer->video->sh= demuxer->v_streams[i]; - } - stream_id = priv->video_streams++; - break; + sh_video->ds = demuxer->video; + if (codec->extradata_size) + memcpy(sh_video->bih + 1, codec->extradata, codec->extradata_size); + if ( mp_msg_test(MSGT_HEADER, MSGL_V)) + print_video_header(sh_video->bih, MSGL_V); + if (demuxer->video->id != priv->video_streams + && demuxer->video->id != -1) + st->discard = AVDISCARD_ALL; + else { + demuxer->video->id = i; + demuxer->video->sh = demuxer->v_streams[i]; } - case AVMEDIA_TYPE_SUBTITLE:{ - sh_sub_t* sh_sub; - char type; - /* only support text subtitles for now */ - if(codec->codec_id == CODEC_ID_TEXT) - type = 't'; - else if(codec->codec_id == CODEC_ID_MOV_TEXT) - type = 'm'; - else if(codec->codec_id == CODEC_ID_SSA) - type = 'a'; - else if(codec->codec_id == CODEC_ID_DVD_SUBTITLE) - type = 'v'; - else if(codec->codec_id == CODEC_ID_XSUB) - type = 'x'; - else if(codec->codec_id == CODEC_ID_DVB_SUBTITLE) - type = 'b'; - else if(codec->codec_id == CODEC_ID_DVB_TELETEXT) - type = 'd'; - else if(codec->codec_id == CODEC_ID_HDMV_PGS_SUBTITLE) - type = 'p'; - else - break; - sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams); - if(!sh_sub) break; - stream_type = "subtitle"; - priv->sstreams[priv->sub_streams] = i; - sh_sub->type = type; - if (codec->extradata_size) { - sh_sub->extradata = malloc(codec->extradata_size); - memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); - sh_sub->extradata_len = codec->extradata_size; - } - if (title && title->value) - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", priv->sub_streams, title->value); - if (lang && lang->value) { - sh_sub->lang = talloc_strdup(sh_sub, lang->value); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", priv->sub_streams, sh_sub->lang); - } - if (st->disposition & AV_DISPOSITION_DEFAULT) - sh_sub->default_track = 1; - stream_id = priv->sub_streams++; + stream_id = priv->video_streams++; + break; + } + case AVMEDIA_TYPE_SUBTITLE: { + sh_sub_t *sh_sub; + char type; + /* only support text subtitles for now */ + if (codec->codec_id == CODEC_ID_TEXT) + type = 't'; + else if (codec->codec_id == CODEC_ID_MOV_TEXT) + type = 'm'; + else if (codec->codec_id == CODEC_ID_SSA) + type = 'a'; + else if (codec->codec_id == CODEC_ID_DVD_SUBTITLE) + type = 'v'; + else if (codec->codec_id == CODEC_ID_XSUB) + type = 'x'; + else if (codec->codec_id == CODEC_ID_DVB_SUBTITLE) + type = 'b'; + else if (codec->codec_id == CODEC_ID_DVB_TELETEXT) + type = 'd'; + else if (codec->codec_id == CODEC_ID_HDMV_PGS_SUBTITLE) + type = 'p'; + else break; - } - case AVMEDIA_TYPE_ATTACHMENT:{ - AVMetadataTag *ftag = av_metadata_get(st->metadata, "filename", - NULL, 0); - char *filename = ftag ? ftag->value : NULL; - if (st->codec->codec_id == CODEC_ID_TTF) - demuxer_add_attachment(demuxer, BSTR(filename), - BSTR("application/x-truetype-font"), - (struct bstr){codec->extradata, - codec->extradata_size}); + sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams); + if (!sh_sub) break; + stream_type = "subtitle"; + priv->sstreams[priv->sub_streams] = i; + sh_sub->type = type; + if (codec->extradata_size) { + sh_sub->extradata = malloc(codec->extradata_size); + memcpy(sh_sub->extradata, codec->extradata, codec->extradata_size); + sh_sub->extradata_len = codec->extradata_size; } - default: - st->discard= AVDISCARD_ALL; + if (title && title->value) + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_NAME=%s\n", + priv->sub_streams, title->value); + if (lang && lang->value) { + sh_sub->lang = talloc_strdup(sh_sub, lang->value); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SID_%d_LANG=%s\n", + priv->sub_streams, sh_sub->lang); + } + if (st->disposition & AV_DISPOSITION_DEFAULT) + sh_sub->default_track = 1; + stream_id = priv->sub_streams++; + break; + } + case AVMEDIA_TYPE_ATTACHMENT: { + AVMetadataTag *ftag = av_metadata_get(st->metadata, "filename", + NULL, 0); + char *filename = ftag ? ftag->value : NULL; + if (st->codec->codec_id == CODEC_ID_TTF) + demuxer_add_attachment(demuxer, BSTR(filename), + BSTR("application/x-truetype-font"), + (struct bstr){codec->extradata, + codec->extradata_size}); + break; + } + default: + st->discard = AVDISCARD_ALL; } if (stream_type) { AVCodec *avc = avcodec_find_decoder(codec->codec_id); const char *codec_name = avc ? avc->name : "unknown"; if (!avc && *stream_type == 's' && demuxer->s_streams[stream_id]) codec_name = sh_sub_type2str(((sh_sub_t *)demuxer->s_streams[stream_id])->type); - mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d", i, stream_type, codec_name, *stream_type, stream_id); + mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d", + i, stream_type, codec_name, *stream_type, stream_id); if (lang && lang->value && *stream_type != 'v') - mp_msg(MSGT_DEMUX, MSGL_INFO, ", -%clang %s", *stream_type, lang->value); + mp_msg(MSGT_DEMUX, MSGL_INFO, ", -%clang %s", + *stream_type, lang->value); if (title && title->value) mp_msg(MSGT_DEMUX, MSGL_INFO, ", %s", title->value); mp_msg(MSGT_DEMUX, MSGL_INFO, "\n"); } } -static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ +static demuxer_t *demux_open_lavf(demuxer_t *demuxer) +{ struct MPOpts *opts = demuxer->opts; struct lavfdopts *lavfdopts = &opts->lavfdopts; AVFormatContext *avfc; AVFormatParameters ap; const AVOption *opt; AVMetadataTag *t = NULL; - lavf_priv_t *priv= demuxer->priv; + lavf_priv_t *priv = demuxer->priv; int i; - char mp_filename[256]="mp:"; + char mp_filename[256] = "mp:"; memset(&ap, 0, sizeof(AVFormatParameters)); @@ -538,7 +558,10 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ ap.prealloced_context = 1; if (lavfdopts->probesize) { opt = av_set_int(avfc, "probesize", lavfdopts->probesize); - if(!opt) mp_msg(MSGT_HEADER,MSGL_ERR, "demux_lavf, couldn't set option probesize to %u\n", lavfdopts->probesize); + if (!opt) + mp_msg(MSGT_HEADER, MSGL_ERR, + "demux_lavf, couldn't set option probesize to %u\n", + lavfdopts->probesize); } if (lavfdopts->analyzeduration) { opt = av_set_int(avfc, "analyzeduration", @@ -548,16 +571,19 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ "analyzeduration to %u\n", lavfdopts->analyzeduration); } - if (lavfdopts->avopt){ - if(parse_avopts(avfc, lavfdopts->avopt) < 0){ - mp_msg(MSGT_HEADER,MSGL_ERR, "Your options /%s/ look like gibberish to me pal\n", lavfdopts->avopt); + if (lavfdopts->avopt) { + if (parse_avopts(avfc, lavfdopts->avopt) < 0) { + mp_msg(MSGT_HEADER, MSGL_ERR, + "Your options /%s/ look like gibberish to me pal\n", + lavfdopts->avopt); return NULL; } } - if(demuxer->stream->url) { + if (demuxer->stream->url) { if (!strncmp(demuxer->stream->url, "ffmpeg://rtsp:", 14)) - av_strlcpy(mp_filename, demuxer->stream->url + 9, sizeof(mp_filename)); + av_strlcpy(mp_filename, demuxer->stream->url + 9, + sizeof(mp_filename)); else av_strlcat(mp_filename, demuxer->stream->url, sizeof(mp_filename)); } else @@ -566,57 +592,68 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ priv->pb = av_alloc_put_byte(priv->buffer, BIO_BUFFER_SIZE, 0, demuxer, mp_read, NULL, mp_seek); priv->pb->read_seek = mp_read_seek; - priv->pb->is_streamed = !demuxer->stream->end_pos || (demuxer->stream->flags & MP_STREAM_SEEK) != MP_STREAM_SEEK; + priv->pb->is_streamed = !demuxer->stream->end_pos || + (demuxer->stream->flags & MP_STREAM_SEEK) != MP_STREAM_SEEK; - if(av_open_input_stream(&avfc, priv->pb, mp_filename, priv->avif, &ap)<0){ - mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_open_input_stream() failed\n"); + if (av_open_input_stream(&avfc, priv->pb, mp_filename, priv->avif, + &ap) < 0) { + mp_msg(MSGT_HEADER, MSGL_ERR, + "LAVF_header: av_open_input_stream() failed\n"); return NULL; } - priv->avfc= avfc; + priv->avfc = avfc; - if(av_find_stream_info(avfc) < 0){ - mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF_header: av_find_stream_info() failed\n"); + if (av_find_stream_info(avfc) < 0) { + mp_msg(MSGT_HEADER, MSGL_ERR, + "LAVF_header: av_find_stream_info() failed\n"); return NULL; } /* Add metadata. */ av_metadata_conv(avfc, NULL, avfc->iformat->metadata_conv); - while((t = av_metadata_get(avfc->metadata, "", t, AV_METADATA_IGNORE_SUFFIX))) + while ((t = av_metadata_get(avfc->metadata, "", t, + AV_METADATA_IGNORE_SUFFIX))) demux_info_add(demuxer, t->key, t->value); - for(i=0; i < avfc->nb_chapters; i++) { + for (i = 0; i < avfc->nb_chapters; i++) { AVChapter *c = avfc->chapters[i]; - uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000000000}); - uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000000000}); + uint64_t start = av_rescale_q(c->start, c->time_base, + (AVRational){1, 1000000000}); + uint64_t end = av_rescale_q(c->end, c->time_base, + (AVRational){1, 1000000000}); t = av_metadata_get(c->metadata, "title", NULL, 0); - demuxer_add_chapter(demuxer, t ? BSTR(t->value) : BSTR(NULL), start, end); + demuxer_add_chapter(demuxer, t ? BSTR(t->value) : BSTR(NULL), + start, end); } - for(i=0; inb_streams; i++) + for (i = 0; i < avfc->nb_streams; i++) handle_stream(demuxer, avfc, i); priv->nb_streams_last = avfc->nb_streams; - if(avfc->nb_programs) { + if (avfc->nb_programs) { int p; for (p = 0; p < avfc->nb_programs; p++) { AVProgram *program = avfc->programs[p]; t = av_metadata_get(program->metadata, "title", NULL, 0); - mp_msg(MSGT_HEADER,MSGL_INFO,"LAVF: Program %d %s\n", program->id, t ? t->value : ""); + mp_msg(MSGT_HEADER, MSGL_INFO, "LAVF: Program %d %s\n", + program->id, t ? t->value : ""); mp_msg(MSGT_IDENTIFY, MSGL_V, "PROGRAM_ID=%d\n", program->id); } } - mp_msg(MSGT_HEADER,MSGL_V,"LAVF: %d audio and %d video streams found\n",priv->audio_streams,priv->video_streams); - mp_msg(MSGT_HEADER,MSGL_V,"LAVF: build %d\n", LIBAVFORMAT_BUILD); + mp_msg(MSGT_HEADER, MSGL_V, "LAVF: %d audio and %d video streams found\n", + priv->audio_streams, priv->video_streams); + mp_msg(MSGT_HEADER, MSGL_V, "LAVF: build %d\n", LIBAVFORMAT_BUILD); demuxer->audio->id = -2; // wait for higher-level code to select track - if(!priv->video_streams){ - if(!priv->audio_streams){ - mp_msg(MSGT_HEADER,MSGL_ERR,"LAVF: no audio or video headers found - broken file?\n"); + if (!priv->video_streams) { + if (!priv->audio_streams) { + mp_msg(MSGT_HEADER, MSGL_ERR, + "LAVF: no audio or video headers found - broken file?\n"); return NULL; } - demuxer->video->id=-2; // audio-only - } //else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video; + demuxer->video->id = -2; // audio-only + } // disabled because unreliable per-stream bitrate values returned // by libavformat trigger this heuristic incorrectly and break things @@ -653,7 +690,7 @@ static void check_internet_radio_hack(struct demuxer *demuxer) return; if (avfc->nb_streams - priv->nb_streams_last == 1 && priv->video_streams == 0 && priv->sub_streams == 0 - && demuxer->a_streams[priv->audio_streams-1]->format == 0x566f // vorbis + && demuxer->a_streams[priv->audio_streams - 1]->format == 0x566f // vorbis && (priv->audio_streams == 2 || priv->internet_radio_hack) && demuxer->a_streams[0]->format == 0x566f) { // extradata match could be checked but would require parsing @@ -683,7 +720,7 @@ static void check_internet_radio_hack(struct demuxer *demuxer) AVMetadataTag *t = NULL; AVStream *stream = avfc->streams[avfc->nb_streams - 1]; while ((t = av_metadata_get(stream->metadata, "", t, - AV_METADATA_IGNORE_SUFFIX))) + AV_METADATA_IGNORE_SUFFIX))) demux_info_add(demuxer, t->key, t->value); } else { if (priv->internet_radio_hack) @@ -694,17 +731,18 @@ static void check_internet_radio_hack(struct demuxer *demuxer) } } -static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ - lavf_priv_t *priv= demux->priv; +static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds) +{ + lavf_priv_t *priv = demux->priv; AVPacket pkt; demux_packet_t *dp; demux_stream_t *ds; int id; - mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_lavf_fill_buffer()\n"); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_lavf_fill_buffer()\n"); - demux->filepos=stream_tell(demux->stream); + demux->filepos = stream_tell(demux->stream); - if(av_read_frame(priv->avfc, &pkt) < 0) + if (av_read_frame(priv->avfc, &pkt) < 0) return 0; // handle any new streams that might have been added @@ -714,67 +752,74 @@ static int demux_lavf_fill_buffer(demuxer_t *demux, demux_stream_t *dsds){ priv->nb_streams_last = priv->avfc->nb_streams; - id= pkt.stream_index; + id = pkt.stream_index; if (id == demux->audio->id || priv->internet_radio_hack) { // audio - ds=demux->audio; - if(!ds->sh){ - ds->sh=demux->a_streams[id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF audio ID = %d\n",ds->id); + ds = demux->audio; + if (!ds->sh) { + ds->sh = demux->a_streams[id]; + mp_msg(MSGT_DEMUX, MSGL_V, "Auto-selected LAVF audio ID = %d\n", + ds->id); } - } else if(id==demux->video->id){ + } else if (id == demux->video->id) { // video - ds=demux->video; - if(!ds->sh){ - ds->sh=demux->v_streams[id]; - mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected LAVF video ID = %d\n",ds->id); + ds = demux->video; + if (!ds->sh) { + ds->sh = demux->v_streams[id]; + mp_msg(MSGT_DEMUX, MSGL_V, "Auto-selected LAVF video ID = %d\n", + ds->id); } - } else if(id==demux->sub->id){ + } else if (id == demux->sub->id) { // subtitle - ds=demux->sub; - sub_utf8=1; + ds = demux->sub; + sub_utf8 = 1; } else { av_free_packet(&pkt); return 1; } - if(0/*pkt.destruct == av_destruct_packet*/){ + if (0 /*pkt.destruct == av_destruct_packet*/) { //ok kids, dont try this at home :) - dp=malloc(sizeof(demux_packet_t)); - dp->len=pkt.size; - dp->next=NULL; - dp->refcount=1; - dp->master=NULL; - dp->buffer=pkt.data; - pkt.destruct= NULL; - }else{ - dp=new_demux_packet(pkt.size); + dp = malloc(sizeof(demux_packet_t)); + dp->len = pkt.size; + dp->next = NULL; + dp->refcount = 1; + dp->master = NULL; + dp->buffer = pkt.data; + pkt.destruct = NULL; + } else { + dp = new_demux_packet(pkt.size); memcpy(dp->buffer, pkt.data, pkt.size); av_free_packet(&pkt); } int64_t ts = priv->use_dts ? pkt.dts : pkt.pts; - if(ts != AV_NOPTS_VALUE){ + if (ts != AV_NOPTS_VALUE) { dp->pts = ts * av_q2d(priv->avfc->streams[id]->time_base); - priv->last_pts= dp->pts * AV_TIME_BASE; + priv->last_pts = dp->pts * AV_TIME_BASE; // always set duration for subtitles, even if AV_PKT_FLAG_KEY isn't set, - // otherwise they will stay on screen to long if e.g. ASS is demuxed from mkv + // otherwise they will stay on screen to long if e.g. ASS is demuxed + // from mkv if ((ds == demux->sub || (pkt.flags & AV_PKT_FLAG_KEY)) && - pkt.convergence_duration > 0) - dp->duration = pkt.convergence_duration * av_q2d(priv->avfc->streams[id]->time_base); + pkt.convergence_duration > 0) + dp->duration = pkt.convergence_duration * + av_q2d(priv->avfc->streams[id]->time_base); } - dp->pos=demux->filepos; + dp->pos = demux->filepos; dp->flags = !!(pkt.flags & AV_PKT_FLAG_KEY); // append packet to DS stream: - ds_add_packet(ds,dp); + ds_add_packet(ds, dp); return 1; } -static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags){ +static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, + float audio_delay, int flags) +{ lavf_priv_t *priv = demuxer->priv; int avsflags = 0; - mp_msg(MSGT_DEMUX,MSGL_DBG2,"demux_seek_lavf(%p, %f, %f, %d)\n", demuxer, rel_seek_secs, audio_delay, flags); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "demux_seek_lavf(%p, %f, %f, %d)\n", + demuxer, rel_seek_secs, audio_delay, flags); if (priv->seek_by_bytes) { int64_t pos = demuxer->filepos; @@ -784,22 +829,20 @@ static void demux_seek_lavf(demuxer_t *demuxer, float rel_seek_secs, float audio return; } - if (flags & SEEK_ABSOLUTE) { - priv->last_pts = 0; - } else { - if (rel_seek_secs < 0) avsflags = AVSEEK_FLAG_BACKWARD; - } + if (flags & SEEK_ABSOLUTE) + priv->last_pts = 0; + else if (rel_seek_secs < 0) + avsflags = AVSEEK_FLAG_BACKWARD; if (flags & SEEK_FORWARD) avsflags = 0; else if (flags & SEEK_BACKWARD) avsflags = AVSEEK_FLAG_BACKWARD; if (flags & SEEK_FACTOR) { - if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) - return; - priv->last_pts += rel_seek_secs * priv->avfc->duration; - } else { - priv->last_pts += rel_seek_secs * AV_TIME_BASE; - } + if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) + return; + priv->last_pts += rel_seek_secs * priv->avfc->duration; + } else + priv->last_pts += rel_seek_secs * AV_TIME_BASE; if (av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags) < 0) { avsflags ^= AVSEEK_FLAG_BACKWARD; av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags); @@ -811,8 +854,8 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) lavf_priv_t *priv = demuxer->priv; switch (cmd) { - case DEMUXER_CTRL_CORRECT_PTS: - return DEMUXER_CTRL_OK; + case DEMUXER_CTRL_CORRECT_PTS: + return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_TIME_LENGTH: if (priv->seek_by_bytes) { /* Our bitrate estimate may be better than would be used in @@ -820,195 +863,185 @@ static int demux_lavf_control(demuxer_t *demuxer, int cmd, void *arg) if (demuxer->movi_end <= 0) return DEMUXER_CTRL_DONTKNOW; *(double *)arg = (demuxer->movi_end - demuxer->movi_start) * 8 / - priv->bitrate; + priv->bitrate; return DEMUXER_CTRL_GUESS; } - if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) - return DEMUXER_CTRL_DONTKNOW; + if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) + return DEMUXER_CTRL_DONTKNOW; - *((double *)arg) = (double)priv->avfc->duration / AV_TIME_BASE; - return DEMUXER_CTRL_OK; + *((double *)arg) = (double)priv->avfc->duration / AV_TIME_BASE; + return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: if (priv->seek_by_bytes) - return DEMUXER_CTRL_DONTKNOW; // let it use the fallback code - if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) - return DEMUXER_CTRL_DONTKNOW; + return DEMUXER_CTRL_DONTKNOW; // let it use the fallback code + if (priv->avfc->duration == 0 || priv->avfc->duration == AV_NOPTS_VALUE) + return DEMUXER_CTRL_DONTKNOW; - *((int *)arg) = (int)((priv->last_pts - priv->avfc->start_time)*100 / priv->avfc->duration); - return DEMUXER_CTRL_OK; - case DEMUXER_CTRL_SWITCH_AUDIO: - case DEMUXER_CTRL_SWITCH_VIDEO: - { - int id = *((int*)arg); - int newid = -2; - int i, curridx = -1; - int nstreams, *pstreams; - demux_stream_t *ds; + *((int *)arg) = (int)((priv->last_pts - priv->avfc->start_time) * 100 / + priv->avfc->duration); + return DEMUXER_CTRL_OK; + case DEMUXER_CTRL_SWITCH_AUDIO: + case DEMUXER_CTRL_SWITCH_VIDEO: + { + int id = *((int *)arg); + int newid = -2; + int i, curridx = -1; + int nstreams, *pstreams; + demux_stream_t *ds; - if(cmd == DEMUXER_CTRL_SWITCH_VIDEO) - { - ds = demuxer->video; - nstreams = priv->video_streams; - pstreams = priv->vstreams; - } - else - { - ds = demuxer->audio; - nstreams = priv->audio_streams; - pstreams = priv->astreams; - } - for(i = 0; i < nstreams; i++) - { - if(pstreams[i] == ds->id) //current stream id - { - curridx = i; - break; - } - } - - if (id == -1) { // next track - i = (curridx + 2) % (nstreams + 1) - 1; - if (i >= 0) - newid = pstreams[i]; - } else if (id >= 0 && id < nstreams) { // select track by id - i = id; - newid = pstreams[i]; - } else // no sound - i = -1; - - if (i == curridx) { - *(int *) arg = curridx < 0 ? -2 : curridx; - return DEMUXER_CTRL_OK; - } else { - ds_free_packs(ds); - if(ds->id >= 0) - priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; - ds->id = newid; - *(int *) arg = i < 0 ? -2 : i; - if(newid >= 0) - priv->avfc->streams[newid]->discard = AVDISCARD_NONE; - return DEMUXER_CTRL_OK; - } + if (cmd == DEMUXER_CTRL_SWITCH_VIDEO) { + ds = demuxer->video; + nstreams = priv->video_streams; + pstreams = priv->vstreams; + } else { + ds = demuxer->audio; + nstreams = priv->audio_streams; + pstreams = priv->astreams; + } + for (i = 0; i < nstreams; i++) { + if (pstreams[i] == ds->id) { //current stream id + curridx = i; + break; + } } - case DEMUXER_CTRL_IDENTIFY_PROGRAM: - { - demux_program_t *prog = arg; - AVProgram *program; - int p, i; - int start; - prog->vid = prog->aid = prog->sid = -2; //no audio and no video by default - if(priv->avfc->nb_programs < 1) - return DEMUXER_CTRL_DONTKNOW; + if (id == -1) { // next track + i = (curridx + 2) % (nstreams + 1) - 1; + if (i >= 0) + newid = pstreams[i]; + } else if (id >= 0 && id < nstreams) { // select track by id + i = id; + newid = pstreams[i]; + } else // no sound + i = -1; - if(prog->progid == -1) - { - p = 0; - while(pavfc->nb_programs && priv->avfc->programs[p]->id != priv->cur_program) - p++; - p = (p + 1) % priv->avfc->nb_programs; - } - else - { - for(i=0; iavfc->nb_programs; i++) - if(priv->avfc->programs[i]->id == prog->progid) - break; - if(i==priv->avfc->nb_programs) - return DEMUXER_CTRL_DONTKNOW; - p = i; - } - start = p; -redo: - program = priv->avfc->programs[p]; - for(i=0; inb_stream_indexes; i++) - { - switch(priv->avfc->streams[program->stream_index[i]]->codec->codec_type) - { - case AVMEDIA_TYPE_VIDEO: - if(prog->vid == -2) - prog->vid = program->stream_index[i]; - break; - case AVMEDIA_TYPE_AUDIO: - if(prog->aid == -2) - prog->aid = program->stream_index[i]; - break; - case AVMEDIA_TYPE_SUBTITLE: - if(prog->sid == -2 && priv->avfc->streams[program->stream_index[i]]->codec->codec_id == CODEC_ID_TEXT) - prog->sid = program->stream_index[i]; - break; - } - } - if (prog->aid >= 0 && prog->aid < MAX_A_STREAMS && - demuxer->a_streams[prog->aid]) { - sh_audio_t *sh = demuxer->a_streams[prog->aid]; - prog->aid = sh->aid; - } else - prog->aid = -2; - if (prog->vid >= 0 && prog->vid < MAX_V_STREAMS && - demuxer->v_streams[prog->vid]) { - sh_video_t *sh = demuxer->v_streams[prog->vid]; - prog->vid = sh->vid; - } else - prog->vid = -2; - if(prog->progid == -1 && prog->vid == -2 && prog->aid == -2) - { - p = (p + 1) % priv->avfc->nb_programs; - if (p == start) - return DEMUXER_CTRL_DONTKNOW; - goto redo; - } - priv->cur_program = prog->progid = program->id; + if (i == curridx) { + *(int *) arg = curridx < 0 ? -2 : curridx; + return DEMUXER_CTRL_OK; + } else { + ds_free_packs(ds); + if (ds->id >= 0) + priv->avfc->streams[ds->id]->discard = AVDISCARD_ALL; + ds->id = newid; + *(int *) arg = i < 0 ? -2 : i; + if (newid >= 0) + priv->avfc->streams[newid]->discard = AVDISCARD_NONE; return DEMUXER_CTRL_OK; } - default: - return DEMUXER_CTRL_NOTIMPL; + } + case DEMUXER_CTRL_IDENTIFY_PROGRAM: + { + demux_program_t *prog = arg; + AVProgram *program; + int p, i; + int start; + + prog->vid = prog->aid = prog->sid = -2; + if (priv->avfc->nb_programs < 1) + return DEMUXER_CTRL_DONTKNOW; + + if (prog->progid == -1) { + p = 0; + while (p < priv->avfc->nb_programs && priv->avfc->programs[p]->id != priv->cur_program) + p++; + p = (p + 1) % priv->avfc->nb_programs; + } else { + for (i = 0; i < priv->avfc->nb_programs; i++) + if (priv->avfc->programs[i]->id == prog->progid) + break; + if (i == priv->avfc->nb_programs) + return DEMUXER_CTRL_DONTKNOW; + p = i; + } + start = p; +redo: + program = priv->avfc->programs[p]; + for (i = 0; i < program->nb_stream_indexes; i++) { + switch (priv->avfc->streams[program->stream_index[i]]->codec->codec_type) { + case AVMEDIA_TYPE_VIDEO: + if (prog->vid == -2) + prog->vid = program->stream_index[i]; + break; + case AVMEDIA_TYPE_AUDIO: + if (prog->aid == -2) + prog->aid = program->stream_index[i]; + break; + case AVMEDIA_TYPE_SUBTITLE: + if (prog->sid == -2 && priv->avfc->streams[program->stream_index[i]]->codec->codec_id == CODEC_ID_TEXT) + prog->sid = program->stream_index[i]; + break; + } + } + if (prog->aid >= 0 && prog->aid < MAX_A_STREAMS && + demuxer->a_streams[prog->aid]) { + sh_audio_t *sh = demuxer->a_streams[prog->aid]; + prog->aid = sh->aid; + } else + prog->aid = -2; + if (prog->vid >= 0 && prog->vid < MAX_V_STREAMS && + demuxer->v_streams[prog->vid]) { + sh_video_t *sh = demuxer->v_streams[prog->vid]; + prog->vid = sh->vid; + } else + prog->vid = -2; + if (prog->progid == -1 && prog->vid == -2 && prog->aid == -2) { + p = (p + 1) % priv->avfc->nb_programs; + if (p == start) + return DEMUXER_CTRL_DONTKNOW; + goto redo; + } + priv->cur_program = prog->progid = program->id; + return DEMUXER_CTRL_OK; + } + default: + return DEMUXER_CTRL_NOTIMPL; } } static void demux_close_lavf(demuxer_t *demuxer) { - lavf_priv_t* priv = demuxer->priv; - if (priv){ - if(priv->avfc) - { - av_freep(&priv->avfc->key); - av_close_input_stream(priv->avfc); + lavf_priv_t *priv = demuxer->priv; + if (priv) { + if (priv->avfc) { + av_freep(&priv->avfc->key); + av_close_input_stream(priv->avfc); } av_freep(&priv->pb); - free(priv); demuxer->priv= NULL; + free(priv); + demuxer->priv = NULL; } } const demuxer_desc_t demuxer_desc_lavf = { - "libavformat demuxer", - "lavf", - "libavformat", - "Michael Niedermayer", - "supports many formats, requires libavformat", - DEMUXER_TYPE_LAVF, - 0, // Check after other demuxer - lavf_check_file, - demux_lavf_fill_buffer, - demux_open_lavf, - demux_close_lavf, - demux_seek_lavf, - demux_lavf_control + "libavformat demuxer", + "lavf", + "libavformat", + "Michael Niedermayer", + "supports many formats, requires libavformat", + DEMUXER_TYPE_LAVF, + 0, // Check after other demuxer + lavf_check_file, + demux_lavf_fill_buffer, + demux_open_lavf, + demux_close_lavf, + demux_seek_lavf, + demux_lavf_control }; const demuxer_desc_t demuxer_desc_lavf_preferred = { - "libavformat preferred demuxer", - "lavfpref", - "libavformat", - "Michael Niedermayer", - "supports many formats, requires libavformat", - DEMUXER_TYPE_LAVF_PREFERRED, - 1, - lavf_check_preferred_file, - demux_lavf_fill_buffer, - demux_open_lavf, - demux_close_lavf, - demux_seek_lavf, - demux_lavf_control + "libavformat preferred demuxer", + "lavfpref", + "libavformat", + "Michael Niedermayer", + "supports many formats, requires libavformat", + DEMUXER_TYPE_LAVF_PREFERRED, + 1, + lavf_check_preferred_file, + demux_lavf_fill_buffer, + demux_open_lavf, + demux_close_lavf, + demux_seek_lavf, + demux_lavf_control }; diff --git a/m_option.c b/m_option.c index 2fe53f5f17..c0fd8b43b0 100644 --- a/m_option.c +++ b/m_option.c @@ -40,185 +40,204 @@ //#define NO_FREE #endif -const m_option_t* m_option_list_find(const m_option_t* list,const char* name) { - int i; +const m_option_t *m_option_list_find(const m_option_t *list, const char *name) +{ + int i; - for(i = 0 ; list[i].name ; i++) { - int l = strlen(list[i].name) - 1; - if((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && - (l > 0) && (list[i].name[l] == '*')) { - if(strncasecmp(list[i].name,name,l) == 0) - return &list[i]; - } else if(strcasecmp(list[i].name,name) == 0) - return &list[i]; - } - return NULL; + for (i = 0; list[i].name; i++) { + int l = strlen(list[i].name) - 1; + if ((list[i].type->flags & M_OPT_TYPE_ALLOW_WILDCARD) + && (l > 0) && (list[i].name[l] == '*')) { + if (strncasecmp(list[i].name, name, l) == 0) + return &list[i]; + } else if (strcasecmp(list[i].name, name) == 0) + return &list[i]; + } + return NULL; } // Default function that just does a memcpy -static void copy_opt(const m_option_t* opt,void* dst,const void* src) { - if(dst && src) - memcpy(dst,src,opt->type->size); +static void copy_opt(const m_option_t *opt, void *dst, const void *src) +{ + if (dst && src) + memcpy(dst, src, opt->type->size); } // Helper for the print funcs (from man printf) -static char* dup_printf(const char *fmt, ...) { - /* Guess we need no more than 50 bytes. */ - int n, size = 50; - char *p; - va_list ap; - if ((p = malloc (size)) == NULL) - return NULL; - while (1) { - /* Try to print in the allocated space. */ - va_start(ap, fmt); - n = vsnprintf (p, size, fmt, ap); - va_end(ap); - /* If that worked, return the string. */ - if (n > -1 && n < size) - return p; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - size = n+1; /* precisely what is needed */ - else /* glibc 2.0 */ - size *= 2; /* twice the old size */ - if ((p = realloc (p, size)) == NULL) - return NULL; - } +static char *dup_printf(const char *fmt, ...) +{ + /* Guess we need no more than 50 bytes. */ + int n, size = 50; + char *p; + va_list ap; + if ((p = malloc(size)) == NULL) + return NULL; + while (1) { + /* Try to print in the allocated space. */ + va_start(ap, fmt); + n = vsnprintf(p, size, fmt, ap); + va_end(ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = realloc(p, size)) == NULL) + return NULL; + } } // Flag -#define VAL(x) (*(int*)(x)) +#define VAL(x) (*(int *)(x)) -static int parse_flag(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - if (src == M_CONFIG_FILE) { - if(!param) return M_OPT_MISSING_PARAM; - if (!strcasecmp(param, "yes") || /* any other language? */ - !strcasecmp(param, "on") || - !strcasecmp(param, "ja") || - !strcasecmp(param, "si") || - !strcasecmp(param, "igen") || - !strcasecmp(param, "y") || - !strcasecmp(param, "j") || - !strcasecmp(param, "i") || - !strcasecmp(param, "tak") || - !strcasecmp(param, "ja") || - !strcasecmp(param, "true") || - !strcmp(param, "1")) { - if(dst) VAL(dst) = opt->max; - } else if (!strcasecmp(param, "no") || - !strcasecmp(param, "off") || - !strcasecmp(param, "nein") || - !strcasecmp(param, "nicht") || - !strcasecmp(param, "nem") || - !strcasecmp(param, "n") || - !strcasecmp(param, "nie") || - !strcasecmp(param, "nej") || - !strcasecmp(param, "false") || - !strcmp(param, "0")) { - if(dst) VAL(dst) = opt->min; +static int parse_flag(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + if (src == M_CONFIG_FILE) { + if (!param) + return M_OPT_MISSING_PARAM; + if (!strcasecmp(param, "yes") || /* any other language? */ + !strcasecmp(param, "on") || + !strcasecmp(param, "ja") || + !strcasecmp(param, "si") || + !strcasecmp(param, "igen") || + !strcasecmp(param, "y") || + !strcasecmp(param, "j") || + !strcasecmp(param, "i") || + !strcasecmp(param, "tak") || + !strcasecmp(param, "ja") || + !strcasecmp(param, "true") || + !strcmp(param, "1")) { + if (dst) + VAL(dst) = opt->max; + } else if (!strcasecmp(param, "no") || + !strcasecmp(param, "off") || + !strcasecmp(param, "nein") || + !strcasecmp(param, "nicht") || + !strcasecmp(param, "nem") || + !strcasecmp(param, "n") || + !strcasecmp(param, "nie") || + !strcasecmp(param, "nej") || + !strcasecmp(param, "false") || + !strcmp(param, "0")) { + if (dst) + VAL(dst) = opt->min; + } else { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Invalid parameter for %s flag: %s\n", name, param); + return M_OPT_INVALID; + } + return 1; } else { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid parameter for %s flag: %s\n",name, param); - return M_OPT_INVALID; + if (dst) + VAL(dst) = opt->max; + return 0; } - return 1; - } else { - if(dst) VAL(dst) = opt->max; - return 0; - } } -static char* print_flag(const m_option_t* opt, const void* val) { - if(VAL(val) == opt->min) - return strdup("no"); - else - return strdup("yes"); +static char *print_flag(const m_option_t *opt, const void *val) +{ + if (VAL(val) == opt->min) + return strdup("no"); + else + return strdup("yes"); } const m_option_type_t m_option_type_flag = { - "Flag", - "need yes or no in config files", - sizeof(int), - 0, - parse_flag, - print_flag, - copy_opt, - copy_opt, - NULL, - NULL + "Flag", + "need yes or no in config files", + sizeof(int), + 0, + parse_flag, + print_flag, + copy_opt, + copy_opt, + NULL, + NULL }; // Integer -static int parse_int(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - long long tmp_int; - char *endptr; - src = 0; +static int parse_int(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + long long tmp_int; + char *endptr; + src = 0; - if (param == NULL) - return M_OPT_MISSING_PARAM; + if (param == NULL) + return M_OPT_MISSING_PARAM; - tmp_int = strtoll(param, &endptr, 10); - if (*endptr) - tmp_int = strtoll(param, &endptr, 0); - if (*endptr) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",name, param); - return M_OPT_INVALID; - } + tmp_int = strtoll(param, &endptr, 10); + if (*endptr) + tmp_int = strtoll(param, &endptr, 0); + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be an integer: %s\n", name, param); + return M_OPT_INVALID; + } - if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %d: %s\n", name, (int) opt->min, param); - return M_OPT_OUT_OF_RANGE; - } + if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be >= %d: %s\n", + name, (int) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } - if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %d: %s\n",name, (int) opt->max, param); - return M_OPT_OUT_OF_RANGE; - } + if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be <= %d: %s\n", + name, (int) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } - if(dst) { - if (opt->type->size == sizeof(int64_t)) - *(int64_t *)dst = tmp_int; - else - VAL(dst) = tmp_int; - } + if (dst) { + if (opt->type->size == sizeof(int64_t)) + *(int64_t *)dst = tmp_int; + else + VAL(dst) = tmp_int; + } - return 1; + return 1; } -static char* print_int(const m_option_t* opt, const void* val) { - if (opt->type->size == sizeof(int64_t)) - return dup_printf("%"PRId64, *(const int64_t *)val); - return dup_printf("%d",VAL(val)); +static char *print_int(const m_option_t *opt, const void *val) +{ + if (opt->type->size == sizeof(int64_t)) + return dup_printf("%"PRId64, *(const int64_t *)val); + return dup_printf("%d", VAL(val)); } const m_option_type_t m_option_type_int = { - "Integer", - "", - sizeof(int), - 0, - parse_int, - print_int, - copy_opt, - copy_opt, - NULL, - NULL + "Integer", + "", + sizeof(int), + 0, + parse_int, + print_int, + copy_opt, + copy_opt, + NULL, + NULL }; const m_option_type_t m_option_type_int64 = { - "Integer64", - "", - sizeof(int64_t), - 0, - parse_int, - print_int, - copy_opt, - copy_opt, - NULL, - NULL + "Integer64", + "", + sizeof(int64_t), + 0, + parse_int, + print_int, + copy_opt, + copy_opt, + NULL, + NULL }; static int parse_intpair(const struct m_option *opt, const char *name, @@ -253,7 +272,7 @@ static int parse_intpair(const struct m_option *opt, const char *name, return 1; - bad: +bad: mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid integer range " "specification for option %s: %s\n", name, param); return M_OPT_INVALID; @@ -292,7 +311,7 @@ static int parse_choice(const struct m_option *opt, const char *name, return 1; } -static char *print_choice(const m_option_t *opt, const void *val) +static char *print_choice(const m_option_t *opt, const void *val) { int v = *(int *)val; struct m_opt_choice_alternatives *alt; @@ -314,229 +333,251 @@ const struct m_option_type m_option_type_choice = { // Float #undef VAL -#define VAL(x) (*(double*)(x)) +#define VAL(x) (*(double *)(x)) -static int parse_double(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - double tmp_float; - char* endptr; - src = 0; +static int parse_double(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + double tmp_float; + char *endptr; + src = 0; - if (param == NULL) - return M_OPT_MISSING_PARAM; + if (param == NULL) + return M_OPT_MISSING_PARAM; - tmp_float = strtod(param, &endptr); + tmp_float = strtod(param, &endptr); - switch(*endptr) { - case ':': - case '/': - tmp_float /= strtod(endptr+1, &endptr); - break; - case '.': - case ',': - /* we also handle floats specified with - * non-locale decimal point ::atmos - */ - if(tmp_float<0) - tmp_float -= 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); - else - tmp_float += 1.0/pow(10,strlen(endptr+1)) * strtod(endptr+1, &endptr); - break; - } - - if (*endptr) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be a floating point " - "number or a ratio (numerator[:/]denominator): %s\n",name, param); - return M_OPT_INVALID; - } - - if (opt->flags & M_OPT_MIN) - if (tmp_float < opt->min) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be >= %f: %s\n", name, opt->min, param); - return M_OPT_OUT_OF_RANGE; + switch (*endptr) { + case ':': + case '/': + tmp_float /= strtod(endptr + 1, &endptr); + break; + case '.': + case ',': + /* we also handle floats specified with + * non-locale decimal point ::atmos + */ + if (tmp_float < 0) + tmp_float -= 1.0 / pow(10, strlen(endptr + 1)) * + strtod(endptr + 1, &endptr); + else + tmp_float += 1.0 / pow(10, strlen(endptr + 1)) * + strtod(endptr + 1, &endptr); + break; } - if (opt->flags & M_OPT_MAX) - if (tmp_float > opt->max) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be <= %f: %s\n", name, opt->max, param); - return M_OPT_OUT_OF_RANGE; + if (*endptr) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be a floating point number or a " + "ratio (numerator[:/]denominator): %s\n", name, param); + return M_OPT_INVALID; } - if(dst) VAL(dst) = tmp_float; - return 1; + if (opt->flags & M_OPT_MIN) + if (tmp_float < opt->min) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be >= %f: %s\n", name, opt->min, param); + return M_OPT_OUT_OF_RANGE; + } + + if (opt->flags & M_OPT_MAX) + if (tmp_float > opt->max) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be <= %f: %s\n", name, opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if (dst) + VAL(dst) = tmp_float; + return 1; } -static char* print_double(const m_option_t* opt, const void* val) { - opt = NULL; - return dup_printf("%f",VAL(val)); +static char *print_double(const m_option_t *opt, const void *val) +{ + opt = NULL; + return dup_printf("%f", VAL(val)); } const m_option_type_t m_option_type_double = { - "Double", - "double precision floating point number or ratio (numerator[:/]denominator)", - sizeof(double), - 0, - parse_double, - print_double, - copy_opt, - copy_opt, - NULL, - NULL + "Double", + "double precision floating point number or ratio (numerator[:/]denominator)", + sizeof(double), + 0, + parse_double, + print_double, + copy_opt, + copy_opt, + NULL, + NULL }; #undef VAL -#define VAL(x) (*(float*)(x)) +#define VAL(x) (*(float *)(x)) -static int parse_float(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { +static int parse_float(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ double tmp; - int r= parse_double(opt, name, param, &tmp, src); - if(r==1 && dst) VAL(dst) = tmp; + int r = parse_double(opt, name, param, &tmp, src); + if (r == 1 && dst) + VAL(dst) = tmp; return r; } -static char* print_float(const m_option_t* opt, const void* val) { - opt = NULL; - return dup_printf("%f",VAL(val)); +static char *print_float(const m_option_t *opt, const void *val) +{ + opt = NULL; + return dup_printf("%f", VAL(val)); } const m_option_type_t m_option_type_float = { - "Float", - "floating point number or ratio (numerator[:/]denominator)", - sizeof(float), - 0, - parse_float, - print_float, - copy_opt, - copy_opt, - NULL, - NULL + "Float", + "floating point number or ratio (numerator[:/]denominator)", + sizeof(float), + 0, + parse_float, + print_float, + copy_opt, + copy_opt, + NULL, + NULL }; ///////////// Position #undef VAL -#define VAL(x) (*(off_t*)(x)) +#define VAL(x) (*(off_t *)(x)) -static int parse_position(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - off_t tmp_off; - char dummy; +static int parse_position(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + off_t tmp_off; + char dummy; - if (param == NULL) - return M_OPT_MISSING_PARAM; - if (sscanf(param, sizeof(off_t) == sizeof(int) ? - "%d%c" : "%"PRId64"%c", &tmp_off, &dummy) != 1) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The %s option must be an integer: %s\n",opt->name,param); - return M_OPT_INVALID; - } - - if (opt->flags & M_OPT_MIN) - if (tmp_off < opt->min) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "The %s option must be >= %"PRId64": %s\n", - name, (int64_t) opt->min, param); - return M_OPT_OUT_OF_RANGE; + if (param == NULL) + return M_OPT_MISSING_PARAM; + if (sscanf(param, sizeof(off_t) == sizeof(int) ? + "%d%c" : "%"PRId64"%c", &tmp_off, &dummy) != 1) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be an integer: %s\n", opt->name, param); + return M_OPT_INVALID; } - if (opt->flags & M_OPT_MAX) - if (tmp_off > opt->max) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "The %s option must be <= %"PRId64": %s\n", - name, (int64_t) opt->max, param); - return M_OPT_OUT_OF_RANGE; - } + if (opt->flags & M_OPT_MIN) + if (tmp_off < opt->min) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be >= %"PRId64 ": %s\n", + name, (int64_t) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } - if(dst) - VAL(dst) = tmp_off; - return 1; + if (opt->flags & M_OPT_MAX) + if (tmp_off > opt->max) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "The %s option must be <= %"PRId64 ": %s\n", + name, (int64_t) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } + + if (dst) + VAL(dst) = tmp_off; + return 1; } -static char* print_position(const m_option_t* opt, const void* val) { - return dup_printf("%"PRId64,(int64_t)VAL(val)); +static char *print_position(const m_option_t *opt, const void *val) +{ + return dup_printf("%"PRId64, (int64_t)VAL(val)); } const m_option_type_t m_option_type_position = { - "Position", - "Integer (off_t)", - sizeof(off_t), - 0, - parse_position, - print_position, - copy_opt, - copy_opt, - NULL, - NULL + "Position", + "Integer (off_t)", + sizeof(off_t), + 0, + parse_position, + print_position, + copy_opt, + copy_opt, + NULL, + NULL }; ///////////// String #undef VAL -#define VAL(x) (*(char**)(x)) +#define VAL(x) (*(char **)(x)) -static int parse_str(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { +static int parse_str(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ - if (param == NULL) - return M_OPT_MISSING_PARAM; + if (param == NULL) + return M_OPT_MISSING_PARAM; - if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be >= %d chars: %s\n", - (int) opt->min, param); - return M_OPT_OUT_OF_RANGE; - } + if ((opt->flags & M_OPT_MIN) && (strlen(param) < opt->min)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be >= %d chars: %s\n", + (int) opt->min, param); + return M_OPT_OUT_OF_RANGE; + } - if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be <= %d chars: %s\n", - (int) opt->max, param); - return M_OPT_OUT_OF_RANGE; - } + if ((opt->flags & M_OPT_MAX) && (strlen(param) > opt->max)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Parameter must be <= %d chars: %s\n", + (int) opt->max, param); + return M_OPT_OUT_OF_RANGE; + } - if(dst) { - free(VAL(dst)); - VAL(dst) = strdup(param); - } + if (dst) { + free(VAL(dst)); + VAL(dst) = strdup(param); + } - return 1; + return 1; } -static char* print_str(const m_option_t* opt, const void* val) { - return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : NULL; +static char *print_str(const m_option_t *opt, const void *val) +{ + return (val && VAL(val) && strlen(VAL(val)) > 0) ? strdup(VAL(val)) : NULL; } -static void copy_str(const m_option_t* opt,void* dst, const void* src) { - if(dst && src) { +static void copy_str(const m_option_t *opt, void *dst, const void *src) +{ + if (dst && src) { #ifndef NO_FREE - free(VAL(dst)); //FIXME!!! + free(VAL(dst)); //FIXME!!! #endif - VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; - } + VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; + } } -static void free_str(void* src) { - if(src && VAL(src)){ +static void free_str(void *src) +{ + if (src && VAL(src)) { #ifndef NO_FREE - free(VAL(src)); //FIXME!!! + free(VAL(src)); //FIXME!!! #endif - VAL(src) = NULL; - } + VAL(src) = NULL; + } } const m_option_type_t m_option_type_string = { - "String", - "", - sizeof(char*), - M_OPT_TYPE_DYNAMIC, - parse_str, - print_str, - copy_str, - copy_str, - copy_str, - free_str + "String", + "", + sizeof(char *), + M_OPT_TYPE_DYNAMIC, + parse_str, + print_str, + copy_str, + copy_str, + copy_str, + free_str }; //////////// String list #undef VAL -#define VAL(x) (*(char***)(x)) +#define VAL(x) (*(char ***)(x)) #define OP_NONE 0 #define OP_ADD 1 @@ -544,263 +585,283 @@ const m_option_type_t m_option_type_string = { #define OP_DEL 3 #define OP_CLR 4 -static void free_str_list(void* dst) { - char** d; - int i; +static void free_str_list(void *dst) +{ + char **d; + int i; - if(!dst || !VAL(dst)) return; - d = VAL(dst); + if (!dst || !VAL(dst)) + return; + d = VAL(dst); // FIXME!!! #ifndef NO_FREE - for(i = 0 ; d[i] != NULL ; i++) - free(d[i]); - free(d); + for (i = 0; d[i] != NULL; i++) + free(d[i]); + free(d); #endif - VAL(dst) = NULL; -} - -static int str_list_add(char** add, int n,void* dst,int pre) { - char** lst = VAL(dst); - int ln; - - if(!dst) return M_OPT_PARSER_ERR; - lst = VAL(dst); - - for(ln = 0 ; lst && lst[ln] ; ln++) - /**/; - - lst = realloc(lst,(n+ln+1)*sizeof(char*)); - - if(pre) { - memmove(&lst[n],lst,ln*sizeof(char*)); - memcpy(lst,add,n*sizeof(char*)); - } else - memcpy(&lst[ln],add,n*sizeof(char*)); - // (re-)add NULL-termination - lst[ln+n] = NULL; - - free(add); - - VAL(dst) = lst; - - return 1; -} - -static int str_list_del(char** del, int n,void* dst) { - char **lst,*ep,**d; - int i,ln,s; - long idx; - - if(!dst) return M_OPT_PARSER_ERR; - lst = VAL(dst); - - for(ln = 0 ; lst && lst[ln] ; ln++) - /**/; - s = ln; - - for(i = 0 ; del[i] != NULL ; i++) { - idx = strtol(del[i], &ep, 0); - if(*ep) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n",del[i]); - free(del[i]); - continue; - } - free(del[i]); - if(idx < 0 || idx >= ln) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Index %ld is out of range.\n",idx); - continue; - } else if(!lst[idx]) - continue; - free(lst[idx]); - lst[idx] = NULL; - s--; - } - free(del); - - if(s == 0) { - free(lst); VAL(dst) = NULL; - return 1; - } - - d = calloc(s+1,sizeof(char*)); - for(i = 0, n = 0 ; i < ln ; i++) { - if(!lst[i]) continue; - d[n] = lst[i]; - n++; - } - d[s] = NULL; - - free(lst); - VAL(dst) = d; - - return 1; } -static char *get_nextsep(char *ptr, char sep, int modify) { +static int str_list_add(char **add, int n, void *dst, int pre) +{ + char **lst = VAL(dst); + int ln; + + if (!dst) + return M_OPT_PARSER_ERR; + lst = VAL(dst); + + for (ln = 0; lst && lst[ln]; ln++) + /**/; + + lst = realloc(lst, (n + ln + 1) * sizeof(char *)); + + if (pre) { + memmove(&lst[n], lst, ln * sizeof(char *)); + memcpy(lst, add, n * sizeof(char *)); + } else + memcpy(&lst[ln], add, n * sizeof(char *)); + // (re-)add NULL-termination + lst[ln + n] = NULL; + + free(add); + + VAL(dst) = lst; + + return 1; +} + +static int str_list_del(char **del, int n, void *dst) +{ + char **lst, *ep, **d; + int i, ln, s; + long idx; + + if (!dst) + return M_OPT_PARSER_ERR; + lst = VAL(dst); + + for (ln = 0; lst && lst[ln]; ln++) + /**/; + s = ln; + + for (i = 0; del[i] != NULL; i++) { + idx = strtol(del[i], &ep, 0); + if (*ep) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid index: %s\n", del[i]); + free(del[i]); + continue; + } + free(del[i]); + if (idx < 0 || idx >= ln) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Index %ld is out of range.\n", idx); + continue; + } else if (!lst[idx]) + continue; + free(lst[idx]); + lst[idx] = NULL; + s--; + } + free(del); + + if (s == 0) { + free(lst); + VAL(dst) = NULL; + return 1; + } + + d = calloc(s + 1, sizeof(char *)); + for (i = 0, n = 0; i < ln; i++) { + if (!lst[i]) + continue; + d[n] = lst[i]; + n++; + } + d[s] = NULL; + + free(lst); + VAL(dst) = d; + + return 1; +} + +static char *get_nextsep(char *ptr, char sep, int modify) +{ char *last_ptr = ptr; - for(;;){ + for (;;) { ptr = strchr(ptr, sep); - if(ptr && ptr>last_ptr && ptr[-1]=='\\'){ - if (modify) memmove(ptr-1, ptr, strlen(ptr)+1); - else ptr++; - }else + if (ptr && ptr > last_ptr && ptr[-1] == '\\') { + if (modify) + memmove(ptr - 1, ptr, strlen(ptr) + 1); + else + ptr++; + } else break; } return ptr; } -static int parse_str_list(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - int n = 0,len = strlen(opt->name); - char *str; - char *ptr = (char *)param, *last_ptr, **res; - int op = OP_NONE; +static int parse_str_list(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + int n = 0, len = strlen(opt->name); + char *str; + char *ptr = (char *)param, *last_ptr, **res; + int op = OP_NONE; - if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) { - const char* n = &name[len-1]; - if(strcasecmp(n,"-add") == 0) - op = OP_ADD; - else if(strcasecmp(n,"-pre") == 0) - op = OP_PRE; - else if(strcasecmp(n,"-del") == 0) - op = OP_DEL; - else if(strcasecmp(n,"-clr") == 0) - op = OP_CLR; - else - return M_OPT_UNKNOWN; - } - - // Clear the list ?? - if(op == OP_CLR) { - if(dst) - free_str_list(dst); - return 0; - } - - // All other ops need a param - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; - - // custom type for "profile" calls this but uses ->priv for something else - char separator = opt->type == &m_option_type_string_list && opt->priv ? - *(char *)opt->priv : OPTION_LIST_SEPARATOR; - while(ptr[0] != '\0') { - ptr = get_nextsep(ptr, separator, 0); - if(!ptr) { - n++; - break; + if (opt->name[len - 1] == '*' && ((int)strlen(name) > len - 1)) { + const char *n = &name[len - 1]; + if (strcasecmp(n, "-add") == 0) + op = OP_ADD; + else if (strcasecmp(n, "-pre") == 0) + op = OP_PRE; + else if (strcasecmp(n, "-del") == 0) + op = OP_DEL; + else if (strcasecmp(n, "-clr") == 0) + op = OP_CLR; + else + return M_OPT_UNKNOWN; } - ptr++; - n++; - } - if(n == 0) - return M_OPT_INVALID; - if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) || - ((opt->flags & M_OPT_MAX) && (n > opt->max)) ) - return M_OPT_OUT_OF_RANGE; - if(!dst) return 1; - - res = malloc((n+2)*sizeof(char*)); - ptr = str = strdup(param); - n = 0; - - while(1) { - last_ptr = ptr; - ptr = get_nextsep(ptr, separator, 1); - if(!ptr) { - res[n] = strdup(last_ptr); - n++; - break; + // Clear the list ?? + if (op == OP_CLR) { + if (dst) + free_str_list(dst); + return 0; } - len = ptr - last_ptr; - res[n] = malloc(len + 1); - if(len) strncpy(res[n],last_ptr,len); - res[n][len] = '\0'; - ptr++; - n++; - } - res[n] = NULL; - free(str); - switch(op) { - case OP_ADD: - return str_list_add(res,n,dst,0); - case OP_PRE: - return str_list_add(res,n,dst,1); - case OP_DEL: - return str_list_del(res,n,dst); - } + // All other ops need a param + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - if(VAL(dst)) - free_str_list(dst); - VAL(dst) = res; + // custom type for "profile" calls this but uses ->priv for something else + char separator = opt->type == &m_option_type_string_list && opt->priv ? + *(char *)opt->priv : OPTION_LIST_SEPARATOR; + while (ptr[0] != '\0') { + ptr = get_nextsep(ptr, separator, 0); + if (!ptr) { + n++; + break; + } + ptr++; + n++; + } + if (n == 0) + return M_OPT_INVALID; + if (((opt->flags & M_OPT_MIN) && (n < opt->min)) || + ((opt->flags & M_OPT_MAX) && (n > opt->max))) + return M_OPT_OUT_OF_RANGE; - return 1; + if (!dst) + return 1; + + res = malloc((n + 2) * sizeof(char *)); + ptr = str = strdup(param); + n = 0; + + while (1) { + last_ptr = ptr; + ptr = get_nextsep(ptr, separator, 1); + if (!ptr) { + res[n] = strdup(last_ptr); + n++; + break; + } + len = ptr - last_ptr; + res[n] = malloc(len + 1); + if (len) + strncpy(res[n], last_ptr, len); + res[n][len] = '\0'; + ptr++; + n++; + } + res[n] = NULL; + free(str); + + switch (op) { + case OP_ADD: + return str_list_add(res, n, dst, 0); + case OP_PRE: + return str_list_add(res, n, dst, 1); + case OP_DEL: + return str_list_del(res, n, dst); + } + + if (VAL(dst)) + free_str_list(dst); + VAL(dst) = res; + + return 1; } -static void copy_str_list(const m_option_t* opt,void* dst, const void* src) { - int n; - char **d,**s; +static void copy_str_list(const m_option_t *opt, void *dst, const void *src) +{ + int n; + char **d, **s; - if(!(dst && src)) return; - s = VAL(src); + if (!(dst && src)) + return; + s = VAL(src); - if(VAL(dst)) - free_str_list(dst); + if (VAL(dst)) + free_str_list(dst); - if(!s) { - VAL(dst) = NULL; - return; - } + if (!s) { + VAL(dst) = NULL; + return; + } - for(n = 0 ; s[n] != NULL ; n++) - /* NOTHING */; - d = malloc((n+1)*sizeof(char*)); - for( ; n >= 0 ; n--) - d[n] = s[n] ? strdup(s[n]) : NULL; + for (n = 0; s[n] != NULL; n++) + /* NOTHING */; + d = malloc((n + 1) * sizeof(char *)); + for (; n >= 0; n--) + d[n] = s[n] ? strdup(s[n]) : NULL; - VAL(dst) = d; + VAL(dst) = d; } -static char* print_str_list(const m_option_t* opt, const void* src) { - char **lst = NULL; - char *ret = NULL,*last = NULL; - int i; +static char *print_str_list(const m_option_t *opt, const void *src) +{ + char **lst = NULL; + char *ret = NULL, *last = NULL; + int i; - if(!(src && VAL(src))) return NULL; - lst = VAL(src); + if (!(src && VAL(src))) + return NULL; + lst = VAL(src); - for(i = 0 ; lst[i] ; i++) { - if(last) { - ret = dup_printf("%s,%s",last,lst[i]); - free(last); - } else - ret = strdup(lst[i]); - last = ret; - } - if(last && last != ret) free(last); - return ret; + for (i = 0; lst[i]; i++) { + if (last) { + ret = dup_printf("%s,%s", last, lst[i]); + free(last); + } else + ret = strdup(lst[i]); + last = ret; + } + if (last && last != ret) + free(last); + return ret; } const m_option_type_t m_option_type_string_list = { - "String list", - "A list of strings separated by ','\n" - "Option with a name ending in an * permits using the following suffix: \n" - "\t-add: Add the given parameters at the end of the list.\n" - "\t-pre: Add the given parameters at the beginning of the list.\n" - "\t-del: Remove the entry at the given indices.\n" - "\t-clr: Clear the list.\n" - "e.g: -vf-add flip,mirror -vf-del 2,5\n", - sizeof(char**), - M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD, - parse_str_list, - print_str_list, - copy_str_list, - copy_str_list, - copy_str_list, - free_str_list + "String list", + "A list of strings separated by ','\n" + "Option with a name ending in an * permits using the following suffix: \n" + "\t-add: Add the given parameters at the end of the list.\n" + "\t-pre: Add the given parameters at the beginning of the list.\n" + "\t-del: Remove the entry at the given indices.\n" + "\t-clr: Clear the list.\n" + "e.g: -vf-add flip,mirror -vf-del 2,5\n", + sizeof(char **), + M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD, + parse_str_list, + print_str_list, + copy_str_list, + copy_str_list, + copy_str_list, + free_str_list }; @@ -809,623 +870,650 @@ const m_option_type_t m_option_type_string_list = { // A chained list to save the various calls for func_param typedef struct m_func_save m_func_save_t; struct m_func_save { - m_func_save_t* next; - char* name; - char* param; + m_func_save_t *next; + char *name; + char *param; }; #undef VAL -#define VAL(x) (*(m_func_save_t**)(x)) +#define VAL(x) (*(m_func_save_t **)(x)) -static void free_func_pf(void* src) { - m_func_save_t *s,*n; +static void free_func_pf(void *src) +{ + m_func_save_t *s, *n; - if(!src) return; + if (!src) + return; - s = VAL(src); + s = VAL(src); - while(s) { - n = s->next; - free(s->name); - free(s->param); - free(s); - s = n; - } - VAL(src) = NULL; + while (s) { + n = s->next; + free(s->name); + free(s->param); + free(s); + s = n; + } + VAL(src) = NULL; } // Parser for func_param -static int parse_func_pf(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - m_func_save_t *s,*p; +static int parse_func_pf(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + m_func_save_t *s, *p; + + if (!dst) + return 1; + + s = calloc(1, sizeof(m_func_save_t)); + s->name = strdup(name); + s->param = param ? strdup(param) : NULL; + + p = VAL(dst); + if (p) { + for (; p->next != NULL; p = p->next) + /**/; + p->next = s; + } else + VAL(dst) = s; - if(!dst) return 1; - - s = calloc(1,sizeof(m_func_save_t)); - s->name = strdup(name); - s->param = param ? strdup(param) : NULL; - - p = VAL(dst); - if(p) { - for( ; p->next != NULL ; p = p->next) - /**/; - p->next = s; - } else - VAL(dst) = s; - - return 1; } -static void copy_func_pf(const m_option_t* opt,void* dst, const void* src) { - m_func_save_t *d = NULL, *s,* last = NULL; +static void copy_func_pf(const m_option_t *opt, void *dst, const void *src) +{ + m_func_save_t *d = NULL, *s, *last = NULL; - if(!(dst && src)) return; - s = VAL(src); + if (!(dst && src)) + return; + s = VAL(src); - if(VAL(dst)) - free_func_pf(dst); + if (VAL(dst)) + free_func_pf(dst); - while(s) { - d = calloc(1,sizeof(m_func_save_t)); - d->name = strdup(s->name); - d->param = s->param ? strdup(s->param) : NULL; - if(last) - last->next = d; - else - VAL(dst) = d; - last = d; - s = s->next; - } + while (s) { + d = calloc(1, sizeof(m_func_save_t)); + d->name = strdup(s->name); + d->param = s->param ? strdup(s->param) : NULL; + if (last) + last->next = d; + else + VAL(dst) = d; + last = d; + s = s->next; + } } /////////////////// Func_param -static void set_func_param(const m_option_t* opt, void* dst, const void* src) { - m_func_save_t* s; +static void set_func_param(const m_option_t *opt, void *dst, const void *src) +{ + m_func_save_t *s; - if(!src) return; - s = VAL(src); + if (!src) + return; + s = VAL(src); - if(!s) return; + if (!s) + return; - for( ; s != NULL ; s = s->next) - ((m_opt_func_param_t) opt->p)(opt,s->param); + for (; s != NULL; s = s->next) + ((m_opt_func_param_t) opt->p)(opt, s->param); } const m_option_type_t m_option_type_func_param = { - "Func param", - "", - sizeof(m_func_save_t*), - M_OPT_TYPE_INDIRECT, - parse_func_pf, - NULL, - NULL, // Nothing to do on save - set_func_param, - copy_func_pf, - free_func_pf + "Func param", + "", + sizeof(m_func_save_t *), + M_OPT_TYPE_INDIRECT, + parse_func_pf, + NULL, + NULL, // Nothing to do on save + set_func_param, + copy_func_pf, + free_func_pf }; /////////////// Func #undef VAL -static int parse_func(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - return 0; +static int parse_func(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + return 0; } -static void set_func(const m_option_t* opt,void* dst, const void* src) { +static void set_func(const m_option_t *opt, void *dst, const void *src) +{ ((m_opt_func_t) opt->p)(opt); } const m_option_type_t m_option_type_func = { - "Func", - "", - sizeof(int), - M_OPT_TYPE_INDIRECT, - parse_func, - NULL, - NULL, // Nothing to do on save - set_func, - NULL, - NULL + "Func", + "", + sizeof(int), + M_OPT_TYPE_INDIRECT, + parse_func, + NULL, + NULL, // Nothing to do on save + set_func, + NULL, + NULL }; /////////////////// Print -static int parse_print(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - if(opt->type == CONF_TYPE_PRINT_INDIRECT) - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) opt->p); - else if(opt->type == CONF_TYPE_PRINT_FUNC) - return ((m_opt_func_full_t) opt->p)(opt,name,param); - else - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", mp_gtext(opt->p)); +static int parse_print(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + if (opt->type == CONF_TYPE_PRINT_INDIRECT) + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) opt->p); + else if (opt->type == CONF_TYPE_PRINT_FUNC) + return ((m_opt_func_full_t) opt->p)(opt, name, param); + else + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", mp_gtext(opt->p)); - if(opt->priv == NULL) - return M_OPT_EXIT; - return 0; + if (opt->priv == NULL) + return M_OPT_EXIT; + return 0; } const m_option_type_t m_option_type_print = { - "Print", - "", - 0, - 0, - parse_print, - NULL, - NULL, - NULL, - NULL, - NULL + "Print", + "", + 0, + 0, + parse_print, + NULL, + NULL, + NULL, + NULL, + NULL }; const m_option_type_t m_option_type_print_indirect = { - "Print", - "", - 0, - 0, - parse_print, - NULL, - NULL, - NULL, - NULL, - NULL + "Print", + "", + 0, + 0, + parse_print, + NULL, + NULL, + NULL, + NULL, + NULL }; const m_option_type_t m_option_type_print_func = { - "Print", - "", - 0, - M_OPT_TYPE_ALLOW_WILDCARD, - parse_print, - NULL, - NULL, - NULL, - NULL, - NULL + "Print", + "", + 0, + M_OPT_TYPE_ALLOW_WILDCARD, + parse_print, + NULL, + NULL, + NULL, + NULL, + NULL }; /////////////////////// Subconfig #undef VAL -#define VAL(x) (*(char***)(x)) +#define VAL(x) (*(char ***)(x)) -static int parse_subconf(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - char *subparam; - char *subopt; - int nr = 0,i,r; - const m_option_t *subopts; - const char *p; - char** lst = NULL; +static int parse_subconf(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + char *subparam; + char *subopt; + int nr = 0, i, r; + const m_option_t *subopts; + const char *p; + char **lst = NULL; - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - subparam = malloc(strlen(param)+1); - subopt = malloc(strlen(param)+1); - p = param; + subparam = malloc(strlen(param) + 1); + subopt = malloc(strlen(param) + 1); + p = param; - subopts = opt->p; + subopts = opt->p; - while(p[0]) - { - int sscanf_ret = 1; - int optlen = strcspn(p, ":="); - /* clear out */ - subopt[0] = subparam[0] = 0; - av_strlcpy(subopt, p, optlen + 1); - p = &p[optlen]; - if (p[0] == '=') { - sscanf_ret = 2; - p = &p[1]; - if (p[0] == '"') { - p = &p[1]; - optlen = strcspn(p, "\""); - av_strlcpy(subparam, p, optlen + 1); - p = &p[optlen]; - if (p[0] != '"') { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Terminating '\"' missing for '%s'\n", subopt); - return M_OPT_INVALID; - } - p = &p[1]; - } else if (p[0] == '%') { - p = &p[1]; - optlen = (int)strtol(p, (char**)&p, 0); - if (!p || p[0] != '%' || (optlen > strlen(p) - 1)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid length %i for '%s'\n", optlen, subopt); - return M_OPT_INVALID; - } - p = &p[1]; - av_strlcpy(subparam, p, optlen + 1); - p = &p[optlen]; - } else { - optlen = strcspn(p, ":"); - av_strlcpy(subparam, p, optlen + 1); - p = &p[optlen]; + while (p[0]) { + int sscanf_ret = 1; + int optlen = strcspn(p, ":="); + /* clear out */ + subopt[0] = subparam[0] = 0; + av_strlcpy(subopt, p, optlen + 1); + p = &p[optlen]; + if (p[0] == '=') { + sscanf_ret = 2; + p = &p[1]; + if (p[0] == '"') { + p = &p[1]; + optlen = strcspn(p, "\""); + av_strlcpy(subparam, p, optlen + 1); + p = &p[optlen]; + if (p[0] != '"') { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Terminating '\"' missing for '%s'\n", subopt); + return M_OPT_INVALID; + } + p = &p[1]; + } else if (p[0] == '%') { + p = &p[1]; + optlen = (int)strtol(p, (char **)&p, 0); + if (!p || p[0] != '%' || (optlen > strlen(p) - 1)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Invalid length %i for '%s'\n", optlen, subopt); + return M_OPT_INVALID; + } + p = &p[1]; + av_strlcpy(subparam, p, optlen + 1); + p = &p[optlen]; + } else { + optlen = strcspn(p, ":"); + av_strlcpy(subparam, p, optlen + 1); + p = &p[optlen]; + } + } + if (p[0] == ':') + p = &p[1]; + else if (p[0]) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Incorrect termination for '%s'\n", subopt); + return M_OPT_INVALID; } - } - if (p[0] == ':') - p = &p[1]; - else if (p[0]) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Incorrect termination for '%s'\n", subopt); - return M_OPT_INVALID; - } - switch(sscanf_ret) - { - case 1: - subparam[0] = 0; - case 2: - for(i = 0 ; subopts[i].name ; i++) { - if(!strcmp(subopts[i].name,subopt)) break; - } - if(!subopts[i].name) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Unknown suboption %s\n",name,subopt); - return M_OPT_UNKNOWN; - } - r = m_option_parse(&subopts[i],subopt, - subparam[0] == 0 ? NULL : subparam,NULL,src); - if(r < 0) return r; - if(dst) { - lst = realloc(lst,2 * (nr+2) * sizeof(char*)); - lst[2*nr] = strdup(subopt); - lst[2*nr+1] = subparam[0] == 0 ? NULL : strdup(subparam); - memset(&lst[2*(nr+1)],0,2*sizeof(char*)); - nr++; - } - break; - } + switch (sscanf_ret) { + case 1: + subparam[0] = 0; + case 2: + for (i = 0; subopts[i].name; i++) + if (!strcmp(subopts[i].name, subopt)) + break; + if (!subopts[i].name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Unknown suboption %s\n", name, subopt); + return M_OPT_UNKNOWN; + } + r = m_option_parse(&subopts[i], subopt, + subparam[0] == 0 ? NULL : subparam, NULL, src); + if (r < 0) + return r; + if (dst) { + lst = realloc(lst, 2 * (nr + 2) * sizeof(char *)); + lst[2 * nr] = strdup(subopt); + lst[2 * nr + 1] = subparam[0] == 0 ? NULL : strdup(subparam); + memset(&lst[2 * (nr + 1)], 0, 2 * sizeof(char *)); + nr++; + } + break; + } } - free(subparam); - free(subopt); - if(dst) - VAL(dst) = lst; + free(subparam); + free(subopt); + if (dst) + VAL(dst) = lst; - return 1; + return 1; } const m_option_type_t m_option_type_subconfig = { - "Subconfig", - "The syntax is -option opt1=foo:flag:opt2=blah", - sizeof(int), - M_OPT_TYPE_HAS_CHILD, - parse_subconf, - NULL, - NULL, - NULL, - NULL, - NULL + "Subconfig", + "The syntax is -option opt1=foo:flag:opt2=blah", + sizeof(int), + M_OPT_TYPE_HAS_CHILD, + parse_subconf, + NULL, + NULL, + NULL, + NULL, + NULL }; #include "libmpcodecs/img_format.h" /* FIXME: snyc with img_format.h */ static struct { - const char* name; - unsigned int fmt; + const char *name; + unsigned int fmt; } mp_imgfmt_list[] = { - {"444p16le", IMGFMT_444P16_LE}, - {"444p16be", IMGFMT_444P16_BE}, - {"444p10le", IMGFMT_444P10_LE}, - {"444p10be", IMGFMT_444P10_BE}, - {"444p9le", IMGFMT_444P9_LE}, - {"444p9be", IMGFMT_444P9_BE}, - {"422p16le", IMGFMT_422P16_LE}, - {"422p16be", IMGFMT_422P16_BE}, - {"422p10le", IMGFMT_422P10_LE}, - {"422p10be", IMGFMT_422P10_BE}, - {"420p16le", IMGFMT_420P16_LE}, - {"420p16be", IMGFMT_420P16_BE}, - {"420p10le", IMGFMT_420P10_LE}, - {"420p10be", IMGFMT_420P10_BE}, - {"420p9le", IMGFMT_420P9_LE}, - {"420p9be", IMGFMT_420P9_BE}, - {"444p16", IMGFMT_444P16}, - {"444p10", IMGFMT_444P10}, - {"444p9", IMGFMT_444P9}, - {"422p16", IMGFMT_422P16}, - {"422p10", IMGFMT_422P10}, - {"420p10", IMGFMT_420P10}, - {"420p9", IMGFMT_420P9}, - {"420p16", IMGFMT_420P16}, - {"420a", IMGFMT_420A}, - {"444p", IMGFMT_444P}, - {"422p", IMGFMT_422P}, - {"411p", IMGFMT_411P}, - {"440p", IMGFMT_440P}, - {"yuy2", IMGFMT_YUY2}, - {"uyvy", IMGFMT_UYVY}, - {"yvu9", IMGFMT_YVU9}, - {"if09", IMGFMT_IF09}, - {"yv12", IMGFMT_YV12}, - {"i420", IMGFMT_I420}, - {"iyuv", IMGFMT_IYUV}, - {"clpl", IMGFMT_CLPL}, - {"hm12", IMGFMT_HM12}, - {"y800", IMGFMT_Y800}, - {"y8", IMGFMT_Y8}, - {"nv12", IMGFMT_NV12}, - {"nv21", IMGFMT_NV21}, - {"bgr24", IMGFMT_BGR24}, - {"bgr32", IMGFMT_BGR32}, - {"bgr16", IMGFMT_BGR16}, - {"bgr15", IMGFMT_BGR15}, - {"bgr12", IMGFMT_BGR12}, - {"bgr8", IMGFMT_BGR8}, - {"bgr4", IMGFMT_BGR4}, - {"bg4b", IMGFMT_BG4B}, - {"bgr1", IMGFMT_BGR1}, - {"rgb48be", IMGFMT_RGB48BE}, - {"rgb48le", IMGFMT_RGB48LE}, - {"rgb48ne", IMGFMT_RGB48NE}, - {"rgb24", IMGFMT_RGB24}, - {"rgb32", IMGFMT_RGB32}, - {"rgb16", IMGFMT_RGB16}, - {"rgb15", IMGFMT_RGB15}, - {"rgb12", IMGFMT_RGB12}, - {"rgb8", IMGFMT_RGB8}, - {"rgb4", IMGFMT_RGB4}, - {"rg4b", IMGFMT_RG4B}, - {"rgb1", IMGFMT_RGB1}, - {"rgba", IMGFMT_RGBA}, - {"argb", IMGFMT_ARGB}, - {"bgra", IMGFMT_BGRA}, - {"abgr", IMGFMT_ABGR}, - {"mjpeg", IMGFMT_MJPEG}, - {"mjpg", IMGFMT_MJPEG}, - { NULL, 0 } + {"444p16le", IMGFMT_444P16_LE}, + {"444p16be", IMGFMT_444P16_BE}, + {"444p10le", IMGFMT_444P10_LE}, + {"444p10be", IMGFMT_444P10_BE}, + {"444p9le", IMGFMT_444P9_LE}, + {"444p9be", IMGFMT_444P9_BE}, + {"422p16le", IMGFMT_422P16_LE}, + {"422p16be", IMGFMT_422P16_BE}, + {"422p10le", IMGFMT_422P10_LE}, + {"422p10be", IMGFMT_422P10_BE}, + {"420p16le", IMGFMT_420P16_LE}, + {"420p16be", IMGFMT_420P16_BE}, + {"420p10le", IMGFMT_420P10_LE}, + {"420p10be", IMGFMT_420P10_BE}, + {"420p9le", IMGFMT_420P9_LE}, + {"420p9be", IMGFMT_420P9_BE}, + {"444p16", IMGFMT_444P16}, + {"444p10", IMGFMT_444P10}, + {"444p9", IMGFMT_444P9}, + {"422p16", IMGFMT_422P16}, + {"422p10", IMGFMT_422P10}, + {"420p10", IMGFMT_420P10}, + {"420p9", IMGFMT_420P9}, + {"420p16", IMGFMT_420P16}, + {"420a", IMGFMT_420A}, + {"444p", IMGFMT_444P}, + {"422p", IMGFMT_422P}, + {"411p", IMGFMT_411P}, + {"440p", IMGFMT_440P}, + {"yuy2", IMGFMT_YUY2}, + {"uyvy", IMGFMT_UYVY}, + {"yvu9", IMGFMT_YVU9}, + {"if09", IMGFMT_IF09}, + {"yv12", IMGFMT_YV12}, + {"i420", IMGFMT_I420}, + {"iyuv", IMGFMT_IYUV}, + {"clpl", IMGFMT_CLPL}, + {"hm12", IMGFMT_HM12}, + {"y800", IMGFMT_Y800}, + {"y8", IMGFMT_Y8}, + {"nv12", IMGFMT_NV12}, + {"nv21", IMGFMT_NV21}, + {"bgr24", IMGFMT_BGR24}, + {"bgr32", IMGFMT_BGR32}, + {"bgr16", IMGFMT_BGR16}, + {"bgr15", IMGFMT_BGR15}, + {"bgr12", IMGFMT_BGR12}, + {"bgr8", IMGFMT_BGR8}, + {"bgr4", IMGFMT_BGR4}, + {"bg4b", IMGFMT_BG4B}, + {"bgr1", IMGFMT_BGR1}, + {"rgb48be", IMGFMT_RGB48BE}, + {"rgb48le", IMGFMT_RGB48LE}, + {"rgb48ne", IMGFMT_RGB48NE}, + {"rgb24", IMGFMT_RGB24}, + {"rgb32", IMGFMT_RGB32}, + {"rgb16", IMGFMT_RGB16}, + {"rgb15", IMGFMT_RGB15}, + {"rgb12", IMGFMT_RGB12}, + {"rgb8", IMGFMT_RGB8}, + {"rgb4", IMGFMT_RGB4}, + {"rg4b", IMGFMT_RG4B}, + {"rgb1", IMGFMT_RGB1}, + {"rgba", IMGFMT_RGBA}, + {"argb", IMGFMT_ARGB}, + {"bgra", IMGFMT_BGRA}, + {"abgr", IMGFMT_ABGR}, + {"mjpeg", IMGFMT_MJPEG}, + {"mjpg", IMGFMT_MJPEG}, + { NULL, 0 } }; -static int parse_imgfmt(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - uint32_t fmt = 0; - int i; +static int parse_imgfmt(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + uint32_t fmt = 0; + int i; - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - if(!strcmp(param,"help")) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:"); - for(i = 0 ; mp_imgfmt_list[i].name ; i++) - mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s",mp_imgfmt_list[i].name); - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n"); - return M_OPT_EXIT - 1; - } - - if (sscanf(param, "0x%x", &fmt) != 1) - { - for(i = 0 ; mp_imgfmt_list[i].name ; i++) { - if(!strcasecmp(param,mp_imgfmt_list[i].name)) { - fmt=mp_imgfmt_list[i].fmt; - break; + if (!strcmp(param, "help")) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:"); + for (i = 0; mp_imgfmt_list[i].name; i++) + mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s", mp_imgfmt_list[i].name); + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n"); + return M_OPT_EXIT - 1; } - } - if(!mp_imgfmt_list[i].name) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",name,param); - return M_OPT_INVALID; - } - } - if(dst) - *((uint32_t*)dst) = fmt; + if (sscanf(param, "0x%x", &fmt) != 1) { + for (i = 0; mp_imgfmt_list[i].name; i++) { + if (!strcasecmp(param, mp_imgfmt_list[i].name)) { + fmt = mp_imgfmt_list[i].fmt; + break; + } + } + if (!mp_imgfmt_list[i].name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: unknown format name: '%s'\n", name, param); + return M_OPT_INVALID; + } + } - return 1; + if (dst) + *((uint32_t *)dst) = fmt; + + return 1; } const m_option_type_t m_option_type_imgfmt = { - "Image format", - "Please report any missing colorspaces.", - sizeof(uint32_t), - 0, - parse_imgfmt, - NULL, - copy_opt, - copy_opt, - NULL, - NULL + "Image format", + "Please report any missing colorspaces.", + sizeof(uint32_t), + 0, + parse_imgfmt, + NULL, + copy_opt, + copy_opt, + NULL, + NULL }; #include "libaf/af_format.h" /* FIXME: snyc with af_format.h */ static struct { - const char* name; - unsigned int fmt; + const char *name; + unsigned int fmt; } mp_afmt_list[] = { - // SPECIAL - {"mulaw", AF_FORMAT_MU_LAW}, - {"alaw", AF_FORMAT_A_LAW}, - {"mpeg2", AF_FORMAT_MPEG2}, - {"ac3le", AF_FORMAT_AC3_LE}, - {"ac3be", AF_FORMAT_AC3_BE}, - {"ac3ne", AF_FORMAT_AC3_NE}, - {"imaadpcm", AF_FORMAT_IMA_ADPCM}, - // ORDINARY - {"u8", AF_FORMAT_U8}, - {"s8", AF_FORMAT_S8}, - {"u16le", AF_FORMAT_U16_LE}, - {"u16be", AF_FORMAT_U16_BE}, - {"u16ne", AF_FORMAT_U16_NE}, - {"s16le", AF_FORMAT_S16_LE}, - {"s16be", AF_FORMAT_S16_BE}, - {"s16ne", AF_FORMAT_S16_NE}, - {"u24le", AF_FORMAT_U24_LE}, - {"u24be", AF_FORMAT_U24_BE}, - {"u24ne", AF_FORMAT_U24_NE}, - {"s24le", AF_FORMAT_S24_LE}, - {"s24be", AF_FORMAT_S24_BE}, - {"s24ne", AF_FORMAT_S24_NE}, - {"u32le", AF_FORMAT_U32_LE}, - {"u32be", AF_FORMAT_U32_BE}, - {"u32ne", AF_FORMAT_U32_NE}, - {"s32le", AF_FORMAT_S32_LE}, - {"s32be", AF_FORMAT_S32_BE}, - {"s32ne", AF_FORMAT_S32_NE}, - {"floatle", AF_FORMAT_FLOAT_LE}, - {"floatbe", AF_FORMAT_FLOAT_BE}, - {"floatne", AF_FORMAT_FLOAT_NE}, - { NULL, 0 } + // SPECIAL + {"mulaw", AF_FORMAT_MU_LAW}, + {"alaw", AF_FORMAT_A_LAW}, + {"mpeg2", AF_FORMAT_MPEG2}, + {"ac3le", AF_FORMAT_AC3_LE}, + {"ac3be", AF_FORMAT_AC3_BE}, + {"ac3ne", AF_FORMAT_AC3_NE}, + {"imaadpcm", AF_FORMAT_IMA_ADPCM}, + // ORDINARY + {"u8", AF_FORMAT_U8}, + {"s8", AF_FORMAT_S8}, + {"u16le", AF_FORMAT_U16_LE}, + {"u16be", AF_FORMAT_U16_BE}, + {"u16ne", AF_FORMAT_U16_NE}, + {"s16le", AF_FORMAT_S16_LE}, + {"s16be", AF_FORMAT_S16_BE}, + {"s16ne", AF_FORMAT_S16_NE}, + {"u24le", AF_FORMAT_U24_LE}, + {"u24be", AF_FORMAT_U24_BE}, + {"u24ne", AF_FORMAT_U24_NE}, + {"s24le", AF_FORMAT_S24_LE}, + {"s24be", AF_FORMAT_S24_BE}, + {"s24ne", AF_FORMAT_S24_NE}, + {"u32le", AF_FORMAT_U32_LE}, + {"u32be", AF_FORMAT_U32_BE}, + {"u32ne", AF_FORMAT_U32_NE}, + {"s32le", AF_FORMAT_S32_LE}, + {"s32be", AF_FORMAT_S32_BE}, + {"s32ne", AF_FORMAT_S32_NE}, + {"floatle", AF_FORMAT_FLOAT_LE}, + {"floatbe", AF_FORMAT_FLOAT_BE}, + {"floatne", AF_FORMAT_FLOAT_NE}, + { NULL, 0 } }; -static int parse_afmt(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - uint32_t fmt = 0; - int i; +static int parse_afmt(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + uint32_t fmt = 0; + int i; - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - if(!strcmp(param,"help")) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:"); - for(i = 0 ; mp_afmt_list[i].name ; i++) - mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s",mp_afmt_list[i].name); - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n"); - return M_OPT_EXIT - 1; - } - - if (sscanf(param, "0x%x", &fmt) != 1) - { - for(i = 0 ; mp_afmt_list[i].name ; i++) { - if(!strcasecmp(param,mp_afmt_list[i].name)) { - fmt=mp_afmt_list[i].fmt; - break; + if (!strcmp(param, "help")) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available formats:"); + for (i = 0; mp_afmt_list[i].name; i++) + mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %s", mp_afmt_list[i].name); + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n"); + return M_OPT_EXIT - 1; } - } - if(!mp_afmt_list[i].name) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: unknown format name: '%s'\n",name,param); - return M_OPT_INVALID; - } - } - if(dst) - *((uint32_t*)dst) = fmt; + if (sscanf(param, "0x%x", &fmt) != 1) { + for (i = 0; mp_afmt_list[i].name; i++) { + if (!strcasecmp(param, mp_afmt_list[i].name)) { + fmt = mp_afmt_list[i].fmt; + break; + } + } + if (!mp_afmt_list[i].name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: unknown format name: '%s'\n", name, param); + return M_OPT_INVALID; + } + } - return 1; + if (dst) + *((uint32_t *)dst) = fmt; + + return 1; } const m_option_type_t m_option_type_afmt = { - "Audio format", - "Please report any missing formats.", - sizeof(uint32_t), - 0, - parse_afmt, - NULL, - copy_opt, - copy_opt, - NULL, - NULL + "Audio format", + "Please report any missing formats.", + sizeof(uint32_t), + 0, + parse_afmt, + NULL, + copy_opt, + copy_opt, + NULL, + NULL }; int parse_timestring(const char *str, double *time, char endchar) { - int a, b, len; - double d; - *time = 0; /* ensure initialization for error cases */ - if (sscanf(str, "%d:%d:%lf%n", &a, &b, &d, &len) >= 3) - *time = 3600*a + 60*b + d; - else if (sscanf(str, "%d:%lf%n", &a, &d, &len) >= 2) - *time = 60*a + d; - else if (sscanf(str, "%lf%n", &d, &len) >= 1) - *time = d; - else - return 0; /* unsupported time format */ - if (str[len] && str[len] != endchar) - return 0; /* invalid extra characters at the end */ - return len; + int a, b, len; + double d; + *time = 0; /* ensure initialization for error cases */ + if (sscanf(str, "%d:%d:%lf%n", &a, &b, &d, &len) >= 3) + *time = 3600 * a + 60 * b + d; + else if (sscanf(str, "%d:%lf%n", &a, &d, &len) >= 2) + *time = 60 * a + d; + else if (sscanf(str, "%lf%n", &d, &len) >= 1) + *time = d; + else + return 0; /* unsupported time format */ + if (str[len] && str[len] != endchar) + return 0; /* invalid extra characters at the end */ + return len; } -static int parse_time(const m_option_t* opt,const char *name, const char *param, void* dst, int src) +static int parse_time(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) { - double time; + double time; - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - if (!parse_timestring(param, &time, 0)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid time: '%s'\n", - name,param); - return M_OPT_INVALID; - } + if (!parse_timestring(param, &time, 0)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid time: '%s'\n", + name, param); + return M_OPT_INVALID; + } - if (dst) - *(double *)dst = time; - return 1; + if (dst) + *(double *)dst = time; + return 1; } const m_option_type_t m_option_type_time = { - "Time", - "", - sizeof(double), - 0, - parse_time, - print_double, - copy_opt, - copy_opt, - NULL, - NULL + "Time", + "", + sizeof(double), + 0, + parse_time, + print_double, + copy_opt, + copy_opt, + NULL, + NULL }; // Time or size (-endpos) -static int parse_time_size(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - m_time_size_t ts; - char unit[4]; - double end_at; +static int parse_time_size(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + m_time_size_t ts; + char unit[4]; + double end_at; - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - ts.pos=0; - /* End at size parsing */ - if(sscanf(param, "%lf%3s", &end_at, unit) == 2) { - ts.type = END_AT_SIZE; - if(!strcasecmp(unit, "b")) - ; - else if(!strcasecmp(unit, "kb")) - end_at *= 1024; - else if(!strcasecmp(unit, "mb")) - end_at *= 1024*1024; - else if(!strcasecmp(unit, "gb")) - end_at *= 1024*1024*1024; - else - ts.type = END_AT_NONE; + ts.pos = 0; + /* End at size parsing */ + if (sscanf(param, "%lf%3s", &end_at, unit) == 2) { + ts.type = END_AT_SIZE; + if (!strcasecmp(unit, "b")) + ; + else if (!strcasecmp(unit, "kb")) + end_at *= 1024; + else if (!strcasecmp(unit, "mb")) + end_at *= 1024 * 1024; + else if (!strcasecmp(unit, "gb")) + end_at *= 1024 * 1024 * 1024; + else + ts.type = END_AT_NONE; - if (ts.type == END_AT_SIZE) { - ts.pos = end_at; - goto out; + if (ts.type == END_AT_SIZE) { + ts.pos = end_at; + goto out; + } } - } - /* End at time parsing. This has to be last because the parsing accepts - * even a number followed by garbage */ - if (!parse_timestring(param, &end_at, 0)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid time or size: '%s'\n", - name,param); - return M_OPT_INVALID; - } + /* End at time parsing. This has to be last because the parsing accepts + * even a number followed by garbage */ + if (!parse_timestring(param, &end_at, 0)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: invalid time or size: '%s'\n", + name, param); + return M_OPT_INVALID; + } - ts.type = END_AT_TIME; - ts.pos = end_at; + ts.type = END_AT_TIME; + ts.pos = end_at; out: - if(dst) - *(m_time_size_t *)dst = ts; - return 1; + if (dst) + *(m_time_size_t *)dst = ts; + return 1; } const m_option_type_t m_option_type_time_size = { - "Time or size", - "", - sizeof(m_time_size_t), - 0, - parse_time_size, - NULL, - copy_opt, - copy_opt, - NULL, - NULL + "Time or size", + "", + sizeof(m_time_size_t), + 0, + parse_time_size, + NULL, + copy_opt, + copy_opt, + NULL, + NULL }; @@ -1434,819 +1522,896 @@ const m_option_type_t m_option_type_time_size = { #include "m_struct.h" #undef VAL -#define VAL(x) (*(m_obj_settings_t**)(x)) +#define VAL(x) (*(m_obj_settings_t **)(x)) -static int find_obj_desc(const char* name,const m_obj_list_t* l,const m_struct_t** ret) { - int i; - char* n; +static int find_obj_desc(const char *name, const m_obj_list_t *l, + const m_struct_t **ret) +{ + int i; + char *n; - for(i = 0 ; l->list[i] ; i++) { - n = M_ST_MB(char*,l->list[i],l->name_off); - if(!strcmp(n,name)) { - *ret = M_ST_MB(m_struct_t*,l->list[i],l->desc_off); - return 1; + for (i = 0; l->list[i]; i++) { + n = M_ST_MB(char *, l->list[i], l->name_off); + if (!strcmp(n, name)) { + *ret = M_ST_MB(m_struct_t *, l->list[i], l->desc_off); + return 1; + } } - } - return 0; + return 0; } -static int get_obj_param(const char* opt_name,const char* obj_name, const m_struct_t* desc, - char* str,int* nold,int oldmax,char** dst) { - char* eq; - const m_option_t* opt; - int r; +static int get_obj_param(const char *opt_name, const char *obj_name, + const m_struct_t *desc, char *str, int *nold, + int oldmax, char **dst) +{ + char *eq; + const m_option_t *opt; + int r; - eq = strchr(str,'='); - if(eq && eq == str) - eq = NULL; + eq = strchr(str, '='); + if (eq && eq == str) + eq = NULL; - if(eq) { - char* p = eq + 1; - if(p[0] == '\0') p = NULL; - eq[0] = '\0'; - opt = m_option_list_find(desc->fields,str); - if(!opt) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't have a %s parameter.\n",opt_name,obj_name,str); - return M_OPT_UNKNOWN; + if (eq) { + char *p = eq + 1; + if (p[0] == '\0') + p = NULL; + eq[0] = '\0'; + opt = m_option_list_find(desc->fields, str); + if (!opt) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: %s doesn't have a %s parameter.\n", + opt_name, obj_name, str); + return M_OPT_UNKNOWN; + } + r = m_option_parse(opt, str, p, NULL, M_CONFIG_FILE); + if (r < 0) { + if (r > M_OPT_EXIT) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while parsing %s parameter %s (%s)\n", + opt_name, obj_name, str, p); + eq[0] = '='; + return r; + } + if (dst) { + dst[0] = strdup(str); + dst[1] = p ? strdup(p) : NULL; + } + eq[0] = '='; + } else { + if ((*nold) >= oldmax) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s has only %d params, so you can't give more than %d unnamed params.\n", + opt_name, obj_name, oldmax, oldmax); + return M_OPT_OUT_OF_RANGE; + } + opt = &desc->fields[(*nold)]; + r = m_option_parse(opt, opt->name, str, NULL, M_CONFIG_FILE); + if (r < 0) { + if (r > M_OPT_EXIT) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while parsing %s parameter %s (%s)\n", + opt_name, obj_name, opt->name, str); + return r; + } + if (dst) { + dst[0] = strdup(opt->name); + dst[1] = strdup(str); + } + (*nold)++; } - r = m_option_parse(opt,str,p,NULL,M_CONFIG_FILE); - if(r < 0) { - if(r > M_OPT_EXIT) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while parsing %s parameter %s (%s)\n",opt_name,obj_name,str,p); - eq[0] = '='; - return r; - } - if(dst) { - dst[0] = strdup(str); - dst[1] = p ? strdup(p) : NULL; - } - eq[0] = '='; - } else { - if((*nold) >= oldmax) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s has only %d params, so you can't give more than %d unnamed params.\n", - opt_name,obj_name,oldmax,oldmax); - return M_OPT_OUT_OF_RANGE; - } - opt = &desc->fields[(*nold)]; - r = m_option_parse(opt,opt->name,str,NULL,M_CONFIG_FILE); - if(r < 0) { - if(r > M_OPT_EXIT) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while parsing %s parameter %s (%s)\n",opt_name,obj_name,opt->name,str); - return r; - } - if(dst) { - dst[0] = strdup(opt->name); - dst[1] = strdup(str); - } - (*nold)++; - } - return 1; + return 1; } -static int get_obj_params(const char* opt_name, const char* name,char* params, - const m_struct_t* desc,char separator, char*** _ret) { - int n = 0,nold = 0, nopts,r; - char* ptr,*last_ptr = params; - char** ret; +static int get_obj_params(const char *opt_name, const char *name, char *params, + const m_struct_t *desc, char separator, char ***_ret) +{ + int n = 0, nold = 0, nopts, r; + char *ptr, *last_ptr = params; + char **ret; - if(!strcmp(params,"help")) { // Help - char min[50],max[50]; - if(!desc->fields) { - printf("%s doesn't have any options.\n\n",name); - return M_OPT_EXIT - 1; + if (!strcmp(params, "help")) { // Help + char min[50], max[50]; + if (!desc->fields) { + printf("%s doesn't have any options.\n\n", name); + return M_OPT_EXIT - 1; + } + printf("\n Name Type Min Max\n\n"); + for (n = 0; desc->fields[n].name; n++) { + const m_option_t *opt = &desc->fields[n]; + if (opt->type->flags & M_OPT_TYPE_HAS_CHILD) + continue; + if (opt->flags & M_OPT_MIN) + sprintf(min, "%-8.0f", opt->min); + else + strcpy(min, "No"); + if (opt->flags & M_OPT_MAX) + sprintf(max, "%-8.0f", opt->max); + else + strcpy(max, "No"); + printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n", + opt->name, + opt->type->name, + min, + max); + } + printf("\n"); + return M_OPT_EXIT - 1; } - printf("\n Name Type Min Max\n\n"); - for(n = 0 ; desc->fields[n].name ; n++) { - const m_option_t* opt = &desc->fields[n]; - if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; - if(opt->flags & M_OPT_MIN) - sprintf(min,"%-8.0f",opt->min); - else - strcpy(min,"No"); - if(opt->flags & M_OPT_MAX) - sprintf(max,"%-8.0f",opt->max); - else - strcpy(max,"No"); - printf(" %-20.20s %-15.15s %-10.10s %-10.10s\n", - opt->name, - opt->type->name, - min, - max); - } - printf("\n"); - return M_OPT_EXIT - 1; - } - for(nopts = 0 ; desc->fields[nopts].name ; nopts++) - /* NOP */; + for (nopts = 0; desc->fields[nopts].name; nopts++) + /* NOP */; - // TODO : Check that each opt can be parsed - r = 1; - while(last_ptr && last_ptr[0] != '\0') { - ptr = strchr(last_ptr,separator); - if(!ptr) { - r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); - n++; - break; + // TODO : Check that each opt can be parsed + r = 1; + while (last_ptr && last_ptr[0] != '\0') { + ptr = strchr(last_ptr, separator); + if (!ptr) { + r = get_obj_param(opt_name, name, desc, last_ptr, &nold, nopts, + NULL); + n++; + break; + } + if (ptr == last_ptr) { // Empty field, count it and go on + nold++; + last_ptr = ptr + 1; + continue; + } + ptr[0] = '\0'; + r = get_obj_param(opt_name, name, desc, last_ptr, &nold, nopts, NULL); + ptr[0] = separator; + if (r < 0) + break; + n++; + last_ptr = ptr + 1; } - if(ptr == last_ptr) { // Empty field, count it and go on - nold++; - last_ptr = ptr+1; - continue; + if (r < 0) + return r; + if (!last_ptr[0]) // count an empty field at the end, too + nold++; + if (nold > nopts) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Too many options for %s\n", name); + return M_OPT_OUT_OF_RANGE; } - ptr[0] = '\0'; - r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); - ptr[0] = separator; - if(r < 0) break; - n++; - last_ptr = ptr+1; - } - if(r < 0) return r; - if (!last_ptr[0]) // count an empty field at the end, too - nold++; - if (nold > nopts) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Too many options for %s\n", name); - return M_OPT_OUT_OF_RANGE; - } - if(!_ret) // Just test + if (!_ret) // Just test + return 1; + if (n == 0) // No options or only empty options + return 1; + + ret = malloc((n + 2) * 2 * sizeof(char *)); + n = nold = 0; + last_ptr = params; + + while (last_ptr && last_ptr[0] != '\0') { + ptr = strchr(last_ptr, separator); + if (!ptr) { + get_obj_param(opt_name, name, desc, last_ptr, &nold, nopts, + &ret[n * 2]); + n++; + break; + } + if (ptr == last_ptr) { // Empty field, count it and go on + last_ptr = ptr + 1; + nold++; + continue; + } + ptr[0] = '\0'; + get_obj_param(opt_name, name, desc, last_ptr, &nold, nopts, + &ret[n * 2]); + n++; + last_ptr = ptr + 1; + } + ret[n * 2] = ret[n * 2 + 1] = NULL; + *_ret = ret; + return 1; - if (n == 0) // No options or only empty options - return 1; - - ret = malloc((n+2)*2*sizeof(char*)); - n = nold = 0; - last_ptr = params; - - while(last_ptr && last_ptr[0] != '\0') { - ptr = strchr(last_ptr,separator); - if(!ptr) { - get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]); - n++; - break; - } - if(ptr == last_ptr) { // Empty field, count it and go on - last_ptr = ptr+1; - nold++; - continue; - } - ptr[0] = '\0'; - get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]); - n++; - last_ptr = ptr+1; - } - ret[n*2] = ret[n*2+1] = NULL; - *_ret = ret; - - return 1; } -static int parse_obj_params(const m_option_t* opt,const char *name, - const char *param, void* dst, int src) { - char** opts; - int r; - m_obj_params_t* p = opt->priv; - const m_struct_t* desc; - char* cpy; +static int parse_obj_params(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + char **opts; + int r; + m_obj_params_t *p = opt->priv; + const m_struct_t *desc; + char *cpy; - // We need the object desc - if(!p) - return M_OPT_INVALID; + // We need the object desc + if (!p) + return M_OPT_INVALID; + + desc = p->desc; + cpy = strdup(param); + r = get_obj_params(name, desc->name, cpy, desc, p->separator, + dst ? &opts : NULL); + free(cpy); + if (r < 0) + return r; + if (!dst) + return 1; + if (!opts) // no arguments given + return 1; + + for (r = 0; opts[r]; r += 2) + m_struct_set(desc, dst, opts[r], opts[r + 1]); - desc = p->desc; - cpy = strdup(param); - r = get_obj_params(name,desc->name,cpy,desc,p->separator,dst ? &opts : NULL); - free(cpy); - if(r < 0) - return r; - if(!dst) return 1; - if (!opts) // no arguments given - return 1; - - for(r = 0 ; opts[r] ; r += 2) - m_struct_set(desc,dst,opts[r],opts[r+1]); - - return 1; } const m_option_type_t m_option_type_obj_params = { - "Object params", - "", - 0, - 0, - parse_obj_params, - NULL, - NULL, - NULL, - NULL, - NULL + "Object params", + "", + 0, + 0, + parse_obj_params, + NULL, + NULL, + NULL, + NULL, + NULL }; /// Some predefined types as a definition would be quite lengthy /// Span arguments -static const m_span_t m_span_params_dflts = { -1, -1 }; +static const m_span_t m_span_params_dflts = { + -1, -1 +}; static const m_option_t m_span_params_fields[] = { - {"start", M_ST_OFF(m_span_t,start), CONF_TYPE_INT, M_OPT_MIN, 1 ,0, NULL}, - {"end", M_ST_OFF(m_span_t,end), CONF_TYPE_INT, M_OPT_MIN , 1 ,0, NULL}, - { NULL, NULL, 0, 0, 0, 0, NULL } + {"start", M_ST_OFF(m_span_t, start), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL}, + {"end", M_ST_OFF(m_span_t, end), CONF_TYPE_INT, M_OPT_MIN, 1, 0, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } }; static const struct m_struct_st m_span_opts = { - "m_span", - sizeof(m_span_t), - &m_span_params_dflts, - m_span_params_fields + "m_span", + sizeof(m_span_t), + &m_span_params_dflts, + m_span_params_fields }; const m_obj_params_t m_span_params_def = { - &m_span_opts, - '-' + &m_span_opts, + '-' }; -static int parse_obj_settings(const char* opt,char* str,const m_obj_list_t* list, - m_obj_settings_t **_ret, int ret_n) { - int r; - char *param,**plist = NULL; - const m_struct_t* desc; - m_obj_settings_t *ret = _ret ? *_ret : NULL; +static int parse_obj_settings(const char *opt, char *str, + const m_obj_list_t *list, + m_obj_settings_t **_ret, int ret_n) +{ + int r; + char *param, **plist = NULL; + const m_struct_t *desc; + m_obj_settings_t *ret = _ret ? *_ret : NULL; - // Now check that the object exists - param = strchr(str,'='); - if(param) { - param[0] = '\0'; - param++; - if(strlen(param) <= 0) - param = NULL; - } - - - if(!find_obj_desc(str,list,&desc)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't exist.\n",opt,str); - return M_OPT_INVALID; - } - - if(param) { - if(!desc && _ret) { - if(!strcmp(param,"help")) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Option %s: %s have no option description.\n",opt,str); - return M_OPT_EXIT - 1; - } - plist = calloc(4,sizeof(char*)); - plist[0] = strdup("_oldargs_"); - plist[1] = strdup(param); - } else if(desc) { - r = get_obj_params(opt,str,param,desc,':',_ret ? &plist : NULL); - if(r < 0) - return r; + // Now check that the object exists + param = strchr(str, '='); + if (param) { + param[0] = '\0'; + param++; + if (strlen(param) <= 0) + param = NULL; } - } - if(!_ret) + + + if (!find_obj_desc(str, list, &desc)) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: %s doesn't exist.\n", + opt, str); + return M_OPT_INVALID; + } + + if (param) { + if (!desc && _ret) { + if (!strcmp(param, "help")) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, + "Option %s: %s have no option description.\n", opt, str); + return M_OPT_EXIT - 1; + } + plist = calloc(4, sizeof(char *)); + plist[0] = strdup("_oldargs_"); + plist[1] = strdup(param); + } else if (desc) { + r = get_obj_params(opt, str, param, desc, ':', + _ret ? &plist : NULL); + if (r < 0) + return r; + } + } + if (!_ret) + return 1; + + ret = realloc(ret, (ret_n + 2) * sizeof(m_obj_settings_t)); + memset(&ret[ret_n], 0, 2 * sizeof(m_obj_settings_t)); + ret[ret_n].name = strdup(str); + ret[ret_n].attribs = plist; + + *_ret = ret; return 1; - - ret = realloc(ret,(ret_n+2)*sizeof(m_obj_settings_t)); - memset(&ret[ret_n],0,2*sizeof(m_obj_settings_t)); - ret[ret_n].name = strdup(str); - ret[ret_n].attribs = plist; - - *_ret = ret; - return 1; } -static int obj_settings_list_del(const char *opt_name,const char *param,void* dst, int src) { - char** str_list = NULL; - int r,i,idx_max = 0; - char* rem_id = "_removed_marker_"; - const m_option_t list_opt = {opt_name , NULL, CONF_TYPE_STRING_LIST, - 0, 0, 0, NULL }; - m_obj_settings_t* obj_list = dst ? VAL(dst) : NULL; +static int obj_settings_list_del(const char *opt_name, const char *param, + void *dst, int src) +{ + char **str_list = NULL; + int r, i, idx_max = 0; + char *rem_id = "_removed_marker_"; + const m_option_t list_opt = { + opt_name, NULL, CONF_TYPE_STRING_LIST, + 0, 0, 0, NULL + }; + m_obj_settings_t *obj_list = dst ? VAL(dst) : NULL; + + if (dst && !obj_list) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: the list is empty.\n", + opt_name); + return 1; + } else if (obj_list) { + for (idx_max = 0; obj_list[idx_max].name != NULL; idx_max++) + /* NOP */; + } + + r = m_option_parse(&list_opt, opt_name, param, &str_list, src); + if (r < 0 || !str_list) + return r; + + for (r = 0; str_list[r]; r++) { + int id; + char *endptr; + id = strtol(str_list[r], &endptr, 0); + if (endptr == str_list[r]) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid parameter. We need a list of integers which are the indices of the elements to remove.\n", opt_name); + m_option_free(&list_opt, &str_list); + return M_OPT_INVALID; + } + if (!obj_list) + continue; + if (id >= idx_max || id < -idx_max) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: Index %d is out of range.\n", opt_name, id); + continue; + } + if (id < 0) + id = idx_max + id; + free(obj_list[id].name); + free_str_list(&(obj_list[id].attribs)); + obj_list[id].name = rem_id; + } + + if (!dst) { + m_option_free(&list_opt, &str_list); + return 1; + } + + for (i = 0; obj_list[i].name; i++) { + while (obj_list[i].name == rem_id) { + memmove(&obj_list[i], &obj_list[i + 1], + sizeof(m_obj_settings_t) * (idx_max - i)); + idx_max--; + } + } + obj_list = realloc(obj_list, sizeof(m_obj_settings_t) * (idx_max + 1)); + VAL(dst) = obj_list; - if(dst && !obj_list) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: the list is empty.\n",opt_name); return 1; - } else if(obj_list) { - for(idx_max = 0 ; obj_list[idx_max].name != NULL ; idx_max++) - /* NOP */; - } - - r = m_option_parse(&list_opt,opt_name,param,&str_list,src); - if(r < 0 || !str_list) - return r; - - for(r = 0 ; str_list[r] ; r++) { - int id; - char* endptr; - id = strtol(str_list[r],&endptr,0); - if(endptr == str_list[r]) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: invalid parameter. We need a list of integers which are the indices of the elements to remove.\n",opt_name); - m_option_free(&list_opt,&str_list); - return M_OPT_INVALID; - } - if(!obj_list) continue; - if(id >= idx_max || id < -idx_max) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: Index %d is out of range.\n",opt_name,id); - continue; - } - if(id < 0) - id = idx_max + id; - free(obj_list[id].name); - free_str_list(&(obj_list[id].attribs)); - obj_list[id].name = rem_id; - } - - if(!dst) { - m_option_free(&list_opt,&str_list); - return 1; - } - - for(i = 0 ; obj_list[i].name ; i++) { - while(obj_list[i].name == rem_id) { - memmove(&obj_list[i],&obj_list[i+1],sizeof(m_obj_settings_t)*(idx_max - i)); - idx_max--; - } - } - obj_list = realloc(obj_list,sizeof(m_obj_settings_t)*(idx_max+1)); - VAL(dst) = obj_list; - - return 1; } -static void free_obj_settings_list(void* dst) { - int n; - m_obj_settings_t *d; +static void free_obj_settings_list(void *dst) +{ + int n; + m_obj_settings_t *d; - if (!dst || !VAL(dst)) return; + if (!dst || !VAL(dst)) + return; - d = VAL(dst); + d = VAL(dst); #ifndef NO_FREE - for (n = 0 ; d[n].name ; n++) { - free(d[n].name); - free_str_list(&(d[n].attribs)); - } - free(d); + for (n = 0; d[n].name; n++) { + free(d[n].name); + free_str_list(&(d[n].attribs)); + } + free(d); #endif - VAL(dst) = NULL; + VAL(dst) = NULL; } -static int parse_obj_settings_list(const m_option_t* opt,const char *name, - const char *param, void* dst, int src) { - int n = 0,r,len = strlen(opt->name); - char *str; - char *ptr, *last_ptr; - m_obj_settings_t *res = NULL,*queue = NULL,*head = NULL; - int op = OP_NONE; +static int parse_obj_settings_list(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + int n = 0, r, len = strlen(opt->name); + char *str; + char *ptr, *last_ptr; + m_obj_settings_t *res = NULL, *queue = NULL, *head = NULL; + int op = OP_NONE; - // We need the objects list - if(!opt->priv) - return M_OPT_INVALID; + // We need the objects list + if (!opt->priv) + return M_OPT_INVALID; - if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) { - const char* n = &name[len-1]; - if(strcasecmp(n,"-add") == 0) - op = OP_ADD; - else if(strcasecmp(n,"-pre") == 0) - op = OP_PRE; - else if(strcasecmp(n,"-del") == 0) - op = OP_DEL; - else if(strcasecmp(n,"-clr") == 0) - op = OP_CLR; - else { - char prefix[len]; - strncpy(prefix,opt->name,len-1); - prefix[len-1] = '\0'; - mp_msg(MSGT_VFILTER,MSGL_ERR, "Option %s: unknown postfix %s\n" - "Supported postfixes are:\n" - " %s-add\n" - " Append the given list to the current list\n\n" - " %s-pre\n" - " Prepend the given list to the current list\n\n" - " %s-del x,y,...\n" - " Remove the given elements. Take the list element index (starting from 0).\n" - " Negative index can be used (i.e. -1 is the last element)\n\n" - " %s-clr\n" - " Clear the current list.\n",name,n,prefix,prefix,prefix,prefix); + if (opt->name[len - 1] == '*' && ((int)strlen(name) > len - 1)) { + const char *n = &name[len - 1]; + if (strcasecmp(n, "-add") == 0) + op = OP_ADD; + else if (strcasecmp(n, "-pre") == 0) + op = OP_PRE; + else if (strcasecmp(n, "-del") == 0) + op = OP_DEL; + else if (strcasecmp(n, "-clr") == 0) + op = OP_CLR; + else { + char prefix[len]; + strncpy(prefix, opt->name, len - 1); + prefix[len - 1] = '\0'; + mp_msg(MSGT_VFILTER, MSGL_ERR, "Option %s: unknown postfix %s\n" + "Supported postfixes are:\n" + " %s-add\n" + " Append the given list to the current list\n\n" + " %s-pre\n" + " Prepend the given list to the current list\n\n" + " %s-del x,y,...\n" + " Remove the given elements. Take the list element index (starting from 0).\n" + " Negative index can be used (i.e. -1 is the last element)\n\n" + " %s-clr\n" + " Clear the current list.\n", + name, n, prefix, prefix, prefix, prefix); - return M_OPT_UNKNOWN; + return M_OPT_UNKNOWN; + } } - } - // Clear the list ?? - if(op == OP_CLR) { - if(dst) - free_obj_settings_list(dst); - return 0; - } - - if (param == NULL || strlen(param) == 0) - return M_OPT_MISSING_PARAM; - - switch(op) { - case OP_ADD: - if(dst) head = VAL(dst); - break; - case OP_PRE: - if(dst) queue = VAL(dst); - break; - case OP_DEL: - return obj_settings_list_del(name,param,dst,src); - case OP_NONE: - if(dst && VAL(dst)) - free_obj_settings_list(dst); - break; - default: - mp_msg(MSGT_VFILTER,MSGL_ERR, "Option %s: FIXME\n",name); - return M_OPT_UNKNOWN; - } - - if(!strcmp(param,"help")) { - m_obj_list_t* ol = opt->priv; - mp_msg(MSGT_VFILTER,MSGL_INFO,"Available video filters:\n"); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_FILTERS\n"); - for(n = 0 ; ol->list[n] ; n++) - mp_msg(MSGT_VFILTER,MSGL_INFO," %-15s: %s\n", - M_ST_MB(char*,ol->list[n],ol->name_off), - M_ST_MB(char*,ol->list[n],ol->info_off)); - mp_msg(MSGT_VFILTER,MSGL_INFO,"\n"); - return M_OPT_EXIT - 1; - } - ptr = str = strdup(param); - - while(ptr[0] != '\0') { - last_ptr = ptr; - ptr = get_nextsep(ptr, OPTION_LIST_SEPARATOR, 1); - - if(!ptr) { - r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n); - if(r < 0) { - free(str); - return r; - } - n++; - break; + // Clear the list ?? + if (op == OP_CLR) { + if (dst) + free_obj_settings_list(dst); + return 0; } - ptr[0] = '\0'; - r = parse_obj_settings(name,last_ptr,opt->priv,dst ? &res : NULL,n); - if(r < 0) { - free(str); - return r; - } - ptr++; - n++; - } - free(str); - if(n == 0) - return M_OPT_INVALID; - if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) || - ((opt->flags & M_OPT_MAX) && (n > opt->max)) ) - return M_OPT_OUT_OF_RANGE; + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; - if(dst) { - if(queue) { - int qsize; - for(qsize = 0 ; queue[qsize].name ; qsize++) - /* NOP */; - res = realloc(res,(qsize+n+1)*sizeof(m_obj_settings_t)); - memcpy(&res[n],queue,(qsize+1)*sizeof(m_obj_settings_t)); - n += qsize; - free(queue); + switch (op) { + case OP_ADD: + if (dst) + head = VAL(dst); + break; + case OP_PRE: + if (dst) + queue = VAL(dst); + break; + case OP_DEL: + return obj_settings_list_del(name, param, dst, src); + case OP_NONE: + if (dst && VAL(dst)) + free_obj_settings_list(dst); + break; + default: + mp_msg(MSGT_VFILTER, MSGL_ERR, "Option %s: FIXME\n", name); + return M_OPT_UNKNOWN; } - if(head) { - int hsize; - for(hsize = 0 ; head[hsize].name ; hsize++) - /* NOP */; - head = realloc(head,(hsize+n+1)*sizeof(m_obj_settings_t)); - memcpy(&head[hsize],res,(n+1)*sizeof(m_obj_settings_t)); - free(res); - res = head; + + if (!strcmp(param, "help")) { + m_obj_list_t *ol = opt->priv; + mp_msg(MSGT_VFILTER, MSGL_INFO, "Available video filters:\n"); + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_FILTERS\n"); + for (n = 0; ol->list[n]; n++) + mp_msg(MSGT_VFILTER, MSGL_INFO, " %-15s: %s\n", + M_ST_MB(char *, ol->list[n], ol->name_off), + M_ST_MB(char *, ol->list[n], ol->info_off)); + mp_msg(MSGT_VFILTER, MSGL_INFO, "\n"); + return M_OPT_EXIT - 1; } - VAL(dst) = res; - } - return 1; + ptr = str = strdup(param); + + while (ptr[0] != '\0') { + last_ptr = ptr; + ptr = get_nextsep(ptr, OPTION_LIST_SEPARATOR, 1); + + if (!ptr) { + r = parse_obj_settings(name, last_ptr, opt->priv, + dst ? &res : NULL, n); + if (r < 0) { + free(str); + return r; + } + n++; + break; + } + ptr[0] = '\0'; + r = parse_obj_settings(name, last_ptr, opt->priv, dst ? &res : NULL, n); + if (r < 0) { + free(str); + return r; + } + ptr++; + n++; + } + free(str); + if (n == 0) + return M_OPT_INVALID; + + if (((opt->flags & M_OPT_MIN) && (n < opt->min)) || + ((opt->flags & M_OPT_MAX) && (n > opt->max))) + return M_OPT_OUT_OF_RANGE; + + if (dst) { + if (queue) { + int qsize; + for (qsize = 0; queue[qsize].name; qsize++) + /* NOP */; + res = realloc(res, (qsize + n + 1) * sizeof(m_obj_settings_t)); + memcpy(&res[n], queue, (qsize + 1) * sizeof(m_obj_settings_t)); + n += qsize; + free(queue); + } + if (head) { + int hsize; + for (hsize = 0; head[hsize].name; hsize++) + /* NOP */; + head = realloc(head, (hsize + n + 1) * sizeof(m_obj_settings_t)); + memcpy(&head[hsize], res, (n + 1) * sizeof(m_obj_settings_t)); + free(res); + res = head; + } + VAL(dst) = res; + } + return 1; } -static void copy_obj_settings_list(const m_option_t* opt,void* dst, const void* src) { - m_obj_settings_t *d,*s; - int n; +static void copy_obj_settings_list(const m_option_t *opt, void *dst, + const void *src) +{ + m_obj_settings_t *d, *s; + int n; - if(!(dst && src)) - return; + if (!(dst && src)) + return; - s = VAL(src); + s = VAL(src); - if(VAL(dst)) - free_obj_settings_list(dst); - if(!s) return; + if (VAL(dst)) + free_obj_settings_list(dst); + if (!s) + return; - for(n = 0 ; s[n].name ; n++) - /* NOP */; - d = malloc((n+1)*sizeof(m_obj_settings_t)); - for(n = 0 ; s[n].name ; n++) { - d[n].name = strdup(s[n].name); + for (n = 0; s[n].name; n++) + /* NOP */; + d = malloc((n + 1) * sizeof(m_obj_settings_t)); + for (n = 0; s[n].name; n++) { + d[n].name = strdup(s[n].name); + d[n].attribs = NULL; + copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs)); + } + d[n].name = NULL; d[n].attribs = NULL; - copy_str_list(NULL,&(d[n].attribs),&(s[n].attribs)); - } - d[n].name = NULL; - d[n].attribs = NULL; - VAL(dst) = d; + VAL(dst) = d; } const m_option_type_t m_option_type_obj_settings_list = { - "Object settings list", - "", - sizeof(m_obj_settings_t*), - M_OPT_TYPE_DYNAMIC|M_OPT_TYPE_ALLOW_WILDCARD, - parse_obj_settings_list, - NULL, - copy_obj_settings_list, - copy_obj_settings_list, - copy_obj_settings_list, - free_obj_settings_list, + "Object settings list", + "", + sizeof(m_obj_settings_t *), + M_OPT_TYPE_DYNAMIC | M_OPT_TYPE_ALLOW_WILDCARD, + parse_obj_settings_list, + NULL, + copy_obj_settings_list, + copy_obj_settings_list, + copy_obj_settings_list, + free_obj_settings_list, }; -static int parse_obj_presets(const m_option_t* opt,const char *name, - const char *param, void* dst, int src) { - m_obj_presets_t* obj_p = (m_obj_presets_t*)opt->priv; - const m_struct_t *in_desc; - const m_struct_t *out_desc; - int s,i; - const unsigned char *pre; - char* pre_name = NULL; +static int parse_obj_presets(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + m_obj_presets_t *obj_p = (m_obj_presets_t *)opt->priv; + const m_struct_t *in_desc; + const m_struct_t *out_desc; + int s, i; + const unsigned char *pre; + char *pre_name = NULL; - if(!obj_p) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Presets need a pointer to a m_obj_presets_t in the priv field.\n",name); - return M_OPT_PARSER_ERR; - } - - if(!param) - return M_OPT_MISSING_PARAM; - - pre = obj_p->presets; - in_desc = obj_p->in_desc; - out_desc = obj_p->out_desc ? obj_p->out_desc : obj_p->in_desc; - s = in_desc->size; - - if(!strcmp(param,"help")) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available presets for %s->%s:",out_desc->name,name); - for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; - pre += s) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name); - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); - return M_OPT_EXIT - 1; - } - - for(pre_name = M_ST_MB(char*,pre,obj_p->name_off) ; pre_name ; - pre += s, pre_name = M_ST_MB(char*,pre,obj_p->name_off)) { - if(!strcmp(pre_name,param)) break; - } - if(!pre_name) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: There is no preset named %s\n" - "Available presets are:",name,param); - for(pre = obj_p->presets;(pre_name = M_ST_MB(char*,pre,obj_p->name_off)) ; - pre += s) - mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s",pre_name); - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); - return M_OPT_INVALID; - } - - if(!dst) return 1; - - for(i = 0 ; in_desc->fields[i].name ; i++) { - const m_option_t* out_opt = m_option_list_find(out_desc->fields, - in_desc->fields[i].name); - if(!out_opt) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Unable to find the target option for field %s.\nPlease report this to the developers.\n",name,in_desc->fields[i].name); - return M_OPT_PARSER_ERR; + if (!obj_p) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Presets need a " + "pointer to a m_obj_presets_t in the priv field.\n", name); + return M_OPT_PARSER_ERR; } - m_option_copy(out_opt,M_ST_MB_P(dst,out_opt->p),M_ST_MB_P(pre,in_desc->fields[i].p)); - } - return 1; + + if (!param) + return M_OPT_MISSING_PARAM; + + pre = obj_p->presets; + in_desc = obj_p->in_desc; + out_desc = obj_p->out_desc ? obj_p->out_desc : obj_p->in_desc; + s = in_desc->size; + + if (!strcmp(param, "help")) { + mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available presets for %s->%s:", + out_desc->name, name); + for (pre = obj_p->presets; + (pre_name = M_ST_MB(char *, pre, obj_p->name_off)); pre += s) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s", pre_name); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); + return M_OPT_EXIT - 1; + } + + for (pre_name = M_ST_MB(char *, pre, obj_p->name_off); pre_name; + pre += s, pre_name = M_ST_MB(char *, pre, obj_p->name_off)) + if (!strcmp(pre_name, param)) + break; + if (!pre_name) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: There is no preset named %s\n" + "Available presets are:", name, param); + for (pre = obj_p->presets; + (pre_name = M_ST_MB(char *, pre, obj_p->name_off)); pre += s) + mp_msg(MSGT_CFGPARSER, MSGL_ERR, " %s", pre_name); + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "\n"); + return M_OPT_INVALID; + } + + if (!dst) + return 1; + + for (i = 0; in_desc->fields[i].name; i++) { + const m_option_t *out_opt = m_option_list_find(out_desc->fields, + in_desc->fields[i].name); + if (!out_opt) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Unable to find the target option for field %s.\n" + "Please report this to the developers.\n", + name, in_desc->fields[i].name); + return M_OPT_PARSER_ERR; + } + m_option_copy(out_opt, M_ST_MB_P(dst, out_opt->p), + M_ST_MB_P(pre, in_desc->fields[i].p)); + } + return 1; } const m_option_type_t m_option_type_obj_presets = { - "Object presets", - "", - 0, - 0, - parse_obj_presets, - NULL, - NULL, - NULL, - NULL, - NULL + "Object presets", + "", + 0, + 0, + parse_obj_presets, + NULL, + NULL, + NULL, + NULL, + NULL }; -static int parse_custom_url(const m_option_t* opt,const char *name, - const char *url, void* dst, int src) { - int pos1, pos2, r, v6addr = 0; - char *ptr1=NULL, *ptr2=NULL, *ptr3=NULL, *ptr4=NULL; - m_struct_t* desc = opt->priv; +static int parse_custom_url(const m_option_t *opt, const char *name, + const char *url, void *dst, int src) +{ + int pos1, pos2, r, v6addr = 0; + char *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL, *ptr4 = NULL; + m_struct_t *desc = opt->priv; - if(!desc) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Custom URL needs a pointer to a m_struct_t in the priv field.\n",name); - return M_OPT_PARSER_ERR; - } - - // extract the protocol - ptr1 = strstr(url, "://"); - if( ptr1==NULL ) { - // Filename only - if(m_option_list_find(desc->fields,"filename")) { - m_struct_set(desc,dst,"filename",url); - return 1; + if (!desc) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Custom URL needs " + "a pointer to a m_struct_t in the priv field.\n", name); + return M_OPT_PARSER_ERR; } - mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Option %s: URL doesn't have a valid protocol!\n",name); - return M_OPT_INVALID; - } - if(m_option_list_find(desc->fields,"string")) { - if(strlen(ptr1)>3) { - m_struct_set(desc,dst,"string",ptr1+3); - return 1; + + // extract the protocol + ptr1 = strstr(url, "://"); + if (ptr1 == NULL) { + // Filename only + if (m_option_list_find(desc->fields, "filename")) { + m_struct_set(desc, dst, "filename", url); + return 1; + } + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: URL doesn't have a valid protocol!\n", name); + return M_OPT_INVALID; } - } - pos1 = ptr1-url; - if(dst && m_option_list_find(desc->fields,"protocol")) { - ptr1[0] = '\0'; - r = m_struct_set(desc,dst,"protocol",url); - ptr1[0] = ':'; - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting protocol.\n",name); - return r; + if (m_option_list_find(desc->fields, "string")) { + if (strlen(ptr1) > 3) { + m_struct_set(desc, dst, "string", ptr1 + 3); + return 1; + } + } + pos1 = ptr1 - url; + if (dst && m_option_list_find(desc->fields, "protocol")) { + ptr1[0] = '\0'; + r = m_struct_set(desc, dst, "protocol", url); + ptr1[0] = ':'; + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting protocol.\n", name); + return r; + } } - } - // jump the "://" - ptr1 += 3; - pos1 += 3; + // jump the "://" + ptr1 += 3; + pos1 += 3; - // check if a username:password is given - ptr2 = strstr(ptr1, "@"); - ptr3 = strstr(ptr1, "/"); - if( ptr3!=NULL && ptr3fields,"username")) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: This URL doesn't have a username part.\n",name); - // skip + // We got something, at least a username... + if (!m_option_list_find(desc->fields, "username")) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: This URL doesn't have a username part.\n", name); + // skip + } else { + ptr3 = strstr(ptr1, ":"); + if (ptr3 != NULL && ptr3 < ptr2) { + // We also have a password + if (!m_option_list_find(desc->fields, "password")) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: This URL doesn't have a password part.\n", + name); + // skip + } else { // Username and password + if (dst) { + ptr3[0] = '\0'; + r = m_struct_set(desc, dst, "username", ptr1); + ptr3[0] = ':'; + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting username.\n", + name); + return r; + } + ptr2[0] = '\0'; + r = m_struct_set(desc, dst, "password", ptr3 + 1); + ptr2[0] = '@'; + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting password.\n", + name); + return r; + } + } + } + } else { // User name only + ptr2[0] = '\0'; + r = m_struct_set(desc, dst, "username", ptr1); + ptr2[0] = '@'; + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting username.\n", name); + return r; + } + } + } + ptr1 = ptr2 + 1; + pos1 = ptr1 - url; + } + + // Before looking for a port number check if we have an IPv6 type + // numeric address. + // In an IPv6 URL the numeric address should be inside square braces. + ptr2 = strstr(ptr1, "["); + ptr3 = strstr(ptr1, "]"); + // If the [] is after the first it isn't the hostname + ptr4 = strstr(ptr1, "/"); + if (ptr2 != NULL && ptr3 != NULL && (ptr2 < ptr3) + && (!ptr4 || ptr4 > ptr3)) { + // we have an IPv6 numeric address + ptr1++; + pos1++; + ptr2 = ptr3; + v6addr = 1; + } else + ptr2 = ptr1; + + // look if the port is given + ptr2 = strstr(ptr2, ":"); + // If the : is after the first / it isn't the port + ptr3 = strstr(ptr1, "/"); + if (ptr3 && ptr3 - ptr2 < 0) + ptr2 = NULL; + if (ptr2 == NULL) { + // No port is given + // Look if a path is given + if (ptr3 == NULL) { + // No path/filename + // So we have an URL like http://www.hostname.com + pos2 = strlen(url); + } else { + // We have an URL like http://www.hostname.com/file.txt + pos2 = ptr3 - url; + } } else { - ptr3 = strstr(ptr1, ":"); - if( ptr3!=NULL && ptr3fields,"password")) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: This URL doesn't have a password part.\n",name); - // skip - } else { // Username and password - if(dst) { - ptr3[0] = '\0'; - r = m_struct_set(desc,dst,"username",ptr1); - ptr3[0] = ':'; - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting username.\n",name); - return r; - } - ptr2[0] = '\0'; - r = m_struct_set(desc,dst,"password",ptr3+1); - ptr2[0] = '@'; - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting password.\n",name); - return r; - } - } - } - } else { // User name only - ptr2[0] = '\0'; - r = m_struct_set(desc,dst,"username",ptr1); - ptr2[0] = '@'; - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting username.\n",name); - return r; - } - } + // We have an URL beginning like http://www.hostname.com:1212 + // Get the port number + if (!m_option_list_find(desc->fields, "port")) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: This URL doesn't have a port part.\n", name); + // skip + } else { + if (dst) { + int p = atoi(ptr2 + 1); + char tmp[100]; + snprintf(tmp, 99, "%d", p); + r = m_struct_set(desc, dst, "port", tmp); + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting port.\n", name); + return r; + } + } + } + pos2 = ptr2 - url; + } + if (v6addr) + pos2--; + // Get the hostname + if (pos2 - pos1 > 0) { + if (!m_option_list_find(desc->fields, "hostname")) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: This URL doesn't have a hostname part.\n", name); + // skip + } else { + char tmp[pos2 - pos1 + 1]; + strncpy(tmp, ptr1, pos2 - pos1); + tmp[pos2 - pos1] = '\0'; + r = m_struct_set(desc, dst, "hostname", tmp); + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting hostname.\n", name); + return r; + } + } } - ptr1 = ptr2+1; - pos1 = ptr1-url; - } - - // before looking for a port number check if we have an IPv6 type numeric address - // in an IPv6 URL the numeric address should be inside square braces. - ptr2 = strstr(ptr1, "["); - ptr3 = strstr(ptr1, "]"); - // If the [] is after the first it isn't the hostname - ptr4 = strstr(ptr1, "/"); - if( ptr2!=NULL && ptr3!=NULL && (ptr2 < ptr3) && (!ptr4 || ptr4 > ptr3)) { - // we have an IPv6 numeric address - ptr1++; - pos1++; - ptr2 = ptr3; - v6addr = 1; - } else { - ptr2 = ptr1; - } - - // look if the port is given - ptr2 = strstr(ptr2, ":"); - // If the : is after the first / it isn't the port - ptr3 = strstr(ptr1, "/"); - if(ptr3 && ptr3 - ptr2 < 0) ptr2 = NULL; - if( ptr2==NULL ) { - // No port is given // Look if a path is given - if( ptr3==NULL ) { - // No path/filename - // So we have an URL like http://www.hostname.com - pos2 = strlen(url); - } else { - // We have an URL like http://www.hostname.com/file.txt - pos2 = ptr3-url; + ptr2 = strstr(ptr1, "/"); + if (ptr2 != NULL) { + // A path/filename is given + // check if it's not a trailing '/' + if (strlen(ptr2) > 1) { + // copy the path/filename in the URL container + if (!m_option_list_find(desc->fields, "filename")) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %s: This URL doesn't have a hostname part.\n", + name); + // skip + } else { + if (dst) { + int l = strlen(ptr2 + 1) + 1; + char *fname = ptr2 + 1; + if (l > 1) { + fname = malloc(l); + url_unescape_string(fname, ptr2 + 1); + } + r = m_struct_set(desc, dst, "filename", fname); + if (fname != ptr2 + 1) + free(fname); + if (r < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %s: Error while setting filename.\n", + name); + return r; + } + } + } + } } - } else { - // We have an URL beginning like http://www.hostname.com:1212 - // Get the port number - if(!m_option_list_find(desc->fields,"port")) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: This URL doesn't have a port part.\n",name); - // skip - } else { - if(dst) { - int p = atoi(ptr2+1); - char tmp[100]; - snprintf(tmp,99,"%d",p); - r = m_struct_set(desc,dst,"port",tmp); - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting port.\n",name); - return r; - } - } - } - pos2 = ptr2-url; - } - if( v6addr ) pos2--; - // Get the hostname - if(pos2-pos1 > 0) { - if(!m_option_list_find(desc->fields,"hostname")) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: This URL doesn't have a hostname part.\n",name); - // skip - } else { - char tmp[pos2-pos1+1]; - strncpy(tmp,ptr1, pos2-pos1); - tmp[pos2-pos1] = '\0'; - r = m_struct_set(desc,dst,"hostname",tmp); - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting hostname.\n",name); - return r; - } - } - } - // Look if a path is given - ptr2 = strstr(ptr1, "/"); - if( ptr2!=NULL ) { - // A path/filename is given - // check if it's not a trailing '/' - if( strlen(ptr2)>1 ) { - // copy the path/filename in the URL container - if(!m_option_list_find(desc->fields,"filename")) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %s: This URL doesn't have a hostname part.\n",name); - // skip - } else { - if(dst) { - int l = strlen(ptr2+1) + 1; - char* fname = ptr2+1; - if(l > 1) { - fname = malloc(l); - url_unescape_string(fname,ptr2+1); - } - r = m_struct_set(desc,dst,"filename",fname); - if(fname != ptr2+1) - free(fname); - if(r < 0) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %s: Error while setting filename.\n",name); - return r; - } - } - } - } - } - return 1; + return 1; } /// TODO : Write the other needed funcs for 'normal' options const m_option_type_t m_option_type_custom_url = { - "Custom URL", - "", - 0, - 0, - parse_custom_url, - NULL, - NULL, - NULL, - NULL, - NULL + "Custom URL", + "", + 0, + 0, + parse_custom_url, + NULL, + NULL, + NULL, + NULL, + NULL }; diff --git a/m_option.h b/m_option.h index 00a5e60305..77dddcef1d 100644 --- a/m_option.h +++ b/m_option.h @@ -24,24 +24,13 @@ #include "config.h" -/// \defgroup Options -/// m_option allows to parse, print and copy data of various types. -/// It is the base of the \ref OptionsStruct, \ref Config and -/// \ref Properties APIs. -///@{ +// m_option allows to parse, print and copy data of various types. -/// \file m_option.h - -/// \ingroup OptionTypes typedef struct m_option_type m_option_type_t; typedef struct m_option m_option_t; struct m_struct_st; -/// \defgroup OptionTypes Options types -/// \ingroup Options -///@{ - -///////////////////////////// Options types declarations //////////////////////////// +///////////////////////////// Options types declarations //////////////////// // Simple types extern const m_option_type_t m_option_type_flag; @@ -68,16 +57,16 @@ extern const m_option_type_t m_option_type_afmt; extern const m_option_type_t m_option_type_func_param; extern const m_option_type_t m_option_type_func; -/// Callback used to reset func options. -typedef void (*m_opt_default_func_t)(const m_option_t *, const char*); +// Callback used to reset func options. +typedef void (*m_opt_default_func_t)(const m_option_t *, const char *); -/// Callback used by m_option_type_func_full options. +// Callback used by m_option_type_func_full options. typedef int (*m_opt_func_full_t)(const m_option_t *, const char *, const char *); -/// Callback used by m_option_type_func_param options. +// Callback used by m_option_type_func_param options. typedef int (*m_opt_func_param_t)(const m_option_t *, const char *); -/// Callback used by m_option_type_func options. +// Callback used by m_option_type_func options. typedef int (*m_opt_func_t)(const m_option_t *); // Backwards compatibility @@ -90,51 +79,51 @@ typedef m_opt_func_t cfg_func_t; #define END_AT_TIME 1 #define END_AT_SIZE 2 typedef struct { - double pos; - int type; + double pos; + int type; } m_time_size_t; -/// Extra definition needed for \ref m_option_type_obj_settings_list options. +// Extra definition needed for \ref m_option_type_obj_settings_list options. typedef struct { - /// Pointer to an array of pointer to some object type description struct. - void** list; - /// Offset of the object type name (char*) in the description struct. - void* name_off; - /// Offset of the object type info string (char*) in the description struct. - void* info_off; - /// \brief Offset of the object type parameter description (\ref m_struct_st) - /// in the description struct. - void* desc_off; + // Pointer to an array of pointer to some object type description struct. + void **list; + // Offset of the object type name (char*) in the description struct. + void *name_off; + // Offset of the object type info string (char*) in the description struct. + void *info_off; + // Offset of the object type parameter description (\ref m_struct_st) + // in the description struct. + void *desc_off; } m_obj_list_t; -/// The data type used by \ref m_option_type_obj_settings_list. +// The data type used by \ref m_option_type_obj_settings_list. typedef struct m_obj_settings { - /// Type of the object. - char* name; - /// NULL terminated array of parameter/value pairs. - char** attribs; + // Type of the object. + char *name; + // NULL terminated array of parameter/value pairs. + char **attribs; } m_obj_settings_t; -/// A parser to set up a list of objects. +// A parser to set up a list of objects. /** It creates a NULL terminated array \ref m_obj_settings. The option priv * field (\ref m_option::priv) must point to a \ref m_obj_list_t describing * the available object types. */ extern const m_option_type_t m_option_type_obj_settings_list; -/// Extra definition needed for \ref m_option_type_obj_presets options. +// Extra definition needed for \ref m_option_type_obj_presets options. typedef struct { - /// Description of the struct holding the presets. - const struct m_struct_st *in_desc; - /// Description of the struct that should be set by the presets. - const struct m_struct_st *out_desc; - /// Pointer to an array of structs defining the various presets. - const void *presets; - /// Offset of the preset's name inside the in_struct. - void* name_off; + // Description of the struct holding the presets. + const struct m_struct_st *in_desc; + // Description of the struct that should be set by the presets. + const struct m_struct_st *out_desc; + // Pointer to an array of structs defining the various presets. + const void *presets; + // Offset of the preset's name inside the in_struct. + void *name_off; } m_obj_presets_t; -/// Set several fields in a struct at once. +// Set several fields in a struct at once. /** For this two struct descriptions are used. One for the struct holding the * preset and one for the struct beeing set. Every field present in both * structs will be copied from the preset struct to the destination one. @@ -143,21 +132,21 @@ typedef struct { */ extern const m_option_type_t m_option_type_obj_presets; -/// Parse an URL into a struct. +// Parse an URL into a struct. /** The option priv field (\ref m_option::priv) must point to a * \ref m_struct_st describing which fields of the URL must be used. */ extern const m_option_type_t m_option_type_custom_url; -/// Extra definition needed for \ref m_option_type_obj_params options. +// Extra definition needed for \ref m_option_type_obj_params options. typedef struct { - /// Field descriptions. - const struct m_struct_st* desc; - /// Field separator to use. - char separator; + // Field descriptions. + const struct m_struct_st *desc; + // Field separator to use. + char separator; } m_obj_params_t; -/// Parse a set of parameters. +// Parse a set of parameters. /** Parameters are separated by the given separator and each one * successively sets a field from the struct. The option priv field * (\ref m_option::priv) must point to a \ref m_obj_params_t. @@ -165,10 +154,10 @@ typedef struct { extern const m_option_type_t m_option_type_obj_params; typedef struct { - int start; - int end; + int start; + int end; } m_span_t; -/// Ready made settings to parse a \ref m_span_t with a start-end syntax. +// Ready made settings to parse a \ref m_span_t with a start-end syntax. extern const m_obj_params_t m_span_params_def; struct m_opt_choice_alternatives { @@ -178,204 +167,186 @@ struct m_opt_choice_alternatives { // FIXME: backward compatibility -#define CONF_TYPE_FLAG (&m_option_type_flag) -#define CONF_TYPE_INT (&m_option_type_int) -#define CONF_TYPE_INT64 (&m_option_type_int64) -#define CONF_TYPE_FLOAT (&m_option_type_float) -#define CONF_TYPE_DOUBLE (&m_option_type_double) -#define CONF_TYPE_STRING (&m_option_type_string) -#define CONF_TYPE_FUNC (&m_option_type_func) -#define CONF_TYPE_FUNC_PARAM (&m_option_type_func_param) -#define CONF_TYPE_PRINT (&m_option_type_print) +#define CONF_TYPE_FLAG (&m_option_type_flag) +#define CONF_TYPE_INT (&m_option_type_int) +#define CONF_TYPE_INT64 (&m_option_type_int64) +#define CONF_TYPE_FLOAT (&m_option_type_float) +#define CONF_TYPE_DOUBLE (&m_option_type_double) +#define CONF_TYPE_STRING (&m_option_type_string) +#define CONF_TYPE_FUNC (&m_option_type_func) +#define CONF_TYPE_FUNC_PARAM (&m_option_type_func_param) +#define CONF_TYPE_PRINT (&m_option_type_print) #define CONF_TYPE_PRINT_INDIRECT (&m_option_type_print_indirect) -#define CONF_TYPE_PRINT_FUNC (&m_option_type_print_func) -#define CONF_TYPE_SUBCONFIG (&m_option_type_subconfig) -#define CONF_TYPE_STRING_LIST (&m_option_type_string_list) -#define CONF_TYPE_POSITION (&m_option_type_position) -#define CONF_TYPE_IMGFMT (&m_option_type_imgfmt) -#define CONF_TYPE_AFMT (&m_option_type_afmt) -#define CONF_TYPE_SPAN (&m_option_type_span) +#define CONF_TYPE_PRINT_FUNC (&m_option_type_print_func) +#define CONF_TYPE_SUBCONFIG (&m_option_type_subconfig) +#define CONF_TYPE_STRING_LIST (&m_option_type_string_list) +#define CONF_TYPE_POSITION (&m_option_type_position) +#define CONF_TYPE_IMGFMT (&m_option_type_imgfmt) +#define CONF_TYPE_AFMT (&m_option_type_afmt) +#define CONF_TYPE_SPAN (&m_option_type_span) #define CONF_TYPE_OBJ_SETTINGS_LIST (&m_option_type_obj_settings_list) -#define CONF_TYPE_OBJ_PRESETS (&m_option_type_obj_presets) -#define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url) -#define CONF_TYPE_OBJ_PARAMS (&m_option_type_obj_params) -#define CONF_TYPE_TIME (&m_option_type_time) -#define CONF_TYPE_TIME_SIZE (&m_option_type_time_size) +#define CONF_TYPE_OBJ_PRESETS (&m_option_type_obj_presets) +#define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url) +#define CONF_TYPE_OBJ_PARAMS (&m_option_type_obj_params) +#define CONF_TYPE_TIME (&m_option_type_time) +#define CONF_TYPE_TIME_SIZE (&m_option_type_time_size) -///////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// -/// Option type description +// Option type description struct m_option_type { - const char* name; - /// Syntax description, etc - const char* comments; - /// Size needed for the data. - unsigned int size; - /// See \ref OptionTypeFlags. - unsigned int flags; + const char *name; + // Syntax description, etc + const char *comments; + // Size needed for the data. + unsigned int size; + // See \ref OptionTypeFlags. + unsigned int flags; - /// Parse the data from a string. - /** It is the only required function, all others can be NULL. - * - * \param opt The option that is parsed. - * \param name The full option name. - * \param param The parameter to parse. - * \param dst Pointer to the memory where the data should be written. - * If NULL the parameter validity should still be checked. - * \param src Source of the option, see \ref OptionParserModes. - * \return On error a negative value is returned, on success the number of arguments - * consumed. For details see \ref OptionParserReturn. - */ - int (*parse)(const m_option_t* opt,const char *name, const char *param, void* dst, int src); + // Parse the data from a string. + /** It is the only required function, all others can be NULL. + * + * \param opt The option that is parsed. + * \param name The full option name. + * \param param The parameter to parse. + * \param dst Pointer to the memory where the data should be written. + * If NULL the parameter validity should still be checked. + * \param src Source of the option, see \ref OptionParserModes. + * \return On error a negative value is returned, on success the number of arguments + * consumed. For details see \ref OptionParserReturn. + */ + int (*parse)(const m_option_t *opt, const char *name, const char *param, void *dst, int src); - /// Print back a value in string form. - /** \param opt The option to print. - * \param val Pointer to the memory holding the data to be printed. - * \return An allocated string containing the text value or (void*)-1 - * on error. - */ - char* (*print)(const m_option_t* opt, const void* val); + // Print back a value in string form. + /** \param opt The option to print. + * \param val Pointer to the memory holding the data to be printed. + * \return An allocated string containing the text value or (void*)-1 + * on error. + */ + char *(*print)(const m_option_t *opt, const void *val); - /** \name - * These functions are called to save/set/restore the status of the - * variables. The difference between the 3 only matters for types like - * \ref m_option_type_func where 'setting' needs to do more than just - * copying some data. - */ - //@{ + /** \name + * These functions are called to save/set/restore the status of the + * variables. The difference between the 3 only matters for types like + * \ref m_option_type_func where 'setting' needs to do more than just + * copying some data. + */ + //@{ - /// Update a save slot (dst) from the current value in the program (src). - /** \param opt The option to copy. - * \param dst Pointer to the destination memory. - * \param src Pointer to the source memory. - */ - void (*save)(const m_option_t* opt,void* dst, const void* src); + // Update a save slot (dst) from the current value in the program (src). + /** \param opt The option to copy. + * \param dst Pointer to the destination memory. + * \param src Pointer to the source memory. + */ + void (*save)(const m_option_t *opt, void *dst, const void *src); - /// Set the value in the program (dst) from a save slot. - /** \param opt The option to copy. - * \param dst Pointer to the destination memory. - * \param src Pointer to the source memory. - */ - void (*set)(const m_option_t* opt,void* dst, const void* src); + // Set the value in the program (dst) from a save slot. + /** \param opt The option to copy. + * \param dst Pointer to the destination memory. + * \param src Pointer to the source memory. + */ + void (*set)(const m_option_t *opt, void *dst, const void *src); - /// Copy the data between two save slots. If NULL and size is > 0 a memcpy will be used. - /** \param opt The option to copy. - * \param dst Pointer to the destination memory. - * \param src Pointer to the source memory. - */ - void (*copy)(const m_option_t* opt,void* dst, const void* src); - //@} + // Copy the data between two save slots. If NULL and size is > 0 a memcpy will be used. + /** \param opt The option to copy. + * \param dst Pointer to the destination memory. + * \param src Pointer to the source memory. + */ + void (*copy)(const m_option_t *opt, void *dst, const void *src); + //@} - /// Free the data allocated for a save slot. - /** This is only needed for dynamic types like strings. - * \param dst Pointer to the data, usually a pointer that should be freed and - * set to NULL. - */ - void (*free)(void* dst); + // Free the data allocated for a save slot. + /** This is only needed for dynamic types like strings. + * \param dst Pointer to the data, usually a pointer that should be freed and + * set to NULL. + */ + void (*free)(void *dst); }; -///@} - -/// Option description -/** \ingroup Options - */ +// Option description struct m_option { - /// Option name. - const char *name; + // Option name. + const char *name; - /// Reserved for higher level APIs, it shouldn't be used by parsers. - /** The suboption parser and func types do use it. They should instead - * use the priv field but this was inherited from older versions of the - * config code. - */ - void *p; + // Reserved for higher level APIs, it shouldn't be used by parsers. + /** The suboption parser and func types do use it. They should instead + * use the priv field but this was inherited from older versions of the + * config code. + */ + void *p; - /// Option type. - const m_option_type_t* type; + // Option type. + const m_option_type_t *type; - /// See \ref OptionFlags. - unsigned int flags; + // See \ref OptionFlags. + unsigned int flags; - /// \brief Mostly useful for numeric types, the \ref M_OPT_MIN flags must - /// also be set. - double min; + // \brief Mostly useful for numeric types, the \ref M_OPT_MIN flags must + // also be set. + double min; - /// \brief Mostly useful for numeric types, the \ref M_OPT_MAX flags must - /// also be set. - double max; + // \brief Mostly useful for numeric types, the \ref M_OPT_MAX flags must + // also be set. + double max; - /// Type dependent data (for all kinds of extended settings). - /** This used to be a function pointer to hold a 'reverse to defaults' func. - * Now it can be used to pass any type of extra args needed by the parser. - * Passing a 'default func' is still valid for all func based option types. - */ - void* priv; + // Type dependent data (for all kinds of extended settings). + /** This used to be a function pointer to hold a 'reverse to defaults' func. + * Now it can be used to pass any type of extra args needed by the parser. + * Passing a 'default func' is still valid for all func based option types. + */ + void *priv; - int new; + int new; - int offset; + int offset; }; -/// \defgroup OptionFlags Option flags -///@{ +// The option has a minimum set in \ref m_option::min. +#define M_OPT_MIN (1 << 0) -/// The option has a minimum set in \ref m_option::min. -#define M_OPT_MIN (1<<0) +// The option has a maximum set in \ref m_option::max. +#define M_OPT_MAX (1 << 1) -/// The option has a maximum set in \ref m_option::max. -#define M_OPT_MAX (1<<1) +// The option has a minimum and maximum in m_option::min and m_option::max. +#define M_OPT_RANGE (M_OPT_MIN | M_OPT_MAX) -/// The option has a minimum and maximum in \ref m_option::min and \ref m_option::max. -#define M_OPT_RANGE (M_OPT_MIN|M_OPT_MAX) +// The option is forbidden in config files. +#define M_OPT_NOCFG (1 << 2) -/// The option is forbidden in config files. -#define M_OPT_NOCFG (1<<2) +// The option is forbidden on the command line. +#define M_OPT_NOCMD (1 << 3) -/// The option is forbidden on the command line. -#define M_OPT_NOCMD (1<<3) - -/// The option is global in the \ref Config. +// The option is global in the \ref Config. /** It won't be saved on push and the command line parser will set it when * it's parsed (i.e. it won't be set later) * e.g options : -v, -quiet */ -#define M_OPT_GLOBAL (1<<4) +#define M_OPT_GLOBAL (1 << 4) -/// The \ref Config won't save this option on push. +// The \ref Config won't save this option on push. /** It won't be saved on push but the command line parser will add it with * its entry (i.e. it may be set later) * e.g options : -include */ -#define M_OPT_NOSAVE (1<<5) +#define M_OPT_NOSAVE (1 << 5) -/// The option should be set during command line pre-parsing -#define M_OPT_PRE_PARSE (1<<6) +// The option should be set during command line pre-parsing +#define M_OPT_PRE_PARSE (1 << 6) -/// \defgroup OldOptionFlags Backward compatibility -/// -/// These are kept for compatibility with older code. -/// @{ -#define CONF_MIN M_OPT_MIN -#define CONF_MAX M_OPT_MAX -#define CONF_RANGE M_OPT_RANGE -#define CONF_NOCFG M_OPT_NOCFG -#define CONF_NOCMD M_OPT_NOCMD -#define CONF_GLOBAL M_OPT_GLOBAL -#define CONF_NOSAVE M_OPT_NOSAVE -#define CONF_PRE_PARSE M_OPT_PRE_PARSE -///@} +// These are kept for compatibility with older code. +#define CONF_MIN M_OPT_MIN +#define CONF_MAX M_OPT_MAX +#define CONF_RANGE M_OPT_RANGE +#define CONF_NOCFG M_OPT_NOCFG +#define CONF_NOCMD M_OPT_NOCMD +#define CONF_GLOBAL M_OPT_GLOBAL +#define CONF_NOSAVE M_OPT_NOSAVE +#define CONF_PRE_PARSE M_OPT_PRE_PARSE -///@} +// These flags are used to describe special parser capabilities or behavior. -/// \defgroup OptionTypeFlags Option type flags -/// \ingroup OptionTypes -/// -/// These flags are used to describe special parser capabilities or behavior. -/// -///@{ - -/// Suboption parser flag. +// Suboption parser flag. /** When this flag is set, m_option::p should point to another m_option * array. Only the parse function will be called. If dst is set, it should * create/update an array of char* containg opt/val pairs. The options in @@ -383,23 +354,23 @@ struct m_option { * Also note that suboptions may be directly accessed by using * -option:subopt blah. */ -#define M_OPT_TYPE_HAS_CHILD (1<<0) +#define M_OPT_TYPE_HAS_CHILD (1 << 0) -/// Wildcard matching flag. +// Wildcard matching flag. /** If set the option type has a use for option names ending with a * * (used for -aa*), this only affects the option name matching. */ -#define M_OPT_TYPE_ALLOW_WILDCARD (1<<1) +#define M_OPT_TYPE_ALLOW_WILDCARD (1 << 1) -/// Dynamic data type. +// Dynamic data type. /** This flag indicates that the data is dynamically allocated (m_option::p * points to a pointer). It enables a little hack in the \ref Config wich * replaces the initial value of such variables with a dynamic copy in case * the initial value is statically allocated (pretty common with strings). */ -#define M_OPT_TYPE_DYNAMIC (1<<2) +#define M_OPT_TYPE_DYNAMIC (1 << 2) -/// Indirect option type. +// Indirect option type. /** If this is set the parse function doesn't directly return * the wanted thing. Options use this if for some reasons they have to wait * until the set call to be able to correctly set the target var. @@ -408,76 +379,58 @@ struct m_option { * target var. It's used by the callback-based options as the callback call * may append later on. */ -#define M_OPT_TYPE_INDIRECT (1<<3) +#define M_OPT_TYPE_INDIRECT (1 << 3) -///@} +///////////////////////////// Parser flags ///////////////////////////////// -///////////////////////////// Parser flags //////////////////////////////////////// +// Some parsers behave differently depending on the mode passed in the src +// parameter of m_option_type::parse. For example the flag type doesn't take +// an argument when parsing from the command line. -/// \defgroup OptionParserModes Option parser modes -/// \ingroup Options -/// -/// Some parsers behave differently depending on the mode passed in the src -/// parameter of m_option_type::parse. For example the flag type doesn't take -/// an argument when parsing from the command line. -///@{ - -/// Set when parsing from a config file. +// Set when parsing from a config file. #define M_CONFIG_FILE 0 -/// Set when parsing command line arguments. +// Set when parsing command line arguments. #define M_COMMAND_LINE 1 -/// Set when pre-parsing the command line +// Set when pre-parsing the command line #define M_COMMAND_LINE_PRE_PARSE 2 -///@} +// On success parsers return the number of arguments consumed: 0 or 1. +// +// To indicate that MPlayer should exit without playing anything, +// parsers return M_OPT_EXIT minus the number of parameters they +// consumed: \ref M_OPT_EXIT or \ref M_OPT_EXIT-1. +// +// On error one of the following (negative) error codes is returned: -/// \defgroup OptionParserReturn Option parser return code -/// \ingroup Options -/// -/// On success parsers return the number of arguments consumed: 0 or 1. -/// -/// To indicate that MPlayer should exit without playing anything, -/// parsers return M_OPT_EXIT minus the number of parameters they -/// consumed: \ref M_OPT_EXIT or \ref M_OPT_EXIT-1. -/// -/// On error one of the following (negative) error codes is returned: -///@{ +// For use by higher level APIs when the option name is invalid. +#define M_OPT_UNKNOWN -1 -/// For use by higher level APIs when the option name is invalid. -#define M_OPT_UNKNOWN -1 +// Returned when a parameter is needed but wasn't provided. +#define M_OPT_MISSING_PARAM -2 -/// Returned when a parameter is needed but wasn't provided. -#define M_OPT_MISSING_PARAM -2 +// Returned when the given parameter couldn't be parsed. +#define M_OPT_INVALID -3 -/// Returned when the given parameter couldn't be parsed. -#define M_OPT_INVALID -3 +// Returned if the value is "out of range". The exact meaning may +// vary from type to type. +#define M_OPT_OUT_OF_RANGE -4 -/// \brief Returned if the value is "out of range". The exact meaning may -/// vary from type to type. -#define M_OPT_OUT_OF_RANGE -4 +// Returned if the parser failed for any other reason than a bad parameter. +#define M_OPT_PARSER_ERR -5 -/// Returned if the parser failed for any other reason than a bad parameter. -#define M_OPT_PARSER_ERR -5 - -/// Returned when MPlayer should exit. Used by various help stuff. +// Returned when MPlayer should exit. Used by various help stuff. /** M_OPT_EXIT must be the lowest number on this list. */ #define M_OPT_EXIT -6 -/// \defgroup OldOptionParserReturn Backward compatibility -/// -/// These are kept for compatibility with older code. -/// -///@{ -#define ERR_NOT_AN_OPTION M_OPT_UNKNOWN -#define ERR_MISSING_PARAM M_OPT_MISSING_PARAM -#define ERR_OUT_OF_RANGE M_OPT_OUT_OF_RANGE -#define ERR_FUNC_ERR M_OPT_PARSER_ERR -///@} +// These are kept for compatibility with older code. +// +#define ERR_NOT_AN_OPTION M_OPT_UNKNOWN +#define ERR_MISSING_PARAM M_OPT_MISSING_PARAM +#define ERR_OUT_OF_RANGE M_OPT_OUT_OF_RANGE +#define ERR_FUNC_ERR M_OPT_PARSER_ERR -///@} - -/// Find the option matching the given name in the list. +// Find the option matching the given name in the list. /** \ingroup Options * This function takes the possible wildcards into account (see * \ref M_OPT_TYPE_ALLOW_WILDCARD). @@ -486,7 +439,7 @@ struct m_option { * \param name Name of the option. * \return The matching option or NULL. */ -const m_option_t* m_option_list_find(const m_option_t* list,const char* name); +const m_option_t *m_option_list_find(const m_option_t *list, const char *name); static inline void *m_option_get_ptr(const struct m_option *opt, void *optstruct) @@ -494,35 +447,37 @@ static inline void *m_option_get_ptr(const struct m_option *opt, return opt->new ? (char *) optstruct + opt->offset : opt->p; } -/// Helper to parse options, see \ref m_option_type::parse. -inline static int -m_option_parse(const m_option_t* opt,const char *name, const char *param, void* dst, int src) { - return opt->type->parse(opt,name,param,dst,src); +// Helper to parse options, see \ref m_option_type::parse. +static inline int m_option_parse(const m_option_t *opt, const char *name, + const char *param, void *dst, int src) +{ + return opt->type->parse(opt, name, param, dst, src); } -/// Helper to print options, see \ref m_option_type::print. -inline static char* -m_option_print(const m_option_t* opt, const void* val_ptr) { - if(opt->type->print) - return opt->type->print(opt,val_ptr); - else - return (char*)-1; +// Helper to print options, see \ref m_option_type::print. +static inline char *m_option_print(const m_option_t *opt, const void *val_ptr) +{ + if (opt->type->print) + return opt->type->print(opt, val_ptr); + else + return (char *)-1; } -/// Helper around \ref m_option_type::copy. -inline static void -m_option_copy(const m_option_t* opt,void* dst, const void* src) { - if(opt->type->copy) - opt->type->copy(opt,dst,src); - else if(opt->type->size > 0) - memcpy(dst,src,opt->type->size); +// Helper around \ref m_option_type::copy. +static inline void m_option_copy(const m_option_t *opt, void *dst, + const void *src) +{ + if (opt->type->copy) + opt->type->copy(opt, dst, src); + else if (opt->type->size > 0) + memcpy(dst, src, opt->type->size); } -/// Helper around \ref m_option_type::free. -inline static void -m_option_free(const m_option_t* opt,void* dst) { - if(opt->type->free) - opt->type->free(dst); +// Helper around \ref m_option_type::free. +static inline void m_option_free(const m_option_t *opt, void *dst) +{ + if (opt->type->free) + opt->type->free(dst); } /*@}*/ @@ -553,9 +508,9 @@ int parse_timestring(const char *str, double *time, char endchar); #define OPT_STRINGLIST(optname, varname, flags) {optname, NULL, &m_option_type_string_list, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} #define OPT_PATHLIST(optname, varname, flags) {optname, NULL, &m_option_type_string_list, flags, 0, 0, (void *)&(const char){OPTION_PATH_SEPARATOR}, 1, offsetof(struct MPOpts, varname)} #define OPT_INT(optname, varname, flags) {optname, NULL, &m_option_type_int, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_INTRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_int, (flags)|CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} +#define OPT_INTRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_int, (flags) | CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} #define OPT_INTPAIR(optname, varname, flags) {optname, NULL, &m_option_type_intpair, (flags), 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} -#define OPT_FLOATRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_float, (flags)|CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} +#define OPT_FLOATRANGE(optname, varname, flags, min, max) {optname, NULL, &m_option_type_float, (flags) | CONF_RANGE, min, max, NULL, 1, offsetof(struct MPOpts, varname)} #define OPT_STRING(optname, varname, flags) {optname, NULL, &m_option_type_string, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} #define OPT_SETTINGSLIST(optname, varname, flags, objlist) {optname, NULL, &m_option_type_obj_settings_list, flags, 0, 0, objlist, 1, offsetof(struct MPOpts, varname)} #define OPT_AUDIOFORMAT(optname, varname, flags) {optname, NULL, &m_option_type_afmt, flags, 0, 0, NULL, 1, offsetof(struct MPOpts, varname)} diff --git a/m_property.c b/m_property.c index 93fa8863fd..9525f3a470 100644 --- a/m_property.c +++ b/m_property.c @@ -32,95 +32,106 @@ #include "mp_msg.h" #include "mpcommon.h" -static int do_action(const m_option_t* prop_list, const char* name, - int action, void* arg, void *ctx) { - const char* sep; - const m_option_t* prop; +static int do_action(const m_option_t *prop_list, const char *name, + int action, void *arg, void *ctx) +{ + const char *sep; + const m_option_t *prop; m_property_action_t ka; int r; - if((sep = strchr(name,'/')) && sep[1]) { - int len = sep-name; - char base[len+1]; - memcpy(base,name,len); + if ((sep = strchr(name, '/')) && sep[1]) { + int len = sep - name; + char base[len + 1]; + memcpy(base, name, len); base[len] = 0; prop = m_option_list_find(prop_list, base); - ka.key = sep+1; + ka.key = sep + 1; ka.action = action; ka.arg = arg; action = M_PROPERTY_KEY_ACTION; arg = &ka; } else prop = m_option_list_find(prop_list, name); - if(!prop) return M_PROPERTY_UNKNOWN; - r = ((m_property_ctrl_f)prop->p)(prop,action,arg,ctx); - if(action == M_PROPERTY_GET_TYPE && r < 0) { - if(!arg) return M_PROPERTY_ERROR; - *(const m_option_t**)arg = prop; + if (!prop) + return M_PROPERTY_UNKNOWN; + r = ((m_property_ctrl_f)prop->p)(prop, action, arg, ctx); + if (action == M_PROPERTY_GET_TYPE && r < 0) { + if (!arg) + return M_PROPERTY_ERROR; + *(const m_option_t **)arg = prop; return M_PROPERTY_OK; } return r; } -int m_property_do(const m_option_t* prop_list, const char* name, - int action, void* arg, void *ctx) { - const m_option_t* opt; - void* val; - char* str; +int m_property_do(const m_option_t *prop_list, const char *name, + int action, void *arg, void *ctx) +{ + const m_option_t *opt; + void *val; + char *str; int r; - switch(action) { + switch (action) { case M_PROPERTY_PRINT: - if((r = do_action(prop_list,name,M_PROPERTY_PRINT,arg,ctx)) >= 0) + if ((r = do_action(prop_list, name, M_PROPERTY_PRINT, arg, ctx)) >= 0) return r; - // fallback on the default print for this type + // fallback on the default print for this type case M_PROPERTY_TO_STRING: - if((r = do_action(prop_list,name,M_PROPERTY_TO_STRING,arg,ctx)) != - M_PROPERTY_NOT_IMPLEMENTED) + if ((r = do_action(prop_list, name, M_PROPERTY_TO_STRING, arg, ctx)) != + M_PROPERTY_NOT_IMPLEMENTED) return r; // fallback on the options API. Get the type, value and print. - if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0) + if ((r = + do_action(prop_list, name, M_PROPERTY_GET_TYPE, &opt, ctx)) <= 0) return r; - val = calloc(1,opt->type->size); - if((r = do_action(prop_list,name,M_PROPERTY_GET,val,ctx)) <= 0) { + val = calloc(1, opt->type->size); + if ((r = do_action(prop_list, name, M_PROPERTY_GET, val, ctx)) <= 0) { free(val); return r; } - if(!arg) return M_PROPERTY_ERROR; - str = m_option_print(opt,val); + if (!arg) + return M_PROPERTY_ERROR; + str = m_option_print(opt, val); free(val); - *(char**)arg = str == (char*)-1 ? NULL : str; - return str != (char*)-1; + *(char **)arg = str == (char *)-1 ? NULL : str; + return str != (char *)-1; case M_PROPERTY_PARSE: // try the property own parsing func - if((r = do_action(prop_list,name,M_PROPERTY_PARSE,arg,ctx)) != - M_PROPERTY_NOT_IMPLEMENTED) + if ((r = do_action(prop_list, name, M_PROPERTY_PARSE, arg, ctx)) != + M_PROPERTY_NOT_IMPLEMENTED) return r; // fallback on the options API, get the type and parse. - if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0) + if ((r = + do_action(prop_list, name, M_PROPERTY_GET_TYPE, &opt, ctx)) <= 0) return r; - if(!arg) return M_PROPERTY_ERROR; - val = calloc(1,opt->type->size); - if((r = m_option_parse(opt,opt->name,arg,val,M_CONFIG_FILE)) <= 0) { + if (!arg) + return M_PROPERTY_ERROR; + val = calloc(1, opt->type->size); + if ((r = + m_option_parse(opt, opt->name, arg, val, M_CONFIG_FILE)) <= 0) { free(val); return r; } - r = do_action(prop_list,name,M_PROPERTY_SET,val,ctx); - m_option_free(opt,val); + r = do_action(prop_list, name, M_PROPERTY_SET, val, ctx); + m_option_free(opt, val); free(val); return r; } - return do_action(prop_list,name,action,arg,ctx); + return do_action(prop_list, name, action, arg, ctx); } -char* m_properties_expand_string(const m_option_t* prop_list,char* str, void *ctx) { - int l,fr=0,pos=0,size=strlen(str)+512; - char *p = NULL,*e,*ret = malloc(size), num_val; +char *m_properties_expand_string(const m_option_t *prop_list, char *str, + void *ctx) +{ + int l, fr = 0, pos = 0, size = strlen(str) + 512; + char *p = NULL, *e, *ret = malloc(size), num_val; int skip = 0, lvl = 0, skip_lvl = 0; - while(str[0]) { - if(str[0] == '\\') { + while (str[0]) { + if (str[0] == '\\') { int sl = 1; - switch(str[1]) { + switch (str[1]) { case 'e': p = "\x1b", l = 1; break; case 'n': @@ -130,84 +141,91 @@ char* m_properties_expand_string(const m_option_t* prop_list,char* str, void *ct case 't': p = "\t", l = 1; break; case 'x': - if(str[2]) { + if (str[2]) { char num[3] = { str[2], str[3], 0 }; - char* end = num; - num_val = strtol(num,&end,16); - sl = end-num; + char *end = num; + num_val = strtol(num, &end, 16); + sl = end - num; l = 1; p = &num_val; } else l = 0; break; default: - p = str+1, l = 1; + p = str + 1, l = 1; } - str+=1+sl; - } else if(lvl > 0 && str[0] == ')') { - if(skip && lvl <= skip_lvl) skip = 0; + str += 1 + sl; + } else if (lvl > 0 && str[0] == ')') { + if (skip && lvl <= skip_lvl) + skip = 0; lvl--, str++, l = 0; - } else if(str[0] == '$' && str[1] == '{' && (e = strchr(str+2,'}'))) { - int pl = e-str-2; - char pname[pl+1]; - memcpy(pname,str+2,pl); + } else if (str[0] == '$' && str[1] == '{' + && (e = strchr(str + 2, '}'))) { + int pl = e - str - 2; + char pname[pl + 1]; + memcpy(pname, str + 2, pl); pname[pl] = 0; - if(m_property_do(prop_list, pname, - M_PROPERTY_PRINT, &p, ctx) >= 0 && p) + if (m_property_do(prop_list, pname, + M_PROPERTY_PRINT, &p, ctx) >= 0 && p) l = strlen(p), fr = 1; else l = 0; - str = e+1; - } else if(str[0] == '?' && str[1] == '(' && (e = strchr(str+2,':'))) { + str = e + 1; + } else if (str[0] == '?' && str[1] == '(' + && (e = strchr(str + 2, ':'))) { lvl++; - if(!skip) { + if (!skip) { int is_not = str[2] == '!'; int pl = e - str - (is_not ? 3 : 2); - char pname[pl+1]; + char pname[pl + 1]; memcpy(pname, str + (is_not ? 3 : 2), pl); pname[pl] = 0; - if(m_property_do(prop_list,pname,M_PROPERTY_GET,NULL,ctx) < 0) { + if (m_property_do(prop_list, pname, M_PROPERTY_GET, NULL, ctx) < 0) { if (!is_not) skip = 1, skip_lvl = lvl; - } - else if (is_not) + } else if (is_not) skip = 1, skip_lvl = lvl; } - str = e+1, l = 0; + str = e + 1, l = 0; } else p = str, l = 1, str++; - if(skip || l <= 0) continue; + if (skip || l <= 0) + continue; - if(pos+l+1 > size) { - size = pos+l+512; - ret = realloc(ret,size); + if (pos + l + 1 > size) { + size = pos + l + 512; + ret = realloc(ret, size); } - memcpy(ret+pos,p,l); + memcpy(ret + pos, p, l); pos += l; - if(fr) free(p), fr = 0; + if (fr) + free(p), fr = 0; } ret[pos] = 0; return ret; } -void m_properties_print_help_list(const m_option_t* list) { - char min[50],max[50]; - int i,count = 0; +void m_properties_print_help_list(const m_option_t *list) +{ + char min[50], max[50]; + int i, count = 0; - mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "\n Name Type Min Max\n\n"); - for(i = 0 ; list[i].name ; i++) { - const m_option_t* opt = &list[i]; - if(opt->flags & M_OPT_MIN) - sprintf(min,"%-8.0f",opt->min); + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, + "\n Name Type Min Max\n\n"); + for (i = 0; list[i].name; i++) { + const m_option_t *opt = &list[i]; + if (opt->flags & M_OPT_MIN) + sprintf(min, "%-8.0f", opt->min); else - strcpy(min,"No"); - if(opt->flags & M_OPT_MAX) - sprintf(max,"%-8.0f",opt->max); + strcpy(min, "No"); + if (opt->flags & M_OPT_MAX) + sprintf(max, "%-8.0f", opt->max); else - strcpy(max,"No"); - mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %-20.20s %-15.15s %-10.10s %-10.10s\n", + strcpy(max, "No"); + mp_msg(MSGT_CFGPARSER, MSGL_INFO, + " %-20.20s %-15.15s %-10.10s %-10.10s\n", opt->name, opt->type->name, min, @@ -219,62 +237,70 @@ void m_properties_print_help_list(const m_option_t* list) { // Some generic property implementations -int m_property_int_ro(const m_option_t* prop,int action, - void* arg,int var) { - switch(action) { +int m_property_int_ro(const m_option_t *prop, int action, + void *arg, int var) +{ + switch (action) { case M_PROPERTY_GET: - if(!arg) return 0; - *(int*)arg = var; + if (!arg) + return 0; + *(int *)arg = var; return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_int_range(const m_option_t* prop,int action, - void* arg,int* var) { - switch(action) { +int m_property_int_range(const m_option_t *prop, int action, + void *arg, int *var) +{ + switch (action) { case M_PROPERTY_SET: - if(!arg) return 0; - M_PROPERTY_CLAMP(prop,*(int*)arg); - *var = *(int*)arg; + if (!arg) + return 0; + M_PROPERTY_CLAMP(prop, *(int *)arg); + *var = *(int *)arg; return 1; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: - *var += (arg ? *(int*)arg : 1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - M_PROPERTY_CLAMP(prop,*var); + *var += (arg ? *(int *)arg : 1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + M_PROPERTY_CLAMP(prop, *var); return 1; } - return m_property_int_ro(prop,action,arg,*var); + return m_property_int_ro(prop, action, arg, *var); } -int m_property_choice(const m_option_t* prop,int action, - void* arg,int* var) { - switch(action) { +int m_property_choice(const m_option_t *prop, int action, + void *arg, int *var) +{ + switch (action) { case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var += action == M_PROPERTY_STEP_UP ? 1 : prop->max; - *var %= (int)prop->max+1; + *var %= (int)prop->max + 1; return 1; } - return m_property_int_range(prop,action,arg,var); + return m_property_int_range(prop, action, arg, var); } -int m_property_flag_ro(const m_option_t* prop,int action, - void* arg,int var) { - switch(action) { +int m_property_flag_ro(const m_option_t *prop, int action, + void *arg, int var) +{ + switch (action) { case M_PROPERTY_PRINT: - if(!arg) return 0; - *(char**)arg = strdup((var > prop->min) ? - mp_gtext("enabled") : mp_gtext("disabled")); + if (!arg) + return 0; + *(char **)arg = strdup((var > prop->min) ? + mp_gtext("enabled") : mp_gtext("disabled")); return 1; } - return m_property_int_ro(prop,action,arg,var); + return m_property_int_ro(prop, action, arg, var); } -int m_property_flag(const m_option_t* prop,int action, - void* arg,int* var) { - switch(action) { +int m_property_flag(const m_option_t *prop, int action, + void *arg, int *var) +{ + switch (action) { case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: *var = *var == prop->min ? prop->max : prop->min; @@ -282,118 +308,134 @@ int m_property_flag(const m_option_t* prop,int action, case M_PROPERTY_PRINT: return m_property_flag_ro(prop, action, arg, *var); } - return m_property_int_range(prop,action,arg,var); + return m_property_int_range(prop, action, arg, var); } -int m_property_float_ro(const m_option_t* prop,int action, - void* arg,float var) { - switch(action) { +int m_property_float_ro(const m_option_t *prop, int action, + void *arg, float var) +{ + switch (action) { case M_PROPERTY_GET: - if(!arg) return 0; - *(float*)arg = var; + if (!arg) + return 0; + *(float *)arg = var; return 1; case M_PROPERTY_PRINT: - if(!arg) return 0; - *(char**)arg = malloc(20); - sprintf(*(char**)arg,"%.2f",var); + if (!arg) + return 0; + *(char **)arg = malloc(20); + sprintf(*(char **)arg, "%.2f", var); return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_float_range(const m_option_t* prop,int action, - void* arg,float* var) { - switch(action) { +int m_property_float_range(const m_option_t *prop, int action, + void *arg, float *var) +{ + switch (action) { case M_PROPERTY_SET: - if(!arg) return 0; - M_PROPERTY_CLAMP(prop,*(float*)arg); - *var = *(float*)arg; + if (!arg) + return 0; + M_PROPERTY_CLAMP(prop, *(float *)arg); + *var = *(float *)arg; return 1; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: - *var += (arg ? *(float*)arg : 0.1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - M_PROPERTY_CLAMP(prop,*var); + *var += (arg ? *(float *)arg : 0.1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + M_PROPERTY_CLAMP(prop, *var); return 1; } - return m_property_float_ro(prop,action,arg,*var); + return m_property_float_ro(prop, action, arg, *var); } -int m_property_delay(const m_option_t* prop,int action, - void* arg,float* var) { - switch(action) { - case M_PROPERTY_PRINT: - if(!arg) return 0; - *(char**)arg = malloc(20); - sprintf(*(char**)arg,"%d ms",ROUND((*var)*1000)); - return 1; - default: - return m_property_float_range(prop,action,arg,var); - } -} - -int m_property_double_ro(const m_option_t* prop,int action, - void* arg,double var) { - switch(action) { - case M_PROPERTY_GET: - if(!arg) return 0; - *(double*)arg = var; - return 1; - case M_PROPERTY_PRINT: - if(!arg) return 0; - *(char**)arg = malloc(20); - sprintf(*(char**)arg,"%.2f",var); - return 1; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -int m_property_time_ro(const m_option_t* prop,int action, - void* arg,double var) { - switch(action) { - case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; - else { - int h, m, s = var; - h = s / 3600; - s -= h * 3600; - m = s / 60; - s -= m * 60; - *(char **) arg = malloc(20); - if (h > 0) - sprintf(*(char **) arg, "%d:%02d:%02d", h, m, s); - else if (m > 0) - sprintf(*(char **) arg, "%d:%02d", m, s); - else - sprintf(*(char **) arg, "%d", s); - return M_PROPERTY_OK; - } - } - return m_property_double_ro(prop,action,arg,var); -} - -int m_property_string_ro(const m_option_t* prop,int action,void* arg,char* str) { - switch(action) { - case M_PROPERTY_GET: - if(!arg) return 0; - *(char**)arg = str; - return 1; - case M_PROPERTY_PRINT: - if(!arg) return 0; - *(char**)arg = str ? strdup(str) : NULL; - return 1; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -int m_property_bitrate(const m_option_t* prop,int action,void* arg,int rate) { - switch(action) { +int m_property_delay(const m_option_t *prop, int action, + void *arg, float *var) +{ + switch (action) { case M_PROPERTY_PRINT: if (!arg) - return M_PROPERTY_ERROR; - *(char**)arg = malloc (16); - sprintf(*(char**)arg, "%d kbps", rate*8/1000); + return 0; + *(char **)arg = malloc(20); + sprintf(*(char **)arg, "%d ms", ROUND((*var) * 1000)); + return 1; + default: + return m_property_float_range(prop, action, arg, var); + } +} + +int m_property_double_ro(const m_option_t *prop, int action, + void *arg, double var) +{ + switch (action) { + case M_PROPERTY_GET: + if (!arg) + return 0; + *(double *)arg = var; + return 1; + case M_PROPERTY_PRINT: + if (!arg) + return 0; + *(char **)arg = malloc(20); + sprintf(*(char **)arg, "%.2f", var); + return 1; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +int m_property_time_ro(const m_option_t *prop, int action, + void *arg, double var) +{ + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + else { + int h, m, s = var; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + *(char **) arg = malloc(20); + if (h > 0) + sprintf(*(char **) arg, "%d:%02d:%02d", h, m, s); + else if (m > 0) + sprintf(*(char **) arg, "%d:%02d", m, s); + else + sprintf(*(char **) arg, "%d", s); + return M_PROPERTY_OK; + } + } + return m_property_double_ro(prop, action, arg, var); +} + +int m_property_string_ro(const m_option_t *prop, int action, void *arg, + char *str) +{ + switch (action) { + case M_PROPERTY_GET: + if (!arg) + return 0; + *(char **)arg = str; + return 1; + case M_PROPERTY_PRINT: + if (!arg) + return 0; + *(char **)arg = str ? strdup(str) : NULL; + return 1; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +int m_property_bitrate(const m_option_t *prop, int action, void *arg, int rate) +{ + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + *(char **)arg = malloc(16); + sprintf(*(char **)arg, "%d kbps", rate * 8 / 1000); return M_PROPERTY_OK; } return m_property_int_ro(prop, action, arg, rate);