Commit | Line | Data |
---|---|---|
de0ef46e RK |
1 | /* |
2 | * This file is part of DisOrder. | |
3 | * Copyright (C) 2013 Richard Kettlewell | |
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 3 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, | |
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 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | /** @file lib/uaudio-pulseaudio.c | |
19 | * @brief Support for PulseAudio backend */ | |
20 | #include "common.h" | |
21 | ||
22 | #if HAVE_PULSEAUDIO | |
23 | ||
24 | #include <pulse/simple.h> | |
25 | #include <pulse/error.h> | |
26 | ||
27 | #include "mem.h" | |
28 | #include "log.h" | |
29 | #include "uaudio.h" | |
30 | #include "configuration.h" | |
31 | ||
32 | static const char *const pulseaudio_options[] = { | |
33 | "application", | |
34 | NULL | |
35 | }; | |
36 | ||
37 | static pa_simple *pulseaudio_simple_handle; | |
38 | ||
39 | /** @brief Open the PulseAudio sound device */ | |
40 | static void pulseaudio_open() { | |
41 | pa_sample_spec ss; | |
42 | int error; | |
43 | ss.format = -1; | |
44 | switch(uaudio_bits) { | |
45 | case 8: | |
46 | if(!uaudio_signed) | |
47 | ss.format = PA_SAMPLE_U8; | |
48 | break; | |
49 | case 16: | |
50 | if(uaudio_signed) | |
51 | ss.format = PA_SAMPLE_S16NE; | |
52 | break; | |
53 | case 32: | |
54 | if(uaudio_signed) | |
55 | ss.format = PA_SAMPLE_S32NE; | |
56 | break; | |
57 | } | |
58 | if(ss.format == -1) | |
59 | disorder_fatal(0, "unsupported uaudio format (%d, %d)", | |
60 | uaudio_bits, uaudio_signed); | |
61 | ss.channels = uaudio_channels; | |
62 | ss.rate = uaudio_rate; | |
63 | pulseaudio_simple_handle = pa_simple_new(NULL, | |
64 | uaudio_get("application", "DisOrder"), | |
65 | PA_STREAM_PLAYBACK, | |
66 | NULL, | |
67 | "DisOrder", | |
68 | &ss, | |
69 | NULL, | |
70 | NULL, | |
71 | &error); | |
72 | if(!pulseaudio_simple_handle) | |
73 | disorder_fatal(0, "pa_simple_new: %s", pa_strerror(error)); | |
74 | } | |
75 | ||
76 | /** @brief Close the PulseAudio sound device */ | |
77 | static void pulseaudio_close(void) { | |
78 | pa_simple_free(pulseaudio_simple_handle); | |
79 | pulseaudio_simple_handle = NULL; | |
80 | } | |
81 | ||
82 | /** @brief Actually play sound via PulseAudio */ | |
83 | static size_t pulseaudio_play(void *buffer, size_t samples, | |
84 | unsigned attribute((unused)) flags) { | |
85 | int error; | |
86 | int ret = pa_simple_write(pulseaudio_simple_handle, | |
87 | buffer, | |
88 | samples * uaudio_sample_size, | |
89 | &error); | |
90 | if(ret < 0) | |
91 | disorder_fatal(0, "pa_simple_write: %s", pa_strerror(error)); | |
92 | return samples; | |
93 | } | |
94 | ||
95 | static void pulseaudio_start(uaudio_callback *callback, | |
96 | void *userdata) { | |
97 | pulseaudio_open(); | |
98 | uaudio_thread_start(callback, userdata, pulseaudio_play, | |
99 | 32 / uaudio_sample_size, | |
100 | 4096 / uaudio_sample_size, | |
101 | 0); | |
102 | } | |
103 | ||
104 | static void pulseaudio_stop(void) { | |
105 | uaudio_thread_stop(); | |
106 | pulseaudio_close(); | |
107 | } | |
108 | ||
109 | static void pulseaudio_open_mixer(void) { | |
110 | disorder_error(0, "no pulseaudio mixer support yet"); | |
111 | } | |
112 | ||
113 | static void pulseaudio_close_mixer(void) { | |
114 | } | |
115 | ||
116 | static void pulseaudio_get_volume(int *left, int *right) { | |
117 | *left = *right = 0; | |
118 | } | |
119 | ||
120 | static void pulseaudio_set_volume(int *left, int *right) { | |
121 | *left = *right = 0; | |
122 | } | |
123 | ||
124 | static void pulseaudio_configure(void) { | |
125 | } | |
126 | ||
127 | const struct uaudio uaudio_pulseaudio = { | |
128 | .name = "pulseaudio", | |
129 | .options = pulseaudio_options, | |
130 | .start = pulseaudio_start, | |
131 | .stop = pulseaudio_stop, | |
132 | .activate = uaudio_thread_activate, | |
133 | .deactivate = uaudio_thread_deactivate, | |
134 | .open_mixer = pulseaudio_open_mixer, | |
135 | .close_mixer = pulseaudio_close_mixer, | |
136 | .get_volume = pulseaudio_get_volume, | |
137 | .set_volume = pulseaudio_set_volume, | |
138 | .configure = pulseaudio_configure, | |
139 | .flags = UAUDIO_API_CLIENT, | |
140 | }; | |
141 | ||
142 | #endif | |
143 | ||
144 | /* | |
145 | Local Variables: | |
146 | c-basic-offset:2 | |
147 | comment-column:40 | |
148 | fill-column:79 | |
149 | indent-tabs-mode:nil | |
150 | End: | |
151 | */ |