1 /// Translated from C to D
2 module sio_list_devices;
3 
4 extern(C): @nogc: nothrow: __gshared:
5 
6 import soundio.api;
7 import soundio.util: printf_stderr;
8 
9 import core.stdc.stdio;
10 import core.stdc..string;
11 
12 // list or keep a watch on audio devices
13 private extern(D) int usage(char* exe) {
14     printf_stderr("Usage: %s [options]\n"
15             ~ "Options:\n"
16             ~ "  [--watch]\n"
17             ~ "  [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n"
18             ~ "  [--short]\n", exe);
19     return 1;
20 }
21 
22 private extern(D) void print_channel_layout(const(SoundIoChannelLayout)* layout) {
23     if (layout.name) {
24         printf_stderr("%s", layout.name);
25     } else {
26         printf_stderr("%s", soundio_get_channel_name(layout.channels[0]));
27         for (int i = 1; i < layout.channel_count; i += 1) {
28             printf_stderr(", %s", soundio_get_channel_name(layout.channels[i]));
29         }
30     }
31 }
32 
33 private extern(D) bool short_output = false;
34 
35 private extern(D) void print_device(SoundIoDevice* device, bool is_default) {
36     const(char)* default_str = is_default ? " (default)" : "";
37     const(char)* raw_str = device.is_raw ? " (raw)" : "";
38     printf_stderr("%s%s%s\n", device.name, default_str, raw_str);
39     if (short_output)
40         return;
41     printf_stderr("  id: %s\n", device.id);
42 
43     if (device.probe_error) {
44         printf_stderr("  probe error: %s\n", soundio_strerror(device.probe_error));
45     } else {
46         printf_stderr("  channel layouts:\n");
47         for (int i = 0; i < device.layout_count; i += 1) {
48             printf_stderr("    ");
49             print_channel_layout(&device.layouts[i]);
50             printf_stderr("\n");
51         }
52         if (device.current_layout.channel_count > 0) {
53             printf_stderr("  current layout: ");
54             print_channel_layout(&device.current_layout);
55             printf_stderr("\n");
56         }
57 
58         printf_stderr("  sample rates:\n");
59         for (int i = 0; i < device.sample_rate_count; i += 1) {
60             SoundIoSampleRateRange* range = &device.sample_rates[i];
61             printf_stderr("    %d - %d\n", range.min, range.max);
62 
63         }
64         if (device.sample_rate_current)
65             printf_stderr("  current sample rate: %d\n", device.sample_rate_current);
66         printf_stderr("  formats: ");
67         for (int i = 0; i < device.format_count; i += 1) {
68             const(char)* comma = (i == device.format_count - 1) ? "" : ", ";
69             printf_stderr("%s%s", soundio_format_string(device.formats[i]), comma);
70         }
71         printf_stderr("\n");
72         if (device.current_format != SoundIoFormat.Invalid)
73             printf_stderr("  current format: %s\n", soundio_format_string(device.current_format));
74 
75         printf_stderr("  min software latency: %0.8f sec\n", device.software_latency_min);
76         printf_stderr("  max software latency: %0.8f sec\n", device.software_latency_max);
77         if (device.software_latency_current != 0.0)
78             printf_stderr("  current software latency: %0.8f sec\n", device.software_latency_current);
79 
80     }
81     printf_stderr("\n");
82 }
83 
84 private extern(D) int list_devices(SoundIo* soundio) {
85     const int output_count = soundio_output_device_count(soundio);
86     const int input_count = soundio_input_device_count(soundio);
87 
88     int default_output = soundio_default_output_device_index(soundio);
89     int default_input = soundio_default_input_device_index(soundio);
90 
91     printf_stderr("--------Input Devices--------\n\n");
92     for (int i = 0; i < input_count; i += 1) {
93         SoundIoDevice* device = soundio_get_input_device(soundio, i);
94         print_device(device, default_input == i);
95         soundio_device_unref(device);
96     }
97     printf_stderr("\n--------Output Devices--------\n\n");
98     for (int i = 0; i < output_count; i += 1) {
99         SoundIoDevice* device = soundio_get_output_device(soundio, i);
100         print_device(device, default_output == i);
101         soundio_device_unref(device);
102     }
103 
104     printf_stderr("\n%d devices found\n", input_count + output_count);
105     return 0;
106 }
107 
108 private extern(C) void on_devices_change(SoundIo* soundio) {
109     printf_stderr("devices changed\n");
110     list_devices(soundio);
111 }
112 
113 int main(int argc, char** argv) {
114     char* exe = argv[0];
115     bool watch = false;
116     SoundIoBackend backend = SoundIoBackend.None;
117 
118     for (int i = 1; i < argc; i += 1) {
119         char* arg = argv[i];
120         if (strcmp("--watch", arg) == 0) {
121             watch = true;
122         } else if (strcmp("--short", arg) == 0) {
123             short_output = true;
124         } else if (arg[0] == '-' && arg[1] == '-') {
125             i += 1;
126             if (i >= argc) {
127                 return usage(exe);
128             } else if (strcmp(arg, "--backend") == 0) {
129                 if (strcmp("dummy", argv[i]) == 0) {
130                     backend = SoundIoBackend.Dummy;
131                 } else if (strcmp("alsa", argv[i]) == 0) {
132                     backend = SoundIoBackend.Alsa;
133                 } else if (strcmp("pulseaudio", argv[i]) == 0) {
134                     backend = SoundIoBackend.PulseAudio;
135                 } else if (strcmp("jack", argv[i]) == 0) {
136                     backend = SoundIoBackend.Jack;
137                 } else if (strcmp("coreaudio", argv[i]) == 0) {
138                     backend = SoundIoBackend.CoreAudio;
139                 } else if (strcmp("wasapi", argv[i]) == 0) {
140                     backend = SoundIoBackend.Wasapi;
141                 } else {
142                     printf_stderr("Invalid backend: %s\n", argv[i]);
143                     return 1;
144                 }
145             } else {
146                 return usage(exe);
147             }
148         } else {
149             return usage(exe);
150         }
151     }
152 
153     SoundIo* soundio = soundio_create();
154     if (!soundio) {
155         printf_stderr("out of memory\n");
156         return 1;
157     }
158 
159     if (int err = (backend == SoundIoBackend.None) ?
160         soundio_connect(soundio) : soundio_connect_backend(soundio, backend)) {
161         printf_stderr("%s\n", soundio_strerror(err));
162         return err;
163     }
164 
165     if (watch) {
166         soundio.on_devices_change = &on_devices_change;
167         for (;;) {
168             soundio_wait_events(soundio);
169         }
170     } else {
171         soundio_flush_events(soundio);
172         const err = list_devices(soundio);
173         soundio_destroy(soundio);
174         return err;
175     }
176 }