chiark / gitweb /
make distcheck in scirpts/dist
[disorder] / clients / playrtp-alsa.c
CommitLineData
c593cf7c 1/*
2 * This file is part of DisOrder.
4dadf1a2 3 * Copyright (C) 2008 Richard Kettlewell
c593cf7c 4 *
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.
9 *
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.
14 *
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
18 * USA
19 */
20/** @file clients/playrtp-alsa.c
21 * @brief RTP player - ALSA support
4dadf1a2
RK
22 *
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.
c593cf7c 26 */
27
05b75f8d 28#include "common.h"
c593cf7c 29
146e86fb 30#if HAVE_ALSA_ASOUNDLIB_H
c593cf7c 31
32#include <poll.h>
33#include <alsa/asoundlib.h>
c593cf7c 34#include <pthread.h>
b28bddbb 35#include <arpa/inet.h>
c593cf7c 36
37#include "mem.h"
38#include "log.h"
39#include "vector.h"
40#include "heap.h"
41#include "playrtp.h"
4dadf1a2 42#include "alsabg.h"
c593cf7c 43
4dadf1a2
RK
44/** @brief Callback from alsa_bg_collect() */
45static int playrtp_alsa_supply(void *dst,
46 unsigned supply_nsamples) {
47 unsigned samples_available;
588b2763 48 const struct packet *p;
c593cf7c 49
4dadf1a2 50 pthread_mutex_lock(&lock);
588b2763 51 p = playrtp_next_packet();
4dadf1a2
RK
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
63 * round */
eabdb9b9 64 } else {
4dadf1a2
RK
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));
eabdb9b9 73 }
4dadf1a2
RK
74 pthread_mutex_unlock(&lock);
75 return samples_available;
c593cf7c 76}
77
78void playrtp_alsa(void) {
4dadf1a2
RK
79 alsa_bg_init(device ? device : "default",
80 playrtp_alsa_supply);
c593cf7c 81 pthread_mutex_lock(&lock);
82 for(;;) {
83 /* Wait for the buffer to fill up a bit */
84 playrtp_fill_buffer();
4dadf1a2 85 /* Start playing now */
c593cf7c 86 info("Playing...");
4dadf1a2
RK
87 next_timestamp = pheap_first(&packets)->timestamp;
88 active = 1;
89 alsa_bg_enable();
90 /* Wait until the buffer empties out */
91 while(nsamples >= minbuffer
92 || (nsamples > 0
93 && contains(pheap_first(&packets), next_timestamp))) {
94 pthread_cond_wait(&cond, &lock);
c593cf7c 95 }
4dadf1a2
RK
96 /* Stop playing for a bit until the buffer re-fills */
97 alsa_bg_disable();
c593cf7c 98 active = 0;
4dadf1a2 99 /* Go back round */
c593cf7c 100 }
101}
102
103#endif
104
105/*
106Local Variables:
107c-basic-offset:2
108comment-column:40
109fill-column:79
110indent-tabs-mode:nil
111End:
112*/