]> git.sesse.net Git - nageru/blobdiff - audio_mixer.h
Actually set the fader positions when making the views for each audio bus.
[nageru] / audio_mixer.h
index e5922674f1245382b2a0dd872ca6291b437d6def..faa0cc52b025b23e6fe541e993e6ee1e085427a0 100644 (file)
@@ -25,6 +25,7 @@
 #include "defs.h"
 #include "ebu_r128_proc.h"
 #include "filter.h"
+#include "input_mapping.h"
 #include "resampling_queue.h"
 #include "stereocompressor.h"
 
@@ -32,26 +33,6 @@ namespace bmusb {
 struct AudioFormat;
 }  // namespace bmusb
 
-enum class InputSourceType { SILENCE, CAPTURE_CARD, ALSA_INPUT };
-struct DeviceSpec {
-       InputSourceType type;
-       unsigned index;
-
-       bool operator== (const DeviceSpec &other) const {
-               return type == other.type && index == other.index;
-       }
-
-       bool operator< (const DeviceSpec &other) const {
-               if (type != other.type)
-                       return type < other.type;
-               return index < other.index;
-       }
-};
-struct DeviceInfo {
-       std::string name;
-       unsigned num_channels;
-};
-
 enum EQBand {
        EQ_BAND_BASS = 0,
        EQ_BAND_MID,
@@ -59,26 +40,6 @@ enum EQBand {
        NUM_EQ_BANDS
 };
 
-static inline uint64_t DeviceSpec_to_key(const DeviceSpec &device_spec)
-{
-       return (uint64_t(device_spec.type) << 32) | device_spec.index;
-}
-
-static inline DeviceSpec key_to_DeviceSpec(uint64_t key)
-{
-       return DeviceSpec{ InputSourceType(key >> 32), unsigned(key & 0xffffffff) };
-}
-
-struct InputMapping {
-       struct Bus {
-               std::string name;
-               DeviceSpec device;
-               int source_channel[2] { -1, -1 };  // Left and right. -1 = none.
-       };
-
-       std::vector<Bus> buses;
-};
-
 class AudioMixer {
 public:
        AudioMixer(unsigned num_cards);
@@ -93,8 +54,16 @@ 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);
 
+       float get_fader_volume(unsigned bus_index) const { return fader_volume_db[bus_index]; }
        void set_fader_volume(unsigned bus_index, float level_db) { fader_volume_db[bus_index] = level_db; }
 
        // Note: This operation holds all ALSA devices (see ALSAPool::get_devices()).
@@ -102,7 +71,23 @@ public:
        // or every card will be held forever.
        std::map<DeviceSpec, DeviceInfo> get_devices();
 
-       void set_name(DeviceSpec device_spec, const std::string &name);
+       // See comments on ALSAPool::get_card_state().
+       ALSAPool::Device::State get_alsa_card_state(unsigned index)
+       {
+               return alsa_pool.get_card_state(index);
+       }
+
+       // See comments on ALSAPool::create_dead_card().
+       DeviceSpec create_dead_card(const std::string &name, const std::string &info, unsigned num_channels)
+       {
+               unsigned dead_card_index = alsa_pool.create_dead_card(name, info, num_channels);
+               return DeviceSpec{InputSourceType::ALSA_INPUT, dead_card_index};
+       }
+
+       void set_display_name(DeviceSpec device_spec, const std::string &name);
+
+       // Note: The card should be held (currently this isn't enforced, though).
+       void serialize_device(DeviceSpec device_spec, DeviceSpecProto *device_spec_proto);
 
        void set_input_mapping(const InputMapping &input_mapping);
        InputMapping get_input_mapping() const;
@@ -249,14 +234,33 @@ public:
                audio_level_callback = callback;
        }
 
+       typedef std::function<void()> state_changed_callback_t;
+       void set_state_changed_callback(state_changed_callback_t callback)
+       {
+               state_changed_callback = callback;
+       }
+
+       state_changed_callback_t get_state_changed_callback() const
+       {
+               return state_changed_callback;
+       }
+
+       void trigger_state_changed_callback()
+       {
+               if (state_changed_callback != nullptr) {
+                       state_changed_callback();
+               }
+       }
+
 private:
        struct AudioDevice {
                std::unique_ptr<ResamplingQueue> resampling_queue;
                int64_t next_local_pts = 0;
-               std::string name;
+               std::string display_name;
                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
@@ -324,6 +328,7 @@ private:
        std::atomic<float> eq_level_db[MAX_BUSES][NUM_EQ_BANDS] {{{ 0.0f }}};
 
        audio_level_callback_t audio_level_callback = nullptr;
+       state_changed_callback_t state_changed_callback = nullptr;
        mutable std::mutex audio_measure_mutex;
        Ebu_r128_proc r128;  // Under audio_measure_mutex.
        CorrelationMeasurer correlation;  // Under audio_measure_mutex.