1 module iota.audio.backend.linux;
2 
3 version (linux):
4 
5 import core.stdc.stdint;
6 import core.stdc.config;
7 
8 // Begining of ALSA bindings (most done by Adam D. Ruppe)
9 // Minimal, only needed functions have bindings.
10 
11 extern(C):
12 
13 @nogc nothrow:
14 
15 pragma(lib, "asound");
16 
17 private import core.sys.posix.poll;
18 
19 
20 const(char)* snd_strerror(int);
21 
22 // ctl
23 
24 enum snd_ctl_elem_iface_t {
25 	SND_CTL_ELEM_IFACE_CARD,
26 	SND_CTL_ELEM_IFACE_HWDEP,
27 	SND_CTL_ELEM_IFACE_MIXER,
28 	SND_CTL_ELEM_IFACE_PCM,
29 	SND_CTL_ELEM_IFACE_RAWMIDI,
30 	SND_CTL_ELEM_IFACE_TIMER,
31 	SND_CTL_ELEM_IFACE_SEQUENCER,
32 }
33 
34 enum snd_ctl_elem_type_t {
35 	SND_CTL_ELEM_TYPE_NONE,
36 	SND_CTL_ELEM_TYPE_BOOLEAN,
37 	SND_CTL_ELEM_TYPE_INTEGER,
38 	SND_CTL_ELEM_TYPE_ENUMERATED,
39 	SND_CTL_ELEM_TYPE_BYTES,
40 	SND_CTL_ELEM_TYPE_IEC958,
41 	SND_CTL_ELEM_TYPE_INTEGER64,
42 }
43 
44 struct snd_ctl_t {}
45 struct snd_sctl_t {}
46 struct snd_ctl_card_info_t {}
47 
48 int snd_card_get_name(int card, char** name);
49 int snd_card_load(int card);
50 int snd_card_next(int* rcard);
51 int snd_ctl_open(snd_ctl_t** ctlp, const (char*) name, int mode);
52 int snd_ctl_close(snd_ctl_t* ctl);
53 int snd_ctl_card_info(snd_ctl_t* ctl, snd_ctl_card_info_t* info);
54 void snd_ctl_card_info_clear(snd_ctl_card_info_t* obj);
55 
56 // pcm
57 
58 enum snd_pcm_stream_t {
59 	SND_PCM_STREAM_PLAYBACK,
60 	SND_PCM_STREAM_CAPTURE
61 }
62 
63 
64 enum snd_pcm_access_t {
65 	/** mmap access with simple interleaved channels */ 
66 	SND_PCM_ACCESS_MMAP_INTERLEAVED = 0, 
67 	/** mmap access with simple non interleaved channels */ 
68 	SND_PCM_ACCESS_MMAP_NONINTERLEAVED, 
69 	/** mmap access with complex placement */ 
70 	SND_PCM_ACCESS_MMAP_COMPLEX, 
71 	/** snd_pcm_readi/snd_pcm_writei access */ 
72 	SND_PCM_ACCESS_RW_INTERLEAVED, 
73 	/** snd_pcm_readn/snd_pcm_writen access */ 
74 	SND_PCM_ACCESS_RW_NONINTERLEAVED, 
75 	SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED
76 }
77 
78 
79 enum snd_pcm_format {
80 	/** Unknown */
81 	SND_PCM_FORMAT_UNKNOWN = -1,
82 	/** Signed 8 bit */
83 	SND_PCM_FORMAT_S8 = 0,
84 	/** Unsigned 8 bit */
85 	SND_PCM_FORMAT_U8,
86 	/** Signed 16 bit Little Endian */
87 	SND_PCM_FORMAT_S16_LE,
88 	/** Signed 16 bit Big Endian */
89 	SND_PCM_FORMAT_S16_BE,
90 	/** Unsigned 16 bit Little Endian */
91 	SND_PCM_FORMAT_U16_LE,
92 	/** Unsigned 16 bit Big Endian */
93 	SND_PCM_FORMAT_U16_BE,
94 	/** Signed 24 bit Little Endian using low three bytes in 32-bit word */
95 	SND_PCM_FORMAT_S24_LE,
96 	/** Signed 24 bit Big Endian using low three bytes in 32-bit word */
97 	SND_PCM_FORMAT_S24_BE,
98 	/** Unsigned 24 bit Little Endian using low three bytes in 32-bit word */
99 	SND_PCM_FORMAT_U24_LE,
100 	/** Unsigned 24 bit Big Endian using low three bytes in 32-bit word */
101 	SND_PCM_FORMAT_U24_BE,
102 	/** Signed 32 bit Little Endian */
103 	SND_PCM_FORMAT_S32_LE,
104 	/** Signed 32 bit Big Endian */
105 	SND_PCM_FORMAT_S32_BE,
106 	/** Unsigned 32 bit Little Endian */
107 	SND_PCM_FORMAT_U32_LE,
108 	/** Unsigned 32 bit Big Endian */
109 	SND_PCM_FORMAT_U32_BE,
110 	/** Float 32 bit Little Endian, Range -1.0 to 1.0 */
111 	SND_PCM_FORMAT_FLOAT_LE,
112 	/** Float 32 bit Big Endian, Range -1.0 to 1.0 */
113 	SND_PCM_FORMAT_FLOAT_BE,
114 	/** Float 64 bit Little Endian, Range -1.0 to 1.0 */
115 	SND_PCM_FORMAT_FLOAT64_LE,
116 	/** Float 64 bit Big Endian, Range -1.0 to 1.0 */
117 	SND_PCM_FORMAT_FLOAT64_BE,
118 	/** IEC-958 Little Endian */
119 	SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
120 	/** IEC-958 Big Endian */
121 	SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
122 	/** Mu-Law */
123 	SND_PCM_FORMAT_MU_LAW,
124 	/** A-Law */
125 	SND_PCM_FORMAT_A_LAW,
126 	/** Ima-ADPCM */
127 	SND_PCM_FORMAT_IMA_ADPCM,
128 	/** MPEG */
129 	SND_PCM_FORMAT_MPEG,
130 	/** GSM */
131 	SND_PCM_FORMAT_GSM,
132 	/** Special */
133 	SND_PCM_FORMAT_SPECIAL = 31,
134 	/** Signed 24bit Little Endian in 3bytes format */
135 	SND_PCM_FORMAT_S24_3LE = 32,
136 	/** Signed 24bit Big Endian in 3bytes format */
137 	SND_PCM_FORMAT_S24_3BE,
138 	/** Unsigned 24bit Little Endian in 3bytes format */
139 	SND_PCM_FORMAT_U24_3LE,
140 	/** Unsigned 24bit Big Endian in 3bytes format */
141 	SND_PCM_FORMAT_U24_3BE,
142 	/** Signed 20bit Little Endian in 3bytes format */
143 	SND_PCM_FORMAT_S20_3LE,
144 	/** Signed 20bit Big Endian in 3bytes format */
145 	SND_PCM_FORMAT_S20_3BE,
146 	/** Unsigned 20bit Little Endian in 3bytes format */
147 	SND_PCM_FORMAT_U20_3LE,
148 	/** Unsigned 20bit Big Endian in 3bytes format */
149 	SND_PCM_FORMAT_U20_3BE,
150 	/** Signed 18bit Little Endian in 3bytes format */
151 	SND_PCM_FORMAT_S18_3LE,
152 	/** Signed 18bit Big Endian in 3bytes format */
153 	SND_PCM_FORMAT_S18_3BE,
154 	/** Unsigned 18bit Little Endian in 3bytes format */
155 	SND_PCM_FORMAT_U18_3LE,
156 	/** Unsigned 18bit Big Endian in 3bytes format */
157 	SND_PCM_FORMAT_U18_3BE,
158 	/* G.723 (ADPCM) 24 kbit/s, 8 samples in 3 bytes */
159 	SND_PCM_FORMAT_G723_24,
160 	/* G.723 (ADPCM) 24 kbit/s, 1 sample in 1 byte */
161 	SND_PCM_FORMAT_G723_24_1B,
162 	/* G.723 (ADPCM) 40 kbit/s, 8 samples in 3 bytes */
163 	SND_PCM_FORMAT_G723_40,
164 	/* G.723 (ADPCM) 40 kbit/s, 1 sample in 1 byte */
165 	SND_PCM_FORMAT_G723_40_1B,
166 	/* Direct Stream Digital (DSD) in 1-byte samples (x8) */
167 	SND_PCM_FORMAT_DSD_U8,
168 	/* Direct Stream Digital (DSD) in 2-byte samples (x16) */
169 	SND_PCM_FORMAT_DSD_U16_LE,
170 	SND_PCM_FORMAT_LAST = SND_PCM_FORMAT_DSD_U16_LE,
171 	// I snipped a bunch of endian-specific ones!
172 }
173 
174 struct snd_pcm_t {}
175 
176 struct snd_pcm_hw_params_t {}
177 
178 struct snd_pcm_sw_params_t {}
179 
180 int snd_pcm_open(snd_pcm_t**, const char*, snd_pcm_stream_t, int);
181 int snd_pcm_close(snd_pcm_t*);
182 int snd_pcm_pause(snd_pcm_t*, int);
183 int	snd_pcm_start(snd_pcm_t *pcm);
184 int snd_pcm_drain(snd_pcm_t *pcm);
185 int snd_pcm_prepare(snd_pcm_t*);
186 int snd_pcm_nonblock(snd_pcm_t* pcm, int nonblock);
187 int snd_pcm_hw_params(snd_pcm_t*, snd_pcm_hw_params_t*);
188 int snd_pcm_hw_params_set_periods(snd_pcm_t*, snd_pcm_hw_params_t*, uint, int);
189 int snd_pcm_hw_params_set_periods_near(snd_pcm_t*, snd_pcm_hw_params_t*, uint*, int);
190 int snd_pcm_hw_params_set_buffer_size(snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t);
191 int snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_uframes_t*);
192 int snd_pcm_hw_params_set_channels(snd_pcm_t*, snd_pcm_hw_params_t*, uint);
193 int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t**);
194 void snd_pcm_hw_params_free(snd_pcm_hw_params_t*);
195 int snd_pcm_hw_params_any(snd_pcm_t*, snd_pcm_hw_params_t*);
196 int snd_pcm_hw_params_set_access(snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_access_t);
197 int snd_pcm_hw_params_set_format(snd_pcm_t*, snd_pcm_hw_params_t*, snd_pcm_format);
198 int snd_pcm_hw_params_set_rate_near(snd_pcm_t*, snd_pcm_hw_params_t*, uint*, int*);
199 int snd_pcm_hw_params_get_channels_max 	(const (snd_pcm_hw_params_t)* params, uint* val);
200 int snd_pcm_sw_params_malloc(snd_pcm_sw_params_t**);
201 void snd_pcm_sw_params_free(snd_pcm_sw_params_t*);
202 int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
203 int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params);
204 int snd_pcm_sw_params_set_avail_min(snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
205 int snd_pcm_sw_params_set_start_threshold(snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
206 int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t*, snd_pcm_sw_params_t*, snd_pcm_uframes_t);
207 
208 alias snd_pcm_sframes_t = c_long;
209 alias snd_pcm_uframes_t = c_ulong;
210 snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t*, const void*, snd_pcm_uframes_t size);
211 snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t*, void*, snd_pcm_uframes_t size);
212 
213 int snd_pcm_wait(snd_pcm_t *pcm, int timeout);
214 snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm);
215 snd_pcm_sframes_t snd_pcm_avail_update(snd_pcm_t *pcm);
216 
217 const(char)* snd_strerror(int errnum);
218 
219 int snd_pcm_recover (snd_pcm_t* pcm, int err, int silent);
220 
221 alias snd_lib_error_handler_t = void function (const(char)* file, int line, const(char)* function_, int err, const(char)* fmt, ...);
222 int snd_lib_error_set_handler (snd_lib_error_handler_t handler);
223 
224 import core.stdc.stdarg;
225 private void alsa_message_silencer (const(char)* file, int line, const(char)* function_, int err, const(char)* fmt, ...) {}
226 //k8: ALSAlib loves to trash stderr; shut it up
227 void silence_alsa_messages () { snd_lib_error_set_handler(&alsa_message_silencer); }
228 extern(D) shared static this () { silence_alsa_messages(); }
229 
230 // raw midi
231 
232 static if(is(size_t == uint))
233 	alias ssize_t = int;
234 else
235 	alias ssize_t = long;
236 
237 
238 struct snd_rawmidi_t {}
239 int snd_rawmidi_open(snd_rawmidi_t**, snd_rawmidi_t**, const char*, int);
240 int snd_rawmidi_close(snd_rawmidi_t*);
241 int snd_rawmidi_drain(snd_rawmidi_t*);
242 ssize_t snd_rawmidi_write(snd_rawmidi_t*, const void*, size_t);
243 ssize_t snd_rawmidi_read(snd_rawmidi_t*, void*, size_t);
244 
245 // mixer
246 
247 struct snd_mixer_t {}
248 struct snd_mixer_elem_t {}
249 struct snd_mixer_selem_id_t {}
250 
251 alias snd_mixer_elem_callback_t = int function(snd_mixer_elem_t*, uint);
252 
253 int snd_mixer_open(snd_mixer_t**, int mode);
254 int snd_mixer_close(snd_mixer_t*);
255 int snd_mixer_attach(snd_mixer_t*, const char*);
256 int snd_mixer_load(snd_mixer_t*);
257 
258 // FIXME: those aren't actually void*
259 int snd_mixer_selem_register(snd_mixer_t*, void*, void*);
260 int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t**);
261 void snd_mixer_selem_id_free(snd_mixer_selem_id_t*);
262 void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t*, uint);
263 void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t*, const char*);
264 snd_mixer_elem_t* snd_mixer_find_selem(snd_mixer_t*, in snd_mixer_selem_id_t*);
265 // FIXME: the int should be an enum for channel identifier
266 int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t*, int, c_long*);
267 int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t*, c_long*, c_long*);
268 
269 int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t*, c_long);
270 
271 void snd_mixer_elem_set_callback(snd_mixer_elem_t*, snd_mixer_elem_callback_t);
272 int snd_mixer_poll_descriptors(snd_mixer_t*, pollfd*, uint space);
273 
274 int snd_mixer_handle_events(snd_mixer_t*);
275 
276 // FIXME: the first int should be an enum for channel identifier
277 int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t*, int, int* value);
278 int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t*, int);
279 // End of ALSA bindings