+void ALSAPool::probe_device_with_retry(unsigned card_index, unsigned dev_index)
+{
+ char address[256];
+ snprintf(address, sizeof(address), "hw:%d,%d", card_index, dev_index);
+
+ lock_guard<mutex> lock(add_device_mutex);
+ if (add_device_tries_left.count(address)) {
+ // Some thread is already busy retrying this,
+ // so just reset its count.
+ add_device_tries_left[address] = num_retries;
+ return;
+ }
+
+ // Try (while still holding the lock) to add the device synchronously.
+ ProbeResult result = probe_device_once(card_index, dev_index);
+ if (result == ProbeResult::SUCCESS) {
+ return;
+ } else if (result == ProbeResult::FAILURE) {
+ return;
+ }
+ assert(result == ProbeResult::DEFER);
+
+ // Add failed for whatever reason (probably just that the device
+ // isn't up yet. Set up a count so that nobody else starts a thread,
+ // then start it ourselves.
+ fprintf(stderr, "Trying %s again in one second...\n", address);
+ add_device_tries_left[address] = num_retries;
+ thread(&ALSAPool::probe_device_retry_thread_func, this, card_index, dev_index).detach();
+}
+
+void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_index)
+{
+ char address[256];
+ snprintf(address, sizeof(address), "hw:%d,%d", card_index, dev_index);
+
+ for ( ;; ) { // Termination condition within the loop.
+ sleep(1);
+
+ // See if there are any retries left.
+ lock_guard<mutex> lock(add_device_mutex);
+ if (!add_device_tries_left.count(address) ||
+ add_device_tries_left[address] == 0) {
+ add_device_tries_left.erase(address);
+ fprintf(stderr, "Giving up probe of %s.\n", address);
+ return;
+ }
+
+ // Seemingly there were. Give it a try (we still hold the mutex).
+ ProbeResult result = probe_device_once(card_index, dev_index);
+ if (result == ProbeResult::SUCCESS) {
+ add_device_tries_left.erase(address);
+ fprintf(stderr, "Probe of %s succeeded.\n", address);
+ return;
+ } else if (result == ProbeResult::FAILURE || --add_device_tries_left[address] == 0) {
+ add_device_tries_left.erase(address);
+ fprintf(stderr, "Giving up probe of %s.\n", address);
+ return;
+ }
+
+ // Failed again.
+ assert(result == ProbeResult::DEFER);
+ fprintf(stderr, "Trying %s again in one second (%d tries left)...\n",
+ address, add_device_tries_left[address]);
+ }
+}
+
+ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned dev_index)