ao_alsa.c

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

C
889
字号
    mp_msg(MSGT_AO,MSGL_V,"alsa-init: using device %s\n", alsa_device);    //setting modes for block or nonblock-mode    if (ao_noblock) {      open_mode = SND_PCM_NONBLOCK;    }    else {      open_mode = 0;    }    //sets buff/chunksize if its set manually    if (ao_data.buffersize) {      switch (ao_data.buffersize)	{	case 1:	  alsa_fragcount = 16;	  chunk_size = 512;	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");	  break;	case 2:	  alsa_fragcount = 8;	  chunk_size = 1024;	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");	  break;	case 3:	  alsa_fragcount = 32;	  chunk_size = 512;	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");	  break;	case 4:	  alsa_fragcount = 16;	  chunk_size = 1024;	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");	  break;	default:	  alsa_fragcount = 16;	  chunk_size = 1024;	  break;	}    }    if (!alsa_handler) {      //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC      if ((err = try_open_device(alsa_device, open_mode, format == AF_FORMAT_AC3)) < 0)	{	  if (err != -EBUSY && ao_noblock) {	    mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_OpenInNonblockModeFailed);	    if ((err = try_open_device(alsa_device, 0, format == AF_FORMAT_AC3)) < 0) {	      mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));	      return(0);	    }	  } else {	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));	    return(0);	  }	}      if ((err = snd_pcm_nonblock(alsa_handler, 0)) < 0) {         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSetBlockMode, snd_strerror(err));      } else {	mp_msg(MSGT_AO,MSGL_V,"alsa-init: pcm opened in blocking mode\n");      }      snd_pcm_hw_params_alloca(&alsa_hwparams);      snd_pcm_sw_params_alloca(&alsa_swparams);      // setting hw-parameters      if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetInitialParameters,		 snd_strerror(err));	  return(0);	}          err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams,					 SND_PCM_ACCESS_RW_INTERLEAVED);      if (err < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetAccessType, 	       snd_strerror(err));	return (0);      }      /* workaround for nonsupported formats	 sets default format to S16_LE if the given formats aren't supported */      if ((err = snd_pcm_hw_params_test_format(alsa_handler, alsa_hwparams,                                             alsa_format)) < 0)      {         mp_msg(MSGT_AO,MSGL_INFO,		MSGTR_AO_ALSA_FormatNotSupportedByHardware, af_fmt2str_short(format));         alsa_format = SND_PCM_FORMAT_S16_LE;         ao_data.format = AF_FORMAT_S16_LE;      }      if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams,					      alsa_format)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetFormat,		 snd_strerror(err));	  return(0);	}      if ((err = snd_pcm_hw_params_set_channels_near(alsa_handler, alsa_hwparams,						     &ao_data.channels)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetChannels,		 snd_strerror(err));	  return(0);	}      /* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11)         prefer our own resampler */#if SND_LIB_VERSION >= 0x010009      if ((err = snd_pcm_hw_params_set_rate_resample(alsa_handler, alsa_hwparams,						     0)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToDisableResampling,		 snd_strerror(err));	  return(0);	}#endif      if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, 						 &ao_data.samplerate, NULL)) < 0)         {	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSamplerate2,		 snd_strerror(err));	  return(0);        }      bytes_per_sample = snd_pcm_format_physical_width(alsa_format) / 8;      bytes_per_sample *= ao_data.channels;      ao_data.bps = ao_data.samplerate * bytes_per_sample;#ifdef BUFFERTIME      {	int alsa_buffer_time = 500000; /* original 60 */	int alsa_period_time;	alsa_period_time = alsa_buffer_time/4;	if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams, 							  &alsa_buffer_time, NULL)) < 0)	  {	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetBufferTimeNear,		   snd_strerror(err));	    return(0);	  } else	    alsa_buffer_time = err;	if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, 							  &alsa_period_time, NULL)) < 0)	  /* original: alsa_buffer_time/ao_data.bps */	  {	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodTime,		   snd_strerror(err));	    return 0;	  }	mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_BufferTimePeriodTime,	       alsa_buffer_time, err);      } #endif//end SET_BUFFERTIME#ifdef SET_CHUNKSIZE      {	//set chunksize	if ((err = snd_pcm_hw_params_set_period_size_near(alsa_handler, alsa_hwparams, 							  &chunk_size, NULL)) < 0)	  {	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodSize,			    chunk_size, snd_strerror(err));	    return 0;	  }	else {	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set to %li\n", chunk_size);	}	if ((err = snd_pcm_hw_params_set_periods_near(alsa_handler, alsa_hwparams,						      &alsa_fragcount, NULL)) < 0) {	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriods, 		 snd_strerror(err));	  return 0;	}	else {	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: fragcount=%i\n", alsa_fragcount);	}      }#endif//end SET_CHUNKSIZE      /* finally install hardware parameters */      if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetHwParameters,		 snd_strerror(err));	  return 0;	}      // end setting hw-params      // gets buffersize for control      if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &bufsize)) < 0)	{	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBufferSize, snd_strerror(err));	  return 0;	}      else {	ao_data.buffersize = bufsize * bytes_per_sample;	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: got buffersize=%i\n", ao_data.buffersize);      }      if ((err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &chunk_size, NULL)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetPeriodSize, snd_strerror(err));	return 0;      } else {	mp_msg(MSGT_AO,MSGL_V,"alsa-init: got period size %li\n", chunk_size);      }      ao_data.outburst = chunk_size * bytes_per_sample;      /* setting software parameters */      if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,	       snd_strerror(err));	return 0;      }#if SND_LIB_VERSION >= 0x000901      if ((err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBoundary,	       snd_strerror(err));	return 0;      }#else      boundary = 0x7fffffff;#endif      /* start playing when one period has been written */      if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, chunk_size)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStartThreshold,	       snd_strerror(err));	return 0;      }      /* disable underrun reporting */      if ((err = snd_pcm_sw_params_set_stop_threshold(alsa_handler, alsa_swparams, boundary)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStopThreshold,	       snd_strerror(err));	return 0;      }#if SND_LIB_VERSION >= 0x000901      /* play silence when there is an underrun */      if ((err = snd_pcm_sw_params_set_silence_size(alsa_handler, alsa_swparams, boundary)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSilenceSize,	       snd_strerror(err));	return 0;      }#endif      if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,	       snd_strerror(err));	return 0;      }      /* end setting sw-params */      mp_msg(MSGT_AO,MSGL_V,"alsa: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",	     ao_data.samplerate, ao_data.channels, bytes_per_sample, ao_data.buffersize,	     snd_pcm_format_description(alsa_format));    } // end switch alsa_handler (spdif)    alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams);    return(1);} // end init/* close audio device */static void uninit(int immed){  if (alsa_handler) {    int err;    if (!immed)      snd_pcm_drain(alsa_handler);    if ((err = snd_pcm_close(alsa_handler)) < 0)      {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmCloseError, snd_strerror(err));	return;      }    else {      alsa_handler = NULL;      mp_msg(MSGT_AO,MSGL_V,"alsa-uninit: pcm closed\n");    }  }  else {    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_NoHandlerDefined);  }}static void audio_pause(void){    int err;    if (alsa_can_pause) {        if ((err = snd_pcm_pause(alsa_handler, 1)) < 0)        {            mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPauseError, snd_strerror(err));            return;        }          mp_msg(MSGT_AO,MSGL_V,"alsa-pause: pause supported by hardware\n");    } else {        if ((err = snd_pcm_drop(alsa_handler)) < 0)        {            mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmDropError, snd_strerror(err));            return;        }    }}static void audio_resume(void){    int err;    if (alsa_can_pause) {        if ((err = snd_pcm_pause(alsa_handler, 0)) < 0)        {            mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmResumeError, snd_strerror(err));            return;        }          mp_msg(MSGT_AO,MSGL_V,"alsa-resume: resume supported by hardware\n");    } else {        if ((err = snd_pcm_prepare(alsa_handler)) < 0)        {           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));            return;        }    }}/* stop playing and empty buffers (for seeking/pause) */static void reset(void){    int err;    if ((err = snd_pcm_drop(alsa_handler)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));	return;    }    if ((err = snd_pcm_prepare(alsa_handler)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));	return;    }    return;}/*    plays 'len' bytes of 'data'    returns: number of bytes played    modified last at 29.06.02 by jp    thanxs for marius <marius@rospot.com> for giving us the light ;)*/static int play(void* data, int len, int flags){  int num_frames = len / bytes_per_sample;  snd_pcm_sframes_t res = 0;  //mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: frames=%i, len=%i\n",num_frames,len);  if (!alsa_handler) {    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_DeviceConfigurationError);    return 0;  }  if (num_frames == 0)    return 0;  do {    res = snd_pcm_writei(alsa_handler, data, num_frames);      if (res == -EINTR) {	/* nothing to do */	res = 0;      }      else if (res == -ESTRPIPE) {	/* suspend */	mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_PcmInSuspendModeTryingResume);	while ((res = snd_pcm_resume(alsa_handler)) == -EAGAIN)	  sleep(1);      }      if (res < 0) {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_WriteError, snd_strerror(res));	mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_TryingToResetSoundcard);	if ((res = snd_pcm_prepare(alsa_handler)) < 0) {	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(res));	  return(0);	  break;	}      }  } while (res == 0);  return res < 0 ? res : res * bytes_per_sample;}/* how many byes are free in the buffer */static int get_space(void){    snd_pcm_status_t *status;    int ret;        snd_pcm_status_alloca(&status);        if ((ret = snd_pcm_status(alsa_handler, status)) < 0)    {	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_CannotGetPcmStatus, snd_strerror(ret));	return(0);    }        ret = snd_pcm_status_get_avail(status) * bytes_per_sample;    if (ret > ao_data.buffersize)  // Buffer underrun?	ret = ao_data.buffersize;    return(ret);}/* delay in seconds between first and last sample in buffer */static float get_delay(void){  if (alsa_handler) {    snd_pcm_sframes_t delay;        if (snd_pcm_delay(alsa_handler, &delay) < 0)      return 0;        if (delay < 0) {      /* underrun - move the application pointer forward to catch up */#if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */      snd_pcm_forward(alsa_handler, -delay);#endif      delay = 0;    }    return (float)delay / (float)ao_data.samplerate;  } else {    return(0);  }}

⌨️ 快捷键说明

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