change license from GPLv3 to GPLv3 or later
[mmq.git] / pa.c
blob2988a7b9067dffe10ec93aaec480a18c55f917e5
1 /*
2 * PulseAudio support
4 * This file is meant to be included in ao.c
5 */
6 #include <pulse/simple.h>
7 #include <pulse/error.h>
8 #include <stdlib.h>
10 static pa_simple *s;
11 static pa_sample_spec ss;
13 static pa_sample_format_t bitformat(unsigned bits)
15 switch (bits) {
16 case 8: return PA_SAMPLE_U8;
17 case 16: return PA_SAMPLE_S16NE;
18 #ifdef PA_SAMPLE_S24NE
19 case 24: return PA_SAMPLE_S24NE;
20 #endif
21 case 32: return PA_SAMPLE_S32NE;
23 return PA_SAMPLE_INVALID;
27 static int _my_open(struct afmt *fmt)
29 pa_sample_format_t bitfmt = bitformat(fmt->bits);
31 if (bitfmt == PA_SAMPLE_INVALID) {
32 warn("unknown bitrate: %u\n", fmt->bits);
33 return -1;
36 ss.format = bitfmt;
37 ss.rate = fmt->rate;
38 ss.channels = fmt->channels;
39 g_sample_size = (fmt->bits / CHAR_BIT) * fmt->channels;
40 s = pa_simple_new(NULL, "mmq", PA_STREAM_PLAYBACK, NULL,
41 "minimalist music queue", &ss, NULL, NULL, NULL);
43 return s ? 0 : -1;
46 static void _my_close(int graceful)
48 int error, rc;
50 if (!s)
51 return;
52 if (graceful)
53 rc = pa_simple_drain(s, &error);
54 else
55 rc = pa_simple_flush(s, &error);
56 if (rc < 0)
57 warn("drain or flush failed: %s\n", pa_strerror(error));
59 pa_simple_free(s);
60 s = NULL;
63 static int _my_inject(void *buf, long samples, conv_fn conv_i)
65 size_t bytes = samples * g_sample_size;
66 void *data;
67 int error;
69 if (bytes == 0)
70 return 0;
72 if (conv_i == audio_copy) {
73 data = buf;
74 } else {
75 static size_t capa;
76 static void *tmp;
77 long nr;
79 if (bytes > capa) {
80 capa = bytes;
81 tmp = realloc(tmp, bytes);
82 assert(tmp && "realloc failed, wtf");
85 nr = conv_i(tmp, buf, samples, 0);
86 if (nr == 0) /* OV_HOLE */
87 return 0;
88 assert(nr > 0 && "nr != 0");
89 bytes = nr * g_sample_size;
90 data = tmp;
92 if (pa_simple_write(s, data, bytes, &error) < 0) {
93 warn("pa_simple_write failed: %s\n", pa_strerror(error));
94 return -1;
96 return samples;