ao_nas.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 614 行 · 第 1/2 页

C
614
字号
	}	nas_data->state=event->cur_state;	return AuTrue;}static AuDeviceID nas_find_device(AuServer *aud, int nch){	int i;	for (i = 0; i < AuServerNumDevices(aud); i++) {		AuDeviceAttributes *dev = AuServerDevice(aud, i);		if ((AuDeviceKind(dev) == AuComponentKindPhysicalOutput) &&		     AuDeviceNumTracks(dev) == nch) {			return AuDeviceIdentifier(dev);		}	}	return AuNone;}static unsigned int nas_aformat_to_auformat(unsigned int *format){	switch (*format) {	case	AF_FORMAT_U8:		return AuFormatLinearUnsigned8;	case	AF_FORMAT_S8:		return AuFormatLinearSigned8;	case	AF_FORMAT_U16_LE:		return AuFormatLinearUnsigned16LSB;	case	AF_FORMAT_U16_BE:		return AuFormatLinearUnsigned16MSB;	case	AF_FORMAT_S16_LE:		return AuFormatLinearSigned16LSB;	case	AF_FORMAT_S16_BE:		return AuFormatLinearSigned16MSB;	case	AF_FORMAT_MU_LAW:		return AuFormatULAW8;	default:		*format=AF_FORMAT_S16_NE;		return nas_aformat_to_auformat(format);	}}// to set/get/query special features/parametersstatic int control(int cmd, void *arg){	AuElementParameters aep;	AuStatus as;	int retval = CONTROL_UNKNOWN;	ao_control_vol_t *vol = (ao_control_vol_t *)arg;	switch (cmd) {	case AOCONTROL_GET_VOLUME:		vol->right = (float)nas_data->gain/AU_FIXED_POINT_SCALE*50;		vol->left = vol->right;		mp_msg(MSGT_AO, MSGL_DBG2, "ao_nas: AOCONTROL_GET_VOLUME: %08x\n", nas_data->gain);		retval = CONTROL_OK;		break;	case AOCONTROL_SET_VOLUME:		/*		 * kn: we should have vol->left == vol->right but i don't		 * know if something can change it outside of ao_nas		 * so i take the mean of both values.		 */		nas_data->gain = AU_FIXED_POINT_SCALE*((vol->left+vol->right)/2)/50;		mp_msg(MSGT_AO, MSGL_DBG2, "ao_nas: AOCONTROL_SET_VOLUME: %08x\n", nas_data->gain);		aep.parameters[AuParmsMultiplyConstantConstant]=nas_data->gain;		aep.flow = nas_data->flow;		aep.element_num = 1;		aep.num_parameters = AuParmsMultiplyConstant;		AuSetElementParameters(nas_data->aud, 1, &aep, &as);		if (as != AuSuccess) {			nas_print_error(nas_data->aud,			                "control(): AuSetElementParameters", as);			retval = CONTROL_ERROR;		} else retval = CONTROL_OK;		break;	};	return retval;}// open & setup audio device// return: 1=success 0=failstatic int init(int rate,int channels,int format,int flags){	AuElement elms[3];	AuStatus as;	unsigned char auformat = nas_aformat_to_auformat(&format);	int bytes_per_sample = channels * AuSizeofFormat(auformat);	int buffer_size;	char *server;	nas_data=malloc(sizeof(struct ao_nas_data));	memset(nas_data, 0, sizeof(struct ao_nas_data));	mp_msg(MSGT_AO, MSGL_V, "ao2: %d Hz  %d chans  %s\n",rate,channels,		af_fmt2str_short(format));	ao_data.format = format;	ao_data.samplerate = rate;	ao_data.channels = channels;	ao_data.outburst = NAS_FRAG_SIZE;	ao_data.bps = rate * bytes_per_sample;	buffer_size = ao_data.bps; /* buffer 1 second */	/*	 * round up to multiple of NAS_FRAG_SIZE	 * divide by 3 first because of 2:1 split	 */	buffer_size = (buffer_size/3 + NAS_FRAG_SIZE-1) & ~(NAS_FRAG_SIZE-1);	ao_data.buffersize = buffer_size*3;	nas_data->client_buffer_size = buffer_size*2;	nas_data->client_buffer = malloc(nas_data->client_buffer_size);	nas_data->server_buffer_size = buffer_size;	nas_data->server_buffer = malloc(nas_data->server_buffer_size);	if (!bytes_per_sample) {		mp_msg(MSGT_AO, MSGL_ERR, "ao_nas: init(): Zero bytes per sample -> nosound\n");		return 0;	}	if (!(server = getenv("AUDIOSERVER")) &&	    !(server = getenv("DISPLAY"))) {		mp_msg(MSGT_AO, MSGL_ERR, "ao_nas: init(): AUDIOSERVER environment variable not set -> nosound\n");		return 0;	}	mp_msg(MSGT_AO, MSGL_V, "ao_nas: init(): Using audioserver %s\n", server);	nas_data->aud = AuOpenServer(server, 0, NULL, 0, NULL, NULL);	if (!nas_data->aud) { 		mp_msg(MSGT_AO, MSGL_ERR, "ao_nas: init(): Can't open nas audio server -> nosound\n");		return 0;	}	while (channels>0) {		nas_data->dev = nas_find_device(nas_data->aud, channels);		if (nas_data->dev != AuNone &&		    ((nas_data->flow = AuCreateFlow(nas_data->aud, NULL)) != 0))			break;		channels--;	}	if (nas_data->flow == 0) {		mp_msg(MSGT_AO, MSGL_ERR, "ao_nas: init(): Can't find a suitable output device -> nosound\n");		AuCloseServer(nas_data->aud);		nas_data->aud = 0;		return 0;	}	AuMakeElementImportClient(elms, rate, auformat, channels, AuTrue,				buffer_size / bytes_per_sample,				(buffer_size - NAS_FRAG_SIZE) /				bytes_per_sample, 0, NULL);	nas_data->gain = AuFixedPointFromFraction(1, 1);	AuMakeElementMultiplyConstant(elms+1, 0, nas_data->gain);	AuMakeElementExportDevice(elms+2, 1, nas_data->dev, rate,				AuUnlimitedSamples, 0, NULL);	AuSetElements(nas_data->aud, nas_data->flow, AuTrue, sizeof(elms)/sizeof(*elms), elms, &as);	if (as != AuSuccess) {		nas_print_error(nas_data->aud, "init(): AuSetElements", as);		AuCloseServer(nas_data->aud);		nas_data->aud = 0;		return 0;	}	AuRegisterEventHandler(nas_data->aud, AuEventHandlerIDMask |				AuEventHandlerTypeMask,				AuEventTypeElementNotify, nas_data->flow,				nas_event_handler, (AuPointer) nas_data);	AuSetErrorHandler(nas_data->aud, nas_error_handler);	nas_data->state=AuStateStop;	nas_data->expect_underrun=0;	pthread_mutex_init(&nas_data->buffer_mutex, NULL);	pthread_create(&nas_data->event_thread, NULL, &nas_event_thread_start, nas_data);	return 1;}// close audio devicestatic void uninit(int immed){	mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: uninit()\n");	nas_data->expect_underrun = 1;	if (!immed)	while (nas_data->state != AuStateStop) usleep(1000);	nas_data->stop_thread = 1;	pthread_join(nas_data->event_thread, NULL);	AuCloseServer(nas_data->aud);	nas_data->aud = 0;	free(nas_data->client_buffer);	free(nas_data->server_buffer);}// stop playing and empty buffers (for seeking/pause)static void reset(void){	AuStatus as;	mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: reset()\n");	pthread_mutex_lock(&nas_data->buffer_mutex);	nas_data->client_buffer_used = 0;	pthread_mutex_unlock(&nas_data->buffer_mutex);	while (nas_data->state != AuStateStop) {		AuStopFlow(nas_data->aud, nas_data->flow, &as);		if (as != AuSuccess)			nas_print_error(nas_data->aud, "reset(): AuStopFlow", as);		usleep(1000);	}}// stop playing, keep buffers (for pause)static void audio_pause(void){	AuStatus as;	mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: audio_pause()\n");	AuStopFlow(nas_data->aud, nas_data->flow, &as);}// resume playing, after audio_pause()static void audio_resume(void){	AuStatus as;	mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: audio_resume()\n");	AuStartFlow(nas_data->aud, nas_data->flow, &as);	if (as != AuSuccess)		nas_print_error(nas_data->aud,		                "play(): AuStartFlow", as);}// return: how many bytes can be played without blockingstatic int get_space(void){	int result;		mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: get_space()\n");	pthread_mutex_lock(&nas_data->buffer_mutex);	result = nas_data->client_buffer_size - nas_data->client_buffer_used;	pthread_mutex_unlock(&nas_data->buffer_mutex);	return result;}// plays 'len' bytes of 'data'// it should round it down to outburst*n// return: number of bytes playedstatic int play(void* data,int len,int flags){	int maxbursts, playbursts, writelen;	AuStatus as;	mp_msg(MSGT_AO, MSGL_DBG3,	       "ao_nas: play(%p, %d, %d)\n",	       data, len, flags);	if (len == 0)		return 0;	pthread_mutex_lock(&nas_data->buffer_mutex);	maxbursts = (nas_data->client_buffer_size -		     nas_data->client_buffer_used) / ao_data.outburst;	playbursts = len / ao_data.outburst;	writelen = (playbursts > maxbursts ? maxbursts : playbursts) *		   ao_data.outburst;	pthread_mutex_unlock(&nas_data->buffer_mutex);	writelen = nas_writeBuffer(nas_data, data, writelen);	if (nas_data->state != AuStateStart &&	    maxbursts == playbursts) {		mp_msg(MSGT_AO, MSGL_DBG2, "ao_nas: play(): Starting flow.\n");		nas_data->expect_underrun = 1;		AuStartFlow(nas_data->aud, nas_data->flow, &as);		if (as != AuSuccess)			nas_print_error(nas_data->aud, "play(): AuStartFlow", as);	}	return writelen;}// return: delay in seconds between first and last sample in bufferstatic float get_delay(void){	float result;		mp_msg(MSGT_AO, MSGL_DBG3, "ao_nas: get_delay()\n");	pthread_mutex_lock(&nas_data->buffer_mutex);	result = ((float)(nas_data->client_buffer_used +			  nas_data->server_buffer_used)) /		 (float)ao_data.bps;	pthread_mutex_unlock(&nas_data->buffer_mutex);	return result;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?