X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=alsa_pool.cpp;h=59ae595f029f8ba6cfef0d7aff12f88a97f61799;hb=b9feb66845bf24465b7671ac9ff7a52b88f6032b;hp=22a61af88d27e982a229bf8f8eccbe593c8c9612;hpb=12ef90072622a8001f2c3cc853e5b89ba7d4e94e;p=nageru diff --git a/alsa_pool.cpp b/alsa_pool.cpp index 22a61af..59ae595 100644 --- a/alsa_pool.cpp +++ b/alsa_pool.cpp @@ -1,15 +1,22 @@ #include "alsa_pool.h" -#include -#include -#include +#include #include +#include #include +#include +#include +#include #include +#include #include #include #include +#include +#include +#include #include +#include #include "alsa_input.h" #include "audio_mixer.h" @@ -20,6 +27,12 @@ using namespace std; using namespace std::placeholders; +ALSAPool::ALSAPool() +{ + should_quit_fd = eventfd(/*initval=*/0, /*flags=*/0); + assert(should_quit_fd != -1); +} + ALSAPool::~ALSAPool() { for (Device &device : devices) { @@ -28,7 +41,16 @@ ALSAPool::~ALSAPool() } } should_quit = true; + const uint64_t one = 1; + if (write(should_quit_fd, &one, sizeof(one)) != sizeof(one)) { + perror("write(should_quit_fd)"); + exit(1); + } inotify_thread.join(); + + while (retry_threads_running > 0) { + this_thread::sleep_for(std::chrono::milliseconds(100)); + } } std::vector ALSAPool::get_devices() @@ -104,6 +126,7 @@ void ALSAPool::probe_device_with_retry(unsigned card_index, unsigned dev_index) // then start it ourselves. fprintf(stderr, "Trying %s again in one second...\n", address); add_device_tries_left[address] = num_retries; + ++retry_threads_running; thread(&ALSAPool::probe_device_retry_thread_func, this, card_index, dev_index).detach(); } @@ -112,16 +135,21 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_ char address[256]; snprintf(address, sizeof(address), "hw:%d,%d", card_index, dev_index); + char thread_name[16]; + snprintf(thread_name, sizeof(thread_name), "Reprobe_hw:%d,%d", card_index, dev_index); + pthread_setname_np(pthread_self(), thread_name); + for ( ;; ) { // Termination condition within the loop. sleep(1); // See if there are any retries left. lock_guard lock(add_device_mutex); - if (!add_device_tries_left.count(address) || + if (should_quit || + !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; + break; } // Seemingly there were. Give it a try (we still hold the mutex). @@ -129,11 +157,11 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_ if (result == ProbeResult::SUCCESS) { add_device_tries_left.erase(address); fprintf(stderr, "Probe of %s succeeded.\n", address); - return; + break; } 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; + break; } // Failed again. @@ -141,6 +169,8 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_ fprintf(stderr, "Trying %s again in one second (%d tries left)...\n", address, add_device_tries_left[address]); } + + --retry_threads_running; } ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned dev_index) @@ -155,19 +185,24 @@ ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned } unique_ptr ctl_closer(ctl, snd_ctl_close); + snprintf(address, sizeof(address), "hw:%d,%d", card_index, dev_index); + snd_pcm_info_t *pcm_info; snd_pcm_info_alloca(&pcm_info); snd_pcm_info_set_device(pcm_info, dev_index); snd_pcm_info_set_subdevice(pcm_info, 0); snd_pcm_info_set_stream(pcm_info, SND_PCM_STREAM_CAPTURE); - if (snd_ctl_pcm_info(ctl, pcm_info) < 0) { + err = snd_ctl_pcm_info(ctl, pcm_info); + if (err == -ENOENT) { + // Not a capture card. + return ALSAPool::ProbeResult::FAILURE; + } + if (err < 0) { // Not available for capture. printf("%s: Not available for capture.\n", address); return ALSAPool::ProbeResult::DEFER; } - snprintf(address, sizeof(address), "hw:%d,%d", card_index, dev_index); - unsigned num_channels = 0; // Find all channel maps for this device, and pick out the one @@ -263,6 +298,8 @@ void ALSAPool::init() void ALSAPool::inotify_thread_func() { + pthread_setname_np(pthread_self(), "ALSA_Hotplug"); + int inotify_fd = inotify_init(); if (inotify_fd == -1) { perror("inotify_init()"); @@ -281,12 +318,15 @@ void ALSAPool::inotify_thread_func() int size = sizeof(inotify_event) + NAME_MAX + 1; unique_ptr buf(new char[size]); while (!should_quit) { - pollfd fds; - fds.fd = inotify_fd; - fds.events = POLLIN; - fds.revents = 0; - - int ret = poll(&fds, 1, 100); + pollfd fds[2]; + fds[0].fd = inotify_fd; + fds[0].events = POLLIN; + fds[0].revents = 0; + fds[1].fd = should_quit_fd; + fds[1].events = POLLIN; + fds[1].revents = 0; + + int ret = poll(fds, 2, -1); if (ret == -1) { if (errno == EINTR) { continue; @@ -299,6 +339,8 @@ void ALSAPool::inotify_thread_func() continue; } + if (fds[1].revents) break; // should_quit_fd asserted. + ret = read(inotify_fd, buf.get(), size); if (ret == -1) { if (errno == EINTR) { @@ -342,6 +384,7 @@ void ALSAPool::inotify_thread_func() } close(watch_fd); close(inotify_fd); + close(should_quit_fd); } void ALSAPool::reset_device(unsigned index) @@ -355,7 +398,7 @@ void ALSAPool::reset_device(unsigned index) inputs[index].reset(); } else { // TODO: Put on a background thread instead of locking? - auto callback = bind(&AudioMixer::add_audio, global_audio_mixer, DeviceSpec{InputSourceType::ALSA_INPUT, index}, _1, _2, _3, _4); + auto callback = bind(&AudioMixer::add_audio, global_audio_mixer, DeviceSpec{InputSourceType::ALSA_INPUT, index}, _1, _2, _3, _4, _5); inputs[index].reset(new ALSAInput(device->address.c_str(), OUTPUT_FREQUENCY, device->num_channels, callback, this, index)); inputs[index]->start_capture_thread(); }