/* * Copyright (C) 2025 BlueKitchen GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * 4. Any redistribution, use, or modification is done solely for * personal benefit and not for any commercial purpose or for * monetary gain. * * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Please inquire about commercial licensing options at * contact@bluekitchen-gmbh.com * */ #ifdef HAVE_ALSA #define BTSTACK_FILE__ "btstack_audio_alsa.c" #include #include #include #include #include #include #include "btstack_debug.h" #include "btstack_audio.h" static const char* device = "default"; static const char* simple_mixer_name = "Master"; static snd_pcm_t *pcm_handle = NULL; static snd_mixer_t *mixer_handle = NULL; static snd_mixer_elem_t* master_volume = NULL; static long volume_max; static uint32_t current_sample_rate; static uint8_t num_channels; static void (*playback_callback)(int16_t *buffer, uint16_t num_samples); static unsigned int buffer_time = 500000; /* ring buffer length in us */ static unsigned int period_time = 100000; /* period time in us */ static int resample = 1; /* enable alsa-lib resampling */ static snd_output_t *output = NULL; static snd_pcm_sframes_t buffer_size; static snd_pcm_sframes_t period_size; static int period_event = 0; /* produce poll event after each period */ static struct pollfd *ufds = NULL; static int ufds_count; // TODO: corner case handling #if 0 /* * Underrun and suspend recovery */ static int xrun_recovery(snd_pcm_t *handle, int err) { printf("stream recovery\n"); if (err == -EPIPE) { /* under-run */ err = snd_pcm_prepare(handle); if (err < 0) printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err)); return 0; } else if (err == -ESTRPIPE) { while ((err = snd_pcm_resume(handle)) == -EAGAIN) sleep(1); /* wait until the suspend flag is released */ if (err < 0) { err = snd_pcm_prepare(handle); if (err < 0) printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err)); } return 0; } return err; } #endif static btstack_data_source_t *btstack_audio_alsa_data_sources; static void btstack_audio_alsa_handler(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type) { int source_fd = ds->source.fd; int err; for(int i=0; i data sources for(int i=0; i