X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=alsa_write.c;h=bc06fc315bc51fb3fc1fa9729ae429b47a70d4b4;hp=3935c8c687be53e25791abbb93697a8d61186527;hb=HEAD;hpb=764e71ceb1e188086c08e38dfd52d45b67dc15ba diff --git a/alsa_write.c b/alsa_write.c index 3935c8c6..53d7b1b4 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -1,8 +1,4 @@ -/* - * Copyright (C) 2005 Andre Noll - * - * Licensed under the GPL v2. For licencing details see COPYING. - */ +/* Copyright (C) 2005 Andre Noll , see file COPYING. */ /** \file alsa_write.c paraslash's alsa output plugin */ @@ -52,7 +48,7 @@ struct private_alsa_write_data { /* time until buffer underrun occurs, in milliseconds */ unsigned buffer_time; struct timeval drain_barrier; - /* File descriptor for select(). */ + /* File descriptor to monitor for reading. */ int poll_fd; }; @@ -206,7 +202,7 @@ out: return ret; } -static void alsa_write_pre_select(struct sched *s, void *context) +static void alsa_write_pre_monitor(struct sched *s, void *context) { struct pollfd pfd; struct writer_node *wn = context; @@ -234,7 +230,7 @@ static void alsa_write_pre_select(struct sched *s, void *context) return; } pad->poll_fd = pfd.fd; - para_fd_set(pfd.fd, &s->rfds, &s->max_fileno); + sched_monitor_readfd(pfd.fd, s); } static void alsa_close(struct writer_node *wn) @@ -244,6 +240,8 @@ static void alsa_close(struct writer_node *wn) if (!pad) return; + if (!pad->handle) + goto free_pad; /* * It's OK to have a blocking operation here because we already made * sure that the PCM output buffer is (nearly) empty. @@ -252,10 +250,11 @@ static void alsa_close(struct writer_node *wn) snd_pcm_drain(pad->handle); snd_pcm_close(pad->handle); snd_config_update_free_global(); +free_pad: free(pad); } -static int alsa_write_post_select(__a_unused struct sched *s, void *context) +static int alsa_write_post_monitor(__a_unused struct sched *s, void *context) { struct writer_node *wn = context; struct private_alsa_write_data *pad = wn->private_data; @@ -270,13 +269,15 @@ static int alsa_write_post_select(__a_unused struct sched *s, void *context) goto err; again: ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF); + if (ret < 0) + goto err; if (ret == 0) return 0; btr_merge(btrn, wn->min_iqs); bytes = btr_next_buffer(btrn, &data); if (ret < 0 || bytes < wn->min_iqs) { /* eof */ assert(btr_no_parent(btrn)); - ret = -E_WRITE_COMMON_EOF; + ret = -E_EOF; if (!pad) goto err; /* wait until pending frames are played */ @@ -295,22 +296,24 @@ again: if (bytes == 0) /* no data available */ return 0; - pad = wn->private_data = para_calloc(sizeof(*pad)); - get_btr_sample_rate(btrn, &val); + pad = wn->private_data = zalloc(sizeof(*pad)); + ret = get_btr_sample_rate(btrn, &val); + if (ret < 0) + goto err; pad->sample_rate = val; - get_btr_channels(btrn, &val); + ret = get_btr_channels(btrn, &val); + if (ret < 0) + goto err; pad->channels = val; - get_btr_sample_format(btrn, &val); + ret = get_btr_sample_format(btrn, &val); + if (ret < 0) + goto err; pad->sample_format = get_alsa_pcm_format(val); - PARA_INFO_LOG("%u channel(s), %uHz\n", pad->channels, pad->sample_rate); ret = alsa_init(wn); - if (ret < 0) { - free(wn->private_data); - wn->private_data = NULL; + if (ret < 0) goto err; - } wn->min_iqs = pad->bytes_per_frame; goto again; } @@ -318,7 +321,7 @@ again: frames = snd_pcm_writei(pad->handle, data, frames); if (frames == 0 || frames == -EAGAIN) { char buf[100]; - if (pad->poll_fd >= 0 && FD_ISSET(pad->poll_fd, &s->rfds)) + if (pad->poll_fd >= 0 && sched_read_ok(pad->poll_fd, s)) if (read(pad->poll_fd, buf, 100)) do_nothing; return 0; @@ -328,7 +331,11 @@ again: goto again; } if (frames == -EPIPE) { - PARA_WARNING_LOG("underrun (tried to write %zu bytes)\n", bytes); + snd_pcm_status_t *status; + snd_pcm_status_malloc(&status); + if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) + PARA_WARNING_LOG("underrun\n"); + snd_pcm_status_free(status); snd_pcm_prepare(pad->handle); return 0; } @@ -342,7 +349,7 @@ err: struct writer lsg_write_cmd_com_alsa_user_data = { - .pre_select = alsa_write_pre_select, - .post_select = alsa_write_post_select, + .pre_monitor = alsa_write_pre_monitor, + .post_monitor = alsa_write_post_monitor, .close = alsa_close, };