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