+ parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING);
+
+ // If the device hasn't been opened already, we need to do so
+ // before we can capture.
+ while (!should_quit && pcm_handle == nullptr) {
+ if (!open_device()) {
+ fprintf(stderr, "[%s] Waiting one second and trying again...\n",
+ device.c_str());
+ sleep(1);
+ }
+ }
+
+ if (should_quit) {
+ // Don't call free_card(); that would be a deadlock.
+ WARN_ON_ERROR("snd_pcm_close()", snd_pcm_close(pcm_handle));
+ pcm_handle = nullptr;
+ return;
+ }
+
+ // Do the actual capture. (Termination condition within loop.)
+ for ( ;; ) {
+ switch (do_capture()) {
+ case CaptureEndReason::REQUESTED_QUIT:
+ // Don't call free_card(); that would be a deadlock.
+ WARN_ON_ERROR("snd_pcm_close()", snd_pcm_close(pcm_handle));
+ pcm_handle = nullptr;
+ return;
+ case CaptureEndReason::DEVICE_GONE:
+ parent_pool->free_card(internal_dev_index);
+ WARN_ON_ERROR("snd_pcm_close()", snd_pcm_close(pcm_handle));
+ pcm_handle = nullptr;
+ return;
+ case CaptureEndReason::OTHER_ERROR:
+ parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING);
+ fprintf(stderr, "[%s] Sleeping one second and restarting capture...\n",
+ device.c_str());
+ sleep(1);
+ break;
+ }
+ }
+}
+
+ALSAInput::CaptureEndReason ALSAInput::do_capture()
+{
+ parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::STARTING);
+ RETURN_ON_ERROR("snd_pcm_start()", snd_pcm_start(pcm_handle));
+ parent_pool->set_card_state(internal_dev_index, ALSAPool::Device::State::RUNNING);
+