add soundio_force_device_scan API

This commit is contained in:
Andrew Kelley 2015-08-27 21:45:22 -07:00
parent 2d8f8e7f31
commit 7a714298c1
10 changed files with 85 additions and 8 deletions

View file

@ -14,7 +14,11 @@
// list or keep a watch on audio devices // list or keep a watch on audio devices
static int usage(char *exe) { static int usage(char *exe) {
fprintf(stderr, "Usage: %s [--watch] [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n", exe); fprintf(stderr, "Usage: %s [options]\n"
"Options:\n"
" [--watch]\n"
" [--backend dummy|alsa|pulseaudio|jack|coreaudio|wasapi]\n"
" [--short]\n", exe);
return 1; return 1;
} }
@ -29,10 +33,14 @@ static void print_channel_layout(const struct SoundIoChannelLayout *layout) {
} }
} }
static bool short_output = false;
static void print_device(struct SoundIoDevice *device, bool is_default) { static void print_device(struct SoundIoDevice *device, bool is_default) {
const char *default_str = is_default ? " (default)" : ""; const char *default_str = is_default ? " (default)" : "";
const char *raw_str = device->is_raw ? " (raw)" : ""; const char *raw_str = device->is_raw ? " (raw)" : "";
fprintf(stderr, "%s%s%s\n", device->name, default_str, raw_str); fprintf(stderr, "%s%s%s\n", device->name, default_str, raw_str);
if (short_output)
return;
fprintf(stderr, " id: %s\n", device->id); fprintf(stderr, " id: %s\n", device->id);
if (device->probe_error) { if (device->probe_error) {
@ -114,6 +122,8 @@ int main(int argc, char **argv) {
char *arg = argv[i]; char *arg = argv[i];
if (strcmp("--watch", arg) == 0) { if (strcmp("--watch", arg) == 0) {
watch = true; watch = true;
} else if (strcmp("--short", arg) == 0) {
short_output = true;
} else if (arg[0] == '-' && arg[1] == '-') { } else if (arg[0] == '-' && arg[1] == '-') {
i += 1; i += 1;
if (i >= argc) { if (i >= argc) {

View file

@ -725,6 +725,22 @@ SOUNDIO_EXPORT void soundio_wait_events(struct SoundIo *soundio);
SOUNDIO_EXPORT void soundio_wakeup(struct SoundIo *soundio); SOUNDIO_EXPORT void soundio_wakeup(struct SoundIo *soundio);
/// If necessary you can manually trigger a device rescan. Normally you will
/// not ever have to call this function, as libsoundio listens to system events
/// for device changes and responds to them by rescanning devices and preparing
/// the new device information for you to be atomically replaced when you call
/// ::soundio_flush_events. However you might run into cases where you want to
/// force trigger a device rescan, for example if an ALSA device has a
/// SoundIoDevice::probe_error.
///
/// After you call this you still have to use ::soundio_flush_events or
/// ::soundio_wait_events and then wait for the
/// SoundIo::on_devices_change callback.
///
/// This can be called from any thread context except for
/// SoundIoOutStream::write_callback and SoundIoInStream::read_callback
SOUNDIO_EXPORT void soundio_force_device_scan(struct SoundIo *soundio);
// Channel Layouts // Channel Layouts

View file

@ -913,6 +913,11 @@ static void wakeup_alsa(SoundIoPrivate *si) {
soundio_os_mutex_unlock(sia->mutex); soundio_os_mutex_unlock(sia->mutex);
} }
static void force_device_scan_alsa(SoundIoPrivate *si) {
SoundIoAlsa *sia = &si->backend_data.alsa;
wakeup_device_poll(sia);
}
static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static void outstream_destroy_alsa(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamAlsa *osa = &os->backend_data.alsa; SoundIoOutStreamAlsa *osa = &os->backend_data.alsa;
@ -1771,6 +1776,7 @@ int soundio_alsa_init(SoundIoPrivate *si) {
si->flush_events = flush_events_alsa; si->flush_events = flush_events_alsa;
si->wait_events = wait_events_alsa; si->wait_events = wait_events_alsa;
si->wakeup = wakeup_alsa; si->wakeup = wakeup_alsa;
si->force_device_scan = force_device_scan_alsa;
si->outstream_open = outstream_open_alsa; si->outstream_open = outstream_open_alsa;
si->outstream_destroy = outstream_destroy_alsa; si->outstream_destroy = outstream_destroy_alsa;

View file

@ -820,6 +820,12 @@ static void wakeup_ca(struct SoundIoPrivate *si) {
soundio_os_cond_signal(sica->cond, nullptr); soundio_os_cond_signal(sica->cond, nullptr);
} }
static void force_device_scan_ca(struct SoundIoPrivate *si) {
SoundIoCoreAudio *sica = &si->backend_data.coreaudio;
sica->device_scan_queued.store(true);
soundio_os_cond_signal(sica->scan_devices_cond, nullptr);
}
static void device_thread_run(void *arg) { static void device_thread_run(void *arg) {
SoundIoPrivate *si = (SoundIoPrivate *)arg; SoundIoPrivate *si = (SoundIoPrivate *)arg;
SoundIo *soundio = &si->pub; SoundIo *soundio = &si->pub;
@ -1365,6 +1371,7 @@ int soundio_coreaudio_init(SoundIoPrivate *si) {
si->flush_events = flush_events_ca; si->flush_events = flush_events_ca;
si->wait_events = wait_events_ca; si->wait_events = wait_events_ca;
si->wakeup = wakeup_ca; si->wakeup = wakeup_ca;
si->force_device_scan = force_device_scan_ca;
si->outstream_open = outstream_open_ca; si->outstream_open = outstream_open_ca;
si->outstream_destroy = outstream_destroy_ca; si->outstream_destroy = outstream_destroy_ca;

View file

@ -129,6 +129,10 @@ static void wakeup_dummy(SoundIoPrivate *si) {
soundio_os_cond_signal(sid->cond, nullptr); soundio_os_cond_signal(sid->cond, nullptr);
} }
static void force_device_scan_dummy(SoundIoPrivate *si) {
// nothing to do; dummy devices never change
}
static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static void outstream_destroy_dummy(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamDummy *osd = &os->backend_data.dummy; SoundIoOutStreamDummy *osd = &os->backend_data.dummy;
@ -508,6 +512,7 @@ int soundio_dummy_init(SoundIoPrivate *si) {
si->flush_events = flush_events_dummy; si->flush_events = flush_events_dummy;
si->wait_events = wait_events_dummy; si->wait_events = wait_events_dummy;
si->wakeup = wakeup_dummy; si->wakeup = wakeup_dummy;
si->force_device_scan = force_device_scan_dummy;
si->outstream_open = outstream_open_dummy; si->outstream_open = outstream_open_dummy;
si->outstream_destroy = outstream_destroy_dummy; si->outstream_destroy = outstream_destroy_dummy;

View file

@ -339,6 +339,16 @@ static void wakeup_jack(struct SoundIoPrivate *si) {
soundio_os_mutex_unlock(sij->mutex); soundio_os_mutex_unlock(sij->mutex);
} }
static void force_device_scan_jack(struct SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoJack *sij = &si->backend_data.jack;
sij->refresh_devices_flag.clear();
soundio_os_mutex_lock(sij->mutex);
soundio_os_cond_signal(sij->cond, sij->mutex);
soundio->on_events_signal(soundio);
soundio_os_mutex_unlock(sij->mutex);
}
static int outstream_process_callback(jack_nframes_t nframes, void *arg) { static int outstream_process_callback(jack_nframes_t nframes, void *arg) {
SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg; SoundIoOutStreamPrivate *os = (SoundIoOutStreamPrivate *)arg;
SoundIoOutStreamJack *osj = &os->backend_data.jack; SoundIoOutStreamJack *osj = &os->backend_data.jack;
@ -892,6 +902,7 @@ int soundio_jack_init(struct SoundIoPrivate *si) {
si->flush_events = flush_events_jack; si->flush_events = flush_events_jack;
si->wait_events = wait_events_jack; si->wait_events = wait_events_jack;
si->wakeup = wakeup_jack; si->wakeup = wakeup_jack;
si->force_device_scan = force_device_scan_jack;
si->outstream_open = outstream_open_jack; si->outstream_open = outstream_open_jack;
si->outstream_destroy = outstream_destroy_jack; si->outstream_destroy = outstream_destroy_jack;

View file

@ -491,9 +491,21 @@ static void wait_events_pa(SoundIoPrivate *si) {
my_flush_events(si, true); my_flush_events(si, true);
} }
static void wakeup(SoundIoPrivate *si) { static void wakeup_pa(SoundIoPrivate *si) {
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio; SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
pa_threaded_mainloop_signal(sipa->main_loop, 0); pa_threaded_mainloop_signal(sipa->main_loop, 0);
pa_threaded_mainloop_unlock(sipa->main_loop);
}
static void force_device_scan_pa(SoundIoPrivate *si) {
SoundIo *soundio = &si->pub;
SoundIoPulseAudio *sipa = &si->backend_data.pulseaudio;
pa_threaded_mainloop_lock(sipa->main_loop);
sipa->device_scan_queued = true;
pa_threaded_mainloop_signal(sipa->main_loop, 0);
soundio->on_events_signal(soundio);
pa_threaded_mainloop_unlock(sipa->main_loop);
} }
static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) { static pa_sample_format_t to_pulseaudio_format(SoundIoFormat format) {
@ -1062,7 +1074,8 @@ int soundio_pulseaudio_init(SoundIoPrivate *si) {
si->destroy = destroy_pa; si->destroy = destroy_pa;
si->flush_events = flush_events_pa; si->flush_events = flush_events_pa;
si->wait_events = wait_events_pa; si->wait_events = wait_events_pa;
si->wakeup = wakeup; si->wakeup = wakeup_pa;
si->force_device_scan = force_device_scan_pa;
si->outstream_open = outstream_open_pa; si->outstream_open = outstream_open_pa;
si->outstream_destroy = outstream_destroy_pa; si->outstream_destroy = outstream_destroy_pa;

View file

@ -417,6 +417,11 @@ void soundio_wakeup(struct SoundIo *soundio) {
si->wakeup(si); si->wakeup(si);
} }
void soundio_force_device_scan(struct SoundIo *soundio) {
SoundIoPrivate *si = (SoundIoPrivate *)soundio;
si->force_device_scan(si);
}
int soundio_outstream_begin_write(struct SoundIoOutStream *outstream, int soundio_outstream_begin_write(struct SoundIoOutStream *outstream,
SoundIoChannelArea **areas, int *frame_count) SoundIoChannelArea **areas, int *frame_count)
{ {

View file

@ -137,6 +137,7 @@ struct SoundIoPrivate {
void (*flush_events)(struct SoundIoPrivate *); void (*flush_events)(struct SoundIoPrivate *);
void (*wait_events)(struct SoundIoPrivate *); void (*wait_events)(struct SoundIoPrivate *);
void (*wakeup)(struct SoundIoPrivate *); void (*wakeup)(struct SoundIoPrivate *);
void (*force_device_scan)(struct SoundIoPrivate *);
int (*outstream_open)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *); int (*outstream_open)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);
void (*outstream_destroy)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *); void (*outstream_destroy)(struct SoundIoPrivate *, struct SoundIoOutStreamPrivate *);

View file

@ -1017,6 +1017,12 @@ static void wakeup_wasapi(struct SoundIoPrivate *si) {
soundio_os_cond_signal(siw->cond, siw->mutex); soundio_os_cond_signal(siw->cond, siw->mutex);
} }
static void force_device_scan_wasapi(struct SoundIoPrivate *si) {
SoundIoWasapi *siw = &si->backend_data.wasapi;
siw->device_scan_queued.store(true);
soundio_os_cond_signal(siw->scan_devices_cond, nullptr);
}
static void outstream_thread_deinit(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) { static void outstream_thread_deinit(SoundIoPrivate *si, SoundIoOutStreamPrivate *os) {
SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi; SoundIoOutStreamWasapi *osw = &os->backend_data.wasapi;
@ -1903,11 +1909,7 @@ static STDMETHODIMP_(ULONG) soundio_MMNotificationClient_Release(IMMNotification
static HRESULT queue_device_scan(IMMNotificationClient *client) { static HRESULT queue_device_scan(IMMNotificationClient *client) {
SoundIoPrivate *si = soundio_MMNotificationClient_si(client); SoundIoPrivate *si = soundio_MMNotificationClient_si(client);
SoundIoWasapi *siw = &si->backend_data.wasapi; force_device_scan_wasapi(si);
siw->device_scan_queued.store(true);
soundio_os_cond_signal(siw->scan_devices_cond, nullptr);
return S_OK; return S_OK;
} }
@ -1986,6 +1988,7 @@ int soundio_wasapi_init(SoundIoPrivate *si) {
si->flush_events = flush_events_wasapi; si->flush_events = flush_events_wasapi;
si->wait_events = wait_events_wasapi; si->wait_events = wait_events_wasapi;
si->wakeup = wakeup_wasapi; si->wakeup = wakeup_wasapi;
si->force_device_scan = force_device_scan_wasapi;
si->outstream_open = outstream_open_wasapi; si->outstream_open = outstream_open_wasapi;
si->outstream_destroy = outstream_destroy_wasapi; si->outstream_destroy = outstream_destroy_wasapi;