mirror of
				https://github.com/Ryujinx/libsoundio.git
				synced 2025-11-04 03:24:59 +00:00 
			
		
		
		
	ALSA backend determines what formats a device supports
This commit is contained in:
		
							parent
							
								
									8887a528ef
								
							
						
					
					
						commit
						3b8d896c8e
					
				| 
						 | 
					@ -43,10 +43,15 @@ static void print_device(struct SoundIoDevice *device, bool is_default) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    raw_str = device->is_raw ? "(raw) " : "";
 | 
					    raw_str = device->is_raw ? "(raw) " : "";
 | 
				
			||||||
    const char *description = soundio_device_description(device);
 | 
					    const char *description = soundio_device_description(device);
 | 
				
			||||||
    int sample_rate = soundio_device_sample_rate(device);
 | 
					    int sample_rate = device->sample_rate_max;
 | 
				
			||||||
    fprintf(stderr, "%s%s device: ", raw_str, purpose_str);
 | 
					    fprintf(stderr, "%s%s device: ", raw_str, purpose_str);
 | 
				
			||||||
    print_channel_layout(soundio_device_channel_layout(device));
 | 
					    if (device->probe_error) {
 | 
				
			||||||
    fprintf(stderr, " %d Hz %s%s\n", sample_rate, description, default_str);
 | 
					        fprintf(stderr, "[%s] %s%s\n", soundio_strerror(device->probe_error),
 | 
				
			||||||
 | 
					                description, default_str);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        print_channel_layout(soundio_device_channel_layout(device));
 | 
				
			||||||
 | 
					        fprintf(stderr, " %d Hz %s%s\n", sample_rate, description, default_str);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int list_devices(struct SoundIo *soundio) {
 | 
					static int list_devices(struct SoundIo *soundio) {
 | 
				
			||||||
| 
						 | 
					@ -97,7 +102,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    if ((err = soundio_connect(soundio))) {
 | 
					    if ((err = soundio_connect(soundio))) {
 | 
				
			||||||
        fprintf(stderr, "%s\n", soundio_error_string(err));
 | 
					        fprintf(stderr, "%s\n", soundio_strerror(err));
 | 
				
			||||||
        return err;
 | 
					        return err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    if ((err = soundio_connect(soundio)))
 | 
					    if ((err = soundio_connect(soundio)))
 | 
				
			||||||
        panic("error connecting: %s", soundio_error_string(err));
 | 
					        panic("error connecting: %s", soundio_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int default_out_device_index = soundio_get_default_output_device_index(soundio);
 | 
					    int default_out_device_index = soundio_get_default_output_device_index(soundio);
 | 
				
			||||||
    if (default_out_device_index < 0)
 | 
					    if (default_out_device_index < 0)
 | 
				
			||||||
| 
						 | 
					@ -73,24 +73,21 @@ int main(int argc, char **argv) {
 | 
				
			||||||
    if (!soundio_channel_layout_equal(in_layout, out_layout))
 | 
					    if (!soundio_channel_layout_equal(in_layout, out_layout))
 | 
				
			||||||
        panic("channel layouts not compatible");
 | 
					        panic("channel layouts not compatible");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (soundio_device_sample_rate(in_device) != soundio_device_sample_rate(out_device))
 | 
					 | 
				
			||||||
        panic("sample rates not compatible");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    double latency = 0.1;
 | 
					    double latency = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct SoundIoInputDevice *input_device;
 | 
					    struct SoundIoInputDevice *input_device;
 | 
				
			||||||
    soundio_input_device_create(in_device, SoundIoSampleFormatFloat32NE, 48000, latency, NULL,
 | 
					    soundio_input_device_create(in_device, SoundIoFormatFloat32NE, 48000, latency, NULL,
 | 
				
			||||||
            read_callback, &input_device);
 | 
					            read_callback, &input_device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct SoundIoOutputDevice *output_device;
 | 
					    struct SoundIoOutputDevice *output_device;
 | 
				
			||||||
    soundio_output_device_create(out_device, SoundIoSampleFormatFloat32NE, 48000, latency, NULL,
 | 
					    soundio_output_device_create(out_device, SoundIoFormatFloat32NE, 48000, latency, NULL,
 | 
				
			||||||
            write_callback, underrun_callback, &output_device);
 | 
					            write_callback, underrun_callback, &output_device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = soundio_input_device_start(input_device)))
 | 
					    if ((err = soundio_input_device_start(input_device)))
 | 
				
			||||||
        panic("unable to start input device: %s", soundio_error_string(err));
 | 
					        panic("unable to start input device: %s", soundio_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = soundio_output_device_start(output_device)))
 | 
					    if ((err = soundio_output_device_start(output_device)))
 | 
				
			||||||
        panic("unable to start output device: %s", soundio_error_string(err));
 | 
					        panic("unable to start output device: %s", soundio_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (;;)
 | 
					    for (;;)
 | 
				
			||||||
        soundio_wait_events(soundio);
 | 
					        soundio_wait_events(soundio);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    if ((err = soundio_connect(soundio)))
 | 
					    if ((err = soundio_connect(soundio)))
 | 
				
			||||||
        panic("error connecting: %s", soundio_error_string(err));
 | 
					        panic("error connecting: %s", soundio_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int default_out_device_index = soundio_get_default_output_device_index(soundio);
 | 
					    int default_out_device_index = soundio_get_default_output_device_index(soundio);
 | 
				
			||||||
    if (default_out_device_index < 0)
 | 
					    if (default_out_device_index < 0)
 | 
				
			||||||
| 
						 | 
					@ -90,11 +90,11 @@ int main(int argc, char **argv) {
 | 
				
			||||||
            soundio_device_description(device));
 | 
					            soundio_device_description(device));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct SoundIoOutputDevice *output_device;
 | 
					    struct SoundIoOutputDevice *output_device;
 | 
				
			||||||
    soundio_output_device_create(device, SoundIoSampleFormatFloat32NE, 48000,
 | 
					    soundio_output_device_create(device, SoundIoFormatFloat32NE, 48000,
 | 
				
			||||||
            0.1, NULL, write_callback, underrun_callback, &output_device);
 | 
					            0.1, NULL, write_callback, underrun_callback, &output_device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = soundio_output_device_start(output_device)))
 | 
					    if ((err = soundio_output_device_start(output_device)))
 | 
				
			||||||
        panic("unable to start device: %s", soundio_error_string(err));
 | 
					        panic("unable to start device: %s", soundio_strerror(err));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (;;)
 | 
					    for (;;)
 | 
				
			||||||
        soundio_wait_events(soundio);
 | 
					        soundio_wait_events(soundio);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										113
									
								
								src/alsa.cpp
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/alsa.cpp
									
									
									
									
									
								
							| 
						 | 
					@ -15,8 +15,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static snd_pcm_stream_t stream_types[] = {SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE};
 | 
					static snd_pcm_stream_t stream_types[] = {SND_PCM_STREAM_PLAYBACK, SND_PCM_STREAM_CAPTURE};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const int MAX_SAMPLE_RATE = 48000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct SoundIoAlsa {
 | 
					struct SoundIoAlsa {
 | 
				
			||||||
    SoundIoOsMutex *mutex;
 | 
					    SoundIoOsMutex *mutex;
 | 
				
			||||||
    SoundIoOsCond *cond;
 | 
					    SoundIoOsCond *cond;
 | 
				
			||||||
| 
						 | 
					@ -158,6 +156,40 @@ static void handle_channel_maps(SoundIoDevice *device, snd_pcm_chmap_query_t **m
 | 
				
			||||||
    snd_pcm_free_chmaps(maps);
 | 
					    snd_pcm_free_chmaps(maps);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static snd_pcm_format_t to_alsa_fmt(SoundIoFormat fmt) {
 | 
				
			||||||
 | 
					    switch (fmt) {
 | 
				
			||||||
 | 
					    case SoundIoFormatS8:           return SND_PCM_FORMAT_S8;
 | 
				
			||||||
 | 
					    case SoundIoFormatU8:           return SND_PCM_FORMAT_U8;
 | 
				
			||||||
 | 
					    case SoundIoFormatS16LE:        return SND_PCM_FORMAT_S16_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatS16BE:        return SND_PCM_FORMAT_S16_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU16LE:        return SND_PCM_FORMAT_U16_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU16BE:        return SND_PCM_FORMAT_U16_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatS24LE:        return SND_PCM_FORMAT_S24_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatS24BE:        return SND_PCM_FORMAT_S24_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU24LE:        return SND_PCM_FORMAT_U24_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU24BE:        return SND_PCM_FORMAT_U24_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatS32LE:        return SND_PCM_FORMAT_S32_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatS32BE:        return SND_PCM_FORMAT_S32_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU32LE:        return SND_PCM_FORMAT_U32_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatU32BE:        return SND_PCM_FORMAT_U32_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatFloat32LE:    return SND_PCM_FORMAT_FLOAT_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatFloat32BE:    return SND_PCM_FORMAT_FLOAT_BE;
 | 
				
			||||||
 | 
					    case SoundIoFormatFloat64LE:    return SND_PCM_FORMAT_FLOAT64_LE;
 | 
				
			||||||
 | 
					    case SoundIoFormatFloat64BE:    return SND_PCM_FORMAT_FLOAT64_BE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case SoundIoFormatInvalid:
 | 
				
			||||||
 | 
					        return SND_PCM_FORMAT_UNKNOWN;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return SND_PCM_FORMAT_UNKNOWN;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_fmt_mask(SoundIoDevice *device, const snd_pcm_format_mask_t *fmt_mask, SoundIoFormat fmt) {
 | 
				
			||||||
 | 
					    if (snd_pcm_format_mask_test(fmt_mask, to_alsa_fmt(fmt))) {
 | 
				
			||||||
 | 
					        device->formats[device->format_count] = fmt;
 | 
				
			||||||
 | 
					        device->format_count += 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
					static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
    snd_pcm_t *handle;
 | 
					    snd_pcm_t *handle;
 | 
				
			||||||
| 
						 | 
					@ -176,23 +208,27 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // disable hardware resampling because we're trying to probe
 | 
					    // disable hardware resampling because we're trying to probe
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 0)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 0)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsigned int channel_count;
 | 
					    unsigned int channel_count;
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_set_channels_last(handle, hwparams, &channel_count)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_set_channels_last(handle, hwparams, &channel_count)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -203,6 +239,7 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
				
			||||||
    int max_dir;
 | 
					    int max_dir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_get_rate_max(hwparams, &max_sample_rate, &max_dir)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_get_rate_max(hwparams, &max_sample_rate, &max_dir)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -210,12 +247,68 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
				
			||||||
        max_sample_rate -= 1;
 | 
					        max_sample_rate -= 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &min_sample_rate, &min_dir)) < 0) {
 | 
					    if ((err = snd_pcm_hw_params_get_rate_min(hwparams, &min_sample_rate, &min_dir)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
        snd_pcm_close(handle);
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
        return SoundIoErrorOpeningDevice;
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (min_dir > 0)
 | 
					    if (min_dir > 0)
 | 
				
			||||||
        min_sample_rate += 1;
 | 
					        min_sample_rate += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_t *fmt_mask;
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_alloca(&fmt_mask);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_none(fmt_mask);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S8);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U8);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S16_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S16_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U16_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U16_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S24_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S24_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U24_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U24_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S32_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_S32_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U32_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_U32_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT_BE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT64_LE);
 | 
				
			||||||
 | 
					    snd_pcm_format_mask_set(fmt_mask, SND_PCM_FORMAT_FLOAT64_BE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((err = snd_pcm_hw_params_set_format_mask(handle, hwparams, fmt_mask)) < 0) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
 | 
					        return SoundIoErrorOpeningDevice;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_pcm_hw_params_get_format_mask(hwparams, fmt_mask);
 | 
				
			||||||
 | 
					    device->formats = allocate<SoundIoFormat>(18);
 | 
				
			||||||
 | 
					    if (!device->formats) {
 | 
				
			||||||
 | 
					        handle_channel_maps(device, maps);
 | 
				
			||||||
 | 
					        snd_pcm_close(handle);
 | 
				
			||||||
 | 
					        return SoundIoErrorNoMem;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    device->format_count = 0;
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS8);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU8);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS16LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS16BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU16LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU16BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS24LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS24BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU24LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU24BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS32LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatS32BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU32LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatU32BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatFloat32LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatFloat32BE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatFloat64LE);
 | 
				
			||||||
 | 
					    test_fmt_mask(device, fmt_mask, SoundIoFormatFloat64BE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_chmap_t *chmap = snd_pcm_get_chmap(handle);
 | 
					    snd_pcm_chmap_t *chmap = snd_pcm_get_chmap(handle);
 | 
				
			||||||
| 
						 | 
					@ -229,16 +322,14 @@ static int probe_device(SoundIoDevice *device, snd_pcm_chmap_query_t **maps) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    device->sample_rate_min = min_sample_rate;
 | 
					    device->sample_rate_min = min_sample_rate;
 | 
				
			||||||
    device->sample_rate_min = max_sample_rate;
 | 
					    device->sample_rate_max = max_sample_rate;
 | 
				
			||||||
    device->sample_rate_default =
 | 
					    // TODO can we figure out what sample rate dmix is currently playing at,
 | 
				
			||||||
            (min_sample_rate <= MAX_SAMPLE_RATE &&
 | 
					    // if dmix applies to this device?
 | 
				
			||||||
            MAX_SAMPLE_RATE <= max_sample_rate) ? MAX_SAMPLE_RATE : max_sample_rate;
 | 
					    device->sample_rate_current = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_close(handle);
 | 
					    snd_pcm_close(handle);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO: device->default_sample_format
 | 
					 | 
				
			||||||
            // TODO: device->default_latency
 | 
					            // TODO: device->default_latency
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -352,7 +443,7 @@ static int refresh_devices(SoundIo *soundio) {
 | 
				
			||||||
                    devices_info->default_input_index = device_list->length;
 | 
					                    devices_info->default_input_index = device_list->length;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            probe_device(device, nullptr);
 | 
					            device->probe_error = probe_device(device, nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (device_list->append(device)) {
 | 
					            if (device_list->append(device)) {
 | 
				
			||||||
                soundio_device_unref(device);
 | 
					                soundio_device_unref(device);
 | 
				
			||||||
| 
						 | 
					@ -461,7 +552,7 @@ static int refresh_devices(SoundIo *soundio) {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps_from_hw(card_index, device_index, -1, stream);
 | 
					                snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps_from_hw(card_index, device_index, -1, stream);
 | 
				
			||||||
                probe_device(device, maps);
 | 
					                device->probe_error = probe_device(device, maps);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (device_list->append(device)) {
 | 
					                if (device_list->append(device)) {
 | 
				
			||||||
                    soundio_device_unref(device);
 | 
					                    soundio_device_unref(device);
 | 
				
			||||||
| 
						 | 
					@ -575,7 +666,7 @@ static void device_thread_run(void *arg) {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (got_rescan_event) {
 | 
					        if (got_rescan_event) {
 | 
				
			||||||
            if ((err = refresh_devices(soundio)))
 | 
					            if ((err = refresh_devices(soundio)))
 | 
				
			||||||
                soundio_panic("error refreshing devices: %s", soundio_error_string(err));
 | 
					                soundio_panic("error refreshing devices: %s", soundio_strerror(err));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,6 +245,34 @@ static void input_device_clear_buffer_dummy(SoundIo *soundio,
 | 
				
			||||||
    soundio_panic("TODO");
 | 
					    soundio_panic("TODO");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int set_all_device_formats(SoundIoDevice *device) {
 | 
				
			||||||
 | 
					    device->format_count = 18;
 | 
				
			||||||
 | 
					    device->formats = allocate<SoundIoFormat>(device->format_count);
 | 
				
			||||||
 | 
					    if (!device->formats)
 | 
				
			||||||
 | 
					        return SoundIoErrorNoMem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    device->formats[0] = SoundIoFormatS8;
 | 
				
			||||||
 | 
					    device->formats[1] = SoundIoFormatU8;
 | 
				
			||||||
 | 
					    device->formats[2] = SoundIoFormatS16LE;
 | 
				
			||||||
 | 
					    device->formats[3] = SoundIoFormatS16BE;
 | 
				
			||||||
 | 
					    device->formats[4] = SoundIoFormatU16LE;
 | 
				
			||||||
 | 
					    device->formats[5] = SoundIoFormatU16BE;
 | 
				
			||||||
 | 
					    device->formats[6] = SoundIoFormatS24LE;
 | 
				
			||||||
 | 
					    device->formats[7] = SoundIoFormatS24BE;
 | 
				
			||||||
 | 
					    device->formats[8] = SoundIoFormatU24LE;
 | 
				
			||||||
 | 
					    device->formats[9] = SoundIoFormatU24BE;
 | 
				
			||||||
 | 
					    device->formats[10] = SoundIoFormatS32LE;
 | 
				
			||||||
 | 
					    device->formats[11] = SoundIoFormatS32BE;
 | 
				
			||||||
 | 
					    device->formats[12] = SoundIoFormatU32LE;
 | 
				
			||||||
 | 
					    device->formats[13] = SoundIoFormatU32BE;
 | 
				
			||||||
 | 
					    device->formats[14] = SoundIoFormatFloat32LE;
 | 
				
			||||||
 | 
					    device->formats[15] = SoundIoFormatFloat32BE;
 | 
				
			||||||
 | 
					    device->formats[16] = SoundIoFormatFloat64LE;
 | 
				
			||||||
 | 
					    device->formats[17] = SoundIoFormatFloat64BE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_dummy_init(SoundIo *soundio) {
 | 
					int soundio_dummy_init(SoundIo *soundio) {
 | 
				
			||||||
    assert(!soundio->backend_data);
 | 
					    assert(!soundio->backend_data);
 | 
				
			||||||
    SoundIoDummy *sid = create<SoundIoDummy>();
 | 
					    SoundIoDummy *sid = create<SoundIoDummy>();
 | 
				
			||||||
| 
						 | 
					@ -287,17 +315,24 @@ int soundio_dummy_init(SoundIo *soundio) {
 | 
				
			||||||
        device->ref_count = 1;
 | 
					        device->ref_count = 1;
 | 
				
			||||||
        device->soundio = soundio;
 | 
					        device->soundio = soundio;
 | 
				
			||||||
        device->name = strdup("dummy-out");
 | 
					        device->name = strdup("dummy-out");
 | 
				
			||||||
        device->description = strdup("Dummy output device");
 | 
					        device->description = strdup("Dummy Output Device");
 | 
				
			||||||
        if (!device->name || !device->description) {
 | 
					        if (!device->name || !device->description) {
 | 
				
			||||||
            free(device->name);
 | 
					            soundio_device_unref(device);
 | 
				
			||||||
            free(device->description);
 | 
					 | 
				
			||||||
            destroy_dummy(soundio);
 | 
					            destroy_dummy(soundio);
 | 
				
			||||||
            return SoundIoErrorNoMem;
 | 
					            return SoundIoErrorNoMem;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
 | 
					        device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
 | 
				
			||||||
        device->default_sample_format = SoundIoSampleFormatFloat32NE;
 | 
					        int err;
 | 
				
			||||||
 | 
					        if ((err = set_all_device_formats(device))) {
 | 
				
			||||||
 | 
					            soundio_device_unref(device);
 | 
				
			||||||
 | 
					            destroy_dummy(soundio);
 | 
				
			||||||
 | 
					            return err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        device->default_latency = 0.01;
 | 
					        device->default_latency = 0.01;
 | 
				
			||||||
        device->sample_rate_default = 48000;
 | 
					        device->sample_rate_min = 2;
 | 
				
			||||||
 | 
					        device->sample_rate_max = 5644800;
 | 
				
			||||||
 | 
					        device->sample_rate_current = 48000;
 | 
				
			||||||
        device->purpose = SoundIoDevicePurposeOutput;
 | 
					        device->purpose = SoundIoDevicePurposeOutput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (soundio->safe_devices_info->output_devices.append(device)) {
 | 
					        if (soundio->safe_devices_info->output_devices.append(device)) {
 | 
				
			||||||
| 
						 | 
					@ -325,9 +360,16 @@ int soundio_dummy_init(SoundIo *soundio) {
 | 
				
			||||||
            return SoundIoErrorNoMem;
 | 
					            return SoundIoErrorNoMem;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
 | 
					        device->channel_layout = *soundio_channel_layout_get_builtin(SoundIoChannelLayoutIdMono);
 | 
				
			||||||
        device->default_sample_format = SoundIoSampleFormatFloat32NE;
 | 
					        int err;
 | 
				
			||||||
 | 
					        if ((err = set_all_device_formats(device))) {
 | 
				
			||||||
 | 
					            soundio_device_unref(device);
 | 
				
			||||||
 | 
					            destroy_dummy(soundio);
 | 
				
			||||||
 | 
					            return err;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        device->default_latency = 0.01;
 | 
					        device->default_latency = 0.01;
 | 
				
			||||||
        device->sample_rate_default = 48000;
 | 
					        device->sample_rate_min = 2;
 | 
				
			||||||
 | 
					        device->sample_rate_max = 5644800;
 | 
				
			||||||
 | 
					        device->sample_rate_current = 48000;
 | 
				
			||||||
        device->purpose = SoundIoDevicePurposeInput;
 | 
					        device->purpose = SoundIoDevicePurposeInput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (soundio->safe_devices_info->input_devices.append(device)) {
 | 
					        if (soundio->safe_devices_info->input_devices.append(device)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,17 +139,17 @@ static double usec_to_sec(pa_usec_t usec) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SoundIoSampleFormat sample_format_from_pulseaudio(pa_sample_spec sample_spec) {
 | 
					static SoundIoFormat format_from_pulseaudio(pa_sample_spec sample_spec) {
 | 
				
			||||||
    switch (sample_spec.format) {
 | 
					    switch (sample_spec.format) {
 | 
				
			||||||
    case PA_SAMPLE_U8:          return SoundIoSampleFormatU8;
 | 
					    case PA_SAMPLE_U8:          return SoundIoFormatU8;
 | 
				
			||||||
    case PA_SAMPLE_S16LE:       return SoundIoSampleFormatS16LE;
 | 
					    case PA_SAMPLE_S16LE:       return SoundIoFormatS16LE;
 | 
				
			||||||
    case PA_SAMPLE_S16BE:       return SoundIoSampleFormatS16BE;
 | 
					    case PA_SAMPLE_S16BE:       return SoundIoFormatS16BE;
 | 
				
			||||||
    case PA_SAMPLE_FLOAT32LE:   return SoundIoSampleFormatFloat32LE;
 | 
					    case PA_SAMPLE_FLOAT32LE:   return SoundIoFormatFloat32LE;
 | 
				
			||||||
    case PA_SAMPLE_FLOAT32BE:   return SoundIoSampleFormatFloat32BE;
 | 
					    case PA_SAMPLE_FLOAT32BE:   return SoundIoFormatFloat32BE;
 | 
				
			||||||
    case PA_SAMPLE_S32LE:       return SoundIoSampleFormatS32LE;
 | 
					    case PA_SAMPLE_S32LE:       return SoundIoFormatS32LE;
 | 
				
			||||||
    case PA_SAMPLE_S32BE:       return SoundIoSampleFormatS32BE;
 | 
					    case PA_SAMPLE_S32BE:       return SoundIoFormatS32BE;
 | 
				
			||||||
    case PA_SAMPLE_S24_32LE:    return SoundIoSampleFormatS24LE;
 | 
					    case PA_SAMPLE_S24_32LE:    return SoundIoFormatS24LE;
 | 
				
			||||||
    case PA_SAMPLE_S24_32BE:    return SoundIoSampleFormatS24BE;
 | 
					    case PA_SAMPLE_S24_32BE:    return SoundIoFormatS24BE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PA_SAMPLE_MAX:
 | 
					    case PA_SAMPLE_MAX:
 | 
				
			||||||
    case PA_SAMPLE_INVALID:
 | 
					    case PA_SAMPLE_INVALID:
 | 
				
			||||||
| 
						 | 
					@ -157,9 +157,9 @@ static SoundIoSampleFormat sample_format_from_pulseaudio(pa_sample_spec sample_s
 | 
				
			||||||
    case PA_SAMPLE_ULAW:
 | 
					    case PA_SAMPLE_ULAW:
 | 
				
			||||||
    case PA_SAMPLE_S24LE:
 | 
					    case PA_SAMPLE_S24LE:
 | 
				
			||||||
    case PA_SAMPLE_S24BE:
 | 
					    case PA_SAMPLE_S24BE:
 | 
				
			||||||
        return SoundIoSampleFormatInvalid;
 | 
					        return SoundIoFormatInvalid;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return SoundIoSampleFormatInvalid;
 | 
					    return SoundIoFormatInvalid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int sample_rate_from_pulseaudio(pa_sample_spec sample_spec) {
 | 
					static int sample_rate_from_pulseaudio(pa_sample_spec sample_spec) {
 | 
				
			||||||
| 
						 | 
					@ -280,9 +280,10 @@ static void sink_info_callback(pa_context *pulse_context, const pa_sink_info *in
 | 
				
			||||||
        if (!device->name || !device->description)
 | 
					        if (!device->name || !device->description)
 | 
				
			||||||
            soundio_panic("out of memory");
 | 
					            soundio_panic("out of memory");
 | 
				
			||||||
        set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
 | 
					        set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
 | 
				
			||||||
        device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
 | 
					        // TODO determine the list of supported formats and the min and max sample rate
 | 
				
			||||||
 | 
					        device->current_format = format_from_pulseaudio(info->sample_spec);
 | 
				
			||||||
        device->default_latency = usec_to_sec(info->configured_latency);
 | 
					        device->default_latency = usec_to_sec(info->configured_latency);
 | 
				
			||||||
        device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
 | 
					        device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
 | 
				
			||||||
        device->purpose = SoundIoDevicePurposeOutput;
 | 
					        device->purpose = SoundIoDevicePurposeOutput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (sipa->current_devices_info->output_devices.append(device))
 | 
					        if (sipa->current_devices_info->output_devices.append(device))
 | 
				
			||||||
| 
						 | 
					@ -309,9 +310,10 @@ static void source_info_callback(pa_context *pulse_context, const pa_source_info
 | 
				
			||||||
        if (!device->name || !device->description)
 | 
					        if (!device->name || !device->description)
 | 
				
			||||||
            soundio_panic("out of memory");
 | 
					            soundio_panic("out of memory");
 | 
				
			||||||
        set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
 | 
					        set_from_pulseaudio_channel_map(info->channel_map, &device->channel_layout);
 | 
				
			||||||
        device->default_sample_format = sample_format_from_pulseaudio(info->sample_spec);
 | 
					        // TODO determine the list of supported formats and the min and max sample rate
 | 
				
			||||||
 | 
					        device->current_format = format_from_pulseaudio(info->sample_spec);
 | 
				
			||||||
        device->default_latency = usec_to_sec(info->configured_latency);
 | 
					        device->default_latency = usec_to_sec(info->configured_latency);
 | 
				
			||||||
        device->sample_rate_default = sample_rate_from_pulseaudio(info->sample_spec);
 | 
					        device->sample_rate_current = sample_rate_from_pulseaudio(info->sample_spec);
 | 
				
			||||||
        device->purpose = SoundIoDevicePurposeInput;
 | 
					        device->purpose = SoundIoDevicePurposeInput;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (sipa->current_devices_info->input_devices.append(device))
 | 
					        if (sipa->current_devices_info->input_devices.append(device))
 | 
				
			||||||
| 
						 | 
					@ -437,28 +439,28 @@ static void wakeup(SoundIo *soundio) {
 | 
				
			||||||
    pa_threaded_mainloop_signal(sipa->main_loop, 0);
 | 
					    pa_threaded_mainloop_signal(sipa->main_loop, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static pa_sample_format_t to_pulseaudio_sample_format(SoundIoSampleFormat sample_format) {
 | 
					static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) {
 | 
				
			||||||
    switch (sample_format) {
 | 
					    switch (format) {
 | 
				
			||||||
    case SoundIoSampleFormatU8:         return PA_SAMPLE_U8;
 | 
					    case SoundIoFormatU8:         return PA_SAMPLE_U8;
 | 
				
			||||||
    case SoundIoSampleFormatS16LE:      return PA_SAMPLE_S16LE;
 | 
					    case SoundIoFormatS16LE:      return PA_SAMPLE_S16LE;
 | 
				
			||||||
    case SoundIoSampleFormatS16BE:      return PA_SAMPLE_S16BE;
 | 
					    case SoundIoFormatS16BE:      return PA_SAMPLE_S16BE;
 | 
				
			||||||
    case SoundIoSampleFormatS24LE:      return PA_SAMPLE_S24_32LE;
 | 
					    case SoundIoFormatS24LE:      return PA_SAMPLE_S24_32LE;
 | 
				
			||||||
    case SoundIoSampleFormatS24BE:      return PA_SAMPLE_S24_32BE;
 | 
					    case SoundIoFormatS24BE:      return PA_SAMPLE_S24_32BE;
 | 
				
			||||||
    case SoundIoSampleFormatS32LE:      return PA_SAMPLE_S32LE;
 | 
					    case SoundIoFormatS32LE:      return PA_SAMPLE_S32LE;
 | 
				
			||||||
    case SoundIoSampleFormatS32BE:      return PA_SAMPLE_S32BE;
 | 
					    case SoundIoFormatS32BE:      return PA_SAMPLE_S32BE;
 | 
				
			||||||
    case SoundIoSampleFormatFloat32LE:  return PA_SAMPLE_FLOAT32LE;
 | 
					    case SoundIoFormatFloat32LE:  return PA_SAMPLE_FLOAT32LE;
 | 
				
			||||||
    case SoundIoSampleFormatFloat32BE:  return PA_SAMPLE_FLOAT32BE;
 | 
					    case SoundIoFormatFloat32BE:  return PA_SAMPLE_FLOAT32BE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case SoundIoSampleFormatInvalid:
 | 
					    case SoundIoFormatInvalid:
 | 
				
			||||||
    case SoundIoSampleFormatS8:
 | 
					    case SoundIoFormatS8:
 | 
				
			||||||
    case SoundIoSampleFormatU16LE:
 | 
					    case SoundIoFormatU16LE:
 | 
				
			||||||
    case SoundIoSampleFormatU16BE:
 | 
					    case SoundIoFormatU16BE:
 | 
				
			||||||
    case SoundIoSampleFormatU24LE:
 | 
					    case SoundIoFormatU24LE:
 | 
				
			||||||
    case SoundIoSampleFormatU24BE:
 | 
					    case SoundIoFormatU24BE:
 | 
				
			||||||
    case SoundIoSampleFormatU32LE:
 | 
					    case SoundIoFormatU32LE:
 | 
				
			||||||
    case SoundIoSampleFormatU32BE:
 | 
					    case SoundIoFormatU32BE:
 | 
				
			||||||
    case SoundIoSampleFormatFloat64LE:
 | 
					    case SoundIoFormatFloat64LE:
 | 
				
			||||||
    case SoundIoSampleFormatFloat64BE:
 | 
					    case SoundIoFormatFloat64BE:
 | 
				
			||||||
        return PA_SAMPLE_INVALID;
 | 
					        return PA_SAMPLE_INVALID;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return PA_SAMPLE_INVALID;
 | 
					    return PA_SAMPLE_INVALID;
 | 
				
			||||||
| 
						 | 
					@ -600,7 +602,7 @@ static int output_device_init_pa(SoundIo *soundio,
 | 
				
			||||||
    pa_threaded_mainloop_lock(sipa->main_loop);
 | 
					    pa_threaded_mainloop_lock(sipa->main_loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sample_spec sample_spec;
 | 
					    pa_sample_spec sample_spec;
 | 
				
			||||||
    sample_spec.format = to_pulseaudio_sample_format(output_device->sample_format);
 | 
					    sample_spec.format = to_pulseaudio_format(output_device->format);
 | 
				
			||||||
    sample_spec.rate = output_device->sample_rate;
 | 
					    sample_spec.rate = output_device->sample_rate;
 | 
				
			||||||
    sample_spec.channels = device->channel_layout.channel_count;
 | 
					    sample_spec.channels = device->channel_layout.channel_count;
 | 
				
			||||||
    pa_channel_map channel_map = to_pulseaudio_channel_map(&device->channel_layout);
 | 
					    pa_channel_map channel_map = to_pulseaudio_channel_map(&device->channel_layout);
 | 
				
			||||||
| 
						 | 
					@ -766,7 +768,7 @@ static int input_device_init_pa(SoundIo *soundio,
 | 
				
			||||||
    pa_threaded_mainloop_lock(sipa->main_loop);
 | 
					    pa_threaded_mainloop_lock(sipa->main_loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sample_spec sample_spec;
 | 
					    pa_sample_spec sample_spec;
 | 
				
			||||||
    sample_spec.format = to_pulseaudio_sample_format(input_device->sample_format);
 | 
					    sample_spec.format = to_pulseaudio_format(input_device->format);
 | 
				
			||||||
    sample_spec.rate = input_device->sample_rate;
 | 
					    sample_spec.rate = input_device->sample_rate;
 | 
				
			||||||
    sample_spec.channels = device->channel_layout.channel_count;
 | 
					    sample_spec.channels = device->channel_layout.channel_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										107
									
								
								src/soundio.cpp
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								src/soundio.cpp
									
									
									
									
									
								
							| 
						 | 
					@ -22,7 +22,7 @@
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <assert.h>
 | 
					#include <assert.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *soundio_error_string(int error) {
 | 
					const char *soundio_strerror(int error) {
 | 
				
			||||||
    switch ((enum SoundIoError)error) {
 | 
					    switch ((enum SoundIoError)error) {
 | 
				
			||||||
        case SoundIoErrorNone: return "(no error)";
 | 
					        case SoundIoErrorNone: return "(no error)";
 | 
				
			||||||
        case SoundIoErrorNoMem: return "out of memory";
 | 
					        case SoundIoErrorNoMem: return "out of memory";
 | 
				
			||||||
| 
						 | 
					@ -33,52 +33,56 @@ const char *soundio_error_string(int error) {
 | 
				
			||||||
    soundio_panic("invalid error enum value: %d", error);
 | 
					    soundio_panic("invalid error enum value: %d", error);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_get_bytes_per_sample(enum SoundIoSampleFormat sample_format) {
 | 
					int soundio_get_bytes_per_sample(enum SoundIoFormat format) {
 | 
				
			||||||
    switch (sample_format) {
 | 
					    switch (format) {
 | 
				
			||||||
    case SoundIoSampleFormatInvalid:    soundio_panic("invalid sample format");
 | 
					    case SoundIoFormatU8:         return 1;
 | 
				
			||||||
    case SoundIoSampleFormatU8:         return 1;
 | 
					    case SoundIoFormatS8:         return 1;
 | 
				
			||||||
    case SoundIoSampleFormatS8:         return 1;
 | 
					    case SoundIoFormatS16LE:      return 2;
 | 
				
			||||||
    case SoundIoSampleFormatS16LE:      return 2;
 | 
					    case SoundIoFormatS16BE:      return 2;
 | 
				
			||||||
    case SoundIoSampleFormatS16BE:      return 2;
 | 
					    case SoundIoFormatU16LE:      return 2;
 | 
				
			||||||
    case SoundIoSampleFormatU16LE:      return 2;
 | 
					    case SoundIoFormatU16BE:      return 2;
 | 
				
			||||||
    case SoundIoSampleFormatU16BE:      return 2;
 | 
					    case SoundIoFormatS24LE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatS24LE:      return 4;
 | 
					    case SoundIoFormatS24BE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatS24BE:      return 4;
 | 
					    case SoundIoFormatU24LE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatU24LE:      return 4;
 | 
					    case SoundIoFormatU24BE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatU24BE:      return 4;
 | 
					    case SoundIoFormatS32LE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatS32LE:      return 4;
 | 
					    case SoundIoFormatS32BE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatS32BE:      return 4;
 | 
					    case SoundIoFormatU32LE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatU32LE:      return 4;
 | 
					    case SoundIoFormatU32BE:      return 4;
 | 
				
			||||||
    case SoundIoSampleFormatU32BE:      return 4;
 | 
					    case SoundIoFormatFloat32LE:  return 4;
 | 
				
			||||||
    case SoundIoSampleFormatFloat32LE:  return 4;
 | 
					    case SoundIoFormatFloat32BE:  return 4;
 | 
				
			||||||
    case SoundIoSampleFormatFloat32BE:  return 4;
 | 
					    case SoundIoFormatFloat64LE:  return 8;
 | 
				
			||||||
    case SoundIoSampleFormatFloat64LE:  return 8;
 | 
					    case SoundIoFormatFloat64BE:  return 8;
 | 
				
			||||||
    case SoundIoSampleFormatFloat64BE:  return 8;
 | 
					
 | 
				
			||||||
 | 
					    case SoundIoFormatInvalid:
 | 
				
			||||||
 | 
					        soundio_panic("invalid sample format");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    soundio_panic("invalid sample format");
 | 
					    soundio_panic("invalid sample format");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char * soundio_sample_format_string(enum SoundIoSampleFormat sample_format) {
 | 
					const char * soundio_format_string(enum SoundIoFormat format) {
 | 
				
			||||||
    switch (sample_format) {
 | 
					    switch (format) {
 | 
				
			||||||
    case SoundIoSampleFormatInvalid: return "(invalid sample format)";
 | 
					    case SoundIoFormatU8:         return "signed 8-bit";
 | 
				
			||||||
    case SoundIoSampleFormatU8:         return "signed 8-bit";
 | 
					    case SoundIoFormatS8:         return "unsigned 8-bit";
 | 
				
			||||||
    case SoundIoSampleFormatS8:         return "unsigned 8-bit";
 | 
					    case SoundIoFormatS16LE:      return "signed 16-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatS16LE:      return "signed 16-bit LE";
 | 
					    case SoundIoFormatS16BE:      return "signed 16-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatS16BE:      return "signed 16-bit BE";
 | 
					    case SoundIoFormatU16LE:      return "unsigned 16-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatU16LE:      return "unsigned 16-bit LE";
 | 
					    case SoundIoFormatU16BE:      return "unsigned 16-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatU16BE:      return "unsigned 16-bit LE";
 | 
					    case SoundIoFormatS24LE:      return "signed 24-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatS24LE:      return "signed 24-bit LE";
 | 
					    case SoundIoFormatS24BE:      return "signed 24-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatS24BE:      return "signed 24-bit BE";
 | 
					    case SoundIoFormatU24LE:      return "unsigned 24-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatU24LE:      return "unsigned 24-bit LE";
 | 
					    case SoundIoFormatU24BE:      return "unsigned 24-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatU24BE:      return "unsigned 24-bit BE";
 | 
					    case SoundIoFormatS32LE:      return "signed 32-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatS32LE:      return "signed 32-bit LE";
 | 
					    case SoundIoFormatS32BE:      return "signed 32-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatS32BE:      return "signed 32-bit BE";
 | 
					    case SoundIoFormatU32LE:      return "unsigned 32-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatU32LE:      return "unsigned 32-bit LE";
 | 
					    case SoundIoFormatU32BE:      return "unsigned 32-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatU32BE:      return "unsigned 32-bit BE";
 | 
					    case SoundIoFormatFloat32LE:  return "float 32-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatFloat32LE:  return "float 32-bit LE";
 | 
					    case SoundIoFormatFloat32BE:  return "float 32-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatFloat32BE:  return "float 32-bit BE";
 | 
					    case SoundIoFormatFloat64LE:  return "float 64-bit LE";
 | 
				
			||||||
    case SoundIoSampleFormatFloat64LE:  return "float 64-bit LE";
 | 
					    case SoundIoFormatFloat64BE:  return "float 64-bit BE";
 | 
				
			||||||
    case SoundIoSampleFormatFloat64BE:  return "float 64-bit BE";
 | 
					
 | 
				
			||||||
 | 
					    case SoundIoFormatInvalid:
 | 
				
			||||||
 | 
					        return "(invalid sample format)";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return "(invalid sample format)";
 | 
					    return "(invalid sample format)";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -250,10 +254,6 @@ const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct So
 | 
				
			||||||
    return &device->channel_layout;
 | 
					    return &device->channel_layout;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_device_sample_rate(const struct SoundIoDevice *device) {
 | 
					 | 
				
			||||||
    return device->sample_rate_default;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void soundio_device_unref(struct SoundIoDevice *device) {
 | 
					void soundio_device_unref(struct SoundIoDevice *device) {
 | 
				
			||||||
    if (!device)
 | 
					    if (!device)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
| 
						 | 
					@ -264,6 +264,7 @@ void soundio_device_unref(struct SoundIoDevice *device) {
 | 
				
			||||||
    if (device->ref_count == 0) {
 | 
					    if (device->ref_count == 0) {
 | 
				
			||||||
        free(device->name);
 | 
					        free(device->name);
 | 
				
			||||||
        free(device->description);
 | 
					        free(device->description);
 | 
				
			||||||
 | 
					        deallocate(device->formats, device->format_count);
 | 
				
			||||||
        destroy(device);
 | 
					        destroy(device);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -313,7 +314,7 @@ void soundio_output_device_write(struct SoundIoOutputDevice *output_device,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_output_device_create(struct SoundIoDevice *device,
 | 
					int soundio_output_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
        enum SoundIoSampleFormat sample_format, int sample_rate,
 | 
					        enum SoundIoFormat format, int sample_rate,
 | 
				
			||||||
        double latency, void *userdata,
 | 
					        double latency, void *userdata,
 | 
				
			||||||
        void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
 | 
					        void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
 | 
				
			||||||
        void (*underrun_callback)(struct SoundIoOutputDevice *),
 | 
					        void (*underrun_callback)(struct SoundIoOutputDevice *),
 | 
				
			||||||
| 
						 | 
					@ -332,10 +333,10 @@ int soundio_output_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
    output_device->userdata = userdata;
 | 
					    output_device->userdata = userdata;
 | 
				
			||||||
    output_device->write_callback = write_callback;
 | 
					    output_device->write_callback = write_callback;
 | 
				
			||||||
    output_device->underrun_callback = underrun_callback;
 | 
					    output_device->underrun_callback = underrun_callback;
 | 
				
			||||||
    output_device->sample_format = sample_format;
 | 
					    output_device->format = format;
 | 
				
			||||||
    output_device->sample_rate = sample_rate;
 | 
					    output_device->sample_rate = sample_rate;
 | 
				
			||||||
    output_device->latency = latency;
 | 
					    output_device->latency = latency;
 | 
				
			||||||
    output_device->bytes_per_frame = soundio_get_bytes_per_frame(sample_format,
 | 
					    output_device->bytes_per_frame = soundio_get_bytes_per_frame(format,
 | 
				
			||||||
            device->channel_layout.channel_count);
 | 
					            device->channel_layout.channel_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SoundIo *soundio = device->soundio;
 | 
					    SoundIo *soundio = device->soundio;
 | 
				
			||||||
| 
						 | 
					@ -368,7 +369,7 @@ int soundio_output_device_start(struct SoundIoOutputDevice *output_device) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_input_device_create(struct SoundIoDevice *device,
 | 
					int soundio_input_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
        enum SoundIoSampleFormat sample_format, int sample_rate,
 | 
					        enum SoundIoFormat format, int sample_rate,
 | 
				
			||||||
        double latency, void *userdata,
 | 
					        double latency, void *userdata,
 | 
				
			||||||
        void (*read_callback)(struct SoundIoInputDevice *),
 | 
					        void (*read_callback)(struct SoundIoInputDevice *),
 | 
				
			||||||
        struct SoundIoInputDevice **out_input_device)
 | 
					        struct SoundIoInputDevice **out_input_device)
 | 
				
			||||||
| 
						 | 
					@ -385,10 +386,10 @@ int soundio_input_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
    sid->device = device;
 | 
					    sid->device = device;
 | 
				
			||||||
    sid->userdata = userdata;
 | 
					    sid->userdata = userdata;
 | 
				
			||||||
    sid->read_callback = read_callback;
 | 
					    sid->read_callback = read_callback;
 | 
				
			||||||
    sid->sample_format = sample_format;
 | 
					    sid->format = format;
 | 
				
			||||||
    sid->latency = latency;
 | 
					    sid->latency = latency;
 | 
				
			||||||
    sid->sample_rate = sample_rate;
 | 
					    sid->sample_rate = sample_rate;
 | 
				
			||||||
    sid->bytes_per_frame = soundio_get_bytes_per_frame(sample_format,
 | 
					    sid->bytes_per_frame = soundio_get_bytes_per_frame(format,
 | 
				
			||||||
            device->channel_layout.channel_count);
 | 
					            device->channel_layout.channel_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SoundIo *soundio = device->soundio;
 | 
					    SoundIo *soundio = device->soundio;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										151
									
								
								src/soundio.h
									
									
									
									
									
								
							
							
						
						
									
										151
									
								
								src/soundio.h
									
									
									
									
									
								
							| 
						 | 
					@ -140,74 +140,115 @@ enum SoundIoDevicePurpose {
 | 
				
			||||||
    SoundIoDevicePurposeOutput,
 | 
					    SoundIoDevicePurposeOutput,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum SoundIoSampleFormat {
 | 
					enum SoundIoFormat {
 | 
				
			||||||
    SoundIoSampleFormatInvalid,
 | 
					    SoundIoFormatInvalid,
 | 
				
			||||||
    SoundIoSampleFormatU8,          // Signed 8 bit
 | 
					    SoundIoFormatS8,          // Signed 8 bit
 | 
				
			||||||
    SoundIoSampleFormatS8,          // Unsigned 8 bit
 | 
					    SoundIoFormatU8,          // Unsigned 8 bit
 | 
				
			||||||
    SoundIoSampleFormatS16LE,       // Signed 16 bit Little Endian
 | 
					    SoundIoFormatS16LE,       // Signed 16 bit Little Endian
 | 
				
			||||||
    SoundIoSampleFormatS16BE,       // Signed 16 bit Big Endian
 | 
					    SoundIoFormatS16BE,       // Signed 16 bit Big Endian
 | 
				
			||||||
    SoundIoSampleFormatU16LE,       // Unsigned 16 bit Little Endian
 | 
					    SoundIoFormatU16LE,       // Unsigned 16 bit Little Endian
 | 
				
			||||||
    SoundIoSampleFormatU16BE,       // Unsigned 16 bit Little Endian
 | 
					    SoundIoFormatU16BE,       // Unsigned 16 bit Little Endian
 | 
				
			||||||
    SoundIoSampleFormatS24LE,       // Signed 24 bit Little Endian using low three bytes in 32-bit word
 | 
					    SoundIoFormatS24LE,       // Signed 24 bit Little Endian using low three bytes in 32-bit word
 | 
				
			||||||
    SoundIoSampleFormatS24BE,       // Signed 24 bit Big Endian using low three bytes in 32-bit word
 | 
					    SoundIoFormatS24BE,       // Signed 24 bit Big Endian using low three bytes in 32-bit word
 | 
				
			||||||
    SoundIoSampleFormatU24LE,       // Unsigned 24 bit Little Endian using low three bytes in 32-bit word
 | 
					    SoundIoFormatU24LE,       // Unsigned 24 bit Little Endian using low three bytes in 32-bit word
 | 
				
			||||||
    SoundIoSampleFormatU24BE,       // Unsigned 24 bit Big Endian using low three bytes in 32-bit word
 | 
					    SoundIoFormatU24BE,       // Unsigned 24 bit Big Endian using low three bytes in 32-bit word
 | 
				
			||||||
    SoundIoSampleFormatS32LE,       // Signed 32 bit Little Endian
 | 
					    SoundIoFormatS32LE,       // Signed 32 bit Little Endian
 | 
				
			||||||
    SoundIoSampleFormatS32BE,       // Signed 32 bit Big Endian
 | 
					    SoundIoFormatS32BE,       // Signed 32 bit Big Endian
 | 
				
			||||||
    SoundIoSampleFormatU32LE,       // Unsigned 32 bit Little Endian
 | 
					    SoundIoFormatU32LE,       // Unsigned 32 bit Little Endian
 | 
				
			||||||
    SoundIoSampleFormatU32BE,       // Unsigned 32 bit Big Endian
 | 
					    SoundIoFormatU32BE,       // Unsigned 32 bit Big Endian
 | 
				
			||||||
    SoundIoSampleFormatFloat32LE,   // Float 32 bit Little Endian, Range -1.0 to 1.0
 | 
					    SoundIoFormatFloat32LE,   // Float 32 bit Little Endian, Range -1.0 to 1.0
 | 
				
			||||||
    SoundIoSampleFormatFloat32BE,   // Float 32 bit Big Endian, Range -1.0 to 1.0
 | 
					    SoundIoFormatFloat32BE,   // Float 32 bit Big Endian, Range -1.0 to 1.0
 | 
				
			||||||
    SoundIoSampleFormatFloat64LE,   // Float 64 bit Little Endian, Range -1.0 to 1.0
 | 
					    SoundIoFormatFloat64LE,   // Float 64 bit Little Endian, Range -1.0 to 1.0
 | 
				
			||||||
    SoundIoSampleFormatFloat64BE,   // Float 64 bit Big Endian, Range -1.0 to 1.0
 | 
					    SoundIoFormatFloat64BE,   // Float 64 bit Big Endian, Range -1.0 to 1.0
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(SOUNDIO_OS_BIG_ENDIAN)
 | 
					#if defined(SOUNDIO_OS_BIG_ENDIAN)
 | 
				
			||||||
#define SoundIoSampleFormatS16NE SoundIoSampleFormatS16BE
 | 
					#define SoundIoFormatS16NE SoundIoFormatS16BE
 | 
				
			||||||
#define SoundIoSampleFormatU16NE SoundIoSampleFormatU16BE
 | 
					#define SoundIoFormatU16NE SoundIoFormatU16BE
 | 
				
			||||||
#define SoundIoSampleFormatS24NE SoundIoSampleFormatS24BE
 | 
					#define SoundIoFormatS24NE SoundIoFormatS24BE
 | 
				
			||||||
#define SoundIoSampleFormatU24NE SoundIoSampleFormatU24BE
 | 
					#define SoundIoFormatU24NE SoundIoFormatU24BE
 | 
				
			||||||
#define SoundIoSampleFormatS32NE SoundIoSampleFormatS32BE
 | 
					#define SoundIoFormatS32NE SoundIoFormatS32BE
 | 
				
			||||||
#define SoundIoSampleFormatU32NE SoundIoSampleFormatU32BE
 | 
					#define SoundIoFormatU32NE SoundIoFormatU32BE
 | 
				
			||||||
#define SoundIoSampleFormatFloat32NE SoundIoSampleFormatFloat32BE
 | 
					#define SoundIoFormatFloat32NE SoundIoFormatFloat32BE
 | 
				
			||||||
#define SoundIoSampleFormatFloat64NE SoundIoSampleFormatFloat64BE
 | 
					#define SoundIoFormatFloat64NE SoundIoFormatFloat64BE
 | 
				
			||||||
#elif defined(SOUNDIO_OS_LITTLE_ENDIAN)
 | 
					#elif defined(SOUNDIO_OS_LITTLE_ENDIAN)
 | 
				
			||||||
#define SoundIoSampleFormatS16NE SoundIoSampleFormatS16LE
 | 
					#define SoundIoFormatS16NE SoundIoFormatS16LE
 | 
				
			||||||
#define SoundIoSampleFormatU16NE SoundIoSampleFormatU16LE
 | 
					#define SoundIoFormatU16NE SoundIoFormatU16LE
 | 
				
			||||||
#define SoundIoSampleFormatS24NE SoundIoSampleFormatS24LE
 | 
					#define SoundIoFormatS24NE SoundIoFormatS24LE
 | 
				
			||||||
#define SoundIoSampleFormatU24NE SoundIoSampleFormatU24LE
 | 
					#define SoundIoFormatU24NE SoundIoFormatU24LE
 | 
				
			||||||
#define SoundIoSampleFormatS32NE SoundIoSampleFormatS32LE
 | 
					#define SoundIoFormatS32NE SoundIoFormatS32LE
 | 
				
			||||||
#define SoundIoSampleFormatU32NE SoundIoSampleFormatU32LE
 | 
					#define SoundIoFormatU32NE SoundIoFormatU32LE
 | 
				
			||||||
#define SoundIoSampleFormatFloat32NE SoundIoSampleFormatFloat32LE
 | 
					#define SoundIoFormatFloat32NE SoundIoFormatFloat32LE
 | 
				
			||||||
#define SoundIoSampleFormatFloat64NE SoundIoSampleFormatFloat64LE
 | 
					#define SoundIoFormatFloat64NE SoundIoFormatFloat64LE
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct SoundIoDevice {
 | 
					struct SoundIoDevice {
 | 
				
			||||||
    struct SoundIo *soundio;
 | 
					    struct SoundIo *soundio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // `name` uniquely identifies this device. `description` is user-friendly
 | 
				
			||||||
 | 
					    // text to describe the device.
 | 
				
			||||||
    char *name;
 | 
					    char *name;
 | 
				
			||||||
    char *description;
 | 
					    char *description;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If this information is missing due to a `probe_error`, the number of
 | 
				
			||||||
 | 
					    // channels will be zero.
 | 
				
			||||||
    struct SoundIoChannelLayout channel_layout;
 | 
					    struct SoundIoChannelLayout channel_layout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // these values might not actually matter. audio hardware has a set of
 | 
					    // A device is either a raw device or it is a virtual device that is
 | 
				
			||||||
    // {sample format, sample rate} that they support. you can't know
 | 
					    // provided by a software mixing service such as dmix or PulseAudio (see
 | 
				
			||||||
    // whether something worked until you try it.
 | 
					    // `is_raw`). If it is a raw device, `current_format` is meaningless;
 | 
				
			||||||
    // these values can be unknown
 | 
					    // the device has no current format until you open it. On the other hand,
 | 
				
			||||||
    enum SoundIoSampleFormat default_sample_format;
 | 
					    // if it is a virtual device, `current_format` describes the destination
 | 
				
			||||||
 | 
					    // sample format that your audio will be converted to. Or, if you're the
 | 
				
			||||||
 | 
					    // lucky first application to open the device, you might cause the
 | 
				
			||||||
 | 
					    // `current_format` to change to your format. Generally, you want to
 | 
				
			||||||
 | 
					    // ignore `current_format` and use whatever format is most convenient
 | 
				
			||||||
 | 
					    // for you which is supported by the device, because when you are the only
 | 
				
			||||||
 | 
					    // application left, the mixer might decide to switch `current_format` to
 | 
				
			||||||
 | 
					    // yours. You can learn the supported formats via `formats` and
 | 
				
			||||||
 | 
					    // `format_count`. If this information is missing due to a probe error,
 | 
				
			||||||
 | 
					    // `formats` will be `NULL`. If `current_format` is unavailable, it will be
 | 
				
			||||||
 | 
					    // set to `SoundIoFormatInvalid`.
 | 
				
			||||||
 | 
					    enum SoundIoFormat *formats;
 | 
				
			||||||
 | 
					    int format_count;
 | 
				
			||||||
 | 
					    enum SoundIoFormat current_format;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Sample rate is handled very similar to sample format; see those docs.
 | 
				
			||||||
 | 
					    // If sample rate information is missing due to a probe error, the field
 | 
				
			||||||
 | 
					    // will be set to zero.
 | 
				
			||||||
    int sample_rate_min;
 | 
					    int sample_rate_min;
 | 
				
			||||||
    int sample_rate_max;
 | 
					    int sample_rate_max;
 | 
				
			||||||
    int sample_rate_default;
 | 
					    int sample_rate_current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double default_latency;
 | 
					    double default_latency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Tells whether this device is an input device or an output device.
 | 
				
			||||||
    enum SoundIoDevicePurpose purpose;
 | 
					    enum SoundIoDevicePurpose purpose;
 | 
				
			||||||
    int ref_count;
 | 
					
 | 
				
			||||||
 | 
					    // raw means that you are directly opening the hardware device and not
 | 
				
			||||||
 | 
					    // going through a proxy such as dmix or PulseAudio. When you open a raw
 | 
				
			||||||
 | 
					    // device, other applications on the computer are not able to
 | 
				
			||||||
 | 
					    // simultaneously access the device. Raw devices do not perform automatic
 | 
				
			||||||
 | 
					    // resampling and thus tend to have fewer formats available.
 | 
				
			||||||
    bool is_raw;
 | 
					    bool is_raw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Devices are reference counted. See `soundio_device_ref` and
 | 
				
			||||||
 | 
					    // `soundio_device_unref`.
 | 
				
			||||||
 | 
					    int ref_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // This is set to a SoundIoError representing the result of the device
 | 
				
			||||||
 | 
					    // probe. Ideally this will be SoundIoErrorNone in which case all the
 | 
				
			||||||
 | 
					    // fields of the device will be populated. If there is an error code here
 | 
				
			||||||
 | 
					    // then information about formats, sample rates, and channel layouts might
 | 
				
			||||||
 | 
					    // be missing.
 | 
				
			||||||
 | 
					    int probe_error;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO rename this to SoundIoOutStream
 | 
				
			||||||
struct SoundIoOutputDevice {
 | 
					struct SoundIoOutputDevice {
 | 
				
			||||||
    void *backend_data;
 | 
					    void *backend_data;
 | 
				
			||||||
    struct SoundIoDevice *device;
 | 
					    struct SoundIoDevice *device;
 | 
				
			||||||
    enum SoundIoSampleFormat sample_format;
 | 
					    enum SoundIoFormat format;
 | 
				
			||||||
    int sample_rate;
 | 
					    int sample_rate;
 | 
				
			||||||
    double latency;
 | 
					    double latency;
 | 
				
			||||||
    int bytes_per_frame;
 | 
					    int bytes_per_frame;
 | 
				
			||||||
| 
						 | 
					@ -217,10 +258,11 @@ struct SoundIoOutputDevice {
 | 
				
			||||||
    void (*write_callback)(struct SoundIoOutputDevice *, int frame_count);
 | 
					    void (*write_callback)(struct SoundIoOutputDevice *, int frame_count);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO rename this to SoundIoInStream
 | 
				
			||||||
struct SoundIoInputDevice {
 | 
					struct SoundIoInputDevice {
 | 
				
			||||||
    void *backend_data;
 | 
					    void *backend_data;
 | 
				
			||||||
    struct SoundIoDevice *device;
 | 
					    struct SoundIoDevice *device;
 | 
				
			||||||
    enum SoundIoSampleFormat sample_format;
 | 
					    enum SoundIoFormat format;
 | 
				
			||||||
    int sample_rate;
 | 
					    int sample_rate;
 | 
				
			||||||
    double latency;
 | 
					    double latency;
 | 
				
			||||||
    int bytes_per_frame;
 | 
					    int bytes_per_frame;
 | 
				
			||||||
| 
						 | 
					@ -276,7 +318,7 @@ void soundio_destroy(struct SoundIo *soundio);
 | 
				
			||||||
int soundio_connect(struct SoundIo *soundio);
 | 
					int soundio_connect(struct SoundIo *soundio);
 | 
				
			||||||
void soundio_disconnect(struct SoundIo *soundio);
 | 
					void soundio_disconnect(struct SoundIo *soundio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *soundio_error_string(int error);
 | 
					const char *soundio_strerror(int error);
 | 
				
			||||||
const char *soundio_backend_name(enum SoundIoBackend backend);
 | 
					const char *soundio_backend_name(enum SoundIoBackend backend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// when you call this, the on_devices_change and on_events_signal callbacks
 | 
					// when you call this, the on_devices_change and on_events_signal callbacks
 | 
				
			||||||
| 
						 | 
					@ -315,19 +357,19 @@ bool soundio_channel_layout_detect_builtin(struct SoundIoChannelLayout *layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sample Formats
 | 
					// Sample Formats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_get_bytes_per_sample(enum SoundIoSampleFormat sample_format);
 | 
					int soundio_get_bytes_per_sample(enum SoundIoFormat format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int soundio_get_bytes_per_frame(enum SoundIoSampleFormat sample_format, int channel_count) {
 | 
					static inline int soundio_get_bytes_per_frame(enum SoundIoFormat format, int channel_count) {
 | 
				
			||||||
    return soundio_get_bytes_per_sample(sample_format) * channel_count;
 | 
					    return soundio_get_bytes_per_sample(format) * channel_count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int soundio_get_bytes_per_second(enum SoundIoSampleFormat sample_format,
 | 
					static inline int soundio_get_bytes_per_second(enum SoundIoFormat format,
 | 
				
			||||||
        int channel_count, int sample_rate)
 | 
					        int channel_count, int sample_rate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return soundio_get_bytes_per_frame(sample_format, channel_count) * sample_rate;
 | 
					    return soundio_get_bytes_per_frame(format, channel_count) * sample_rate;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char * soundio_sample_format_string(enum SoundIoSampleFormat sample_format);
 | 
					const char * soundio_format_string(enum SoundIoFormat format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -359,7 +401,6 @@ const char *soundio_device_name(const struct SoundIoDevice *device);
 | 
				
			||||||
const char *soundio_device_description(const struct SoundIoDevice *device);
 | 
					const char *soundio_device_description(const struct SoundIoDevice *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct SoundIoDevice *device);
 | 
					const struct SoundIoChannelLayout *soundio_device_channel_layout(const struct SoundIoDevice *device);
 | 
				
			||||||
int soundio_device_sample_rate(const struct SoundIoDevice *device);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool soundio_device_equal(
 | 
					bool soundio_device_equal(
 | 
				
			||||||
        const struct SoundIoDevice *a,
 | 
					        const struct SoundIoDevice *a,
 | 
				
			||||||
| 
						 | 
					@ -371,7 +412,7 @@ enum SoundIoDevicePurpose soundio_device_purpose(const struct SoundIoDevice *dev
 | 
				
			||||||
// Output Devices
 | 
					// Output Devices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_output_device_create(struct SoundIoDevice *device,
 | 
					int soundio_output_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
        enum SoundIoSampleFormat sample_format, int sample_rate,
 | 
					        enum SoundIoFormat format, int sample_rate,
 | 
				
			||||||
        double latency, void *userdata,
 | 
					        double latency, void *userdata,
 | 
				
			||||||
        void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
 | 
					        void (*write_callback)(struct SoundIoOutputDevice *, int frame_count),
 | 
				
			||||||
        void (*underrun_callback)(struct SoundIoOutputDevice *),
 | 
					        void (*underrun_callback)(struct SoundIoOutputDevice *),
 | 
				
			||||||
| 
						 | 
					@ -397,7 +438,7 @@ void soundio_output_device_clear_buffer(struct SoundIoOutputDevice *output_devic
 | 
				
			||||||
// Input Devices
 | 
					// Input Devices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int soundio_input_device_create(struct SoundIoDevice *device,
 | 
					int soundio_input_device_create(struct SoundIoDevice *device,
 | 
				
			||||||
        enum SoundIoSampleFormat sample_format, int sample_rate,
 | 
					        enum SoundIoFormat format, int sample_rate,
 | 
				
			||||||
        double latency, void *userdata,
 | 
					        double latency, void *userdata,
 | 
				
			||||||
        void (*read_callback)(struct SoundIoInputDevice *),
 | 
					        void (*read_callback)(struct SoundIoInputDevice *),
 | 
				
			||||||
        struct SoundIoInputDevice **out_input_device);
 | 
					        struct SoundIoInputDevice **out_input_device);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void ok_or_panic(int err) {
 | 
					static inline void ok_or_panic(int err) {
 | 
				
			||||||
    if (err)
 | 
					    if (err)
 | 
				
			||||||
        soundio_panic("%s", soundio_error_string(err));
 | 
					        soundio_panic("%s", soundio_strerror(err));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_os_get_time(void) {
 | 
					static void test_os_get_time(void) {
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ static void test_create_output_device(void) {
 | 
				
			||||||
    soundio_device_name(device);
 | 
					    soundio_device_name(device);
 | 
				
			||||||
    soundio_device_description(device);
 | 
					    soundio_device_description(device);
 | 
				
			||||||
    struct SoundIoOutputDevice *output_device;
 | 
					    struct SoundIoOutputDevice *output_device;
 | 
				
			||||||
    soundio_output_device_create(device, SoundIoSampleFormatFloat32NE, 48000, 0.1, NULL,
 | 
					    soundio_output_device_create(device, SoundIoFormatFloat32NE, 48000, 0.1, NULL,
 | 
				
			||||||
            write_callback, underrun_callback, &output_device);
 | 
					            write_callback, underrun_callback, &output_device);
 | 
				
			||||||
    soundio_output_device_destroy(output_device);
 | 
					    soundio_output_device_destroy(output_device);
 | 
				
			||||||
    soundio_device_unref(device);
 | 
					    soundio_device_unref(device);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue