aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/alsa/alsa-core-pcm.c
diff options
context:
space:
mode:
authorThierry Bultel <thierry.bultel@iot.bzh>2018-08-31 13:53:47 +0200
committerThierry Bultel <thierry.bultel@iot.bzh>2018-08-31 13:53:47 +0200
commit80deafbe1bfb87c3a5e9f547c9491afd210e736a (patch)
tree67f83684cf67268dcb65d8062280f848057a74c2 /plugins/alsa/alsa-core-pcm.c
parentded8e37b50982677480869763f3573ff43858505 (diff)
Added bluez sound playback support
This adds sound playback for incoming sound from connected bluetooth devices. In this version, the softmixer relies on a modified bluez-alsa version (https://github.com/iotbzh/bluez-alsa), that provides an ioplug PCM bluezalsa connection proxy. The softmixer api has a new verb to dynamically set the device to listen to: afb-client-demo ws://localhost:1234/api?token=\uuid=123 smixer bluezalsa_dev '{"interface":"hci0", "device":"F6:32:15:2A:80:70", "profile":"a2dp"}' In this way it is possible to switch from a bluezalsa audio source to another without any further configuration. For now, only interface hci0 is supported. This commit also migrates the softmixer binding to API v3 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
Diffstat (limited to 'plugins/alsa/alsa-core-pcm.c')
-rw-r--r--plugins/alsa/alsa-core-pcm.c68
1 files changed, 46 insertions, 22 deletions
diff --git a/plugins/alsa/alsa-core-pcm.c b/plugins/alsa/alsa-core-pcm.c
index c1b59b2..50e1384 100644
--- a/plugins/alsa/alsa-core-pcm.c
+++ b/plugins/alsa/alsa-core-pcm.c
@@ -269,7 +269,6 @@ PUBLIC int AlsaPcmConf(SoftMixerT *mixer, AlsaPcmCtlT *pcm, int mode) {
};
snd_pcm_sw_params_get_avail_min(pxmSwParams, &pcm->avail_min);
- printf("GET AVAILABLE MIN: %ld\n", n);
int start_delay = 0;
snd_pcm_uframes_t start_threshold;
@@ -362,7 +361,7 @@ STATIC int AlsaPcmReadCB( struct pollfd * pfd, AlsaPcmCopyHandleT * pcmCopyHandl
* hopefully we will have more luck next time */
if (availIn > availInBuf) {
- printf("INCOMING BUFFER TOO SMALL !\n");
+// printf("INCOMING BUFFER TOO SMALL !\n");
availIn = availInBuf;
}
@@ -373,8 +372,8 @@ STATIC int AlsaPcmReadCB( struct pollfd * pfd, AlsaPcmCopyHandleT * pcmCopyHandl
if (r <= 0) {
pthread_mutex_unlock(&pcmCopyHandle->mutex);
- // Wakeup the reader, in case it would be sleeping,
- // that lets it an opportunity to pop.
+ // Wake up the reader, in case it is sleeping,
+ // that lets it an opportunity to pop something.
sem_post(&pcmCopyHandle->sem);
break;
}
@@ -386,6 +385,7 @@ STATIC int AlsaPcmReadCB( struct pollfd * pfd, AlsaPcmCopyHandleT * pcmCopyHandl
pthread_mutex_unlock(&pcmCopyHandle->mutex);
r = snd_pcm_readi(pcmIn, buf, r);
+
if (r == 0) {
break;
}
@@ -469,7 +469,7 @@ static void readResume(AlsaPcmCopyHandleT * pcmCopyHandle) {
static void *readThreadEntry(void *handle) {
-#define LOOP_TIMEOUT_MSEC 10*1000
+#define LOOP_TIMEOUT_MSEC 10*1000 /* 10 seconds */
AlsaPcmCopyHandleT *pcmCopyHandle = (AlsaPcmCopyHandleT*) handle;
pcmCopyHandle->tid = (int) syscall(SYS_gettid);
@@ -478,8 +478,11 @@ static void *readThreadEntry(void *handle) {
"%s :%s/%d Started, muted=%d",
__func__, pcmCopyHandle->info, pcmCopyHandle->tid, pcmCopyHandle->pcmIn->mute);
- struct pollfd * mutePfd = &pcmCopyHandle->pollFds[1];
- mutePfd->events = POLLIN | POLLHUP;
+ struct pollfd * mutePfd = &pcmCopyHandle->pollFds[0];
+ struct pollfd * framePfd = &pcmCopyHandle->pollFds[1];
+
+ mutePfd->events = POLLIN | POLLHUP;
+ framePfd->events = POLLIN | POLLHUP;
bool muted = pcmCopyHandle->pcmIn->mute;
@@ -489,7 +492,7 @@ static void *readThreadEntry(void *handle) {
/* loop until end */
for (;;) {
- int err = poll(pcmCopyHandle->pollFds, 2, LOOP_TIMEOUT_MSEC);
+ int err = poll(pcmCopyHandle->pollFds, pcmCopyHandle->nbPcmFds, LOOP_TIMEOUT_MSEC);
if (err < 0) {
AFB_ApiError(pcmCopyHandle->api, "%s: poll err %s", __func__, strerror(errno));
continue;
@@ -522,7 +525,21 @@ static void *readThreadEntry(void *handle) {
continue;
}
- AlsaPcmReadCB(&pcmCopyHandle->pollFds[0], pcmCopyHandle);
+ unsigned short revents;
+
+ int ret = snd_pcm_poll_descriptors_revents(pcmCopyHandle->pcmIn->handle, &pcmCopyHandle->pollFds[1], 1, &revents);
+
+ if (ret == -ENODEV) {
+ sleep(1);
+ continue;
+ }
+
+ if (framePfd->revents & POLLHUP) {
+ AFB_ApiNotice(pcmCopyHandle->api, "Frame POLLHUP");
+ continue;
+ }
+
+ AlsaPcmReadCB(&pcmCopyHandle->pollFds[1], pcmCopyHandle);
}
pthread_exit(0);
@@ -631,6 +648,8 @@ PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT
pcmIn->mixer = mixer;
pcmOut->mixer = mixer;
+ AFB_ApiInfo(mixer->api, "%s: Configure CAPTURE PCM", __func__);
+
// prepare PCM for capture and replay
error = AlsaPcmConf(mixer, pcmIn, SND_PCM_STREAM_CAPTURE);
if (error) {
@@ -703,13 +722,13 @@ PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT
if (pcmInCount > 1) {
AFB_ApiError(mixer->api,
- "%s: Fail, pcmIn=%s; having more than one FD on capture PCM is not supported",
- __func__, ALSA_PCM_UID(pcmOut->handle, string) );
+ "%s: Fail, pcmIn=%s; having more than one FD on capture PCM is not supported (here, %d)",
+ __func__, ALSA_PCM_UID(pcmOut->handle, string) , pcmInCount);
goto OnErrorExit;
}
- struct pollfd pcmInFds[1];
- if ((error = snd_pcm_poll_descriptors(pcmIn->handle, pcmInFds, 1)) < 0) {
+ struct pollfd pcmInFd;
+ if ((error = snd_pcm_poll_descriptors(pcmIn->handle, &pcmInFd, 1)) < 0) {
AFB_ApiError(mixer->api,
"%s: Fail pcmIn=%s get pollfds error=%s",
__func__, ALSA_PCM_UID(pcmOut->handle, string), snd_strerror(error));
@@ -717,23 +736,27 @@ PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT
};
// create the mute pipe
- int pFd[2];
- error = pipe(pFd);
+ int pMuteFd[2];
+ error = pipe(pMuteFd);
if (error < 0) {
AFB_ApiError(mixer->api,
"Unable to create the mute signaling pipe\n");
goto OnErrorExit;
}
- struct pollfd pipePoll;
- pipePoll.fd = pFd[0];
- pipePoll.events = POLLIN;
- pipePoll.revents = 0;
+ struct pollfd mutePFd;
+ // read end
+ mutePFd.fd = pMuteFd[0];
+ mutePFd.events = POLLIN;
+ mutePFd.revents = 0;
+
+ // write end
+ pcmIn->muteFd = pMuteFd[1];
- pcmIn->muteFd = pFd[1];
+ cHandle->pollFds[0] = mutePFd;
+ cHandle->pollFds[1] = pcmInFd;
- cHandle->pollFds[0] = pcmInFds[0];
- cHandle->pollFds[1] = pipePoll;
+ cHandle->nbPcmFds = pcmInCount+1;
error = sem_init(&cHandle->sem, 0 , 0);
if (error < 0) {
@@ -754,6 +777,7 @@ PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT
__func__, ALSA_PCM_UID(pcmIn->handle, string), error);
}
+
/// start a thread for writing
if ((error = pthread_create(&cHandle->wthread, NULL, &readThreadEntry, cHandle)) < 0) {
AFB_ApiError(mixer->api,