1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PA_ADAPTER_MANAGER_H
17 #define PA_ADAPTER_MANAGER_H
18 
19 #include <map>
20 #include <mutex>
21 #include <pulse/pulseaudio.h>
22 #include <pulse/thread-mainloop.h>
23 #include "audio_timer.h"
24 #include "i_stream_manager.h"
25 #include "audio_effect.h"
26 
27 namespace OHOS {
28 namespace AudioStandard {
29 
30 static std::map<uint8_t, AudioChannelLayout> defaultChCountToLayoutMap = {
31     {1, CH_LAYOUT_MONO}, {2, CH_LAYOUT_STEREO}, {3, CH_LAYOUT_SURROUND},
32     {4, CH_LAYOUT_2POINT0POINT2}, {5, CH_LAYOUT_5POINT0_BACK}, {6, CH_LAYOUT_5POINT1},
33     {7, CH_LAYOUT_6POINT1_BACK}, {8, CH_LAYOUT_5POINT1POINT2}, {9, CH_LAYOUT_HOA_ORDER2_ACN_N3D},
34     {10, CH_LAYOUT_7POINT1POINT2}, {12, CH_LAYOUT_7POINT1POINT4}, {14, CH_LAYOUT_9POINT1POINT4},
35     {16, CH_LAYOUT_9POINT1POINT6}
36 };
37 
38 static std::map<AudioChannelSet, pa_channel_position> chSetToPaPositionMap = {
39     {FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {FRONT_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT},
40     {FRONT_CENTER, PA_CHANNEL_POSITION_FRONT_CENTER}, {LOW_FREQUENCY, PA_CHANNEL_POSITION_LFE},
41     {SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_LEFT}, {SIDE_RIGHT, PA_CHANNEL_POSITION_SIDE_RIGHT},
42     {BACK_LEFT, PA_CHANNEL_POSITION_REAR_LEFT}, {BACK_RIGHT, PA_CHANNEL_POSITION_REAR_RIGHT},
43     {FRONT_LEFT_OF_CENTER, PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER},
44     {FRONT_RIGHT_OF_CENTER, PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER},
45     {BACK_CENTER, PA_CHANNEL_POSITION_REAR_CENTER}, {TOP_CENTER, PA_CHANNEL_POSITION_TOP_CENTER},
46     {TOP_FRONT_LEFT, PA_CHANNEL_POSITION_TOP_FRONT_LEFT}, {TOP_FRONT_CENTER, PA_CHANNEL_POSITION_TOP_FRONT_CENTER},
47     {TOP_FRONT_RIGHT, PA_CHANNEL_POSITION_TOP_FRONT_RIGHT}, {TOP_BACK_LEFT, PA_CHANNEL_POSITION_TOP_REAR_LEFT},
48     {TOP_BACK_CENTER, PA_CHANNEL_POSITION_TOP_REAR_CENTER}, {TOP_BACK_RIGHT, PA_CHANNEL_POSITION_TOP_REAR_RIGHT},
49     /** Channel layout positions below do not have precise mapped pulseaudio positions */
50     {STEREO_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {STEREO_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT},
51     {WIDE_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {WIDE_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT},
52     {SURROUND_DIRECT_LEFT, PA_CHANNEL_POSITION_SIDE_LEFT}, {SURROUND_DIRECT_RIGHT, PA_CHANNEL_POSITION_SIDE_LEFT},
53     {BOTTOM_FRONT_CENTER, PA_CHANNEL_POSITION_FRONT_CENTER},
54     {BOTTOM_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {BOTTOM_FRONT_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT},
55     {TOP_SIDE_LEFT, PA_CHANNEL_POSITION_TOP_REAR_LEFT}, {TOP_SIDE_RIGHT, PA_CHANNEL_POSITION_TOP_REAR_RIGHT},
56     {LOW_FREQUENCY_2, PA_CHANNEL_POSITION_LFE},
57 };
58 
59 class PaAdapterManager : public IStreamManager {
60 public:
61     PaAdapterManager(ManagerType type);
62 
63     int32_t CreateRender(AudioProcessConfig processConfig, std::shared_ptr<IRendererStream> &stream) override;
64     int32_t ReleaseRender(uint32_t streamIndex_) override;
65     int32_t StartRender(uint32_t streamIndex) override;
66     int32_t StopRender(uint32_t streamIndex) override;
67     int32_t PauseRender(uint32_t streamIndex) override;
68     int32_t GetStreamCount() const noexcept override;
69     int32_t TriggerStartIfNecessary() override;
70     int32_t CreateCapturer(AudioProcessConfig processConfig, std::shared_ptr<ICapturerStream> &stream) override;
71     int32_t ReleaseCapturer(uint32_t streamIndex_) override;
72     uint32_t ConvertChLayoutToPaChMap(const uint64_t &channelLayout, pa_channel_map &paMap);
73 
74 private:
75     // audio channel index
76     static const uint8_t CHANNEL1_IDX = 0;
77     static const uint8_t CHANNEL2_IDX = 1;
78     static const uint8_t CHANNEL3_IDX = 2;
79     static const uint8_t CHANNEL4_IDX = 3;
80     static const uint8_t CHANNEL5_IDX = 4;
81     static const uint8_t CHANNEL6_IDX = 5;
82     static const uint8_t CHANNEL7_IDX = 6;
83     static const uint8_t CHANNEL8_IDX = 7;
84 
85     int32_t ResetPaContext();
86     int32_t InitPaContext();
87     int32_t HandleMainLoopStart();
88     pa_stream *InitPaStream(AudioProcessConfig processConfig, uint32_t sessionId, bool isRecording);
89     bool IsEffectNone(StreamUsage streamUsage);
90     int32_t SetPaProplist(pa_proplist *propList, pa_channel_map &map, AudioProcessConfig &processConfig,
91         const std::string &streamName, uint32_t sessionId);
92     std::shared_ptr<IRendererStream> CreateRendererStream(AudioProcessConfig processConfig, pa_stream *paStream);
93     std::shared_ptr<ICapturerStream> CreateCapturerStream(AudioProcessConfig processConfig, pa_stream *paStream);
94     int32_t ConnectStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
95         SourceType source, const std::string &deviceName = "");
96     void ReleasePaStream(pa_stream *paStream);
97     int32_t ConnectRendererStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec);
98     int32_t ConnectCapturerStreamToPA(pa_stream *paStream, pa_sample_spec sampleSpec,
99         SourceType source, const std::string &deviceName);
100 
101     int32_t SetStreamAudioEnhanceMode(pa_stream *paStream, AudioEffectMode audioEnhanceMode);
102     const std::string GetEnhanceModeName(AudioEffectMode audioEnhanceMode);
103     const std::string GetEnhanceSceneName(SourceType sourceType);
104 
105     // Callbacks to be implemented
106     static void PAStreamStateCb(pa_stream *stream, void *userdata);
107     static void PAContextStateCb(pa_context *context, void *userdata);
108 
109     static void PAStreamUpdateStreamIndexSuccessCb(pa_stream *stream, int32_t success, void *userdata);
110 
111     const std::string GetStreamName(AudioStreamType audioType);
112     pa_sample_spec ConvertToPAAudioParams(AudioProcessConfig processConfig);
113 
114     int32_t GetDeviceNameForConnect(AudioProcessConfig processConfig,
115         uint32_t sessionId, std::string &deviceName);
116 
117     void SetHighResolution(pa_proplist *propList, AudioProcessConfig &processConfig, uint32_t sessionId);
118     bool CheckHighResolution(const AudioProcessConfig &processConfig);
119     void SetRecordProplist(pa_proplist *propList, AudioProcessConfig &processConfig);
120 
121     std::mutex paElementsMutex_;
122     pa_threaded_mainloop *mainLoop_;
123     pa_mainloop_api *api_;
124     pa_context *context_;
125     std::mutex streamMapMutex_;
126     std::map<int32_t, std::shared_ptr<IRendererStream>> rendererStreamMap_;
127     std::map<int32_t, std::shared_ptr<ICapturerStream>> capturerStreamMap_;
128     bool isContextConnected_;
129     bool isMainLoopStarted_;
130     ManagerType managerType_ = PLAYBACK;
131     bool waitConnect_ = true;
132     AudioEffectMode enhanceMode_ = EFFECT_NONE;
133     uint32_t highResolutionIndex_ = 0;
134     bool isHighResolutionExist_ = false;
135 };
136 } // namespace AudioStandard
137 } // namespace OHOS
138 #endif // PA_ADAPTER_MANAGER_H
139