libsoundio 2.0.0
sio_list_devices.c

List the available input and output devices on the system and their properties.

List the available input and output devices on the system and their properties. Supports watching for changes and specifying backend to use.

/*
* Copyright (c) 2015 Andrew Kelley
*
* This file is part of libsoundio, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
// list or keep a watch on audio devices
static int usage(char *exe) {
fprintf(stderr, "Usage: %s [options]\n"
"Options:\n"
" [--watch]\n"
" [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n"
" [--short]\n", exe);
return 1;
}
static void print_channel_layout(const struct SoundIoChannelLayout *layout) {
if (layout->name) {
fprintf(stderr, "%s", layout->name);
} else {
fprintf(stderr, "%s", soundio_get_channel_name(layout->channels[0]));
for (int i = 1; i < layout->channel_count; i += 1) {
fprintf(stderr, ", %s", soundio_get_channel_name(layout->channels[i]));
}
}
}
static bool short_output = false;
static void print_device(struct SoundIoDevice *device, bool is_default) {
const char *default_str = is_default ? " (default)" : "";
const char *raw_str = device->is_raw ? " (raw)" : "";
fprintf(stderr, "%s%s%s\n", device->name, default_str, raw_str);
if (short_output)
return;
fprintf(stderr, " id: %s\n", device->id);
if (device->probe_error) {
fprintf(stderr, " probe error: %s\n", soundio_strerror(device->probe_error));
} else {
fprintf(stderr, " channel layouts:\n");
for (int i = 0; i < device->layout_count; i += 1) {
fprintf(stderr, " ");
print_channel_layout(&device->layouts[i]);
fprintf(stderr, "\n");
}
if (device->current_layout.channel_count > 0) {
fprintf(stderr, " current layout: ");
print_channel_layout(&device->current_layout);
fprintf(stderr, "\n");
}
fprintf(stderr, " sample rates:\n");
for (int i = 0; i < device->sample_rate_count; i += 1) {
struct SoundIoSampleRateRange *range = &device->sample_rates[i];
fprintf(stderr, " %d - %d\n", range->min, range->max);
}
if (device->sample_rate_current)
fprintf(stderr, " current sample rate: %d\n", device->sample_rate_current);
fprintf(stderr, " formats: ");
for (int i = 0; i < device->format_count; i += 1) {
const char *comma = (i == device->format_count - 1) ? "" : ", ";
fprintf(stderr, "%s%s", soundio_format_string(device->formats[i]), comma);
}
fprintf(stderr, "\n");
fprintf(stderr, " current format: %s\n", soundio_format_string(device->current_format));
fprintf(stderr, " min software latency: %0.8f sec\n", device->software_latency_min);
fprintf(stderr, " max software latency: %0.8f sec\n", device->software_latency_max);
if (device->software_latency_current != 0.0)
fprintf(stderr, " current software latency: %0.8f sec\n", device->software_latency_current);
}
fprintf(stderr, "\n");
}
static int list_devices(struct SoundIo *soundio) {
int output_count = soundio_output_device_count(soundio);
int input_count = soundio_input_device_count(soundio);
int default_output = soundio_default_output_device_index(soundio);
int default_input = soundio_default_input_device_index(soundio);
fprintf(stderr, "--------Input Devices--------\n\n");
for (int i = 0; i < input_count; i += 1) {
print_device(device, default_input == i);
}
fprintf(stderr, "\n--------Output Devices--------\n\n");
for (int i = 0; i < output_count; i += 1) {
print_device(device, default_output == i);
}
fprintf(stderr, "\n%d devices found\n", input_count + output_count);
return 0;
}
static void on_devices_change(struct SoundIo *soundio) {
fprintf(stderr, "devices changed\n");
list_devices(soundio);
}
int main(int argc, char **argv) {
char *exe = argv[0];
bool watch = false;
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
if (strcmp("--watch", arg) == 0) {
watch = true;
} else if (strcmp("--short", arg) == 0) {
short_output = true;
} else if (arg[0] == '-' && arg[1] == '-') {
i += 1;
if (i >= argc) {
return usage(exe);
} else if (strcmp(arg, "--backend") == 0) {
if (strcmp("dummy", argv[i]) == 0) {
} else if (strcmp("alsa", argv[i]) == 0) {
backend = SoundIoBackendAlsa;
} else if (strcmp("pulseaudio", argv[i]) == 0) {
} else if (strcmp("jack", argv[i]) == 0) {
backend = SoundIoBackendJack;
} else if (strcmp("coreaudio", argv[i]) == 0) {
} else if (strcmp("wasapi", argv[i]) == 0) {
} else {
fprintf(stderr, "Invalid backend: %s\n", argv[i]);
return 1;
}
} else {
return usage(exe);
}
} else {
return usage(exe);
}
}
struct SoundIo *soundio = soundio_create();
if (!soundio) {
fprintf(stderr, "out of memory\n");
return 1;
}
int err = (backend == SoundIoBackendNone) ?
soundio_connect(soundio) : soundio_connect_backend(soundio, backend);
if (err) {
fprintf(stderr, "%s\n", soundio_strerror(err));
return err;
}
if (watch) {
for (;;) {
}
} else {
int err = list_devices(soundio);
soundio_destroy(soundio);
return err;
}
}
void soundio_wait_events(struct SoundIo *soundio)
This function calls soundio_flush_events then blocks until another event is ready or you call soundio...
SoundIoBackend
Definition: soundio.h:218
@ SoundIoBackendNone
Definition: soundio.h:219
@ SoundIoBackendPulseAudio
Definition: soundio.h:221
@ SoundIoBackendCoreAudio
Definition: soundio.h:223
@ SoundIoBackendWasapi
Definition: soundio.h:224
@ SoundIoBackendJack
Definition: soundio.h:220
@ SoundIoBackendDummy
Definition: soundio.h:225
@ SoundIoBackendAlsa
Definition: soundio.h:222
int soundio_output_device_count(struct SoundIo *soundio)
Get the number of output devices.
struct SoundIoDevice * soundio_get_output_device(struct SoundIo *soundio, int index)
Always returns a device.
const char * soundio_get_channel_name(enum SoundIoChannelId id)
void soundio_device_unref(struct SoundIoDevice *device)
Remove 1 to the reference count of device.
void soundio_destroy(struct SoundIo *soundio)
void soundio_flush_events(struct SoundIo *soundio)
Atomically update information for all connected devices.
int soundio_default_input_device_index(struct SoundIo *soundio)
returns the index of the default input device returns -1 if there are no devices or if you never call...
struct SoundIoDevice * soundio_get_input_device(struct SoundIo *soundio, int index)
Always returns a device.
int soundio_default_output_device_index(struct SoundIo *soundio)
returns the index of the default output device returns -1 if there are no devices or if you never cal...
int soundio_input_device_count(struct SoundIo *soundio)
When you call soundio_flush_events, a snapshot of all device state is saved and these functions merel...
const char * soundio_strerror(int error)
Get a string representation of a SoundIoError.
int soundio_connect_backend(struct SoundIo *soundio, enum SoundIoBackend backend)
Instead of calling soundio_connect you may call this function to try a specific backend.
int soundio_connect(struct SoundIo *soundio)
Tries soundio_connect_backend on all available backends in order.
struct SoundIo * soundio_create(void)
Create a SoundIo context.
@ SoundIoFormatInvalid
Definition: soundio.h:236
const char * soundio_format_string(enum SoundIoFormat format)
Returns string representation of format.
The size of this struct is OK to use.
Definition: soundio.h:306
enum SoundIoChannelId channels[SOUNDIO_MAX_CHANNELS]
Definition: soundio.h:309
const char * name
Definition: soundio.h:307
int channel_count
Definition: soundio.h:308
The size of this struct is not part of the API or ABI.
Definition: soundio.h:387
double software_latency_min
Software latency minimum in seconds.
Definition: soundio.h:460
int probe_error
This is set to a SoundIoError representing the result of the device probe.
Definition: soundio.h:493
int format_count
How many formats are available in SoundIoDevice::formats.
Definition: soundio.h:420
int layout_count
Definition: soundio.h:412
char * name
User-friendly UTF-8 encoded text to describe the device.
Definition: soundio.h:401
double software_latency_max
Software latency maximum in seconds.
Definition: soundio.h:465
struct SoundIoChannelLayout * layouts
Channel layouts are handled similarly to SoundIoDevice::formats.
Definition: soundio.h:411
struct SoundIoSampleRateRange * sample_rates
Sample rate is the number of frames per second.
Definition: soundio.h:447
int sample_rate_current
See SoundIoDevice::current_format 0 if sample rate information is missing due to a probe error.
Definition: soundio.h:454
struct SoundIoChannelLayout current_layout
See SoundIoDevice::current_format.
Definition: soundio.h:414
char * id
A string of bytes that uniquely identifies this device.
Definition: soundio.h:399
struct SoundIo * soundio
Read-only. Set automatically.
Definition: soundio.h:389
int sample_rate_count
How many sample rate ranges are available in SoundIoDevice::sample_rates.
Definition: soundio.h:451
double software_latency_current
Software latency in seconds.
Definition: soundio.h:471
enum SoundIoFormat current_format
A device is either a raw device or it is a virtual device that is provided by a software mixing servi...
Definition: soundio.h:439
enum SoundIoFormat * formats
List of formats this device supports.
Definition: soundio.h:418
bool is_raw
Raw means that you are directly opening the hardware device and not going through a proxy such as dmi...
Definition: soundio.h:478
The size of this struct is OK to use.
Definition: soundio.h:313
int max
Definition: soundio.h:315
int min
Definition: soundio.h:314
The size of this struct is not part of the API or ABI.
Definition: soundio.h:328
void(* on_devices_change)(struct SoundIo *)
Optional callback.
Definition: soundio.h:333