]> git.sesse.net Git - nageru/blobdiff - alsa_pool.cpp
Support audio-only FFmpeg inputs. Somewhat wonky, though.
[nageru] / alsa_pool.cpp
index 0a7da5946292a45291bae50cf9c21a373596e177..3092dc32335551deed1b2b7b2255c07b7e9a19db 100644 (file)
@@ -1,16 +1,22 @@
 #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 <pthread.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"
@@ -36,7 +42,10 @@ ALSAPool::~ALSAPool()
        }
        should_quit = true;
        const uint64_t one = 1;
-       write(should_quit_fd, &one, sizeof(one));
+       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) {
@@ -126,6 +135,10 @@ 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);
 
@@ -172,19 +185,24 @@ ALSAPool::ProbeResult ALSAPool::probe_device_once(unsigned card_index, unsigned
        }
        unique_ptr<snd_ctl_t, decltype(snd_ctl_close)*> 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
@@ -280,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()");
@@ -371,6 +391,10 @@ void ALSAPool::reset_device(unsigned index)
 {
        lock_guard<mutex> lock(mu);
        Device *device = &devices[index];
+       if (device->state == Device::State::DEAD) {
+               // Not running, and should not be started.
+               return;
+       }
        if (inputs[index] != nullptr) {
                inputs[index]->stop_capture_thread();
        }
@@ -378,7 +402,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();
        }