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-04-25 08:05:53 Functions: 0 8 0.0 %

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

Generated by: LCOV version 1.14