chiark / gitweb /
Mention track adoption in CHANGES.
[disorder] / clients / playrtp-alsa.c
CommitLineData
c593cf7c 1/*
2 * This file is part of DisOrder.
4dadf1a2 3 * Copyright (C) 2008 Richard Kettlewell
c593cf7c 4 *
e7eb3a27 5 * This program is free software: you can redistribute it and/or modify
c593cf7c 6 * it under the terms of the GNU General Public License as published by
e7eb3a27 7 * the Free Software Foundation, either version 3 of the License, or
c593cf7c 8 * (at your option) any later version.
9 *
e7eb3a27
RK
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
c593cf7c 15 * You should have received a copy of the GNU General Public License
e7eb3a27 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
c593cf7c 17 */
18/** @file clients/playrtp-alsa.c
19 * @brief RTP player - ALSA support
4dadf1a2
RK
20 *
21 * This has been rewritten to use the @ref alsabg.h interface and is therefore
22 * now closely modelled on @ref playrtp-coreaudio.c. Given a similar interface
23 * wrapping OSS the whole of playrtp could probably be greatly simplified.
c593cf7c 24 */
25
05b75f8d 26#include "common.h"
c593cf7c 27
146e86fb 28#if HAVE_ALSA_ASOUNDLIB_H
c593cf7c 29
30#include <poll.h>
31#include <alsa/asoundlib.h>
c593cf7c 32#include <pthread.h>
b28bddbb 33#include <arpa/inet.h>
c593cf7c 34
35#include "mem.h"
36#include "log.h"
37#include "vector.h"
38#include "heap.h"
39#include "playrtp.h"
4dadf1a2 40#include "alsabg.h"
c593cf7c 41
4dadf1a2
RK
42/** @brief Callback from alsa_bg_collect() */
43static int playrtp_alsa_supply(void *dst,
44 unsigned supply_nsamples) {
45 unsigned samples_available;
588b2763 46 const struct packet *p;
c593cf7c 47
4dadf1a2 48 pthread_mutex_lock(&lock);
588b2763 49 p = playrtp_next_packet();
4dadf1a2
RK
50 if(p && contains(p, next_timestamp)) {
51 /* This packet is ready to play */
52 const uint32_t packet_end = p->timestamp + p->nsamples;
53 const uint32_t offset = next_timestamp - p->timestamp;
54 const uint16_t *src = (void *)(p->samples_raw + offset);
55 samples_available = packet_end - next_timestamp;
56 if(samples_available > supply_nsamples)
57 samples_available = supply_nsamples;
58 next_timestamp += samples_available;
59 memcpy(dst, src, samples_available * sizeof (int16_t));
60 /* We don't bother junking the packet - that'll be dealt with next time
61 * round */
eabdb9b9 62 } else {
4dadf1a2
RK
63 /* No packet is ready to play (and there might be no packet at all) */
64 samples_available = p ? p->timestamp - next_timestamp : supply_nsamples;
65 if(samples_available > supply_nsamples)
66 samples_available = supply_nsamples;
67 /*info("infill %d", samples_available);*/
68 next_timestamp += samples_available;
69 /* Unlike Core Audio the buffer is not guaranteed to be 0-filled */
70 memset(dst, 0, samples_available * sizeof (int16_t));
eabdb9b9 71 }
4dadf1a2
RK
72 pthread_mutex_unlock(&lock);
73 return samples_available;
c593cf7c 74}
75
76void playrtp_alsa(void) {
4dadf1a2
RK
77 alsa_bg_init(device ? device : "default",
78 playrtp_alsa_supply);
c593cf7c 79 pthread_mutex_lock(&lock);
80 for(;;) {
81 /* Wait for the buffer to fill up a bit */
82 playrtp_fill_buffer();
4dadf1a2 83 /* Start playing now */
c593cf7c 84 info("Playing...");
4dadf1a2
RK
85 next_timestamp = pheap_first(&packets)->timestamp;
86 active = 1;
87 alsa_bg_enable();
88 /* Wait until the buffer empties out */
89 while(nsamples >= minbuffer
90 || (nsamples > 0
91 && contains(pheap_first(&packets), next_timestamp))) {
92 pthread_cond_wait(&cond, &lock);
c593cf7c 93 }
4dadf1a2
RK
94 /* Stop playing for a bit until the buffer re-fills */
95 alsa_bg_disable();
c593cf7c 96 active = 0;
4dadf1a2 97 /* Go back round */
c593cf7c 98 }
99}
100
101#endif
102
103/*
104Local Variables:
105c-basic-offset:2
106comment-column:40
107fill-column:79
108indent-tabs-mode:nil
109End:
110*/