Silences the warning spew from the resampler that no data is coming.
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) {
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()
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;
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) {
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;
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; }
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