📄 alsa_a.c
字号:
ret = snd_pcm_close (handle); if (ret < 0 && ret != -EINVAL) /* Maybe alsa-driver 0.5 has a bug */ error_report (ret); handle = NULL; dpm.fd = -1;}static int output_data(char *buf, int32 nbytes){ int n; snd_pcm_channel_status_t status; if (! handle) return -1; n = snd_pcm_write (handle, buf, nbytes); if (n <= 0) { memset (&status, 0, sizeof(status)); status.channel = SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_channel_status(handle, &status) < 0) { ctl->cmsg(CMSG_WARNING, VERB_DEBUG, "%s: could not get channel status", alsa_device_name()); return -1; } if (status.status == SND_PCM_STATUS_UNDERRUN || n == -EPIPE) { ctl->cmsg(CMSG_INFO, VERB_DEBUG, "%s: underrun at %d", alsa_device_name(), status.scount); output_counter += status.scount; snd_pcm_channel_flush (handle, SND_PCM_CHANNEL_PLAYBACK); snd_pcm_channel_prepare (handle, SND_PCM_CHANNEL_PLAYBACK); n = snd_pcm_write (handle, buf, nbytes); } if (n <= 0) { ctl->cmsg(CMSG_WARNING, VERB_DEBUG, "%s: %s", alsa_device_name(), (n < 0) ? snd_strerror(n) : "write error"); if (n != -EPIPE) /* buffer underrun is ignored */ return -1; } } return 0;}static int acntl(int request, void *arg){ int i; snd_pcm_channel_status_t pstatus; memset (&pstatus, 0, sizeof (pstatus)); pstatus.channel = SND_PCM_CHANNEL_PLAYBACK; if (handle == NULL) return -1; switch (request) { case PM_REQ_GETFRAGSIZ: if (frag_size == 0) return -1; *((int *)arg) = frag_size; return 0; case PM_REQ_GETQSIZ: if (total_bytes == -1) return -1; *((int *)arg) = total_bytes; return 0; case PM_REQ_GETFILLABLE: if (total_bytes == -1) return -1; if (snd_pcm_channel_status(handle, &pstatus) < 0) return -1; i = pstatus.free >> sample_shift; *((int *)arg) = i; return 0; case PM_REQ_GETFILLED: if (total_bytes == -1) return -1; if (snd_pcm_channel_status(handle, &pstatus) < 0) return -1; i = pstatus.count >> sample_shift; *((int *)arg) = i; return 0; case PM_REQ_GETSAMPLES: if (total_bytes == -1) return -1; if (snd_pcm_channel_status(handle, &pstatus) < 0) return -1; i = (output_counter + pstatus.scount) >> sample_shift; *((int *)arg) = i; return 0; case PM_REQ_DISCARD: if (snd_pcm_playback_drain(handle) < 0) return -1; if (snd_pcm_channel_prepare(handle, SND_PCM_CHANNEL_PLAYBACK) < 0) return -1; output_counter = 0; return 0; case PM_REQ_FLUSH: if (snd_pcm_channel_flush(handle, SND_PCM_CHANNEL_PLAYBACK) < 0) return -1; if (snd_pcm_channel_prepare(handle, SND_PCM_CHANNEL_PLAYBACK) < 0) return -1; output_counter = 0; return 0; } return -1;}/* end ALSA API 0.5.x */#elif ALSA_LIB < 5/*================================================================ * ALSA API version 0.4.x *================================================================*//*return value == 0 sucess == 1 warning == -1 fails */static int set_playback_info (snd_pcm_t* handle__, int32* encoding__, int32* rate__, const int32 extra_param[5]){ int ret_val = 0; const int32 orig_encoding = *encoding__; const int32 orig_rate = *rate__; int tmp; snd_pcm_playback_info_t pinfo; snd_pcm_format_t pcm_format; struct snd_pcm_playback_params pparams; struct snd_pcm_playback_status pstatus; memset (&pcm_format, 0, sizeof (pcm_format)); memset (&pinfo, 0, sizeof (pinfo)); memset (&pparams, 0, sizeof (pparams)); tmp = snd_pcm_playback_info (handle__, &pinfo); if (tmp < 0) { error_report (tmp); return -1; } /*check sample bit*/ if ((pinfo.flags & SND_PCM_PINFO_8BITONLY) != 0) *encoding__ &= ~PE_16BIT; /*force 8bit samples*/ if ((pinfo.flags & SND_PCM_PINFO_16BITONLY) != 0) *encoding__ |= PE_16BIT; /*force 16bit samples*/ /*check rate*/ if (pinfo.min_rate > *rate__) *rate__ = pinfo.min_rate; if (pinfo.max_rate < *rate__) *rate__ = pinfo.max_rate; pcm_format.rate = *rate__; /*check channels*/ if ((*encoding__ & PE_MONO) != 0 && pinfo.min_channels > 1) *encoding__ &= ~PE_MONO; if ((*encoding__ & PE_MONO) == 0 && pinfo.max_channels < 2) *encoding__ |= PE_MONO; if ((*encoding__ & PE_MONO) != 0) pcm_format.channels = 1; /*mono*/ else pcm_format.channels = 2; /*stereo*/ /*check format*/ if ((*encoding__ & PE_16BIT) != 0) { /*16bit*/ if ((pinfo.formats & SND_PCM_FMT_S16_LE) != 0) { pcm_format.format = SND_PCM_SFMT_S16_LE; *encoding__ |= PE_SIGNED; } else { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s doesn't support 16 bit sample width", alsa_device_name()); return -1; } } else { /*8bit*/ if ((pinfo.formats & SND_PCM_FMT_U8) != 0) { pcm_format.format = SND_PCM_SFMT_U8; *encoding__ &= ~PE_SIGNED; }#if 0 else if ((pinfo.formats & SND_PCM_FMT_S8) != 0) { pcm_format.format = SND_PCM_SFMT_U16_LE; *encoding__ |= PE_SIGNED; }#endif else { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s doesn't support 8 bit sample width", alsa_device_name()); return -1; } } tmp = snd_pcm_playback_format (handle__, &pcm_format); if (tmp < 0) { error_report (tmp); return -1; } /*check result of snd_pcm_playback_format*/ if ((*encoding__ & PE_16BIT) != (orig_encoding & PE_16BIT )) { ctl->cmsg (CMSG_WARNING, VERB_VERBOSE, "Sample width adjusted to %d bits", ((*encoding__ & PE_16BIT) != 0)? 16:8); ret_val = 1; } if (((pcm_format.channels == 1)? PE_MONO:0) != (orig_encoding & PE_MONO)) { ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Sound adjusted to %sphonic", ((*encoding__ & PE_MONO) != 0)? "mono" : "stereo"); ret_val = 1; } sample_shift = 0; if (!(dpm.encoding & PE_MONO)) sample_shift++; if (dpm.encoding & PE_16BIT) sample_shift++; /* Set buffer fragment size (in extra_param[1]) */ if (extra_param[1] != 0) tmp = extra_param[1]; else tmp = audio_buffer_size << sample_shift; /* Set buffer fragments (in extra_param[0]) */ pparams.fragment_size = tmp; pparams.fragments_max = (extra_param[0] == 0) ? -1 : extra_param[0]; pparams.fragments_room = 1; tmp = snd_pcm_playback_params (handle__, &pparams); if (tmp < 0) { ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "%s doesn't support buffer fragments" ":request size=%d, max=%d, room=%d\n", alsa_device_name(), pparams.fragment_size, pparams.fragments_max, pparams.fragments_room); ret_val = 1; } if (snd_pcm_playback_status(handle__, &pstatus) == 0) { if (pstatus.rate != orig_rate) { ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Output rate adjusted to %d Hz (requested %d Hz)", pstatus.rate, orig_rate); dpm.rate = pstatus.rate; ret_val = 1; } frag_size = pstatus.fragment_size; total_bytes = pstatus.count; } else { frag_size = 0; total_bytes = -1; /* snd_pcm_playback_status fails */ } return ret_val;}static int open_output(void){ int tmp, warnings=0; int ret; tmp = check_sound_cards (&card, &device, dpm.extra_param); if (tmp < 0) return -1; /* Open the audio device */ ret = snd_pcm_open (&handle, card, device, SND_PCM_OPEN_PLAYBACK); if (ret < 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", alsa_device_name(), snd_strerror (ret)); return -1; } /* They can't mean these */ dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP); warnings = set_playback_info (handle, &dpm.encoding, &dpm.rate, dpm.extra_param); if (warnings < 0) { close_output (); return -1; } dpm.fd = snd_pcm_file_descriptor (handle); output_counter = 0; return warnings;}static void close_output(void){ int ret; if (handle == NULL) return; ret = snd_pcm_close (handle); if (ret < 0) error_report (ret); handle = NULL; dpm.fd = -1;}static int output_data(char *buf, int32 nbytes){ int n; if (! handle) return -1; while (nbytes > 0) { n = snd_pcm_write (handle, buf, nbytes); if (n < 0) { ctl->cmsg(CMSG_WARNING, VERB_DEBUG, "%s: %s", alsa_device_name(), snd_strerror(n)); if (n == -EWOULDBLOCK) continue; return -1; } buf += n; nbytes -= n; output_counter += n; } return 0;}static int acntl(int request, void *arg){ int i; struct snd_pcm_playback_status pstatus; if (handle == NULL) return -1; switch (request) { case PM_REQ_GETFRAGSIZ: if (frag_size == 0) return -1; *((int *)arg) = frag_size; return 0; case PM_REQ_GETQSIZ: if (total_bytes == -1) return -1; *((int *)arg) = total_bytes; return 0; case PM_REQ_GETFILLABLE: if (total_bytes == -1) return -1; if (snd_pcm_playback_status(handle, &pstatus) < 0) return -1; i = pstatus.count >> sample_shift; *((int *)arg) = i; return 0; case PM_REQ_GETFILLED: if (total_bytes == -1) return -1; if (snd_pcm_playback_status(handle, &pstatus) < 0) return -1; i = pstatus.queue >> sample_shift; *((int *)arg) = i; return 0; case PM_REQ_GETSAMPLES: if (total_bytes == -1) return -1; if (snd_pcm_playback_status(handle, &pstatus) < 0) return -1; i = output_counter - pstatus.queue; i >>= sample_shift; *((int *)arg) = i; return 0; case PM_REQ_DISCARD: if (snd_pcm_drain_playback (handle) < 0) return -1; /* error */ output_counter = 0; return 0; case PM_REQ_FLUSH: if (snd_pcm_flush_playback(handle) < 0) return -1; /* error */ output_counter = 0; return 0; } return -1;}/* end ALSA API 0.4.x */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -