diff --git a/cfg-common.h b/cfg-common.h index 4a8876eea3..ac222efd6f 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -150,7 +150,8 @@ {"pphelp", &pp_help, CONF_TYPE_PRINT_INDIRECT, CONF_NOCFG, 0, 0, NULL}, #endif - {"vop", &vo_plugin_args, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL}, + {"vop", &vo_plugin_args, CONF_TYPE_OBJ_SETTINGS_LIST, 0, 0, 0,&vf_obj_list }, + {"vf", &vf_settings, CONF_TYPE_OBJ_SETTINGS_LIST, 0, 0, 0, &vf_obj_list}, // scaling: {"sws", &sws_flags, CONF_TYPE_INT, 0, 0, 2, NULL}, @@ -336,6 +337,8 @@ extern int mf_w; extern int mf_h; extern float mf_fps; extern char * mf_type; +extern m_obj_settings_t* vf_settings; +extern m_obj_list_t vf_obj_list; struct config mfopts_conf[]={ {"on", &mf_support, CONF_TYPE_FLAG, 0, 0, 1, NULL}, @@ -346,7 +349,7 @@ struct config mfopts_conf[]={ {NULL, NULL, 0, 0, 0, 0, NULL} }; -extern char** vo_plugin_args; +extern m_obj_settings_t* vo_plugin_args; #include "libaf/af.h" extern af_cfg_t af_cfg; // Audio filter configuration, defined in libmpcodecs/dec_audio.c diff --git a/libmpcodecs/vf.c b/libmpcodecs/vf.c index d4629d7e12..e833065ad3 100644 --- a/libmpcodecs/vf.c +++ b/libmpcodecs/vf.c @@ -9,6 +9,8 @@ #include "../mp_msg.h" #include "../help_mp.h" +#include "../m_option.h" +#include "../m_struct.h" #include "img_format.h" @@ -60,8 +62,6 @@ extern vf_info_t vf_info_detc; extern vf_info_t vf_info_telecine; extern vf_info_t vf_info_tfields; -char** vo_plugin_args=(char**) NULL; - // list of available filters: static vf_info_t* filter_list[]={ &vf_info_rectangle, @@ -116,6 +116,17 @@ static vf_info_t* filter_list[]={ NULL }; +// For the vf option +m_obj_settings_t* vf_settings = NULL; +// For the vop option +m_obj_settings_t* vo_plugin_args = NULL; +m_obj_list_t vf_obj_list = { + (void**)filter_list, + M_ST_OFF(vf_info_t,name), + M_ST_OFF(vf_info_t,info), + M_ST_OFF(vf_info_t,opts) +}; + //============================================================================ // mpi stuff: @@ -306,7 +317,7 @@ static int vf_default_query_format(struct vf_instance_s* vf, unsigned int fmt){ return vf_next_query_format(vf,fmt); } -vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char *name, char *args){ +vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char *name, char **args){ vf_instance_t* vf; int i; for(i=0;;i++){ @@ -326,18 +337,48 @@ vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char vf->put_image=vf_next_put_image; vf->default_caps=VFCAP_ACCEPT_STRIDE; vf->default_reqs=0; - if(vf->info->open(vf,args)>0) return vf; // Success! + if(vf->info->opts) { // vf_vo get some special argument + m_struct_t* st = vf->info->opts; + void* vf_priv = m_struct_alloc(st); + int n; + for(n = 0 ; args && args[2*n] ; n++) + m_struct_set(st,vf_priv,args[2*n],args[2*n+1]); + vf->priv = vf_priv; + args = NULL; + } else // Otherwise we should have the '_oldargs_' + if(args && !strcmp(args[0],"_oldargs_")) + args = (char**)args[1]; + else + args = NULL; + if(vf->info->open(vf,(char*)args)>0) return vf; // Success! free(vf); mp_msg(MSGT_VFILTER,MSGL_ERR,MSGTR_CouldNotOpenVideoFilter,name); return NULL; } -vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char *args){ - if(strcmp(name,"vo")) - mp_msg(MSGT_VFILTER,MSGL_INFO, - args ? MSGTR_OpeningVideoFilter "[%s=%s]\n" - : MSGTR_OpeningVideoFilter "[%s]\n",name,args); - return vf_open_plugin(filter_list,next,name,args); +vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char **args){ + if(args && strcmp(args[0],"_oldargs_")) { + int i,l = 0; + for(i = 0 ; args && args[2*i] ; i++) + l += 1 + strlen(args[2*i]) + 1 + strlen(args[2*i+1]); + l += strlen(name); + { + char str[l+1]; + char* p = str; + p += sprintf(str,"%s",name); + for(i = 0 ; args && args[2*i] ; i++) + p += sprintf(p," %s=%s",args[2*i],args[2*i+1]); + mp_msg(MSGT_VFILTER,MSGL_INFO,MSGTR_OpeningVideoFilter "[%s]\n",str); + } + } else if(strcmp(name,"vo")) { + if(args && strcmp(args[0],"_oldargs_") == 0) + mp_msg(MSGT_VFILTER,MSGL_INFO,MSGTR_OpeningVideoFilter + "[%s=%s]\n", name,args[1]); + else + mp_msg(MSGT_VFILTER,MSGL_INFO,MSGTR_OpeningVideoFilter + "[%s]\n", name); + } + return vf_open_plugin(filter_list,next,name,args); } //============================================================================ @@ -425,19 +466,27 @@ void vf_next_draw_slice(struct vf_instance_s* vf,unsigned char** src, int * stri //============================================================================ vf_instance_t* append_filters(vf_instance_t* last){ - vf_instance_t* vf; - char** plugin_args = vo_plugin_args; - if(!vo_plugin_args) return last; - while(*plugin_args){ - char* name=strdup(*plugin_args); - char* args=strchr(name,'='); - if(args){args[0]=0;++args;} - vf=vf_open_filter(last,name,args); - if(vf) last=vf; - free(name); - ++plugin_args; + vf_instance_t* vf; + int i; + + // -vf take precedence over -vop + if(vf_settings) { + // We want to add them in the 'right order' + for(i = 0 ; vf_settings[i].name ; i++) + /* NOP */; + for(i-- ; i >= 0 ; i--) { + //printf("Open filter %s\n",vf_settings[i].name); + vf = vf_open_filter(last,vf_settings[i].name,vf_settings[i].attribs); + if(vf) last=vf; } - return last; + } else if(vo_plugin_args) { + for(i = 0 ; vo_plugin_args[i].name ; i++) { + vf = vf_open_filter(last,vo_plugin_args[i].name, + vo_plugin_args[i].attribs); + if(vf) last=vf; + } + } + return last; } //============================================================================ diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h index ffe8ef934a..1f21500ac7 100644 --- a/libmpcodecs/vf.h +++ b/libmpcodecs/vf.h @@ -8,6 +8,8 @@ typedef struct vf_info_s { const char *author; const char *comment; int (*open)(struct vf_instance_s* vf,char* args); + // Ptr to a struct dscribing the options + void* opts; } vf_info_t; typedef struct vf_image_context_s { @@ -67,8 +69,8 @@ typedef struct vf_seteq_s void vf_mpi_clear(mp_image_t* mpi,int x0,int y0,int w,int h); mp_image_t* vf_get_image(vf_instance_t* vf, unsigned int outfmt, int mp_imgtype, int mp_imgflag, int w, int h); -vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char *name, char *args); -vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char *args); +vf_instance_t* vf_open_plugin(vf_info_t** filter_list, vf_instance_t* next, char *name, char **args); +vf_instance_t* vf_open_filter(vf_instance_t* next, char *name, char **args); vf_instance_t* vf_open_encoder(vf_instance_t* next, char *name, char *args); unsigned int vf_match_csp(vf_instance_t** vfp,unsigned int* list,unsigned int preferred); diff --git a/libmpcodecs/vf_1bpp.c b/libmpcodecs/vf_1bpp.c index 2d6a959dc9..f1c9e5920d 100644 --- a/libmpcodecs/vf_1bpp.c +++ b/libmpcodecs/vf_1bpp.c @@ -178,7 +178,8 @@ vf_info_t vf_info_1bpp = { "1bpp", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_2xsai.c b/libmpcodecs/vf_2xsai.c index 20db798722..21a8f48ab9 100644 --- a/libmpcodecs/vf_2xsai.c +++ b/libmpcodecs/vf_2xsai.c @@ -357,7 +357,8 @@ vf_info_t vf_info_2xsai = { "2xsai", "A'rpi", "http://elektron.its.tudelft.nl/~dalikifa/", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_bmovl.c b/libmpcodecs/vf_bmovl.c index 5cba56d6f0..8f5bad8f53 100644 --- a/libmpcodecs/vf_bmovl.c +++ b/libmpcodecs/vf_bmovl.c @@ -452,5 +452,6 @@ vf_info_t vf_info_bmovl = { "bmovl", "Per Wigren", "", - vf_open + vf_open, + NULL }; diff --git a/libmpcodecs/vf_boxblur.c b/libmpcodecs/vf_boxblur.c index a5e7f9767a..729c174d72 100644 --- a/libmpcodecs/vf_boxblur.c +++ b/libmpcodecs/vf_boxblur.c @@ -212,7 +212,8 @@ vf_info_t vf_info_boxblur = { "boxblur", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_crop.c b/libmpcodecs/vf_crop.c index f00cccadad..110bac5176 100644 --- a/libmpcodecs/vf_crop.c +++ b/libmpcodecs/vf_crop.c @@ -115,7 +115,8 @@ vf_info_t vf_info_crop = { "crop", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_cropdetect.c b/libmpcodecs/vf_cropdetect.c index c8d4aae560..e8bdf83e88 100644 --- a/libmpcodecs/vf_cropdetect.c +++ b/libmpcodecs/vf_cropdetect.c @@ -133,7 +133,8 @@ vf_info_t vf_info_cropdetect = { "cropdetect", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_denoise3d.c b/libmpcodecs/vf_denoise3d.c index 03b4569991..ea9e5f27a0 100644 --- a/libmpcodecs/vf_denoise3d.c +++ b/libmpcodecs/vf_denoise3d.c @@ -265,7 +265,8 @@ vf_info_t vf_info_denoise3d = { "denoise3d", "Daniel Moreno", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_detc.c b/libmpcodecs/vf_detc.c index bccd3c6c9e..bf311d7938 100644 --- a/libmpcodecs/vf_detc.c +++ b/libmpcodecs/vf_detc.c @@ -457,7 +457,8 @@ vf_info_t vf_info_detc = { "detc", "Rich Felker", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_dint.c b/libmpcodecs/vf_dint.c index 679a306ae6..80f95b1263 100644 --- a/libmpcodecs/vf_dint.c +++ b/libmpcodecs/vf_dint.c @@ -191,5 +191,6 @@ vf_info_t vf_info_dint = { "dint", "A.G.", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_down3dright.c b/libmpcodecs/vf_down3dright.c index c142c05675..6a9f979420 100644 --- a/libmpcodecs/vf_down3dright.c +++ b/libmpcodecs/vf_down3dright.c @@ -139,6 +139,7 @@ vf_info_t vf_info_down3dright = { "down3dright", "Zdenek Kabelac", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_dvbscale.c b/libmpcodecs/vf_dvbscale.c index 987482e12b..3dcdb1b3fa 100644 --- a/libmpcodecs/vf_dvbscale.c +++ b/libmpcodecs/vf_dvbscale.c @@ -42,7 +42,8 @@ vf_info_t vf_info_dvbscale = { "dvbscale", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_eq.c b/libmpcodecs/vf_eq.c index 8ee2f6bf30..a5c27b7fd1 100644 --- a/libmpcodecs/vf_eq.c +++ b/libmpcodecs/vf_eq.c @@ -219,6 +219,7 @@ vf_info_t vf_info_eq = { "eq", "Richard Felker", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_eq2.c b/libmpcodecs/vf_eq2.c index 919b2ad8c9..ae7ce9beda 100644 --- a/libmpcodecs/vf_eq2.c +++ b/libmpcodecs/vf_eq2.c @@ -463,5 +463,6 @@ vf_info_t vf_info_eq2 = { "eq2", "Hampa Hug, Daniel Moreno, Richard Felker", "", - &open + &open, + NULL }; diff --git a/libmpcodecs/vf_expand.c b/libmpcodecs/vf_expand.c index 550fdb20b6..e3681d9d84 100644 --- a/libmpcodecs/vf_expand.c +++ b/libmpcodecs/vf_expand.c @@ -356,7 +356,8 @@ vf_info_t vf_info_expand = { "expand", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_fame.c b/libmpcodecs/vf_fame.c index a996019aa8..820865e0a5 100644 --- a/libmpcodecs/vf_fame.c +++ b/libmpcodecs/vf_fame.c @@ -145,7 +145,8 @@ vf_info_t vf_info_fame = { "fame", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_field.c b/libmpcodecs/vf_field.c index 0e2a5c9585..21efc7b59e 100644 --- a/libmpcodecs/vf_field.c +++ b/libmpcodecs/vf_field.c @@ -72,7 +72,8 @@ vf_info_t vf_info_field = { "field", "Rich Felker", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_flip.c b/libmpcodecs/vf_flip.c index 78706aff2f..7977dd9229 100644 --- a/libmpcodecs/vf_flip.c +++ b/libmpcodecs/vf_flip.c @@ -90,7 +90,8 @@ vf_info_t vf_info_flip = { "flip", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_format.c b/libmpcodecs/vf_format.c index 5e351f0d2d..772a575478 100644 --- a/libmpcodecs/vf_format.c +++ b/libmpcodecs/vf_format.c @@ -66,7 +66,8 @@ vf_info_t vf_info_format = { "format", "A'rpi", "FIXME! get_image()/put_image()", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_halfpack.c b/libmpcodecs/vf_halfpack.c index dac3c61630..b4fc0e648f 100644 --- a/libmpcodecs/vf_halfpack.c +++ b/libmpcodecs/vf_halfpack.c @@ -216,6 +216,7 @@ vf_info_t vf_info_halfpack = { "halfpack", "Richard Felker", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_hqdn3d.c b/libmpcodecs/vf_hqdn3d.c index 341c282288..ce59d0f66e 100644 --- a/libmpcodecs/vf_hqdn3d.c +++ b/libmpcodecs/vf_hqdn3d.c @@ -290,7 +290,8 @@ vf_info_t vf_info_hqdn3d = { "hqdn3d", "Daniel Moreno & A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_il.c b/libmpcodecs/vf_il.c index d4e9a840db..1cbf1135ec 100644 --- a/libmpcodecs/vf_il.c +++ b/libmpcodecs/vf_il.c @@ -145,7 +145,8 @@ vf_info_t vf_info_il = { "il", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_lavc.c b/libmpcodecs/vf_lavc.c index 5c84665368..57378e9b05 100644 --- a/libmpcodecs/vf_lavc.c +++ b/libmpcodecs/vf_lavc.c @@ -200,7 +200,8 @@ vf_info_t vf_info_lavc = { "lavc", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_lavcdeint.c b/libmpcodecs/vf_lavcdeint.c index eee128768c..7b4188eefe 100644 --- a/libmpcodecs/vf_lavcdeint.c +++ b/libmpcodecs/vf_lavcdeint.c @@ -183,7 +183,8 @@ vf_info_t vf_info_lavcdeint = { "Joe Rabinoff", "libavcodec's internal deinterlacer, in case you don't like " "the builtin ones (invoked with -pp or -npp)", - open + open, + NULL }; diff --git a/libmpcodecs/vf_mirror.c b/libmpcodecs/vf_mirror.c index a16a062ab4..3d77730e12 100644 --- a/libmpcodecs/vf_mirror.c +++ b/libmpcodecs/vf_mirror.c @@ -109,7 +109,8 @@ vf_info_t vf_info_mirror = { "mirror", "Eyck", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_noise.c b/libmpcodecs/vf_noise.c index 7a1ce5b739..d11178a100 100644 --- a/libmpcodecs/vf_noise.c +++ b/libmpcodecs/vf_noise.c @@ -464,7 +464,8 @@ vf_info_t vf_info_noise = { "noise", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_palette.c b/libmpcodecs/vf_palette.c index b7f2cd7d2d..51d69405dc 100644 --- a/libmpcodecs/vf_palette.c +++ b/libmpcodecs/vf_palette.c @@ -190,7 +190,8 @@ vf_info_t vf_info_palette = { "palette", "A'rpi & Alex", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_perspective.c b/libmpcodecs/vf_perspective.c index 30ee17fcd3..59e2f3f467 100644 --- a/libmpcodecs/vf_perspective.c +++ b/libmpcodecs/vf_perspective.c @@ -335,7 +335,8 @@ vf_info_t vf_info_perspective = { "perspective", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_pp.c b/libmpcodecs/vf_pp.c index 58b996bc72..f9b79039ea 100644 --- a/libmpcodecs/vf_pp.c +++ b/libmpcodecs/vf_pp.c @@ -239,7 +239,8 @@ vf_info_t vf_info_pp = { "pp", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_rectangle.c b/libmpcodecs/vf_rectangle.c index a27c3f8bff..2325c08410 100644 --- a/libmpcodecs/vf_rectangle.c +++ b/libmpcodecs/vf_rectangle.c @@ -168,5 +168,6 @@ vf_info_t vf_info_rectangle = { "rectangle", "Kim Minh Kaplan", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_rgb2bgr.c b/libmpcodecs/vf_rgb2bgr.c index 99574b17db..0db4b2c4d2 100644 --- a/libmpcodecs/vf_rgb2bgr.c +++ b/libmpcodecs/vf_rgb2bgr.c @@ -97,7 +97,8 @@ vf_info_t vf_info_rgb2bgr = { "rgb2bgr", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_rotate.c b/libmpcodecs/vf_rotate.c index fb5e7e96e8..5cb42a86ae 100644 --- a/libmpcodecs/vf_rotate.c +++ b/libmpcodecs/vf_rotate.c @@ -130,7 +130,8 @@ vf_info_t vf_info_rotate = { "rotate", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_sab.c b/libmpcodecs/vf_sab.c index d4b6d5b419..3c6e686ac9 100644 --- a/libmpcodecs/vf_sab.c +++ b/libmpcodecs/vf_sab.c @@ -311,7 +311,8 @@ vf_info_t vf_info_sab = { "sab", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_scale.c b/libmpcodecs/vf_scale.c index fd8a1f061b..9637804dd7 100644 --- a/libmpcodecs/vf_scale.c +++ b/libmpcodecs/vf_scale.c @@ -13,7 +13,10 @@ #include "../libvo/fastmemcpy.h" #include "../postproc/swscale.h" -struct vf_priv_s { +#include "m_option.h" +#include "m_struct.h" + +static struct vf_priv_s { int w,h; int v_chr_drop; int param; @@ -21,6 +24,14 @@ struct vf_priv_s { struct SwsContext *ctx; unsigned char* palette; mp_image_t *dmpi; +} vf_priv_dflt = { + -1,-1, + 0, + 0, + 0, + NULL, + NULL, + NULL }; extern int opt_screen_size_x; @@ -348,6 +359,7 @@ static int open(vf_instance_t *vf, char* args){ vf->put_image=put_image; vf->query_format=query_format; vf->control= control; + if(!vf->priv) { vf->priv=malloc(sizeof(struct vf_priv_s)); // TODO: parse args -> vf->priv->ctx=NULL; @@ -356,6 +368,7 @@ static int open(vf_instance_t *vf, char* args){ vf->priv->v_chr_drop=0; vf->priv->param=0; vf->priv->palette=NULL; + } // if(!vf->priv) if(args) sscanf(args, "%d:%d:%d:%d", &vf->priv->w, &vf->priv->h, @@ -367,12 +380,66 @@ static int open(vf_instance_t *vf, char* args){ return 1; } +/// An example of presets usage +static struct size_preset { + char* name; + int w, h; +} vf_size_presets_defs[] = { + // TODO add more 'standard' resolutions + { "pal", 768, 576 }, + { NULL, 0, 0} +}; + +#define ST_OFF(f) M_ST_OFF(struct size_preset,f) +static m_option_t vf_size_preset_fields[] = { + {"w", ST_OFF(w), CONF_TYPE_INT, M_OPT_MIN,1 ,0, NULL}, + {"h", ST_OFF(h), CONF_TYPE_INT, M_OPT_MIN,1 ,0, NULL}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; + +static m_struct_t vf_size_preset = { + "scale_size_preset", + sizeof(struct size_preset), + NULL, + vf_size_preset_fields +}; + +static m_struct_t vf_opts; +static m_obj_presets_t size_preset = { + &vf_size_preset, // Input struct desc + &vf_opts, // Output struct desc + vf_size_presets_defs, // The list of presets + ST_OFF(name) // At wich offset is the name field in the preset struct +}; + +/// Now the options +#undef ST_OFF +#define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f) +static m_option_t vf_opts_fields[] = { + {"w", ST_OFF(w), CONF_TYPE_INT, M_OPT_MIN,1 ,0, NULL}, + {"h", ST_OFF(h), CONF_TYPE_INT, M_OPT_MIN,1 ,0, NULL}, + {"chr-drop", ST_OFF(v_chr_drop), CONF_TYPE_INT, M_OPT_RANGE, 0, 3, NULL}, + {"param", ST_OFF(param), CONF_TYPE_INT, M_OPT_RANGE, 0, 100, NULL}, + // Note that here the 2 field is NULL (ie 0) + // As we want this option to act on the option struct itself + {"presize", 0, CONF_TYPE_OBJ_PRESETS, 0, 0, 0, &size_preset}, + { NULL, NULL, 0, 0, 0, 0, NULL } +}; + +static m_struct_t vf_opts = { + "scale", + sizeof(struct vf_priv_s), + &vf_priv_dflt, + vf_opts_fields +}; + vf_info_t vf_info_scale = { "software scaling", "scale", "A'rpi", "", - open + open, + &vf_opts }; //===========================================================================// diff --git a/libmpcodecs/vf_smartblur.c b/libmpcodecs/vf_smartblur.c index 006a3f3471..3156bd17d8 100644 --- a/libmpcodecs/vf_smartblur.c +++ b/libmpcodecs/vf_smartblur.c @@ -266,7 +266,8 @@ vf_info_t vf_info_smartblur = { "smartblur", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_swapuv.c b/libmpcodecs/vf_swapuv.c index 5e1df3a845..d624bedc9e 100644 --- a/libmpcodecs/vf_swapuv.c +++ b/libmpcodecs/vf_swapuv.c @@ -106,7 +106,8 @@ vf_info_t vf_info_swapuv = { "swapuv", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_telecine.c b/libmpcodecs/vf_telecine.c index a71494d611..b29f72cf45 100644 --- a/libmpcodecs/vf_telecine.c +++ b/libmpcodecs/vf_telecine.c @@ -145,7 +145,8 @@ vf_info_t vf_info_telecine = { "telecine", "Rich Felker", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_test.c b/libmpcodecs/vf_test.c index 1f3a63b945..d4adfdef9d 100644 --- a/libmpcodecs/vf_test.c +++ b/libmpcodecs/vf_test.c @@ -325,7 +325,8 @@ vf_info_t vf_info_test = { "test", "Michael Niedermayer", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_tfields.c b/libmpcodecs/vf_tfields.c index 635fa405f8..6b1a2264c8 100644 --- a/libmpcodecs/vf_tfields.c +++ b/libmpcodecs/vf_tfields.c @@ -181,7 +181,8 @@ vf_info_t vf_info_tfields = { "tfields", "Rich Felker", "", - open + open, + NULL }; diff --git a/libmpcodecs/vf_unsharp.c b/libmpcodecs/vf_unsharp.c index 7a2384cf18..63248a77e6 100644 --- a/libmpcodecs/vf_unsharp.c +++ b/libmpcodecs/vf_unsharp.c @@ -334,7 +334,8 @@ vf_info_t vf_info_unsharp = { "unsharp", "Rémi Guyomarch", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c index 05f6511080..4fe36e048b 100644 --- a/libmpcodecs/vf_vo.c +++ b/libmpcodecs/vf_vo.c @@ -143,7 +143,8 @@ vf_info_t vf_info_vo = { "vo", "A'rpi", "for internal use", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_yuy2.c b/libmpcodecs/vf_yuy2.c index b7ab4b18bc..9d60d9a38e 100644 --- a/libmpcodecs/vf_yuy2.c +++ b/libmpcodecs/vf_yuy2.c @@ -73,7 +73,8 @@ vf_info_t vf_info_yuy2 = { "yuy2", "A'rpi", "", - open + open, + NULL }; //===========================================================================// diff --git a/libmpcodecs/vf_yvu9.c b/libmpcodecs/vf_yvu9.c index c2dc0797c1..6ab5a3399a 100644 --- a/libmpcodecs/vf_yvu9.c +++ b/libmpcodecs/vf_yvu9.c @@ -81,7 +81,8 @@ vf_info_t vf_info_yvu9 = { "yvu9", "alex", "", - open + open, + NULL }; //===========================================================================// diff --git a/m_config.c b/m_config.c index abaf2b9cf0..06f32fc400 100644 --- a/m_config.c +++ b/m_config.c @@ -239,7 +239,7 @@ m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { char** lst = NULL; int i,sr; // Parse the child options - r = m_option_parse(co->opt,arg,param,&lst,config->mode); + r = m_option_parse(co->opt,arg,param,&lst,M_COMMAND_LINE); // Set them now if(r >= 0) for(i = 0 ; lst && lst[2*i] ; i++) { diff --git a/m_option.c b/m_option.c index 418214a989..f623047621 100644 --- a/m_option.c +++ b/m_option.c @@ -15,6 +15,26 @@ //#include "m_config.h" #include "mp_msg.h" +// Don't free for 'production' atm +#ifndef MP_DEBUG +#define NO_FREE +#endif + +m_option_t* m_option_list_find(m_option_t* list,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; +} + // Default function that just do a memcpy static void copy_opt(m_option_t* opt,void* dst,void* src) { @@ -321,14 +341,18 @@ static char* print_str(m_option_t* opt, void* val) { static void copy_str(m_option_t* opt,void* dst, void* src) { if(dst && src) { -// if(VAL(dst)) free(VAL(dst)); //FIXME!!! +#ifndef NO_FREE + if(VAL(dst)) free(VAL(dst)); //FIXME!!! +#endif VAL(dst) = VAL(src) ? strdup(VAL(src)) : NULL; } } static void free_str(void* src) { - if(src && VAL(src)){ -// free(VAL(src)); //FIXME!!! + if(src && VAL(src)){ +#ifndef NO_FREE + free(VAL(src)); //FIXME!!! +#endif VAL(src) = NULL; } } @@ -366,9 +390,11 @@ static void free_str_list(void* dst) { d = VAL(dst); // FIXME!!! -// for(i = 0 ; d[i] != NULL ; i++) -// free(d[i]); -// free(d); +#ifndef NO_FREE + for(i = 0 ; d[i] != NULL ; i++) + free(d[i]); + free(d); +#endif VAL(dst) = NULL; } @@ -809,7 +835,7 @@ m_option_type_t m_option_type_print_indirect = { static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int src) { char *subparam; char *subopt; - int nr = 0; + int nr = 0,i,r; m_option_t *subopts; char *token; char *p; @@ -839,6 +865,16 @@ static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int 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: Unknow suboption %s\n",name,subopt); + return M_OPT_UNKNOW; + } + r = m_option_parse(&subopts[i],subopt, + subparam[0] == 0 ? NULL : subparam,NULL,src); + if(r < 0) return r; if(dst) { lst = (char**)realloc(lst,2 * (nr+2) * sizeof(char*)); lst[2*nr] = strdup(subopt); @@ -857,7 +893,8 @@ static int parse_subconf(m_option_t* opt,char *name, char *param, void* dst, int free(subparam); free(subopt); free(p); - VAL(dst) = lst; + if(dst) + VAL(dst) = lst; return 1; } @@ -1040,4 +1077,395 @@ m_option_type_t m_option_type_span = { NULL }; + +//// Objects (ie filters, etc) settings + +#include "m_struct.h" + +#undef VAL +#define VAL(x) (*(m_obj_settings_t**)(x)) + +static int find_obj_desc(char* name,m_obj_list_t* l,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; + } + } + return 0; +} + +static int get_obj_param(char* opt_name,char* obj_name, m_struct_t* desc, + char* str,int* nold,int oldmax,char** dst) { + char* eq,param; + m_option_t* opt; + int r; + + 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_UNKNOW; + } + r = m_option_parse(opt,str,p,NULL,M_CONFIG_FILE); + if(r < 0) { + 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 have only %d params, so yon can't give more than that unnamed params\n", + opt_name,obj_name,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) { + 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; +} + +static int get_obj_params(char* opt_name, char* name,char* params, + m_struct_t* desc,char*** _ret) { + int n = 0,nold = 0, nopts,r; + char* ptr,*last_ptr = params,*eq; + 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); + //exit_player(); + exit(0); + } + printf("\n Name Type Min Max\n\n"); + for(n = 0 ; desc->fields[n].name ; n++) { + 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"); + //exit_player() isn't avaible in mencoder + exit(0); + } + + 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,':'); + if(!ptr) { + r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); + n++; + break; + } + ptr[0] = '\0'; + r = get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,NULL); + ptr[0] = ':'; + if(r < 0) break; + n++; + last_ptr = ptr+1; + } + if(r < 0) return r; + if(!_ret) // Just test + 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,':'); + if(!ptr) { + get_obj_param(opt_name,name,desc,last_ptr,&nold,nopts,&ret[n*2]); + n++; + break; + } + 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_settings(char* opt,char* str,m_obj_list_t* list, + m_obj_settings_t **_ret, int ret_n) { + int r; + char *param,**plist = NULL; + m_struct_t* desc; + m_obj_settings_t *ret = _ret ? *_ret : NULL; + + + // Now check that the object exist + 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) { + 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; +} + + +static int parse_obj_settings_list(m_option_t* opt,char *name, + char *param, void* dst, int src) { + int n = 0,r; + char *str; + char *ptr, *last_ptr; + m_obj_settings_t *res = NULL; + + // We need the objects list + if(!opt->priv) + return M_OPT_INVALID; + + if (param == NULL || strlen(param) == 0) + return M_OPT_MISSING_PARAM; + + if(!strcmp(param,"help")) { + m_obj_list_t* ol = opt->priv; + 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)); + exit(0); + } + ptr = str = strdup(param); + + while(ptr[0] != '\0') { + last_ptr = ptr; + ptr = strchr(ptr,LIST_SEPARATOR); + 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) + VAL(dst) = res; + + return 1; +} + +static void free_obj_settings_list(void* dst) { + int n; + m_obj_settings_t *d; + + if(!dst || !VAL(dst)) return; + + 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); +#endif + VAL(dst) = NULL; +} + +static void copy_obj_settings_list(m_option_t* opt,void* dst, void* src) { + m_obj_settings_t *d,*s; + int n; + + if(!(dst && src)) + return; + + s = VAL(src); + + 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); + d[n].attribs = NULL; + copy_str_list(NULL,&(d[n].attribs),&(s[n].attribs)); + } + d[n].name = d[n].attribs = NULL; + VAL(dst) = d; +} + +m_option_type_t m_option_type_obj_settings_list = { + "Object settings list", + "", + sizeof(m_obj_settings_t*), + M_OPT_TYPE_DYNAMIC, + 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(m_option_t* opt,char *name, + char *param, void* dst, int src) { + m_obj_presets_t* obj_p = (m_obj_presets_t*)opt->priv; + m_struct_t *in_desc,*out_desc; + int s,i; + unsigned char* pre = obj_p->presets; + 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; + + 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, "Avaible 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"); + exit(0); + } + + 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 no preset named %s\n" + "Avaible 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++) { + 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.\nYou should report that to the developpers\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; +} + + +m_option_type_t m_option_type_obj_presets = { + "Object presets", + "", + 0, + 0, + parse_obj_presets, + NULL, + NULL, + NULL, + NULL, + NULL +}; + #endif diff --git a/m_option.h b/m_option.h index 03cb3645c7..33a3bb39bb 100644 --- a/m_option.h +++ b/m_option.h @@ -5,6 +5,7 @@ typedef struct m_option_type m_option_type_t; typedef struct m_option m_option_t; +struct m_struct; ///////////////////////////// Options types declarations //////////////////////////// @@ -52,6 +53,30 @@ typedef struct { } m_span_t; extern m_option_type_t m_option_type_span; +typedef struct { + void** list; + void* name_off; + void* info_off; + void* desc_off; +} m_obj_list_t; + +typedef struct { + char* name; + char** attribs; +} m_obj_settings_t; +extern m_option_type_t m_option_type_obj_settings_list; + +// Presets are mean to be used with options struct + + +typedef struct { + struct m_struct* in_desc; + struct m_struct* out_desc; + void* presets; // Pointer to an arry of struct defined by in_desc + void* name_off; // Offset of the preset name inside the in_struct +} m_obj_presets_t; +extern m_option_type_t m_option_type_obj_presets; + // Don't be stupid keep tho old names ;-) #define CONF_TYPE_FLAG (&m_option_type_flag) #define CONF_TYPE_INT (&m_option_type_int) @@ -67,7 +92,8 @@ extern m_option_type_t m_option_type_span; #define CONF_TYPE_POSITION (&m_option_type_position) #define CONF_TYPE_IMGFMT (&m_option_type_imgfmt) #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) ///////////////////////////////////////////////////////////////////////////////////////////// @@ -181,6 +207,7 @@ struct m_option { #define M_OPT_OUT_OF_RANGE -4 #define M_OPT_PARSER_ERR -5 +m_option_t* m_option_list_find(m_option_t* list,char* name); inline static int m_option_parse(m_option_t* opt,char *name, char *param, void* dst, int src) { diff --git a/mplayer.c b/mplayer.c index d295efe070..8d5210ed0b 100644 --- a/mplayer.c +++ b/mplayer.c @@ -772,13 +772,6 @@ int gui_no_filename=0; } #endif - if(vo_plugin_args && vo_plugin_args[0] && strcmp(vo_plugin_args[0],"help")==0){ - mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AvailableVideoOutputPlugins); - vf_list_plugins(); - printf("\n"); - exit(0); - } - if(video_driver_list && strcmp(video_driver_list[0],"help")==0){ list_video_out(); exit(0); @@ -1539,11 +1532,14 @@ inited_flags|=INITED_VO; } current_module="init_video_filters"; - -sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",(char *)video_out); +{ + char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL }; + sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg); +} #ifdef HAVE_MENU if(use_menu) { - vf_menu = vf_open_plugin(libmenu_vfs,sh_video->vfilter,"menu",menu_root); + char* vf_arg[] = { "_oldargs_", menu_root, NULL }; + vf_menu = vf_open_plugin(libmenu_vfs,sh_video->vfilter,"menu",vf_arg); if(!vf_menu) { mp_msg(MSGT_CPLAYER,MSGL_ERR,"Can't open libmenu video filter with root menu %s\n",menu_root); use_menu = 0;