2 * This file is part of DisOrder.
3 * Copyright (C) 2008 Richard Kettlewell
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 /** @file clients/playrtp-alsa.c
21 * @brief RTP player - ALSA support
23 * This has been rewritten to use the @ref alsabg.h interface and is therefore
24 * now closely modelled on @ref playrtp-coreaudio.c. Given a similar interface
25 * wrapping OSS the whole of playrtp could probably be greatly simplified.
30 #if HAVE_ALSA_ASOUNDLIB_H
34 #include <alsa/asoundlib.h>
37 #include <arpa/inet.h>
46 /** @brief Callback from alsa_bg_collect() */
47 static int playrtp_alsa_supply(void *dst,
48 unsigned supply_nsamples) {
49 unsigned samples_available;
50 const struct packet *p;
52 pthread_mutex_lock(&lock);
53 p = playrtp_next_packet();
54 if(p && contains(p, next_timestamp)) {
55 /* This packet is ready to play */
56 const uint32_t packet_end = p->timestamp + p->nsamples;
57 const uint32_t offset = next_timestamp - p->timestamp;
58 const uint16_t *src = (void *)(p->samples_raw + offset);
59 samples_available = packet_end - next_timestamp;
60 if(samples_available > supply_nsamples)
61 samples_available = supply_nsamples;
62 next_timestamp += samples_available;
63 memcpy(dst, src, samples_available * sizeof (int16_t));
64 /* We don't bother junking the packet - that'll be dealt with next time
67 /* No packet is ready to play (and there might be no packet at all) */
68 samples_available = p ? p->timestamp - next_timestamp : supply_nsamples;
69 if(samples_available > supply_nsamples)
70 samples_available = supply_nsamples;
71 /*info("infill %d", samples_available);*/
72 next_timestamp += samples_available;
73 /* Unlike Core Audio the buffer is not guaranteed to be 0-filled */
74 memset(dst, 0, samples_available * sizeof (int16_t));
76 pthread_mutex_unlock(&lock);
77 return samples_available;
80 void playrtp_alsa(void) {
81 alsa_bg_init(device ? device : "default",
83 pthread_mutex_lock(&lock);
85 /* Wait for the buffer to fill up a bit */
86 playrtp_fill_buffer();
87 /* Start playing now */
89 next_timestamp = pheap_first(&packets)->timestamp;
92 /* Wait until the buffer empties out */
93 while(nsamples >= minbuffer
95 && contains(pheap_first(&packets), next_timestamp))) {
96 pthread_cond_wait(&cond, &lock);
98 /* Stop playing for a bit until the buffer re-fills */