#include "ao_playasync.h" #include #include #include #include #include #include typedef enum { PLAY = 1, STOP = 2 } Command_t; typedef struct _queue_ { Command_t command; void *buf; int buflen; struct _queue_ *next; struct _queue_ *prev; } Queue_t; typedef struct { Queue_t *play_queue; Queue_t *last_frame; ao_device *ao_device; pthread_mutex_t mutex; pthread_t thread; } AO_Handle; static Queue_t *front(AO_Handle *h) { assert(h->play_queue != NULL); return h->play_queue; } static Queue_t *get(AO_Handle *h) { assert(h->play_queue != NULL); Queue_t *q = h->play_queue; h->play_queue = h->play_queue->next; h->play_queue->prev = NULL; if (h->play_queue == NULL) { h->last_frame = NULL; } return q; } static void add(AO_Handle *h, Queue_t *elem) { if (h->last_frame == NULL) { h->play_queue = elem; elem->next = NULL; elem->prev = NULL; h->last_frame = h->play_queue; } else { h->last_frame->next = elem; elem->prev = h->last_frame; elem->next = NULL; h->last_frame = elem; } } static Queue_t *new_elem(int command, int buf_len, void *buf) { Queue_t *q = (Queue_t *) malloc(sizeof(Queue_t)); void *new_buf; if (buf_len != 0) { new_buf = (void *) malloc(buf_len); memcpy(new_buf, buf, buf_len); } else { new_buf = NULL; } q->buf = new_buf; q->buflen = buf_len; q->command = command; q->next = NULL; q->prev = NULL; return q; } static void clear(AO_Handle *h) { while (h->play_queue != NULL) { Queue_t *q = get(h); if (q->buflen != 0) { free(q->buf); } free(q); } } static void *run(void *arg) { AO_Handle *handle = (AO_Handle *) arg; int go_on = (1 == 1); while(go_on) { pthread_mutex_lock(&handle->mutex); int has_frames = (handle->play_queue != NULL); if (has_frames) { pthread_mutex_unlock(&handle->mutex); } else { pthread_mutex_unlock(&handle->mutex); usleep(5000); // sleep for 5ms } } return NULL; } void *ao_create_async(void *ao_device_yeah) { AO_Handle *handle = (AO_Handle *) malloc(sizeof(AO_Handle)); handle->ao_device = (ao_device *) ao_device_yeah; handle->play_queue = NULL; handle->last_frame = NULL; pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; handle->mutex = m; pthread_create(&handle->thread, NULL, run, handle); return (void *) handle; } void ao_stop_async(void *ao_handle) { AO_Handle *h = (AO_Handle *) ao_handle; clear(h); Queue_t *q = new_elem(STOP, 0, NULL); add(h, q); } void ao_play_async(void *ao_handle, int buf_size, void *mem) { AO_Handle *h = (AO_Handle *) ao_handle; Queue_t *q = new_elem(PLAY, buf_size, mem); add(h, q); }