Mercurial > mplayer.hg
view libao2/ao_plugin.c @ 9278:caea8ed36b48
The reason why mplayer crashes (in some cases) when using x11
output and -wid (>0) parameter is this:
Mplayer by default creates a colormap using DirectColor visual. If the
window given to mplayer uses TrueColor visual there will be an error
when mplayer sets the colormap for the window. This patch
modifies mplayer to use TrueColor visual if the window given to mplayer
uses TrueColor. Another solution is to make sure that the window given to
mplayer is created using DirectColor visual if it is supported by the
display.
Jouni Tulkki <jitulkki@cc.hut.fi>
author | arpi |
---|---|
date | Tue, 04 Feb 2003 18:31:44 +0000 |
parents | eaee773aee9c |
children | 12b1790038b0 |
line wrap: on
line source
#include "../config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "afmt.h" #include "audio_out.h" #include "audio_out_internal.h" #include "audio_plugin.h" static ao_info_t info = { "Plugin audio output", "plugin", "Anders", "" }; LIBAO_EXTERN(plugin) #define plugin(i) (ao_plugin_local_data.plugins[i]) #define driver() (ao_plugin_local_data.driver) // local data typedef struct ao_plugin_local_data_s { void* buf; // Output data buffer int len; // Amount of data in buffer int channels; int format; int bpm; //bit of format float bps; // Bytes per second out ao_functions_t* driver; // Output driver ao_plugin_functions_t** plugins; // List of used plugins ao_plugin_functions_t* available_plugins[NPL]; // List of available plugins } ao_plugin_local_data_t; static ao_plugin_local_data_t ao_plugin_local_data={NULL,0,0,0,0,0.0,NULL,NULL,AO_PLUGINS}; // global data volatile ao_plugin_data_t ao_plugin_data; // Data used by the plugins ao_plugin_cfg_t ao_plugin_cfg=CFG_DEFAULTS; // Set in cfg-mplayer.h // to set/get/query special features/parameters static int control(int cmd,int arg){ switch(cmd){ case AOCONTROL_SET_PLUGIN_DRIVER: ao_plugin_local_data.driver=(ao_functions_t*)arg; return CONTROL_OK; case AOCONTROL_GET_VOLUME: case AOCONTROL_SET_VOLUME: { int r=audio_plugin_volume.control(cmd,arg); if(CONTROL_OK != r) return driver()->control(cmd,arg); else return r; } default: return driver()->control(cmd,arg); } return CONTROL_UNKNOWN; } // Recursive function for adding plugins // return 1 for success and 0 for error int add_plugin(int i,char* cfg){ int cnt=0; // Find end of plugin name while((cfg[cnt]!=',')&&(cfg[cnt]!='\0')&&(cnt<100)) cnt++; if(cnt >= 100) return 0; // Is this the last iteration or just another plugin if(cfg[cnt]=='\0'){ ao_plugin_local_data.plugins=malloc((i+2)*sizeof(ao_plugin_functions_t*)); if(ao_plugin_local_data.plugins){ ao_plugin_local_data.plugins[i+1]=NULL; // Find the plugin matching the cfg string name cnt=0; while(ao_plugin_local_data.available_plugins[cnt] && cnt<20){ if(0==strcmp(ao_plugin_local_data.available_plugins[cnt]->info->short_name,cfg)){ ao_plugin_local_data.plugins[i]=ao_plugin_local_data.available_plugins[cnt]; return 1; } cnt++; } printf("[plugin]: Invalid plugin: %s \n",cfg); return 0; } else return 0; } else { cfg[cnt]='\0'; if(add_plugin(i+1,&cfg[cnt+1])){ cnt=0; // Find the plugin matching the cfg string name while(ao_plugin_local_data.available_plugins[cnt] && cnt < 20){ if(0==strcmp(ao_plugin_local_data.available_plugins[cnt]->info->short_name,cfg)){ ao_plugin_local_data.plugins[i]=ao_plugin_local_data.available_plugins[cnt]; return 1; } cnt++; } printf("[plugin]: Invalid plugin: %s \n",cfg); return 0; } else return 0; } return 0; // Will never happen... } // open & setup audio device and plugins // return: 1=success 0=fail static int init(int rate,int channels,int format,int flags){ int use_plugin[NPL]; int x,npl,unused=0; int ok=1; char *config; // Create list of plugins from cfg option int i=0; if(ao_plugin_cfg.plugin_list){ config = malloc(strlen(ao_plugin_cfg.plugin_list)+1); if(!config) return 0; if(!strcpy(config, ao_plugin_cfg.plugin_list) || !add_plugin(i,config)){ free(config); return 0; } free(config); } /* Set input parameters and itterate through plugins each plugin changes the parameters according to its output */ ao_plugin_local_data.format=format; ao_plugin_local_data.channels=channels; ao_plugin_local_data.bpm=audio_out_format_bits(format); ao_plugin_data.rate=rate; ao_plugin_data.channels=channels; ao_plugin_data.format=format; ao_plugin_data.sz_mult=1; ao_plugin_data.sz_fix=0; ao_plugin_data.delay_mult=1; ao_plugin_data.delay_fix=0; for(i=0;i<NPL && plugin(i);i++){ use_plugin[i]=plugin(i)->init(); if(!use_plugin[i]) plugin(i)->uninit(); } npl=i; for(i=0;i<npl && plugin(i);i++) if(!use_plugin[i+unused]){ unused++; for(x=i;x<npl && plugin(x+1);x++) plugin(x)=plugin(x+1); plugin(x)=NULL; npl--; i--; } i=npl; // Calculate bps ao_plugin_local_data.bps=(float)(ao_plugin_data.rate * ao_plugin_data.channels); ao_plugin_local_data.bps*=audio_out_format_bits(ao_plugin_data.format)/8; // This should never happen but check anyway if(NULL==ao_plugin_local_data.driver) return 0; ok = driver()->init(ao_plugin_data.rate, ao_plugin_data.channels, ao_plugin_data.format, flags); if(!ok) return 0; /* Now that the driver is initialized we can calculate and set the input and output buffers for each plugin */ ao_plugin_data.len=driver()->get_space(); while((i>0) && ok) ok=plugin(--i)->control(AOCONTROL_PLUGIN_SET_LEN,0); if(!ok) return 0; // Allocate output buffer if(ao_plugin_local_data.buf) free(ao_plugin_local_data.buf); ao_plugin_local_data.buf=malloc(MAX_OUTBURST); if(!ao_plugin_local_data.buf) return 0; return 1; } // close audio device static void uninit(){ int i=0; driver()->uninit(); while(plugin(i)) plugin(i++)->uninit(); if(ao_plugin_local_data.plugins) free(ao_plugin_local_data.plugins); ao_plugin_local_data.plugins=NULL; if(ao_plugin_local_data.buf) free(ao_plugin_local_data.buf); ao_plugin_local_data.buf=NULL; } // stop playing and empty buffers (for seeking/pause) static void reset(){ int i=0; driver()->reset(); while(plugin(i)) plugin(i++)->reset(); ao_plugin_local_data.len=0; } // stop playing, keep buffers (for pause) static void audio_pause(){ driver()->pause(); } // resume playing, after audio_pause() static void audio_resume(){ driver()->resume(); } // return: how many bytes can be played without blocking static int get_space(){ double sz; int isz; sz=(double)(driver()->get_space()); if(sz+(double)ao_plugin_local_data.len > (double)MAX_OUTBURST) sz=(double)MAX_OUTBURST-(double)ao_plugin_local_data.len; sz*=ao_plugin_data.sz_mult; sz+=ao_plugin_data.sz_fix; isz=(int)(sz); isz-=isz%(ao_plugin_local_data.channels*ao_plugin_local_data.bpm/8); return isz; } // plays 'len' bytes of 'data' // return: number of bytes played static int play(void* data,int len,int flags){ int l,i=0; // Limit length to avoid over flow in plugins int tmp = get_space(); int ret_len =(tmp<len)?tmp:len; // keep all channels of each sample together ret_len -= ret_len % (ao_plugin_local_data.channels*ao_plugin_local_data.bpm/8); if(ret_len){ // Filter data ao_plugin_data.len=ret_len; ao_plugin_data.data=data; while(plugin(i)) plugin(i++)->play(); // Copy data to output buffer memcpy(ao_plugin_local_data.buf+ao_plugin_local_data.len, ao_plugin_data.data,ao_plugin_data.len); // Send data to output l=driver()->play(ao_plugin_local_data.buf, ao_plugin_data.len+ao_plugin_local_data.len,flags); // Save away unsent data ao_plugin_local_data.len=ao_plugin_data.len+ao_plugin_local_data.len-l; memcpy(ao_plugin_local_data.buf,ao_plugin_local_data.buf+l, ao_plugin_local_data.len); } return ret_len; } // return: delay in seconds between first and last sample in buffer static float get_delay(){ float delay=driver()->get_delay(); delay+=(float)ao_plugin_local_data.len/ao_plugin_local_data.bps; delay*=ao_plugin_data.delay_mult; delay+=ao_plugin_data.delay_fix; return delay; }