Mercurial > mplayer.hg
view m_property.c @ 23978:ef6e50c3c172
Revert setting audio output channel count for FFmpeg
The FFmpeg API needs to be fixed before this can be done sanely.
ffdca wants the desired output channel count to be set in
avctx->channels. Unfortunately it also completely fails if the requested
number of channels is not available rather than returning a different
amount (if 6 channels are requested we'd probably rather use stereo than
fail completely).
ffvorbis ignores caller-set values in avctx->channels. It writes the
channel count there once during init. This means the caller can only
set the count before init because later there would be no indication
whether the channel count in avctx reflects real output.
ffwma requires the caller to supply the encoded channel count
in avctx->channels during init or it fails. So it is not possible to
set a different number of desired output channels there before init
either.
author | uau |
---|---|
date | Thu, 02 Aug 2007 21:54:14 +0000 |
parents | ae4237717601 |
children | 3086b6d39052 |
line wrap: on
line source
/// \file /// \ingroup Properties #include "config.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #include <inttypes.h> #include <unistd.h> #include "m_option.h" #include "m_property.h" #include "mp_msg.h" #include "help_mp.h" #define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5)) static int do_action(m_option_t* prop_list, const char* name, int action, void* arg, void *ctx) { const char* sep; 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); base[len] = 0; prop = m_option_list_find(prop_list, base); 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; *(m_option_t**)arg = prop; return M_PROPERTY_OK; } return r; } int m_property_do(m_option_t* prop_list, const char* name, int action, void* arg, void *ctx) { m_option_t* opt; void* val; char* str; int r; switch(action) { case M_PROPERTY_PRINT: if((r = do_action(prop_list,name,M_PROPERTY_PRINT,arg,ctx)) >= 0) return r; // 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) 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) return r; 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); free(val); *(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) 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) 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) { free(val); return r; } 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); } char* m_properties_expand_string(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] == '\\') { int sl = 1; switch(str[1]) { case 'e': p = "\x1b", l = 1; break; case 'n': p = "\n", l = 1; break; case 'r': p = "\r", l = 1; break; case 't': p = "\t", l = 1; break; case 'x': if(str[2]) { char num[3] = { str[2], str[3], 0 }; 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; } 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); pname[pl] = 0; 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,':'))) { int pl = e-str-2; char pname[pl+1]; lvl++; if(!skip) { memcpy(pname,str+2,pl); pname[pl] = 0; if(m_property_do(prop_list,pname,M_PROPERTY_GET,NULL,ctx) < 0) skip = 1, skip_lvl = lvl; } str = e+1, l = 0; } else p = str, l = 1, str++; if(skip || l <= 0) continue; if(pos+l+1 > size) { size = pos+l+512; ret = realloc(ret,size); } memcpy(ret+pos,p,l); pos += l; if(fr) free(p), fr = 0; } ret[pos] = 0; return ret; } void m_properties_print_help_list(m_option_t* list) { char min[50],max[50]; int i,count = 0; mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_PropertyListHeader); for(i = 0 ; list[i].name ; i++) { 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); else strcpy(max,"No"); mp_msg(MSGT_CFGPARSER, MSGL_INFO, " %-20.20s %-15.15s %-10.10s %-10.10s\n", opt->name, opt->type->name, min, max); count++; } mp_msg(MSGT_CFGPARSER, MSGL_INFO, MSGTR_TotalProperties, count); } // Some generic property implementations int m_property_int_ro(m_option_t* prop,int action, void* arg,int var) { switch(action) { case M_PROPERTY_GET: if(!arg) return 0; *(int*)arg = var; return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_int_range(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; 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); return 1; } return m_property_int_ro(prop,action,arg,*var); } int m_property_choice(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; return 1; } return m_property_int_range(prop,action,arg,var); } int m_property_flag(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; return 1; case M_PROPERTY_PRINT: if(!arg) return 0; *(char**)arg = strdup((*var > prop->min) ? MSGTR_Enabled : MSGTR_Disabled); return 1; } return m_property_int_range(prop,action,arg,var); } int m_property_float_ro(m_option_t* prop,int action, void* arg,float var) { switch(action) { case M_PROPERTY_GET: 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); return 1; } return M_PROPERTY_NOT_IMPLEMENTED; } int m_property_float_range(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; 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); return 1; } return m_property_float_ro(prop,action,arg,*var); } int m_property_delay(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(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(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(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(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); }