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
33 #include <alsa/asoundlib.h>
35 #include <arpa/inet.h>
44 /** @brief Callback from alsa_bg_collect() */
45 static int playrtp_alsa_supply(void *dst
,
46 unsigned supply_nsamples
) {
47 unsigned samples_available
;
48 const struct packet
*p
;
50 pthread_mutex_lock(&lock
);
51 p
= playrtp_next_packet();
52 if(p
&& contains(p
, next_timestamp
)) {
53 /* This packet is ready to play */
54 const uint32_t packet_end
= p
->timestamp
+ p
->nsamples
;
55 const uint32_t offset
= next_timestamp
- p
->timestamp
;
56 const uint16_t *src
= (void *)(p
->samples_raw
+ offset
);
57 samples_available
= packet_end
- next_timestamp
;
58 if(samples_available
> supply_nsamples
)
59 samples_available
= supply_nsamples
;
60 next_timestamp
+= samples_available
;
61 memcpy(dst
, src
, samples_available
* sizeof (int16_t));
62 /* We don't bother junking the packet - that'll be dealt with next time
65 /* No packet is ready to play (and there might be no packet at all) */
66 samples_available
= p ? p
->timestamp
- next_timestamp
: supply_nsamples
;
67 if(samples_available
> supply_nsamples
)
68 samples_available
= supply_nsamples
;
69 /*info("infill %d", samples_available);*/
70 next_timestamp
+= samples_available
;
71 /* Unlike Core Audio the buffer is not guaranteed to be 0-filled */
72 memset(dst
, 0, samples_available
* sizeof (int16_t));
74 pthread_mutex_unlock(&lock
);
75 return samples_available
;
78 void playrtp_alsa(void) {
79 alsa_bg_init(device ? device
: "default",
81 pthread_mutex_lock(&lock
);
83 /* Wait for the buffer to fill up a bit */
84 playrtp_fill_buffer();
85 /* Start playing now */
87 next_timestamp
= pheap_first(&packets
)->timestamp
;
90 /* Wait until the buffer empties out */
91 while(nsamples
>= minbuffer
93 && contains(pheap_first(&packets
), next_timestamp
))) {
94 pthread_cond_wait(&cond
, &lock
);
96 /* Stop playing for a bit until the buffer re-fills */