⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a2dpd_output_alsa.c

📁 linux蓝牙剖面实现
💻 C
字号:
/***  BlueZ - Bluetooth protocol stack for Linux**  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>***  This library is free software; you can redistribute it and/or*  modify it under the terms of the GNU Lesser General Public*  License as published by the Free Software Foundation; either*  version 2.1 of the License, or (at your option) any later version.**  This library is distributed in the hope that it will be useful,*  but WITHOUT ANY WARRANTY; without even the implied warranty of*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU*  Lesser General Public License for more details.**  You should have received a copy of the GNU Lesser General Public*  License along with this library; if not, write to the Free Software*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA**/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <malloc.h>#include <signal.h>#include <string.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/select.h>#include <netinet/in.h>#include <alsa/asoundlib.h>#include "a2dpd_output_alsa.h"#include "a2dpd_protocol.h"#include "a2dpd_tools.h"typedef struct snd_pcm_alsa {	snd_pcm_t *playback_handle;} snd_pcm_alsa_t;/**   Underrun and suspend recovery*/static int xrun_recovery(snd_pcm_t * handle, int err){	if (err == -EPIPE) {	/* under-run */		err = snd_pcm_prepare(handle);		if (err < 0)			DBG("Can't recovery from underrun, prepare failed: %s", snd_strerror(err));	} else if (err == -ESTRPIPE) {		while ((err = snd_pcm_resume(handle)) == -EAGAIN) {			DBG("Suspend flag not released: %s", snd_strerror(err));			usleep(1);	/* wait until the suspend flag is released */		}		if (err < 0) {			err = snd_pcm_prepare(handle);			if (err < 0)				DBG("Can't recovery from suspend, prepare failed: %s", snd_strerror(err));		}	}	return err;}int alsa_transfer_raw(LPALSA alsa, const char *pcm_buffer, int pcm_buffer_size){	int result = 0;	int errcount = 0;//	dump_stream((const short*)pcm_buffer, pcm_buffer_size);begin:	result = snd_pcm_writei(alsa->playback_handle, pcm_buffer, pcm_buffer_size / A2DPD_FRAME_BYTES);	switch (result) {	case -EBADFD:		DBG("EBADFD(%d)", result);		break;	case -EPIPE:		DBG("EPIPE(%d)", result);		// To manage underrun, we will try to ignore		if(errcount<10 && xrun_recovery(alsa->playback_handle, result) == 0) {			usleep(1);			errcount++;			goto begin;		}		break;	case -ESTRPIPE:		DBG("ESTRPIPE(%d)", result);		if(errcount<10 && xrun_recovery(alsa->playback_handle, result) == 0) {			usleep(1);			errcount++;			goto begin;		}		break;	default:		if(result>0)			result = result * A2DPD_FRAME_BYTES;		break;	}	return result;}snd_pcm_alsa_t *alsa_alloc(void){	snd_pcm_alsa_t *alsa;	alsa = malloc(sizeof(*alsa));	if (!alsa)		return NULL;	memset(alsa, 0, sizeof(*alsa));	return alsa;}void alsa_free(snd_pcm_alsa_t * alsa){	free(alsa);}void alsa_init(void){}void alsa_exit(void){}LPALSA alsa_new(char *device, int framerate){	DBG("");	snd_pcm_alsa_t *alsa = NULL;	snd_pcm_hw_params_t *hw_params = NULL;	int bcontinue = 1;	char *devname = (device && device[0]) ? device : "plughw:0,0";	DBG("Frame rate is %d", framerate);	alsa = alsa_alloc();	if (!alsa) {		DBG("Can't allocate");		return NULL;	}	// Setup alsa	bcontinue = bcontinue && (snd_pcm_open(&alsa->playback_handle, devname, SND_PCM_STREAM_PLAYBACK, 0) >= 0);	DBG("snd_pcm_open()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_malloc(&hw_params) >= 0);	DBG("snd_pcm_hw_params_malloc()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_any(alsa->playback_handle, hw_params) >= 0);	DBG("snd_pcm_hw_params_any()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_set_access(alsa->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) >= 0);	DBG("snd_pcm_hw_params_set_access()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_set_format(alsa->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE) >= 0);	DBG("snd_pcm_hw_params_set_format()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_set_rate(alsa->playback_handle, hw_params, framerate, 0) >= 0);	DBG("snd_pcm_hw_params_set_rate()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params_set_channels(alsa->playback_handle, hw_params, 2) >= 0);	DBG("snd_pcm_hw_params_set_channels()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_hw_params(alsa->playback_handle, hw_params) >= 0);	DBG("snd_pcm_hw_params()==%d", bcontinue);	bcontinue = bcontinue && (snd_pcm_prepare(alsa->playback_handle) >= 0);	DBG("snd_pcm_prepare()==%d", bcontinue);	// Free if allocated	if (hw_params != NULL)		snd_pcm_hw_params_free(hw_params);	DBG("params freed");	if (!bcontinue) {		alsa_destroy(&alsa);	}	DBG("returning %p", alsa);	return alsa;}void alsa_destroy(LPALSA *alsa){	DBG("");	if((*alsa)) {		if ((*alsa)->playback_handle != NULL) {			snd_pcm_close((*alsa)->playback_handle);		}		alsa_free(*alsa);		*alsa = NULL;	}	DBG("OK");}

⌨️ 快捷键说明

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