LCOV - code coverage report
Current view: top level - src/media/audio/pulseaudio - pulselayer.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 0.0 % 32 0
Test Date: 2026-06-13 09:18:46 Functions: 0.0 % 8 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 2.0-1