2 * Copyright (C) 2011 Andre Noll <maan@tuebingen.mpg.de>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file ao_write.c Paraslash's libao output plugin. */
14 #include "write_cmd.lsg.h"
20 #include "buffer_tree.h"
24 struct private_aow_data {
30 /* The mutex and the condition variable serialize access to ->btrn */
31 pthread_mutex_t mutex;
32 pthread_cond_t data_available;
33 struct btr_node *thread_btrn;
36 static void aow_close(struct writer_node *wn)
38 struct private_aow_data *pawd = wn->private_data;
42 assert(!pawd->thread_btrn);
45 wn->private_data = NULL;
49 static void aow_pre_select(struct sched *s, void *context)
51 struct writer_node *wn = context;
52 struct private_aow_data *pawd = wn->private_data;
55 if (!pawd) { /* not yet started */
57 ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
60 return; /* no data available */
62 if (!wn->btrn) { /* EOF */
63 if (!pawd->thread_btrn) /* ready to exit */
65 /* wait for the play thread to terminate */
68 pthread_mutex_lock(&pawd->mutex);
69 ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
70 pthread_mutex_unlock(&pawd->mutex);
74 * Even though the node status is zero, we might have data available,
75 * but the output buffer is full. If we don't set a timeout here, we
76 * are woken up only if new data arrives, which might be too late and
77 * result in a buffer underrun in the playing thread. To avoid this we
78 * never sleep longer than the (default) buffer time.
81 return sched_request_timeout_ms(20, s);
86 static int aow_set_sample_format(unsigned sample_rate, unsigned channels,
87 int sample_format, ao_sample_format *result)
89 memset(result, 0, sizeof(*result));
90 switch (sample_format) {
94 return -E_AO_BAD_SAMPLE_FORMAT;
96 /* no need to set byte_format */
101 result->byte_format = AO_FMT_LITTLE;
105 result->byte_format = AO_FMT_BIG;
108 PARA_EMERG_LOG("bug: invalid sample format\n");
111 result->channels = channels;
112 result->rate = sample_rate;
116 static int aow_open_device(int id, ao_sample_format *asf, ao_option *options,
120 ao_device *dev = ao_open_live(id, asf, options);
128 msg = "No driver corresponds to driver_id";
131 msg = "This driver is not a live output device";
134 msg = "A valid option key has an invalid value";
137 msg = "Cannot open the device";
140 msg = "General libao error";
143 msg = "Unknown ao error";
146 PARA_ERROR_LOG("%s\n", msg);
147 return -E_AO_OPEN_LIVE;
150 static void aow_show_drivers(void)
152 int i, j, num_drivers;
153 ao_info **driver_list;
155 PARA_DEBUG_LOG("libao drivers available on this host:\n");
156 PARA_DEBUG_LOG("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
158 driver_list = ao_driver_info_list(&num_drivers);
160 for (i = 0; i < num_drivers; i++) {
161 ao_info *info = driver_list[i];
162 char *keys = NULL, *tmp = NULL;
164 if (info->type == AO_TYPE_FILE)
166 PARA_DEBUG_LOG("%s: %s", info->short_name, info->name);
167 PARA_DEBUG_LOG("priority: %d", info->priority);
168 for (j = 0; j < info->option_count; j++) {
169 tmp = make_message("%s%s%s", keys? keys : "",
175 PARA_DEBUG_LOG("keys: %s", keys? keys : "[none]");
177 PARA_DEBUG_LOG("comment: %s", info->comment?
178 info->comment : "[none]");
182 static int aow_init(struct writer_node *wn, unsigned sample_rate,
183 unsigned channels, int sample_format)
186 ao_option *aoo = NULL;
187 ao_sample_format asf;
189 const struct lls_opt_result *r;
191 struct private_aow_data *pawd = para_malloc(sizeof(*pawd));
195 if (WRITE_CMD_OPT_GIVEN(AO, DRIVER, wn->lpr)) {
196 ret = -E_AO_BAD_DRIVER;
197 id = ao_driver_id(WRITE_CMD_OPT_STRING_VAL(AO, DRIVER, wn->lpr));
199 ret = -E_AO_DEFAULT_DRIVER;
200 id = ao_default_driver_id();
204 info = ao_driver_info(id);
205 assert(info && info->short_name);
206 if (info->type == AO_TYPE_FILE) {
207 ret = -E_AO_FILE_NOT_SUPP;
210 PARA_INFO_LOG("using %s driver\n", info->short_name);
211 r = WRITE_CMD_OPT_RESULT(AO, AO_OPTION, wn->lpr);
212 n = lls_opt_given(r);
213 for (i = 0; i < n; i++) {
214 char *o = para_strdup(lls_string_val(i, r));
217 ret = -E_AO_BAD_OPTION;
218 value = strchr(o, ':');
225 PARA_INFO_LOG("appending option: key=%s, value=%s\n", o, value);
226 ret = ao_append_option(&aoo, o, value);
229 ret = -E_AO_APPEND_OPTION;
233 ret = aow_set_sample_format(sample_rate, channels, sample_format, &asf);
236 if (sample_format == SF_S8 || sample_format == SF_U8)
237 pawd->bytes_per_frame = channels;
239 pawd->bytes_per_frame = channels * 2;
240 ret = aow_open_device(id, &asf, aoo, &pawd->dev);
243 PARA_INFO_LOG("successfully opened %s\n", info->short_name);
244 wn->private_data = pawd;
251 __noreturn static void *aow_play(void *priv)
253 struct writer_node *wn = priv;
254 struct private_aow_data *pawd = wn->private_data;
255 struct btr_node *btrn = pawd->thread_btrn;
256 size_t frames, bytes;
260 pthread_mutex_lock(&pawd->mutex);
263 ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
267 btr_merge(btrn, wn->min_iqs);
268 bytes = btr_next_buffer(btrn, &data);
269 frames = bytes / pawd->bytes_per_frame;
272 /* eof and less than a single frame available */
273 ret = -E_WRITE_COMMON_EOF;
277 * No data available, go to sleep and wait for the main
278 * thread to wake us up. pthread_cond_wait() unlocks
279 * the mutex while it waits and locks it again upon
282 ret = pthread_cond_wait(&pawd->data_available,
284 /* pthread_cond_wait() can never fail here */
288 bytes = frames * pawd->bytes_per_frame;
289 pthread_mutex_unlock(&pawd->mutex);
290 ret = ao_play(pawd->dev, data, bytes);
291 pthread_mutex_lock(&pawd->mutex);
292 if (ret == 0) { /* failure */
296 btr_consume(btrn, bytes);
299 btr_remove_node(&pawd->thread_btrn);
301 PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
302 pthread_mutex_unlock(&pawd->mutex);
306 static int aow_create_thread(struct writer_node *wn)
308 struct private_aow_data *pawd = wn->private_data;
312 /* initialize with default attributes */
313 msg = "could not init mutex";
314 ret = pthread_mutex_init(&pawd->mutex, NULL);
318 msg = "could not initialize condition variable";
319 ret = pthread_cond_init(&pawd->data_available, NULL);
323 msg = "could not initialize thread attributes";
324 ret = pthread_attr_init(&pawd->attr);
328 /* schedule this thread under the real-time policy SCHED_FIFO */
329 msg = "could not set sched policy";
330 ret = pthread_attr_setschedpolicy(&pawd->attr, SCHED_FIFO);
334 msg = "could not set detach state to joinable";
335 ret = pthread_attr_setdetachstate(&pawd->attr, PTHREAD_CREATE_JOINABLE);
339 msg = "could not create thread";
340 ret = pthread_create(&pawd->thread, &pawd->attr, aow_play, wn);
345 PARA_ERROR_LOG("%s (%s)\n", msg, strerror(ret));
346 return -E_AO_PTHREAD;
349 static int aow_post_select(__a_unused struct sched *s, void *context)
351 struct writer_node *wn = context;
352 struct private_aow_data *pawd = wn->private_data;
356 int32_t rate, ch, format;
357 struct btr_node_description bnd;
359 ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
364 get_btr_sample_rate(wn->btrn, &rate);
365 get_btr_channels(wn->btrn, &ch);
366 get_btr_sample_format(wn->btrn, &format);
367 ret = aow_init(wn, rate, ch, format);
370 pawd = wn->private_data;
372 /* set up thread btr node */
373 bnd.name = "ao_thread_btrn";
374 bnd.parent = wn->btrn;
378 pawd->thread_btrn = btr_new_node(&bnd);
379 wn->private_data = pawd;
381 ret = aow_create_thread(wn);
383 goto remove_thread_btrn;
387 if (!pawd->thread_btrn) {
388 pthread_join(pawd->thread, NULL);
391 PARA_INFO_LOG("waiting for play thread to terminate\n");
394 pthread_mutex_lock(&pawd->mutex);
395 ret = btr_node_status(wn->btrn, wn->min_iqs, BTR_NT_LEAF);
397 btr_pushdown(wn->btrn);
398 if (pthread_cond_signal(&pawd->data_available) != 0) {
400 PARA_ERROR_LOG("pthread_cond_signal() failed\n");
401 goto remove_thread_btrn;
405 pthread_mutex_unlock(&pawd->mutex);
408 btr_remove_node(&wn->btrn);
409 pthread_cond_signal(&pawd->data_available);
410 pthread_mutex_unlock(&pawd->mutex);
413 btr_remove_node(&pawd->thread_btrn);
415 btr_remove_node(&wn->btrn);
420 struct writer lsg_write_cmd_com_ao_user_data = {
422 .pre_select = aow_pre_select,
423 .post_select = aow_post_select,