LCOV - code coverage report
Current view: top level - foo/src/media/audio/pulseaudio - pulselayer.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 32 0.0 %
Date: 2026-02-28 10:41:24 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #pragma once
      19             : 
      20             : #include "noncopyable.h"
      21             : #include "logger.h"
      22             : #include "audio/audiolayer.h"
      23             : #include "pulseloopbackcapture.h"
      24             : 
      25             : #include <pulse/pulseaudio.h>
      26             : #include <pulse/stream.h>
      27             : 
      28             : #include <list>
      29             : #include <string>
      30             : #include <memory>
      31             : #include <thread>
      32             : 
      33             : namespace jami {
      34             : 
      35             : class AudioPreference;
      36             : class AudioStream;
      37             : class RingBuffer;
      38             : 
      39             : /**
      40             :  * Convenience structure to hold PulseAudio device propreties such as supported channel number etc.
      41             :  */
      42             : struct PaDeviceInfos
      43             : {
      44             :     uint32_t index {0};
      45             :     std::string name {};
      46             :     std::string description {"default"};
      47             :     pa_sample_spec sample_spec {};
      48             :     pa_channel_map channel_map {};
      49             :     uint32_t monitor_of {PA_INVALID_INDEX};
      50             : 
      51           0 :     PaDeviceInfos() {}
      52             : 
      53           0 :     PaDeviceInfos(const pa_source_info& source)
      54           0 :         : index(source.index)
      55           0 :         , name(source.name)
      56           0 :         , description(source.description)
      57           0 :         , sample_spec(source.sample_spec)
      58           0 :         , channel_map(source.channel_map)
      59           0 :         , monitor_of(source.monitor_of_sink)
      60           0 :     {}
      61             : 
      62           0 :     PaDeviceInfos(const pa_sink_info& source)
      63           0 :         : index(source.index)
      64           0 :         , name(source.name)
      65           0 :         , description(source.description)
      66           0 :         , sample_spec(source.sample_spec)
      67           0 :         , channel_map(source.channel_map)
      68           0 :     {}
      69             : 
      70             :     /**
      71             :      * Unary function to search for a device by name in a list using std functions.
      72             :      */
      73             :     class NameComparator
      74             :     {
      75             :     public:
      76           0 :         explicit NameComparator(const std::string& ref)
      77           0 :             : baseline(ref)
      78           0 :         {}
      79           0 :         bool operator()(const PaDeviceInfos& arg) { return arg.name == baseline; }
      80             : 
      81             :     private:
      82             :         const std::string& baseline;
      83             :     };
      84             : 
      85             :     class DescriptionComparator
      86             :     {
      87             :     public:
      88           0 :         explicit DescriptionComparator(const std::string& ref)
      89           0 :             : baseline(ref)
      90           0 :         {}
      91           0 :         bool operator()(const PaDeviceInfos& arg) { return arg.description == baseline; }
      92             : 
      93             :     private:
      94             :         const std::string& baseline;
      95             :     };
      96             : };
      97             : 
      98             : class PulseMainLoopLock
      99             : {
     100             : public:
     101             :     explicit PulseMainLoopLock(pa_threaded_mainloop* loop);
     102             :     ~PulseMainLoopLock();
     103             : 
     104             : private:
     105             :     NON_COPYABLE(PulseMainLoopLock);
     106             :     pa_threaded_mainloop* loop_;
     107             : };
     108             : 
     109             : class PulseLayer : public AudioLayer
     110             : {
     111             : public:
     112             :     PulseLayer(AudioPreference& pref);
     113             :     ~PulseLayer();
     114             : 
     115             :     /**
     116             :      * Write data from the ring buffer to the hardware and read data
     117             :      * from the hardware.
     118             :      */
     119             :     void readFromMic();
     120             :     void writeToSpeaker();
     121             :     void ringtoneToSpeaker();
     122             : 
     123             :     void updateSinkList();
     124             :     void updateSourceList();
     125             :     void updateServerInfo();
     126             : 
     127             :     bool inSinkList(const std::string& deviceName);
     128             :     bool inSourceList(const std::string& deviceName);
     129             : 
     130             :     virtual std::vector<std::string> getCaptureDeviceList() const;
     131             :     virtual std::vector<std::string> getPlaybackDeviceList() const;
     132             :     int getAudioDeviceIndex(const std::string& descr, AudioDeviceType type) const;
     133             :     int getAudioDeviceIndexByName(const std::string& name, AudioDeviceType type) const;
     134             : 
     135             :     std::string getAudioDeviceName(int index, AudioDeviceType type) const;
     136             : 
     137             :     virtual void startStream(AudioDeviceType stream);
     138             :     virtual void startCaptureStream(const std::string& id) override;
     139             :     virtual void stopCaptureStream(const std::string& id) override;
     140             :     virtual void stopStream(AudioDeviceType stream = AudioDeviceType::ALL);
     141             : 
     142             : private:
     143             :     static void context_state_callback(pa_context* c, void* user_data);
     144             :     static void context_changed_callback(pa_context* c, pa_subscription_event_type_t t, uint32_t idx, void* userdata);
     145             :     void contextStateChanged(pa_context* c);
     146             :     void contextChanged(pa_context*, pa_subscription_event_type_t, uint32_t idx);
     147             : 
     148             :     static void source_input_info_callback(pa_context* c, const pa_source_info* i, int eol, void* userdata);
     149             :     static void sink_input_info_callback(pa_context* c, const pa_sink_info* i, int eol, void* userdata);
     150             :     static void server_info_callback(pa_context*, const pa_server_info* i, void* userdata);
     151             : 
     152             :     virtual void updatePreference(AudioPreference& pref, int index, AudioDeviceType type);
     153             : 
     154             :     virtual int getIndexCapture() const;
     155             :     virtual int getIndexPlayback() const;
     156             :     virtual int getIndexRingtone() const;
     157             : 
     158             :     void waitForDevices();
     159             :     void waitForDeviceList();
     160             : 
     161             :     std::string getPreferredPlaybackDevice() const;
     162             :     std::string getPreferredRingtoneDevice() const;
     163             :     std::string getPreferredCaptureDevice() const;
     164             : 
     165             :     NON_COPYABLE(PulseLayer);
     166             : 
     167             :     /**
     168             :      * Create the audio stream
     169             :      */
     170             :     void createStream(std::unique_ptr<AudioStream>& stream,
     171             :                       AudioDeviceType type,
     172             :                       const PaDeviceInfos& dev_infos,
     173             :                       bool ec,
     174             :                       std::function<void(size_t)>&& onData);
     175             : 
     176           0 :     std::unique_ptr<AudioStream>& getStream(AudioDeviceType type)
     177             :     {
     178           0 :         if (type == AudioDeviceType::PLAYBACK)
     179           0 :             return playback_;
     180           0 :         else if (type == AudioDeviceType::RINGTONE)
     181           0 :             return ringtone_;
     182           0 :         else if (type == AudioDeviceType::CAPTURE)
     183           0 :             return record_;
     184             :         else
     185           0 :             return playback_;
     186             :     }
     187             : 
     188             :     /**
     189             :      * Close the connection with the local pulseaudio server
     190             :      */
     191             :     void disconnectAudioStream();
     192             :     void onStreamReady();
     193             : 
     194             :     /**
     195             :      * Returns a pointer to the PaEndpointInfos with the given name in sourceList_, or nullptr if
     196             :      * not found.
     197             :      */
     198             :     const PaDeviceInfos* getDeviceInfos(const std::vector<PaDeviceInfos>&, const std::string& name) const;
     199             : 
     200             :     std::atomic_uint pendingStreams {0};
     201             : 
     202             :     /**
     203             :      * A stream object to handle the pulseaudio playback stream
     204             :      */
     205             :     std::unique_ptr<AudioStream> playback_;
     206             : 
     207             :     /**
     208             :      * A stream object to handle the pulseaudio capture stream
     209             :      */
     210             :     std::unique_ptr<AudioStream> record_;
     211             : 
     212             :     /**
     213             :      * A special stream object to handle specific playback stream for ringtone
     214             :      */
     215             :     std::unique_ptr<AudioStream> ringtone_;
     216             : 
     217             :     /**
     218             :      * A class that implements methods to capture desktop audio
     219             :      */
     220             :     PulseLoopbackCapture loopbackCapture_;
     221             : 
     222             :     /**
     223             :      * Contains the list of playback devices
     224             :      */
     225             :     std::vector<PaDeviceInfos> sinkList_ {};
     226             : 
     227             :     /**
     228             :      * Contains the list of capture devices
     229             :      */
     230             :     std::vector<PaDeviceInfos> sourceList_ {};
     231             : 
     232             :     /** PulseAudio server defaults */
     233             :     AudioFormat defaultAudioFormat_ {AudioFormat::MONO()};
     234             :     std::string defaultSink_ {};
     235             :     std::string defaultSource_ {};
     236             : 
     237             :     /** PulseAudio context and asynchronous loop */
     238             :     pa_context* context_ {nullptr};
     239             :     std::unique_ptr<pa_threaded_mainloop, decltype(pa_threaded_mainloop_free)&> mainloop_;
     240             :     bool enumeratingSinks_ {false};
     241             :     bool enumeratingSources_ {false};
     242             :     bool gettingServerInfo_ {false};
     243             :     std::atomic_bool waitingDeviceList_ {false};
     244             :     std::mutex readyMtx_ {};
     245             :     std::condition_variable readyCv_ {};
     246             :     std::thread streamStarter_ {};
     247             : 
     248             :     AudioPreference& preference_;
     249             : 
     250             :     pa_operation* subscribeOp_ {nullptr};
     251             :     friend class AudioLayerTest;
     252             : };
     253             : 
     254             : } // namespace jami

Generated by: LCOV version 1.14