]> git.sesse.net Git - nageru/commitdiff
When an ALSA input goes away, replace it by silence.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sat, 10 Sep 2016 12:06:54 +0000 (14:06 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Wed, 19 Oct 2016 22:55:44 +0000 (00:55 +0200)
Silences the warning spew from the resampler that no data is coming.

alsa_input.cpp
audio_mixer.cpp
audio_mixer.h

index a6487a4287e221f649f3aefa8738cb5a2afd66b1..0a39d3f1a5c55364387f4c4e1ad50c0bc6b99f5b 100644 (file)
@@ -166,6 +166,8 @@ void ALSAInput::stop_capture_thread()
 
 void ALSAInput::capture_thread_func()
 {
+       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) {
@@ -549,8 +551,15 @@ ALSAPool::Device::State ALSAPool::get_card_state(unsigned index)
 
 void ALSAPool::set_card_state(unsigned index, ALSAPool::Device::State state)
 {
-       lock_guard<mutex> lock(mu);
-       devices[index].state = state;
+       {
+               lock_guard<mutex> lock(mu);
+               devices[index].state = state;
+       }
+
+       DeviceSpec spec{InputSourceType::ALSA_INPUT, index};
+       bool silence = (state != ALSAPool::Device::State::RUNNING);
+       while (!global_audio_mixer->silence_card(spec, silence))
+               ;
 }
 
 unsigned ALSAPool::find_free_device_index()
@@ -570,6 +579,10 @@ unsigned ALSAPool::find_free_device_index()
 
 void ALSAPool::free_card(unsigned index)
 {
+       DeviceSpec spec{InputSourceType::ALSA_INPUT, index};
+       while (!global_audio_mixer->silence_card(spec, true))
+               ;
+
        lock_guard<mutex> lock(mu);
        if (devices[index].held) {
                devices[index].state = Device::State::DEAD;
index 8485d0a6343fec00a97fe2417dd46d7aac0bb248..87a99bddc3c732dc81b29c044306bb739976815b 100644 (file)
@@ -294,6 +294,22 @@ bool AudioMixer::add_silence(DeviceSpec device_spec, unsigned samples_per_frame,
        return true;
 }
 
+bool AudioMixer::silence_card(DeviceSpec device_spec, bool silence)
+{
+       AudioDevice *device = find_audio_device(device_spec);
+
+       unique_lock<timed_mutex> lock(audio_mutex, defer_lock);
+       if (!lock.try_lock_for(chrono::milliseconds(10))) {
+               return false;
+       }
+
+       if (device->silenced && !silence) {
+               reset_resampler_mutex_held(device_spec);
+       }
+       device->silenced = silence;
+       return true;
+}
+
 AudioMixer::AudioDevice *AudioMixer::find_audio_device(DeviceSpec device)
 {
        switch (device.type) {
@@ -383,11 +399,15 @@ vector<float> AudioMixer::get_output(double pts, unsigned num_samples, Resamplin
        for (const DeviceSpec &device_spec : get_active_devices()) {
                AudioDevice *device = find_audio_device(device_spec);
                samples_card[device_spec].resize(num_samples * device->interesting_channels.size());
-               device->resampling_queue->get_output_samples(
-                       pts,
-                       &samples_card[device_spec][0],
-                       num_samples,
-                       rate_adjustment_policy);
+               if (device->silenced) {
+                       memset(&samples_card[device_spec][0], 0, samples_card[device_spec].size() * sizeof(float));
+               } else {
+                       device->resampling_queue->get_output_samples(
+                               pts,
+                               &samples_card[device_spec][0],
+                               num_samples,
+                               rate_adjustment_policy);
+               }
        }
 
        vector<float> samples_out, left, right;
index c845a26608aec82a3534826aacb86fd418d2ded1..855295dcd60f0bf207f435c75484a763eba77b89 100644 (file)
@@ -93,6 +93,13 @@ public:
        bool add_audio(DeviceSpec device_spec, const uint8_t *data, unsigned num_samples, bmusb::AudioFormat audio_format, int64_t frame_length);
        bool add_silence(DeviceSpec device_spec, unsigned samples_per_frame, unsigned num_frames, int64_t frame_length);
 
+       // If a given device is offline for whatever reason and cannot deliver audio
+       // (by means of add_audio() or add_silence()), you can call put it in silence mode,
+       // where it will be taken to only output silence. Note that when taking it _out_
+       // of silence mode, the resampler will be reset, so that old audio will not
+       // affect it. Same true/false behavior as add_audio().
+       bool silence_card(DeviceSpec device_spec, bool silence);
+
        std::vector<float> get_output(double pts, unsigned num_samples, ResamplingQueue::RateAdjustmentPolicy rate_adjustment_policy);
 
        void set_fader_volume(unsigned bus_index, float level_db) { fader_volume_db[bus_index] = level_db; }
@@ -263,6 +270,7 @@ private:
                unsigned capture_frequency = OUTPUT_FREQUENCY;
                // Which channels we consider interesting (ie., are part of some input_mapping).
                std::set<unsigned> interesting_channels;
+               bool silenced = false;
        };
 
        const AudioDevice *find_audio_device(DeviceSpec device_spec) const