LCOV - code coverage report
Current view: top level - src/media/audio/pulseaudio - pulselayer.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 32 0.0 %
Date: 2024-12-21 08:56:24 Functions: 0 8 0.0 %

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

Generated by: LCOV version 1.14