]> git.sesse.net Git - nageru/blobdiff - alsa_pool.cpp
Write 1.4.0 changelog.
[nageru] / alsa_pool.cpp
index 22a61af88d27e982a229bf8f8eccbe593c8c9612..bcda16315329e87b039a5240a015e7b050c4d5d3 100644 (file)
@@ -1,15 +1,21 @@
 #include "alsa_pool.h"
 
-#include <alsa/control.h>
-#include <alsa/error.h>
-#include <alsa/pcm.h>
+#include <alsa/asoundlib.h>
 #include <assert.h>
+#include <errno.h>
 #include <limits.h>
+#include <poll.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <sys/eventfd.h>
 #include <sys/inotify.h>
 #include <unistd.h>
 #include <algorithm>
+#include <chrono>
+#include <functional>
+#include <iterator>
 #include <memory>
+#include <ratio>
 
 #include "alsa_input.h"
 #include "audio_mixer.h"
 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 +40,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::Device> ALSAPool::get_devices()
@@ -104,6 +125,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();
 }
 
@@ -117,11 +139,12 @@ void ALSAPool::probe_device_retry_thread_func(unsigned card_index, unsigned dev_
 
                // See if there are any retries left.
                lock_guard<mutex> 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 +152,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 +164,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)
@@ -281,12 +306,15 @@ void ALSAPool::inotify_thread_func()
        int size = sizeof(inotify_event) + NAME_MAX + 1;
        unique_ptr<char[]> 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 +327,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 +372,7 @@ void ALSAPool::inotify_thread_func()
        }
        close(watch_fd);
        close(inotify_fd);
+       close(should_quit_fd);
 }
 
 void ALSAPool::reset_device(unsigned index)