static void a2dp_timer(snd_async_handler_t *async) { snd_timer_t *handle = snd_async_handler_get_timer(async); snd_timer_read_t tr; int i, ticks = 0; while (snd_timer_read(handle, &tr, sizeof(tr)) == sizeof(tr)) ticks += tr.ticks; a2dp_lock(); for (i = 0; i < MAX_CONNECTIONS; i++) { snd_pcm_a2dp_t *a2dp = connections[i]; if (a2dp && a2dp->refcnt <= 0) { a2dp->timeout = ((a2dp->timeout * 1000) - ticks) / 1000; if (a2dp->timeout <= 0) { connections[i] = NULL; a2dp_free(a2dp); } } } a2dp_unlock(); }
static int a2dp_close(snd_pcm_ioplug_t * io) { snd_pcm_a2dp_t *a2dp = io->private_data; a2dp_disconnect(a2dp); a2dp_free(a2dp); return 0; }
static void a2dp_exit(void) { int err, i; err = snd_timer_stop(timer); err = snd_timer_close(timer); a2dp_lock(); for (i = 0; i < MAX_CONNECTIONS; i++) { snd_pcm_a2dp_t *a2dp = connections[i]; if (a2dp) { connections[i] = NULL; a2dp_free(a2dp); } } a2dp_unlock(); }
int a2dp_init(int rate, int channels, a2dpData* dataPtr) { struct bluetooth_data* data; pthread_attr_t attr; int err; DBG("a2dp_init rate: %d channels: %d", rate, channels); *dataPtr = NULL; data = malloc(sizeof(struct bluetooth_data)); if (!data) return -1; memset(data, 0, sizeof(struct bluetooth_data)); data->server.fd = -1; data->stream.fd = -1; data->state = A2DP_STATE_NONE; data->command = A2DP_CMD_NONE; strncpy(data->address, "00:00:00:00:00:00", 18); data->rate = rate; data->channels = channels; sbc_init(&data->sbc, 0); pthread_mutex_init(&data->mutex, NULL); pthread_cond_init(&data->thread_start, NULL); pthread_cond_init(&data->thread_wait, NULL); pthread_cond_init(&data->client_wait, NULL); pthread_mutex_lock(&data->mutex); data->started = 0; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); err = pthread_create(&data->thread, &attr, a2dp_thread, data); if (err) { /* If the thread create fails we must not wait */ pthread_mutex_unlock(&data->mutex); err = -err; goto error; } /* Make sure the state machine is ready and waiting */ while (!data->started) { pthread_cond_wait(&data->thread_start, &data->mutex); } /* Poke the state machine to get it going */ pthread_cond_signal(&data->thread_wait); pthread_mutex_unlock(&data->mutex); pthread_attr_destroy(&attr); *dataPtr = data; return 0; error: bluetooth_close(data); sbc_finish(&data->sbc); pthread_attr_destroy(&attr); a2dp_free(data); return err; }
static void* a2dp_thread(void *d) { struct bluetooth_data* data = (struct bluetooth_data*)d; a2dp_command_t command = A2DP_CMD_NONE; int err = 0; DBG("a2dp_thread started"); prctl(PR_SET_NAME, (int)"a2dp_thread", 0, 0, 0); pthread_mutex_lock(&data->mutex); data->started = 1; pthread_cond_signal(&data->thread_start); while (1) { while (1) { pthread_cond_wait(&data->thread_wait, &data->mutex); /* Initialization needed */ if (data->state == A2DP_STATE_NONE && data->command != A2DP_CMD_QUIT) { err = bluetooth_init(data); } /* New state command signaled */ if (command != data->command) { command = data->command; break; } } switch (command) { case A2DP_CMD_CONFIGURE: if (data->state != A2DP_STATE_INITIALIZED) break; err = bluetooth_configure(data); break; case A2DP_CMD_START: if (data->state != A2DP_STATE_CONFIGURED) break; err = bluetooth_start(data); break; case A2DP_CMD_STOP: if (data->state != A2DP_STATE_STARTED) break; err = bluetooth_stop(data); break; case A2DP_CMD_QUIT: bluetooth_close(data); sbc_finish(&data->sbc); a2dp_free(data); goto done; case A2DP_CMD_INIT: /* already called bluetooth_init() */ default: break; } // reset last command in case of error to allow // re-execution of the same command if (err < 0) { command = A2DP_CMD_NONE; } } done: pthread_mutex_unlock(&data->mutex); DBG("a2dp_thread finished"); return NULL; }