diff --git a/BUILD.gn b/BUILD.gn
old mode 100755
new mode 100644
index f39feefe86afe40526820ef0db5e632249365a58..5d33a819a6b886fdce647fd2d05bb15d007b064d
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -16,6 +16,8 @@ import("//build/ohos.gni")
group("audio_packages") {
public_deps = [
"interfaces/innerkits/native/audiocapturer:audio_capturer",
+ "interfaces/innerkits/native/audiorenderer:audio_renderer",
+ "interfaces/innerkits/native/audiorecorder:audio_recorder",
"services:audio_service",
"interfaces/innerkits/native/audiomanager:audio_client",
]
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
index 80fd4977b588979a7de87b31c76caa4d14ae75e6..660d5e8b010d540a1e64b8bcfe677c7134438f61
--- a/README.md
+++ b/README.md
@@ -1,22 +1,23 @@
# Audio
-- [Introduction](#section119mcpsimp)
- - [Basic Concepts](#section122mcpsimp)
-
-- [Directory Structure](#section179mcpsimp)
-- [Usage Guidelines](#section112738505318)
-- [Repositories Involved](#section340mcpsimp)
-
-## Introduction
-
-The **audio\_standard** repository supports the development of audio services. You can use this module to manage audio volume.
+ - [Introduction](#introduction)
+ - [Basic Concepts](#basic-concepts)
+ - [Directory Structure](#directory-structure)
+ - [Usage Guidelines](#usage-guidelines)
+ - [Audio Playback](#audio-playback)
+ - [Audio Recording](#audio-recording)
+ - [Audio Management](#audio-management)
+ - [Repositories Involved](#repositories-involved)
+
+## Introduction
+The **audio\_standard** repository is used to implement audio-related features, including audio playback, recording, volume management and device management.
**Figure 1** Position in the subsystem architecture

-### Basic Concepts
+### Basic Concepts
- **Sampling**
@@ -24,7 +25,7 @@ Sampling is a process to obtain discrete-time signals by extracting samples from
- **Sampling rate**
-Sampling rate is the number of samples extracted from a continuous signal per second to form a discrete signal. It is measured in Hz. Generally, human hearing range is from 20 Hz to 20 kHz. Common audio sampling rates include 8 kHz, 11.025 kHz, 22.05 kHz, 16 kHz, 37.8 kHz, 44.1 kHz, 48 kHz, 96 kHz, and 192 kHz.
+Sampling rate is the number of samples extracted from a continuous signal per second to form a discrete signal. It is measured in Hz. Generally, human hearing range is from 20 Hz to 20 kHz. Common audio sampling rates include 8 kHz, 11.025 kHz, 22.05 kHz, 16 kHz, 37.8 kHz, 44.1 kHz, 48 kHz, and 96 kHz.
- **Channel**
@@ -38,58 +39,117 @@ Audio data is in stream form. For the convenience of audio algorithm processing
Pulse code modulation \(PCM\) is a method used to digitally represent sampled analog signals. It converts continuous-time analog signals into discrete-time digital signal samples.
-## Directory Structure
+## Directory Structure
The structure of the repository directory is as follows:
```
/foundation/multimedia/audio_standard # Audio code
├── frameworks # Framework code
-│ ├── innerkitsimpl # Internal interfaces implementation
-│ └── kitsimpl # External interfaces implementation
-├── interfaces # Interfaces code
-│ ├── innerkits # Internal interfaces
-│ └── kits # External interfaces
+│ ├── innerkitsimpl # Internal Native API Implementation.
+| | Pulseaudio, libsndfile build configuration and pulseaudio-hdi modules
+│ └── kitsimpl # External JS API Implementation
+├── interfaces # Interfaces
+│ ├── innerkits # Internal Native APIs
+│ └── kits # External JS APIs
├── sa_profile # Service configuration profile
├── services # Service code
├── LICENSE # License file
└── ohos.build # Build file
```
-## Usage Guidelines
-
-1. Obtain an **AudioManager** instance.
+## Usage Guidelines
+### Audio Playback
+You can use APIs provided in this repository to convert audio data into audible analog signals, play the audio signals using output devices, and manage playback tasks. The following steps describe how to use **AudioRenderer** to develop the audio playback function:
+1. Use **Create** API with required stream type to get **AudioRenderer** instance.
+ ```
+ AudioStreamType streamType = STREAM_MUSIC; // example stream type
+ std::unique_ptr audioRenderer = AudioRenderer::Create(streamType);
+ ```
+2. (Optional) Static APIs **GetSupportedFormats**(), **GetSupportedChannels**(), **GetSupportedEncodingTypes**(), **GetSupportedSamplingRates**() can be used to get the supported values of the params.
+3. To Prepare the device, call **SetParams** on the instance.
+ ```
+ AudioRendererParams rendererParams;
+ rendererParams.sampleFormat = SAMPLE_S16LE;
+ rendererParams.sampleRate = SAMPLE_RATE_44100;
+ rendererParams.channelCount = STEREO;
+ rendererParams.encodingType = ENCODING_PCM;
+ audioRenderer->SetParams(rendererParams);
+ ```
+4. (Optional) use audioRenderer->**GetParams**(rendererParams) to validate SetParams
+5. Call **audioRenderer->Start()** function on the AudioRenderer instance to start the playback task.
+6. Get the buffer length to be written, using **GetBufferSize** API .
+ ```
+ audioRenderer->GetBufferSize(bufferLen);
+ ```
+7. Read the audio data to be played from the source(for example, an audio file) and transfer it into the bytes stream. Call the **Write** function repeatedly to write the render data.
```
- const audioManager = audio.getAudioManager();
+ bytesToWrite = fread(buffer, 1, bufferLen, wavFile);
+ while ((bytesWritten < bytesToWrite) && ((bytesToWrite - bytesWritten) > minBytes)) {
+ bytesWritten += audioRenderer->Write(buffer + bytesWritten, bytesToWrite - bytesWritten);
+ if (bytesWritten < 0)
+ break;
+ }
```
+8. Call audioRenderer->**Drain**() to drain the playback stream.
-2. Obtain the audio stream volume.
+9. Call audioRenderer->**Stop()** function to Stop rendering.
+10. After the playback task is complete, call the audioRenderer->**Release**() function on the AudioRenderer instance to release the resources.
+Provided the basic playback usecase above. Please refer [**audio_renderer.h**](https://gitee.com/openharmony/multimedia_audio_standard/blob/master/interfaces/innerkits/native/audiorenderer/include/audio_renderer.h) and [**audio_info.h**](https://gitee.com/openharmony/multimedia_audio_standard/blob/master/interfaces/innerkits/native/audiocommon/include/audio_info.h) for more APIs.
+
+
+### Audio Recording
+You can use the APIs provided in this repository for your application to record voices using input devices, convert the voices into audio data, and manage recording tasks. The following steps describe how to use AudioReorder to develop the audio recording function:
+
+1. Use **Create** API with required stream type to get **AudioRecorder** instance.
```
- audioManager.getVolume(audio.AudioVolumeType.MEDIA, (err, value) => {
- if (err) {
- console.error(`failed to get volume ${err.message}`);
- return;
- }
- console.log(`Media getVolume successful callback`);
- });
+ AudioStreamType streamType = STREAM_MUSIC;
+ std::unique_ptr audioRecorder = AudioRecorder::Create(streamType);
```
+2. (Optional) Static APIs **GetSupportedFormats**(), **GetSupportedChannels**(), **GetSupportedEncodingTypes**(), **GetSupportedSamplingRates()** can be used to get the supported values of the params.
+3. To Prepare the device, call **SetParams** on the instance.
+ ```
+ AudioRecorderParams recorderParams;
+ recorderParams.sampleFormat = SAMPLE_S16LE;
+ recorderParams.sampleRate = SAMPLE_RATE_44100;
+ recorderParams.channelCount = STEREO;
+ recorderParams.encodingType = ENCODING_PCM;
-3. Set the audio stream volume.
-
+ audioRecorder->SetParams(recorderParams);
```
- audioManager.setVolume(audio.AudioVolumeType.MEDIA, 30, (err)=>{
- if (err) {
- console.error(`failed to set volume ${err.message}`);
- return;
- }
- console.log(`Media setVolume successful callback`);
- })
+4. (Optional) use audioRecorder->**GetParams**(recorderParams) to validate SetParams()
+5. Call audioRenderer->**Start**() function on the AudioRecorder instance to start the recording task.
+6. Get the buffer length to be read, using **GetBufferSize** API.
```
+ audioRecorder->GetBufferSize(bufferLen);
+ ```
+7. Read the recorded audio data and convert it to a byte stream. Call the read function repeatedly to read data untill you want to stop recording
+ ```
+ bytesRead = audioRecorder->Read(*buffer, bufferLen, isBlocking); // set isBlocking = true/false for blocking/non-blocking read
+ while (numBuffersToRecord) {
+ bytesRead = audioRecorder->Read(*buffer, bufferLen, isBlockingRead);
+ if (bytesRead < 0) {
+ break;
+ } else if (bytesRead > 0) {
+ fwrite(buffer, size, bytesRead, recFile); // example shows writes the recored data into a file
+ numBuffersToRecord--;
+ }
+ }
+ ```
+8. (Optional) Call audioRecorder->**Flush**() to flush the record buffer of this stream.
+9. Call the audioRecorder->**Stop**() function on the AudioRecorder instance to stop the recording.
+10. After the recording task is complete, call the audioRecorder->**Release**() function on the AudioRecorder instance to release resources.
+
+Provided the basic recording usecase above. Please refer [**audio_recorder.h**](https://gitee.com/openharmony/multimedia_audio_standard/blob/master/interfaces/innerkits/native/audiorecorder/include/audio_recorder.h) and [**audio_info.h**](https://gitee.com/openharmony/multimedia_audio_standard/blob/master/interfaces/innerkits/native/audiocommon/include/audio_info.h) for more APIs.
+### Audio Management
-## Repositories Involved
+JS apps can use the APIs provided by audio manager to control the volume and the device.\
+Please refer [**audio-management.md**](https://gitee.com/openharmony/docs/blob/master/en/application-dev/js-reference/audio-management.md) for JS usage of audio volume and device management.
-multimedia\_audio\_standard
+## Repositories Involved
+[multimedia\_audio\_standard](https://gitee.com/openharmony/multimedia_audio_standard)\
+[multimedia\_media\_standard](https://gitee.com/openharmony/multimedia_media_standard)
diff --git a/frameworks/innerkitsimpl/audiocapturer/BUILD.gn b/frameworks/innerkitsimpl/audiocapturer/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..2b73a0d4119bcad577a686b9174ce74c8f9c3b73
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiocapturer/BUILD.gn
@@ -0,0 +1,57 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+import("//drivers/adapter/uhdf2/uhdf.gni")
+
+ohos_shared_library("audio_capturer_source") {
+ install_enable = true
+ sources = [
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_source.cpp",
+ ]
+ cflags = [ "-fPIC" ]
+ cflags += [ "-Wall" ]
+ cflags_cc = cflags
+
+ include_dirs = [
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiocapturer/include",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/common/include",
+ "//foundation/multimedia/media_standard/interfaces/innerkits/native/media/include",
+ "//utils/native/base/include",
+ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
+ "//drivers/peripheral/audio/interfaces/include",
+ "//third_party/bounds_checking_function/include",
+ ]
+ public_configs = [ ":audio_external_library_config" ]
+
+ deps = [
+ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",
+ "//third_party/bounds_checking_function:libsec_static",
+ "$hdf_uhdf_path/config:libhdf_hcs",
+ "$hdf_uhdf_path/hcs:hdf_default.hcb",
+ "$hdf_uhdf_path/hdi:libhdi",
+ "$hdf_uhdf_path/host:hdf_devhost",
+ "$hdf_uhdf_path/host:libhdf_host",
+ "$hdf_uhdf_path/ipc:libhdf_ipc_adapter",
+ "$hdf_uhdf_path/manager:hdf_devmgr",
+ "$hdf_uhdf_path/manager:hdf_devmgr.rc",
+ "$hdf_uhdf_path/osal:libhdf_utils",
+ ]
+
+ part_name = "multimedia_audio_standard"
+ subsystem_name = "multimedia"
+}
+
+config("audio_external_library_config") {
+ include_dirs = ["//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/common/include"]
+}
diff --git a/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source.h b/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2e675cdea3ac1a3a07fdab4eddccd87bc107794
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_CAPTURER_SOURCE_H
+#define AUDIO_CAPTURER_SOURCE_H
+
+#include "audio_manager.h"
+
+#include
+
+namespace OHOS {
+namespace AudioStandard {
+#define AUDIO_CHANNELCOUNT 2
+#define AUDIO_SAMPLE_RATE_48K 48000
+#define DEEP_BUFFER_CAPTURE_PERIOD_SIZE 4096
+#define INT_32_MAX 0x7fffffff
+#define PERIOD_SIZE 1024
+#define PATH_LEN 256
+#define AUDIO_BUFF_SIZE (16 * 1024)
+#define PCM_8_BIT 8
+#define PCM_16_BIT 16
+
+typedef struct {
+ AudioFormat format;
+ uint32_t sampleFmt;
+ uint32_t sampleRate;
+ uint32_t channel;
+ float volume;
+} AudioSourceAttr;
+
+class AudioCapturerSource {
+public:
+ int32_t Init(AudioSourceAttr &atrr);
+ void DeInit(void);
+
+ int32_t Start(void);
+ int32_t Stop(void);
+ int32_t Flush(void);
+ int32_t Reset(void);
+ int32_t Pause(void);
+ int32_t Resume(void);
+ int32_t CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes);
+ int32_t SetVolume(float left, float right);
+ int32_t GetVolume(float &left, float &right);
+ int32_t SetMute(bool isMute);
+ int32_t GetMute(bool &isMute);
+
+ static AudioCapturerSource* GetInstance(void);
+ bool capturerInited_;
+
+private:
+ const int32_t HALF_FACTOR = 2;
+ const int32_t MAX_AUDIO_ADAPTER_NUM = 3;
+ const float MAX_VOLUME_LEVEL = 15.0f;
+
+ AudioSourceAttr attr_;
+ bool started_;
+ bool paused_;
+ float leftVolume_;
+ float rightVolume_;
+
+ struct AudioManager *audioManager_;
+ struct AudioAdapter *audioAdapter_;
+ struct AudioCapture *audioCapture_;
+
+ void *handle_;
+
+ int32_t CreateCapture(struct AudioPort &capturePort);
+ int32_t InitAudioManager();
+
+#ifdef CAPTURE_DUMP
+ FILE *pfd;
+#endif
+
+ AudioCapturerSource();
+ ~AudioCapturerSource();
+};
+} // namespace AudioStandard
+} // namespace OHOS
+#endif // AUDIO_CAPTURER_SOURCE_H
diff --git a/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source_intf.h b/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source_intf.h
new file mode 100644
index 0000000000000000000000000000000000000000..a7e89c3617bdfcf56f1cca7bbd42e81b66844342
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiocapturer/include/audio_capturer_source_intf.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_CAPTURER_SINK_INTF_H
+#define AUDIO_CAPTURER_SINK_INTF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ enum AudioFormat format;
+ uint32_t sampleFmt;
+ uint32_t sampleRate;
+ uint32_t channel;
+ float volume;
+} AudioSourceAttr;
+
+int32_t AudioCapturerSourceInit(AudioSourceAttr *);
+void AudioCapturerSourceDeInit(void);
+int32_t AudioCapturerSourceStart(void);
+int32_t AudioCapturerSourceStop(void);
+int32_t AudioCapturerSourceFrame(char *, uint64_t, uint64_t *);
+int32_t AudioCapturerSourceSetVolume(float, float);
+int32_t AudioCapturerSourceGetVolume(float *left, float *right);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // AUDIO_CAPTURER_SINK_INTF_H
\ No newline at end of file
diff --git a/frameworks/innerkitsimpl/audiocapturer/include/audio_encoder.h b/frameworks/innerkitsimpl/audiocapturer/include/audio_encoder.h
index 68afee6392b2d59950d96a2eaa697b186c71a5ab..4c0a2b832eb00bb8d0e4c77e433c1e844f406e00 100755
--- a/frameworks/innerkitsimpl/audiocapturer/include/audio_encoder.h
+++ b/frameworks/innerkitsimpl/audiocapturer/include/audio_encoder.h
@@ -21,7 +21,7 @@
#include
#include
#include
-#include "media_errors.h"
+#include "audio_errors.h"
#include "media_info.h"
#include "format.h"
#include "codec_interface.h"
diff --git a/frameworks/innerkitsimpl/audiocapturer/include/audio_source.h b/frameworks/innerkitsimpl/audiocapturer/include/audio_source.h
index 1b03fa5a5a2eb0b1b75ba26f13e216607bdd9d6c..a540a0542be5b9ab715400ef2b8d6cde2d2c690d 100755
--- a/frameworks/innerkitsimpl/audiocapturer/include/audio_source.h
+++ b/frameworks/innerkitsimpl/audiocapturer/include/audio_source.h
@@ -22,7 +22,7 @@
#include
#include
-#include "media_errors.h"
+#include "audio_errors.h"
#include "media_info.h"
#include "format.h"
#include "audio_manager.h"
diff --git a/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_impl.cpp b/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_impl.cpp
index 902047351b389feb6c2b4493e9008b70f2f79d50..7035b166b9477c9190d912f8ae2f64c6938681b1 100755
--- a/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_impl.cpp
+++ b/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_impl.cpp
@@ -23,6 +23,7 @@
namespace OHOS {
namespace Audio {
using namespace OHOS::Media;
+using namespace OHOS::AudioStandard;
const unsigned long long TIME_CONVERSION_US_S = 1000000ULL; /* us to s */
const unsigned long long TIME_CONVERSION_NS_US = 1000ULL; /* ns to us */
diff --git a/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_source.cpp b/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_source.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..915f97e9e0a914dee32620010734409fed65b025
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiocapturer/src/audio_capturer_source.cpp
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+
+#include "audio_capturer_source.h"
+#include "audio_errors.h"
+#include "media_log.h"
+
+namespace OHOS {
+namespace AudioStandard {
+#ifdef CAPTURE_DUMP
+const char *g_audioOutTestFilePath = "/data/local/tmp/audio_capture.pcm";
+#endif // CAPTURE_DUMP
+
+AudioCapturerSource::AudioCapturerSource()
+ : capturerInited_(false), started_(false), paused_(false),
+ leftVolume_(MAX_VOLUME_LEVEL), rightVolume_(MAX_VOLUME_LEVEL),
+ audioManager_(nullptr), audioAdapter_(nullptr), audioCapture_(nullptr)
+{
+ attr_ = {};
+#ifdef CAPTURE_DUMP
+ pfd = nullptr;
+#endif // CAPTURE_DUMP
+}
+
+AudioCapturerSource::~AudioCapturerSource()
+{
+ DeInit();
+}
+
+AudioCapturerSource* AudioCapturerSource::GetInstance()
+{
+ static AudioCapturerSource audioCapturer_;
+ return &audioCapturer_;
+}
+
+void AudioCapturerSource::DeInit()
+{
+ started_ = false;
+ capturerInited_ = false;
+
+ if ((audioCapture_ != nullptr) && (audioAdapter_ != nullptr)) {
+ audioAdapter_->DestroyCapture(audioAdapter_, audioCapture_);
+ }
+ audioCapture_ = nullptr;
+
+ if ((audioManager_ != nullptr) && (audioAdapter_ != nullptr)) {
+ audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
+ }
+ audioAdapter_ = nullptr;
+ audioManager_ = nullptr;
+ dlclose(handle_);
+#ifdef CAPTURE_DUMP
+ if (pfd) {
+ fclose(pfd);
+ pfd = nullptr;
+ }
+#endif // CAPTURE_DUMP
+}
+
+int32_t InitAttrsCapture(struct AudioSampleAttributes &attrs)
+{
+ /* Initialization of audio parameters for playback */
+ attrs.format = AUDIO_FORMAT_PCM_16_BIT;
+ attrs.channelCount = AUDIO_CHANNELCOUNT;
+ attrs.sampleRate = AUDIO_SAMPLE_RATE_48K;
+ attrs.interleaved = 0;
+ attrs.type = AUDIO_IN_MEDIA;
+ attrs.period = DEEP_BUFFER_CAPTURE_PERIOD_SIZE;
+ attrs.frameSize = PCM_16_BIT * attrs.channelCount / PCM_8_BIT;
+ attrs.isBigEndian = false;
+ attrs.isSignedData = true;
+ attrs.startThreshold = DEEP_BUFFER_CAPTURE_PERIOD_SIZE / (attrs.frameSize);
+ attrs.stopThreshold = INT_32_MAX;
+ /* 16 * 1024 */
+ attrs.silenceThreshold = AUDIO_BUFF_SIZE;
+
+ return SUCCESS;
+}
+
+int32_t SwitchAdapterCapture(struct AudioAdapterDescriptor *descs, const char *adapterNameCase,
+ enum AudioPortDirection portFlag, struct AudioPort *capturePort, const int32_t size)
+{
+ for (int32_t index = 0; index < size; index++) {
+ struct AudioAdapterDescriptor *desc = &descs[index];
+ if (desc == nullptr) {
+ MEDIA_ERR_LOG("SwitchAdapter Fail AudioAdapterDescriptor desc NULL");
+ return ERR_INVALID_INDEX; // note: return invalid index not invalid handle
+ }
+ if (!strcmp(desc->adapterName, adapterNameCase)) {
+ for (uint32_t port = 0; ((desc != NULL) && (port < desc->portNum)); port++) {
+ // Only find out the port of out in the sound card
+ if (desc->ports[port].dir == portFlag) {
+ *capturePort = desc->ports[port];
+ return index;
+ }
+ }
+ }
+ }
+ MEDIA_ERR_LOG("SwitchAdapter Fail");
+
+ return ERR_INVALID_INDEX;
+}
+
+int32_t AudioCapturerSource::InitAudioManager()
+{
+ char resolvedPath[100] = "/system/lib/libhdi_audio.z.so";
+ struct AudioManager *(*getAudioManager)() = nullptr;
+
+ handle_ = dlopen(resolvedPath, 1);
+ if (handle_ == nullptr) {
+ MEDIA_ERR_LOG("Open Capturer so Fail");
+ return ERR_INVALID_HANDLE;
+ }
+
+ getAudioManager = (struct AudioManager *(*)())(dlsym(handle_, "GetAudioManagerFuncs"));
+ audioManager_ = getAudioManager();
+ if (audioManager_ == nullptr) {
+ return ERR_INVALID_HANDLE;
+ }
+
+ return 0;
+}
+
+int32_t AudioCapturerSource::CreateCapture(struct AudioPort &capturePort)
+{
+ // Initialization port information, can fill through mode and other parameters
+ int32_t ret = audioAdapter_->InitAllPorts(audioAdapter_);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("InitAllPorts failed");
+ return ERR_DEVICE_INIT;
+ }
+
+ struct AudioSampleAttributes param;
+ // User needs to set
+ InitAttrsCapture(param);
+ param.sampleRate = attr_.sampleRate;
+ param.format = attr_.format;
+ param.channelCount = attr_.channel;
+
+ struct AudioDeviceDescriptor deviceDesc;
+ deviceDesc.portId = capturePort.portId;
+ deviceDesc.pins = PIN_IN_MIC;
+ deviceDesc.desc = nullptr;
+
+ ret = audioAdapter_->CreateCapture(audioAdapter_, &deviceDesc, ¶m, &audioCapture_);
+ if (audioCapture_ == nullptr || ret < 0) {
+ MEDIA_ERR_LOG("Create capture failed");
+ return ERR_NOT_STARTED;
+ }
+
+ capturerInited_ = true;
+
+ return 0;
+}
+
+int32_t AudioCapturerSource::Init(AudioSourceAttr &attr)
+{
+ attr_ = attr;
+ int32_t ret;
+ int32_t index;
+ int32_t size = 0;
+ struct AudioAdapterDescriptor *descs = nullptr;
+ struct AudioPort capturePort;
+
+ if (InitAudioManager() != 0) {
+ MEDIA_ERR_LOG("Init audio manager Fail");
+ return ERR_INVALID_HANDLE;
+ }
+
+ ret = audioManager_->GetAllAdapters(audioManager_, &descs, &size);
+ // adapters is 0~3
+ if (size > MAX_AUDIO_ADAPTER_NUM || size == 0 || descs == nullptr || ret < 0) {
+ MEDIA_ERR_LOG("Get adapters Fail");
+ return ERR_NOT_STARTED;
+ }
+
+ // Get qualified sound card and port
+ char adapterNameCase[PATH_LEN] = "internal";
+ index = SwitchAdapterCapture(descs, adapterNameCase, PORT_IN, &capturePort, size);
+ if (index < 0) {
+ MEDIA_ERR_LOG("Switch Adapter Fail");
+ return ERR_NOT_STARTED;
+ }
+
+ struct AudioAdapterDescriptor *desc = &descs[index];
+ if (audioManager_->LoadAdapter(audioManager_, desc, &audioAdapter_) != 0) {
+ MEDIA_ERR_LOG("Load Adapter Fail");
+ return ERR_NOT_STARTED;
+ }
+ if (audioAdapter_ == nullptr) {
+ MEDIA_ERR_LOG("Load audio device failed");
+ return ERR_NOT_STARTED;
+ }
+
+ if (CreateCapture(capturePort) != 0) {
+ MEDIA_ERR_LOG("Create capture failed");
+ return ERR_NOT_STARTED;
+ }
+#ifdef CAPTURE_DUMP
+ pfd = fopen(g_audioOutTestFilePath, "wb+");
+ if (pfd == nullptr) {
+ MEDIA_ERR_LOG("Error opening pcm test file!");
+ }
+#endif // CAPTURE_DUMP
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::CaptureFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
+{
+ int32_t ret;
+ if (audioCapture_ == nullptr) {
+ MEDIA_ERR_LOG("Audio capture Handle is nullptr!");
+ return ERR_INVALID_HANDLE;
+ }
+
+ ret = audioCapture_->CaptureFrame(audioCapture_, frame, requestBytes, &replyBytes);
+ if (ret < 0) {
+ MEDIA_ERR_LOG("Capture Frame Fail");
+ return ERR_READ_FAILED;
+ }
+
+#ifdef CAPTURE_DUMP
+ size_t writeResult = fwrite(frame, replyBytes, 1, pfd);
+ if (writeResult != replyBytes) {
+ MEDIA_ERR_LOG("Failed to write the file.");
+ }
+#endif // CAPTURE_DUMP
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Start(void)
+{
+ int32_t ret;
+ if (!started_ && audioCapture_ != nullptr) {
+ ret = audioCapture_->control.Start((AudioHandle)audioCapture_);
+ if (ret < 0) {
+ return ERR_NOT_STARTED;
+ }
+ started_ = true;
+ audioCapture_->volume.SetVolume(reinterpret_cast(audioCapture_), MAX_VOLUME_LEVEL);
+ }
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::SetVolume(float left, float right)
+{
+ float volume;
+ if (audioCapture_ == nullptr) {
+ MEDIA_ERR_LOG("AudioCapturerSource::SetVolume failed audioCapture_ null");
+ return ERR_INVALID_HANDLE;
+ }
+
+ leftVolume_ = left;
+ rightVolume_ = right;
+ if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
+ volume = rightVolume_;
+ } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
+ volume = leftVolume_;
+ } else {
+ volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
+ }
+
+ audioCapture_->volume.SetVolume(reinterpret_cast(audioCapture_), volume);
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::GetVolume(float &left, float &right)
+{
+ float val = 0.0;
+ audioCapture_->volume.GetVolume((AudioHandle)audioCapture_, &val);
+ left = val;
+ right = val;
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::SetMute(bool isMute)
+{
+ int32_t ret;
+ if (audioCapture_ == nullptr) {
+ MEDIA_ERR_LOG("AudioCapturerSource::SetMute failed audioCapture_ handle is null!");
+ return ERR_INVALID_HANDLE;
+ }
+
+ ret = audioCapture_->volume.SetMute((AudioHandle)audioCapture_, isMute);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("AudioCapturerSource::SetMute failed");
+ return ERR_OPERATION_FAILED;
+ }
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::GetMute(bool &isMute)
+{
+ int32_t ret;
+ if (audioCapture_ == nullptr) {
+ MEDIA_ERR_LOG("AudioCapturerSource::GetMute failed audioCapture_ handle is null!");
+ return ERR_INVALID_HANDLE;
+ }
+
+ ret = audioCapture_->volume.GetMute((AudioHandle)audioCapture_, &isMute);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("AudioCapturerSource::GetMute failed");
+ return ERR_OPERATION_FAILED;
+ }
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Stop(void)
+{
+ int32_t ret;
+ if (started_ && audioCapture_ != nullptr) {
+ ret = audioCapture_->control.Stop(reinterpret_cast(audioCapture_));
+ if (ret < 0) {
+ MEDIA_ERR_LOG("Stop capture Failed");
+ return ERR_OPERATION_FAILED;
+ }
+ }
+ started_ = false;
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Pause(void)
+{
+ int32_t ret;
+ if (started_ && audioCapture_ != nullptr) {
+ ret = audioCapture_->control.Pause(reinterpret_cast(audioCapture_));
+ if (ret != 0) {
+ MEDIA_ERR_LOG("pause capture Failed");
+ return ERR_OPERATION_FAILED;
+ }
+ }
+ paused_ = true;
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Resume(void)
+{
+ int32_t ret;
+ if (paused_ && audioCapture_ != nullptr) {
+ ret = audioCapture_->control.Resume(reinterpret_cast(audioCapture_));
+ if (ret != 0) {
+ MEDIA_ERR_LOG("resume capture Failed");
+ return ERR_OPERATION_FAILED;
+ }
+ }
+ paused_ = false;
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Reset(void)
+{
+ if (started_ && audioCapture_ != nullptr) {
+ audioCapture_->control.Flush(reinterpret_cast(audioCapture_));
+ }
+
+ return SUCCESS;
+}
+
+int32_t AudioCapturerSource::Flush(void)
+{
+ if (started_ && audioCapture_ != nullptr) {
+ audioCapture_->control.Flush(reinterpret_cast(audioCapture_));
+ }
+
+ return SUCCESS;
+}
+} // namespace AudioStandard
+} // namesapce OHOS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+using namespace OHOS::AudioStandard;
+
+AudioCapturerSource* g_audioCaptureSourceInstance = AudioCapturerSource::GetInstance();
+
+int32_t AudioCapturerSourceInit(AudioSourceAttr *attr)
+{
+ int32_t ret;
+
+ if (g_audioCaptureSourceInstance->capturerInited_)
+ return SUCCESS;
+
+ ret = g_audioCaptureSourceInstance->Init(*attr);
+
+ return ret;
+}
+
+void AudioCapturerSourceDeInit()
+{
+ if (g_audioCaptureSourceInstance->capturerInited_)
+ g_audioCaptureSourceInstance->DeInit();
+}
+
+int32_t AudioCapturerSourceStop()
+{
+ int32_t ret;
+
+ if (!g_audioCaptureSourceInstance->capturerInited_)
+ return SUCCESS;
+
+ ret = g_audioCaptureSourceInstance->Stop();
+
+ return ret;
+}
+
+int32_t AudioCapturerSourceStart()
+{
+ int32_t ret;
+
+ if (!g_audioCaptureSourceInstance->capturerInited_) {
+ MEDIA_ERR_LOG("audioCapturer Not Inited! Init the capturer first\n");
+ return ERR_DEVICE_INIT;
+ }
+
+ ret = g_audioCaptureSourceInstance->Start();
+
+ return ret;
+}
+
+int32_t AudioCapturerSourceFrame(char *frame, uint64_t requestBytes, uint64_t &replyBytes)
+{
+ int32_t ret;
+
+ if (!g_audioCaptureSourceInstance->capturerInited_) {
+ MEDIA_ERR_LOG("audioCapturer Not Inited! Init the capturer first\n");
+ return ERR_DEVICE_INIT;
+ }
+
+ ret = g_audioCaptureSourceInstance->CaptureFrame(frame, requestBytes, replyBytes);
+
+ return ret;
+}
+
+int32_t AudioCapturerSourceSetVolume(float left, float right)
+{
+ int32_t ret;
+
+ if (!g_audioCaptureSourceInstance->capturerInited_) {
+ MEDIA_ERR_LOG("audioCapturer Not Inited! Init the capturer first\n");
+ return ERR_DEVICE_INIT;
+ }
+
+ ret = g_audioCaptureSourceInstance->SetVolume(left, right);
+
+ return ret;
+}
+
+int32_t AudioCapturerSourceGetVolume(float *left, float *right)
+{
+ int32_t ret;
+
+ if (!g_audioCaptureSourceInstance->capturerInited_) {
+ MEDIA_ERR_LOG("audioCapturer Not Inited! Init the capturer first\n");
+ return ERR_DEVICE_INIT;
+ }
+ ret = g_audioCaptureSourceInstance->GetVolume(*left, *right);
+
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/frameworks/innerkitsimpl/audiocapturer/src/audio_encoder.cpp b/frameworks/innerkitsimpl/audiocapturer/src/audio_encoder.cpp
index e84726f2cd900158afd40bb0bc5aa95ce035e7a6..fa9fed58ed7c88117f16eba36853cf0af7fd6c50 100755
--- a/frameworks/innerkitsimpl/audiocapturer/src/audio_encoder.cpp
+++ b/frameworks/innerkitsimpl/audiocapturer/src/audio_encoder.cpp
@@ -20,6 +20,7 @@
namespace OHOS {
namespace Audio {
using namespace OHOS::Media;
+using namespace OHOS::AudioStandard;
constexpr uint32_t AUDIO_READ_STREAM_TIME_OUT_MS = 1000; /* 1S */
diff --git a/frameworks/innerkitsimpl/audiocapturer/src/audio_source.cpp b/frameworks/innerkitsimpl/audiocapturer/src/audio_source.cpp
index 92be601e06657b808bbc426bae6f91b432effad3..d17860fe8aab8ce26e84ba2d6a3f27c47bdfda18 100755
--- a/frameworks/innerkitsimpl/audiocapturer/src/audio_source.cpp
+++ b/frameworks/innerkitsimpl/audiocapturer/src/audio_source.cpp
@@ -27,6 +27,7 @@ namespace Audio {
} while (0)
using namespace OHOS::Media;
+using namespace OHOS::AudioStandard;
static AudioManager *g_audioManager = nullptr;
AudioSource::AudioSource()
: initialized_(false),
diff --git a/frameworks/innerkitsimpl/audiorecorder/include/audio_recorder_private.h b/frameworks/innerkitsimpl/audiorecorder/include/audio_recorder_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..03354f80e78265d344350662e350d66cd449345f
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorecorder/include/audio_recorder_private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "audio_recorder.h"
+#include "audio_stream.h"
+
+namespace OHOS {
+namespace AudioStandard {
+class AudioRecorderPrivate : public AudioRecorder {
+public:
+ int32_t GetFrameCount(uint32_t &frameCount) const override;
+ int32_t SetParams(const AudioRecorderParams params) const override;
+ int32_t GetParams(AudioRecorderParams ¶ms) const override;
+ bool Start() const override;
+ int32_t Read(uint8_t &buffer, size_t userSize, bool isBlockingRead) const override;
+ RecorderState GetStatus() const override;
+ bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const override;
+ bool Stop() const override;
+ bool Flush() const override;
+ bool Release() const override;
+ int32_t GetBufferSize(size_t &bufferSize) const override;
+
+ std::unique_ptr audioRecorder;
+
+ explicit AudioRecorderPrivate(AudioStreamType audioStreamType);
+ virtual ~AudioRecorderPrivate();
+};
+} // namespace AudioStandard
+} // namespace OHOS
diff --git a/frameworks/innerkitsimpl/audiorecorder/src/audio_recorder.cpp b/frameworks/innerkitsimpl/audiorecorder/src/audio_recorder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f7346036ce4ce5cd825e359c095117282e190d4d
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorecorder/src/audio_recorder.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "audio_errors.h"
+#include "audio_recorder.h"
+#include "audio_recorder_private.h"
+#include "audio_stream.h"
+
+namespace OHOS {
+namespace AudioStandard {
+AudioRecorder::~AudioRecorder() = default;
+AudioRecorderPrivate::~AudioRecorderPrivate() = default;
+
+std::unique_ptr AudioRecorder::Create(AudioStreamType audioStreamType)
+{
+ return std::make_unique(audioStreamType);
+}
+
+AudioRecorderPrivate::AudioRecorderPrivate(AudioStreamType audioStreamType)
+{
+ audioRecorder = std::make_unique(audioStreamType, AUDIO_MODE_RECORD);
+}
+
+int32_t AudioRecorderPrivate::GetFrameCount(uint32_t &frameCount) const
+{
+ return audioRecorder->GetFrameCount(frameCount);
+}
+
+int32_t AudioRecorderPrivate::SetParams(const AudioRecorderParams params) const
+{
+ AudioStreamParams audioStreamParams;
+ audioStreamParams.format = params.audioSampleFormat;
+ audioStreamParams.samplingRate = params.samplingRate;
+ audioStreamParams.channels = params.audioChannel;
+ audioStreamParams.encoding = params.audioEncoding;
+
+ return audioRecorder->SetAudioStreamInfo(audioStreamParams);
+}
+
+int32_t AudioRecorderPrivate::GetParams(AudioRecorderParams ¶ms) const
+{
+ AudioStreamParams audioStreamParams;
+ int32_t result = audioRecorder->GetAudioStreamInfo(audioStreamParams);
+ if (SUCCESS == result) {
+ params.audioSampleFormat = static_cast(audioStreamParams.format);
+ params.samplingRate = static_cast(audioStreamParams.samplingRate);
+ params.audioChannel = static_cast(audioStreamParams.channels);
+ params.audioEncoding = static_cast(audioStreamParams.encoding);
+ }
+
+ return result;
+}
+
+bool AudioRecorderPrivate::Start() const
+{
+ return audioRecorder->StartAudioStream();
+}
+
+int32_t AudioRecorderPrivate::Read(uint8_t &buffer, size_t userSize, bool isBlockingRead) const
+{
+ return audioRecorder->Read(buffer, userSize, isBlockingRead);
+}
+
+RecorderState AudioRecorderPrivate::GetStatus() const
+{
+ return (RecorderState)audioRecorder->GetState();
+}
+
+bool AudioRecorderPrivate::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const
+{
+ return audioRecorder->GetAudioTime(timestamp, base);
+}
+
+bool AudioRecorderPrivate::Stop() const
+{
+ return audioRecorder->StopAudioStream();
+}
+
+bool AudioRecorderPrivate::Flush() const
+{
+ return audioRecorder->FlushAudioStream();
+}
+
+bool AudioRecorderPrivate::Release() const
+{
+ return audioRecorder->ReleaseAudioStream();
+}
+
+int32_t AudioRecorderPrivate::GetBufferSize(size_t &bufferSize) const
+{
+ return audioRecorder->GetBufferSize(bufferSize);
+}
+
+std::vector AudioRecorder::GetSupportedFormats()
+{
+ return AUDIO_SUPPORTED_FORMATS;
+}
+
+std::vector AudioRecorder::GetSupportedChannels()
+{
+ return AUDIO_SUPPORTED_CHANNELS;
+}
+
+std::vector AudioRecorder::GetSupportedEncodingTypes()
+{
+ return AUDIO_SUPPORTED_ENCODING_TYPES;
+}
+
+std::vector AudioRecorder::GetSupportedSamplingRates()
+{
+ return AUDIO_SUPPORTED_SAMPLING_RATES;
+}
+} // namespace AudioStandard
+} // namespace OHOS
\ No newline at end of file
diff --git a/frameworks/innerkitsimpl/audiorenderer/BUILD.gn b/frameworks/innerkitsimpl/audiorenderer/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..002a9e5c2644fb9ceb751d18e168d7cc15613aa8
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+import("//drivers/adapter/uhdf2/uhdf.gni")
+
+ohos_shared_library("audio_renderer_sink") {
+ install_enable = true
+
+ sources = [
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer_sink.cpp",
+ ]
+
+ cflags = ["-fPIC"]
+ cflags += ["-Wall"]
+ cflags_cc = cflags
+
+ include_dirs = [
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiorenderer/include",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/common/include",
+ "//foundation/multimedia/media_standard/interfaces/innerkits/native/media/include",
+ "//utils/native/base/include",
+ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
+ "//drivers/peripheral/audio/interfaces/include",
+ "//utils/native/base/include",
+ ]
+
+ public_configs = [":audio_external_library_config"]
+
+ deps = [
+ "//third_party/bounds_checking_function:libsec_static",
+ "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",
+ "//utils/native/base:utils",
+ "$hdf_uhdf_path/ipc:libhdf_ipc_adapter",
+ "$hdf_uhdf_path/hcs:hdf_default.hcb",
+ "$hdf_uhdf_path/hdi:libhdi",
+ "$hdf_uhdf_path/host:hdf_devhost",
+ "$hdf_uhdf_path/host:libhdf_host",
+ "$hdf_uhdf_path/config:libhdf_hcs",
+ "$hdf_uhdf_path/manager:hdf_devmgr.rc",
+ "$hdf_uhdf_path/manager:hdf_devmgr",
+ "$hdf_uhdf_path/osal:libhdf_utils",
+ ]
+
+ part_name = "multimedia_audio_standard"
+ subsystem_name = "multimedia"
+}
+
+config("audio_external_library_config") {
+ include_dirs = ["//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/common/include"]
+}
diff --git a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..997439e025c509a81812dce1b7ee0207c57cf60e
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_private.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_RECORDER_PRIVATE_H
+#define AUDIO_RECORDER_PRIVATE_H
+
+#include "audio_renderer.h"
+#include "audio_stream.h"
+
+namespace OHOS {
+namespace AudioStandard {
+class AudioRendererPrivate : public AudioRenderer {
+public:
+ int32_t GetFrameCount(uint32_t &frameCount) const override;
+ int32_t GetLatency(uint64_t &latency) const override;
+ int32_t SetParams(const AudioRendererParams params) const override;
+ int32_t GetParams(AudioRendererParams ¶ms) const override;
+ bool Start() const override;
+ int32_t Write(uint8_t *buffer, size_t bufferSize) override;
+ RendererState GetStatus() const override;
+ bool GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const override;
+ bool Drain() const override;
+ bool Pause() const override;
+ bool Stop() const override;
+ bool Flush() const override;
+ bool Release() const override;
+ int32_t GetBufferSize(size_t &bufferSize) const override;
+
+ std::unique_ptr audioRenderer;
+
+ explicit AudioRendererPrivate(AudioStreamType audioStreamType);
+ virtual ~AudioRendererPrivate();
+};
+} // namespace AudioStandard
+} // namespace OHOS
+#endif // AUDIO_RECORDER_PRIVATE_H
diff --git a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink.h b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink.h
new file mode 100644
index 0000000000000000000000000000000000000000..b756adfd5cdbd4a7f8710e41fb7e5572ac9efee0
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_RENDERER_SINK_H
+#define AUDIO_RENDERER_SINK_H
+
+#include "audio_manager.h"
+
+#include
+
+namespace OHOS {
+namespace AudioStandard {
+typedef struct {
+ AudioFormat format;
+ uint32_t sampleFmt;
+ uint32_t sampleRate;
+ uint32_t channel;
+ float volume;
+} AudioSinkAttr;
+
+class AudioRendererSink {
+public:
+ int32_t Init(AudioSinkAttr &atrr);
+ void DeInit(void);
+ int32_t Start(void);
+ int32_t Stop(void);
+ int32_t Flush(void);
+ int32_t Reset(void);
+ int32_t Pause(void);
+ int32_t Resume(void);
+ int32_t RenderFrame(char &frame, uint64_t len, uint64_t &writeLen);
+ int32_t SetVolume(float left, float right);
+ int32_t GetVolume(float &left, float &right);
+ int32_t GetLatency(uint32_t *latency);
+ static AudioRendererSink* GetInstance(void);
+ bool rendererInited_;
+private:
+ AudioRendererSink();
+ ~AudioRendererSink();
+ AudioSinkAttr attr_;
+ bool started_;
+ bool paused_;
+ float leftVolume_;
+ float rightVolume_;
+ struct AudioManager *audioManager_;
+ struct AudioAdapter *audioAdapter_;
+ struct AudioRender *audioRender_;
+ void *handle_;
+
+ int32_t CreateRender(struct AudioPort &renderPort);
+ int32_t InitAudioManager();
+#ifdef DUMPFILE
+ FILE *pfd;
+#endif // DUMPFILE
+};
+} // namespace AudioStandard
+} // namespace OHOS
+#endif // AUDIO_RENDERER_SINK_H
diff --git a/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink_intf.h b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink_intf.h
new file mode 100644
index 0000000000000000000000000000000000000000..6219e31c01d434f185db1352e3ce26f34d30c203
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/include/audio_renderer_sink_intf.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_RENDERER_SINK_INTF_H
+#define AUDIO_RENDERER_SINK_INTF_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef struct {
+ enum AudioFormat format;
+ uint32_t sampleFmt;
+ uint32_t sampleRate;
+ uint32_t channel;
+ float volume;
+} AudioSinkAttr;
+
+int32_t AudioRendererSinkInit(AudioSinkAttr *);
+void AudioRendererSinkDeInit(void);
+int32_t AudioRendererSinkStart(void);
+int32_t AudioRendererSinkStop(void);
+int32_t AudioRendererRenderFrame(char*, uint64_t, uint64_t*);
+int32_t AudioRendererSinkSetVolume(float, float);
+int32_t AudioRendererSinkGetLatency(uint32_t *);
+#ifdef __cplusplus
+}
+#endif
+#endif // AUDIO_RENDERER_SINK_INTF_H
diff --git a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..df37e8ca5352bc0455014b3b94c9787ef9786bc5
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+#include "audio_errors.h"
+#include "audio_renderer.h"
+#include "audio_renderer_private.h"
+#include "audio_stream.h"
+
+namespace OHOS {
+namespace AudioStandard {
+AudioRenderer::~AudioRenderer() = default;
+AudioRendererPrivate::~AudioRendererPrivate() = default;
+
+std::unique_ptr AudioRenderer::Create(AudioStreamType audioStreamType)
+{
+ return std::make_unique(audioStreamType);
+}
+
+AudioRendererPrivate::AudioRendererPrivate(AudioStreamType audioStreamType)
+{
+ audioRenderer = std::make_unique(audioStreamType, AUDIO_MODE_PLAYBACK);
+}
+
+int32_t AudioRendererPrivate::GetFrameCount(uint32_t &frameCount) const
+{
+ return audioRenderer->GetFrameCount(frameCount);
+}
+
+int32_t AudioRendererPrivate::GetLatency(uint64_t &latency) const
+{
+ return audioRenderer->GetLatency(latency);
+}
+
+int32_t AudioRendererPrivate::SetParams(const AudioRendererParams params) const
+{
+ AudioStreamParams audioStreamParams;
+ audioStreamParams.format = params.sampleFormat;
+ audioStreamParams.samplingRate = params.sampleRate;
+ audioStreamParams.channels = params.channelCount;
+ audioStreamParams.encoding = params.encodingType;
+
+ return audioRenderer->SetAudioStreamInfo(audioStreamParams);
+}
+
+int32_t AudioRendererPrivate::GetParams(AudioRendererParams ¶ms) const
+{
+ AudioStreamParams audioStreamParams;
+ int32_t result = audioRenderer->GetAudioStreamInfo(audioStreamParams);
+ if (!result) {
+ params.sampleFormat = static_cast(audioStreamParams.format);
+ params.sampleRate = static_cast(audioStreamParams.samplingRate);
+ params.channelCount = static_cast(audioStreamParams.channels);
+ params.encodingType = static_cast(audioStreamParams.encoding);
+ }
+
+ return result;
+}
+
+bool AudioRendererPrivate::Start() const
+{
+ return audioRenderer->StartAudioStream();
+}
+
+int32_t AudioRendererPrivate::Write(uint8_t *buffer, size_t bufferSize)
+{
+ return audioRenderer->Write(buffer, bufferSize);
+}
+
+RendererState AudioRendererPrivate::GetStatus() const
+{
+ return static_cast(audioRenderer->GetState());
+}
+
+bool AudioRendererPrivate::GetAudioTime(Timestamp ×tamp, Timestamp::Timestampbase base) const
+{
+ return audioRenderer->GetAudioTime(timestamp, base);
+}
+
+bool AudioRendererPrivate::Drain() const
+{
+ return audioRenderer->DrainAudioStream();
+}
+
+bool AudioRendererPrivate::Flush() const
+{
+ return audioRenderer->FlushAudioStream();
+}
+
+bool AudioRendererPrivate::Pause() const
+{
+ return audioRenderer->PauseAudioStream();
+}
+
+bool AudioRendererPrivate::Stop() const
+{
+ return audioRenderer->StopAudioStream();
+}
+
+bool AudioRendererPrivate::Release() const
+{
+ return audioRenderer->ReleaseAudioStream();
+}
+
+int32_t AudioRendererPrivate::GetBufferSize(size_t &bufferSize) const
+{
+ return audioRenderer->GetBufferSize(bufferSize);
+}
+
+std::vector AudioRenderer::GetSupportedFormats()
+{
+ return AUDIO_SUPPORTED_FORMATS;
+}
+
+std::vector AudioRenderer::GetSupportedSamplingRates()
+{
+ return AUDIO_SUPPORTED_SAMPLING_RATES;
+}
+
+std::vector AudioRenderer::GetSupportedChannels()
+{
+ return AUDIO_SUPPORTED_CHANNELS;
+}
+
+std::vector AudioRenderer::GetSupportedEncodingTypes()
+{
+ return AUDIO_SUPPORTED_ENCODING_TYPES;
+}
+} // namespace AudioStandard
+} // namespace OHOS
diff --git a/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer_sink.cpp b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer_sink.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c0271f061fb749d7ff73cc4d5453e45707ef468c
--- /dev/null
+++ b/frameworks/innerkitsimpl/audiorenderer/src/audio_renderer_sink.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+
+#include "audio_errors.h"
+#include "audio_renderer_sink.h"
+#include "media_log.h"
+
+namespace OHOS {
+namespace AudioStandard {
+namespace {
+const int32_t HALF_FACTOR = 2;
+const int32_t MAX_AUDIO_ADAPTER_NUM = 3;
+const float DEFAULT_VOLUME_LEVEL = 1.0f;
+const uint32_t AUDIO_CHANNELCOUNT = 2;
+const uint32_t AUDIO_SAMPLE_RATE_48K = 48000;
+const uint32_t DEEP_BUFFER_RENDER_PERIOD_SIZE = 4096;
+const uint32_t INT_32_MAX = 0x7fffffff;
+#define PCM_8_BIT 8
+#define PCM_16_BIT 16
+}
+
+#ifdef DUMPFILE
+const char *g_audioOutTestFilePath = "/data/local/tmp/audioout_test.pcm";
+#endif // DUMPFILE
+
+AudioRendererSink::AudioRendererSink()
+ : rendererInited_(false), started_(false), paused_(false), leftVolume_(DEFAULT_VOLUME_LEVEL),
+ rightVolume_(DEFAULT_VOLUME_LEVEL), audioManager_(nullptr), audioAdapter_(nullptr), audioRender_(nullptr)
+{
+ attr_ = {};
+#ifdef DUMPFILE
+ pfd = nullptr;
+#endif // DUMPFILE
+}
+
+AudioRendererSink::~AudioRendererSink()
+{
+ DeInit();
+}
+
+AudioRendererSink* AudioRendererSink::GetInstance()
+{
+ static AudioRendererSink audioRenderer_;
+
+ return &audioRenderer_;
+}
+
+void AudioRendererSink::DeInit()
+{
+ started_ = false;
+ rendererInited_ = false;
+ if ((audioRender_ != nullptr) && (audioAdapter_ != nullptr)) {
+ audioAdapter_->DestroyRender(audioAdapter_, audioRender_);
+ }
+ audioRender_ = nullptr;
+
+ if ((audioManager_ != nullptr) && (audioAdapter_ != nullptr)) {
+ audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
+ }
+ audioAdapter_ = nullptr;
+ audioManager_ = nullptr;
+
+ dlclose(handle_);
+
+#ifdef DUMPFILE
+ if (pfd) {
+ fclose(pfd);
+ pfd = nullptr;
+ }
+#endif // DUMPFILE
+}
+
+int32_t InitAttrs(struct AudioSampleAttributes &attrs)
+{
+ /* Initialization of audio parameters for playback */
+ attrs.format = AUDIO_FORMAT_PCM_16_BIT;
+ attrs.channelCount = AUDIO_CHANNELCOUNT;
+ attrs.sampleRate = AUDIO_SAMPLE_RATE_48K;
+ attrs.interleaved = 0;
+ attrs.type = AUDIO_IN_MEDIA;
+ attrs.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
+ attrs.frameSize = PCM_16_BIT * attrs.channelCount / PCM_8_BIT;
+ attrs.isBigEndian = false;
+ attrs.isSignedData = true;
+ attrs.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs.frameSize);
+ attrs.stopThreshold = INT_32_MAX;
+ attrs.silenceThreshold = 0;
+
+ return SUCCESS;
+}
+
+static int32_t SwitchAdapter(struct AudioAdapterDescriptor *descs, const char *adapterNameCase,
+ enum AudioPortDirection portFlag, struct AudioPort *renderPort, int32_t size)
+{
+ for (int32_t index = 0; index < size; index++) {
+ struct AudioAdapterDescriptor *desc = &descs[index];
+ if (desc == nullptr) {
+ MEDIA_ERR_LOG("SwitchAdapter Fail AudioAdapterDescriptor desc NULL");
+ return ERR_INVALID_INDEX; // note: return invalid index not invalid handle
+ }
+ if (!strcmp(desc->adapterName, adapterNameCase)) {
+ for (uint32_t port = 0; ((desc != NULL) && (port < desc->portNum)); port++) {
+ // Only find out the port of out in the sound card
+ if (desc->ports[port].dir == portFlag) {
+ *renderPort = desc->ports[port];
+ return index;
+ }
+ }
+ }
+ }
+ MEDIA_ERR_LOG("SwitchAdapter Fail");
+
+ return ERR_INVALID_INDEX;
+}
+
+int32_t AudioRendererSink::InitAudioManager()
+{
+ char resolvedPath[100] = "/system/lib/libhdi_audio.z.so";
+ struct AudioManager *(*getAudioManager)() = nullptr;
+
+ handle_ = dlopen(resolvedPath, 1);
+ if (handle_ == nullptr) {
+ MEDIA_ERR_LOG("Open so Fail");
+ return ERR_INVALID_HANDLE;
+ }
+
+ getAudioManager = (struct AudioManager* (*)())(dlsym(handle_, "GetAudioManagerFuncs"));
+ audioManager_ = getAudioManager();
+ if (audioManager_ == nullptr) {
+ return ERR_INVALID_HANDLE;
+ }
+
+ return 0;
+}
+
+int32_t AudioRendererSink::CreateRender(struct AudioPort &renderPort)
+{
+ // Initialization port information, can fill through mode and other parameters
+ int32_t ret = audioAdapter_->InitAllPorts(audioAdapter_);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("InitAllPorts failed");
+ return ERR_NOT_STARTED;
+ }
+
+ struct AudioSampleAttributes param;
+ InitAttrs(param);
+ param.sampleRate = attr_.sampleRate;
+ param.channelCount = attr_.channel;
+
+ struct AudioDeviceDescriptor deviceDesc;
+ deviceDesc.portId = renderPort.portId;
+ deviceDesc.pins = PIN_OUT_SPEAKER;
+ deviceDesc.desc = nullptr;
+ ret = audioAdapter_->CreateRender(audioAdapter_, &deviceDesc, ¶m, &audioRender_);
+ if (ret != 0 || audioRender_ == nullptr) {
+ MEDIA_ERR_LOG("AudioDeviceCreateRender failed");
+ audioManager_->UnloadAdapter(audioManager_, audioAdapter_);
+ return ERR_NOT_STARTED;
+ }
+
+ rendererInited_ = true;
+ return 0;
+}
+
+int32_t AudioRendererSink::Init(AudioSinkAttr &attr)
+{
+ attr_ = attr;
+ struct AudioPort renderPort;
+ const char *adapterNameCase = "usb"; // Set sound card information
+ enum AudioPortDirection port = PORT_OUT; // Set port information
+
+ if (InitAudioManager() != 0) {
+ MEDIA_ERR_LOG("Init audio manager Fail");
+ return ERR_NOT_STARTED;
+ }
+
+ int32_t size = -1;
+ struct AudioAdapterDescriptor *descs = nullptr;
+ audioManager_->GetAllAdapters(audioManager_, &descs, &size);
+ if (size > MAX_AUDIO_ADAPTER_NUM || size == 0 || descs == nullptr) {
+ MEDIA_ERR_LOG("Get adapters Fail");
+ return ERR_NOT_STARTED;
+ }
+
+ // Get qualified sound card and port
+ int32_t index = SwitchAdapter(descs, adapterNameCase, port, &renderPort, size);
+ if (index < 0) {
+ MEDIA_ERR_LOG("Switch Adapter Fail");
+ return ERR_NOT_STARTED;
+ }
+
+ struct AudioAdapterDescriptor *desc = &descs[index];
+ if (audioManager_->LoadAdapter(audioManager_, desc, &audioAdapter_) != 0) {
+ MEDIA_ERR_LOG("Load Adapter Fail");
+ return ERR_NOT_STARTED;
+ }
+ if (audioAdapter_ == nullptr) {
+ MEDIA_ERR_LOG("Load audio device failed");
+ return ERR_NOT_STARTED;
+ }
+
+ if (CreateRender(renderPort) != 0) {
+ MEDIA_ERR_LOG("Create render failed");
+ return ERR_NOT_STARTED;
+ }
+
+#ifdef DUMPFILE
+ pfd = fopen(g_audioOutTestFilePath, "wb+");
+ if (pfd == nullptr) {
+ MEDIA_ERR_LOG("Error opening pcm test file!");
+ }
+#endif // DUMPFILE
+
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::RenderFrame(char &data, uint64_t len, uint64_t &writeLen)
+{
+ int32_t ret;
+ if (audioRender_ == nullptr) {
+ MEDIA_ERR_LOG("Audio Render Handle is nullptr!");
+ return ERR_INVALID_HANDLE;
+ }
+
+#ifdef DUMPFILE
+ size_t writeResult = fwrite((void*)&data, 1, len, pfd);
+ if (writeResult != len) {
+ MEDIA_ERR_LOG("Failed to write the file.");
+ }
+#endif // DUMPFILE
+
+ ret = audioRender_->RenderFrame(audioRender_, (void*)&data, len, &writeLen);
+ if (ret != 0) {
+ MEDIA_ERR_LOG("RenderFrame failed ret: %{public}x", ret);
+ return ERR_WRITE_FAILED;
+ }
+
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::Start(void)
+{
+ if (!started_ && audioRender_ != nullptr) {
+ audioRender_->control.Start((AudioHandle)audioRender_);
+ started_ = true;
+ }
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::SetVolume(float left, float right)
+{
+ float volume;
+ if (audioRender_ == nullptr) {
+ MEDIA_ERR_LOG("AudioRendererSink::SetVolume failed audioRender_ null");
+ return ERR_INVALID_HANDLE;
+ }
+
+ leftVolume_ = left;
+ rightVolume_ = right;
+ if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
+ volume = rightVolume_;
+ } else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
+ volume = leftVolume_;
+ } else {
+ volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
+ }
+ audioRender_->volume.SetVolume(reinterpret_cast(audioRender_), volume);
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::GetVolume(float &left, float &right)
+{
+ left = leftVolume_;
+ right = rightVolume_;
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::GetLatency(uint32_t *latency)
+{
+ if (audioRender_ == nullptr) {
+ MEDIA_ERR_LOG("AudioRendererSink: GetLatency failed audio render null");
+ return ERR_INVALID_HANDLE;
+ }
+
+ if (!latency) {
+ MEDIA_ERR_LOG("AudioRendererSink: GetLatency failed latency null");
+ return ERR_INVALID_PARAM;
+ }
+
+ uint32_t hdiLatency;
+ if (audioRender_->GetLatency(audioRender_, &hdiLatency) == 0) {
+ *latency = hdiLatency;
+ MEDIA_INFO_LOG("AudioRendererSink: Latency: %{public}u", *latency);
+ return SUCCESS;
+ } else {
+ return ERR_OPERATION_FAILED;
+ }
+}
+
+int32_t AudioRendererSink::Stop(void)
+{
+ if (started_ && audioRender_ != nullptr) {
+ audioRender_->control.Stop(reinterpret_cast(audioRender_));
+ }
+ started_ = false;
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::Pause(void)
+{
+ if (started_ && audioRender_ != nullptr) {
+ audioRender_->control.Pause(reinterpret_cast(audioRender_));
+ }
+ paused_ = true;
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::Resume(void)
+{
+ audioRender_->control.Resume(reinterpret_cast(audioRender_));
+ paused_ = false;
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::Reset(void)
+{
+ if (started_ && audioRender_ != nullptr) {
+ audioRender_->control.Flush(reinterpret_cast(audioRender_));
+ }
+ return SUCCESS;
+}
+
+int32_t AudioRendererSink::Flush(void)
+{
+ if (started_ && audioRender_ != nullptr) {
+ audioRender_->control.Flush(reinterpret_cast(audioRender_));
+ }
+ return SUCCESS;
+}
+} // namespace AudioStandard
+} // namespace OHOS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+using namespace OHOS::AudioStandard;
+
+AudioRendererSink* g_audioRendrSinkInstance = AudioRendererSink::GetInstance();
+
+int32_t AudioRendererSinkInit(AudioSinkAttr *attr)
+{
+ int32_t ret;
+
+ if (g_audioRendrSinkInstance->rendererInited_)
+ return SUCCESS;
+
+ ret = g_audioRendrSinkInstance->Init(*attr);
+ return ret;
+}
+
+void AudioRendererSinkDeInit()
+{
+ if (g_audioRendrSinkInstance->rendererInited_)
+ g_audioRendrSinkInstance->DeInit();
+}
+
+int32_t AudioRendererSinkStop()
+{
+ int32_t ret;
+
+ if (!g_audioRendrSinkInstance->rendererInited_)
+ return SUCCESS;
+
+ ret = g_audioRendrSinkInstance->Stop();
+ return ret;
+}
+
+int32_t AudioRendererSinkStart()
+{
+ int32_t ret;
+
+ if (!g_audioRendrSinkInstance->rendererInited_) {
+ MEDIA_ERR_LOG("audioRenderer Not Inited! Init the renderer first\n");
+ return ERR_NOT_STARTED;
+ }
+
+ ret = g_audioRendrSinkInstance->Start();
+ return ret;
+}
+
+int32_t AudioRendererRenderFrame(char &data, uint64_t len, uint64_t &writeLen)
+{
+ int32_t ret;
+
+ if (!g_audioRendrSinkInstance->rendererInited_) {
+ MEDIA_ERR_LOG("audioRenderer Not Inited! Init the renderer first\n");
+ return ERR_NOT_STARTED;
+ }
+
+ ret = g_audioRendrSinkInstance->RenderFrame(data, len, writeLen);
+ return ret;
+}
+
+int32_t AudioRendererSinkSetVolume(float left, float right)
+{
+ int32_t ret;
+
+ if (!g_audioRendrSinkInstance->rendererInited_) {
+ MEDIA_ERR_LOG("audioRenderer Not Inited! Init the renderer first\n");
+ return ERR_NOT_STARTED;
+ }
+
+ ret = g_audioRendrSinkInstance->SetVolume(left, right);
+ return ret;
+}
+
+int32_t AudioRendererSinkGetLatency(uint32_t *latency)
+{
+ int32_t ret;
+
+ if (!g_audioRendrSinkInstance->rendererInited_) {
+ MEDIA_ERR_LOG("audioRenderer Not Inited! Init the renderer first\n");
+ return ERR_NOT_STARTED;
+ }
+
+ if (!latency) {
+ MEDIA_ERR_LOG("AudioRendererSinkGetLatency failed latency null");
+ return ERR_INVALID_PARAM;
+ }
+
+ ret = g_audioRendrSinkInstance->GetLatency(latency);
+ return ret;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/frameworks/innerkitsimpl/common/include/media_errors.h b/frameworks/innerkitsimpl/common/include/audio_errors.h
old mode 100755
new mode 100644
similarity index 39%
rename from frameworks/innerkitsimpl/common/include/media_errors.h
rename to frameworks/innerkitsimpl/common/include/audio_errors.h
index 3e4da13ed8a1743296021e1d86ee4a6d3ebd38b5..bd076132c6fb24830d770fd1496b91d8d10630f0
--- a/frameworks/innerkitsimpl/common/include/media_errors.h
+++ b/frameworks/innerkitsimpl/common/include/audio_errors.h
@@ -1,104 +1,119 @@
-/*
- * Copyright (C) 2021 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @addtogroup MultiMedia_MediaCommon
- * @{
- *
- * @brief Provides data types and media formats required for recording and playing audio and videos.
- *
- *
- * @since 1.0
- * @version 1.0
- */
-
-/**
- * @file media_errors.h
- *
- * @brief Declares the media_errors class to define errors that may occur during media operations.
- *
- *
- * @since 1.0
- * @version 1.0
- */
-
-#ifndef MEDIA_ERRORS_H
-#define MEDIA_ERRORS_H
-
-#include
-
-namespace OHOS {
-namespace Media {
-constexpr int MODULE_MEDIA = 1;
-constexpr int SUBSYS_MEDIA = 30;
-
-using ErrCode = int32_t;
-constexpr int SUBSYSTEM_BIT_NUM = 21;
-constexpr int MODULE_BIT_NUM = 16;
-
-/**
- * @brief Generates a start error code with a unique identifier based on specified subsystem and module bit numbers.
- *
- * @param subsystem Indicates the subsystem bit number.
- * @param module Indicates the module bit number.
- * @return
- * @since 1.0
- * @version 1.0
- */
-constexpr ErrCode ErrCodeOffset(unsigned int subsystem, unsigned int module = 0)
-{
- return (subsystem << SUBSYSTEM_BIT_NUM) | (module << MODULE_BIT_NUM);
-}
-
-constexpr int32_t BASE_MEDIA_ERR_OFFSET = ErrCodeOffset(SUBSYS_MEDIA, MODULE_MEDIA);
-
-/** Invalid data size that has been read */
-const int32_t ERR_INVALID_READ = -1;
-
-/** Success */
-const int32_t SUCCESS = 0;
-
-/** Fail */
-const int32_t ERROR = BASE_MEDIA_ERR_OFFSET;
-
-/** Status error */
-const int32_t ERR_ILLEGAL_STATE = BASE_MEDIA_ERR_OFFSET + 1;
-
-/** Invalid parameter */
-const int32_t ERR_INVALID_PARAM = BASE_MEDIA_ERR_OFFSET + 2;
-
-/** Early media preparation */
-const int32_t ERR_EARLY_PREPARE = BASE_MEDIA_ERR_OFFSET + 3;
-
-/** No media source */
-const int32_t ERR_SOURCE_NOT_SET = BASE_MEDIA_ERR_OFFSET + 4;
-
-/** Invalid operation */
-const int32_t ERR_INVALID_OPERATION = BASE_MEDIA_ERR_OFFSET + 5;
-
-/** No idle channel */
-const int32_t ERR_NOFREE_CHANNEL = BASE_MEDIA_ERR_OFFSET + 6;
-
-/** Buffer reading failed */
-const int32_t ERR_READ_BUFFER = BASE_MEDIA_ERR_OFFSET + 7;
-
-/** Device not started */
-const int32_t ERR_NOT_STARTED = BASE_MEDIA_ERR_OFFSET + 8;
-
-/** Unknown error */
-const int32_t ERR_UNKNOWN = BASE_MEDIA_ERR_OFFSET + 200;
-} // namespace Media
-} // namespace OHOS
-#endif // MEDIA_ERRORS_H
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @addtogroup MultiMedia_AudioCommon
+ * @{
+ *
+ * @brief Provides data types and audio formats required for recording and playing and recording audio.
+ *
+ *
+ * @since 1.0
+ * @version 1.0
+ */
+
+/**
+ * @file audio_errors.h
+ *
+ * @brief Declares the audio_errors class to define errors that may occur during audio operations.
+ *
+ *
+ * @since 1.0
+ * @version 1.0
+ */
+
+#ifndef AUDIO_ERRORS_H
+#define AUDIO_ERRORS_H
+
+#include
+
+namespace OHOS {
+namespace AudioStandard {
+constexpr int MODULE_AUDIO = 1;
+constexpr int SUBSYS_AUDIO = 30;
+
+using ErrCode = int32_t;
+constexpr int SUBSYSTEM_BIT_NUM = 21;
+constexpr int MODULE_BIT_NUM = 16;
+
+constexpr ErrCode ErrCodeOffset(unsigned int subsystem, unsigned int module = 0)
+{
+ return (subsystem << SUBSYSTEM_BIT_NUM) | (module << MODULE_BIT_NUM);
+}
+
+constexpr int32_t BASE_AUDIO_ERR_OFFSET = -ErrCodeOffset(SUBSYS_AUDIO, MODULE_AUDIO);
+
+/** Success */
+const int32_t SUCCESS = 0;
+
+/** Fail */
+const int32_t ERROR = BASE_AUDIO_ERR_OFFSET;
+
+/** Status error */
+const int32_t ERR_ILLEGAL_STATE = BASE_AUDIO_ERR_OFFSET - 1;
+
+/** Invalid parameter */
+const int32_t ERR_INVALID_PARAM = BASE_AUDIO_ERR_OFFSET - 2;
+
+/** Early media preparation */
+const int32_t ERR_EARLY_PREPARE = BASE_AUDIO_ERR_OFFSET - 3;
+
+/** Invalid operation */
+const int32_t ERR_INVALID_OPERATION = BASE_AUDIO_ERR_OFFSET - 4;
+
+/** error operation failed */
+const int32_t ERR_OPERATION_FAILED = BASE_AUDIO_ERR_OFFSET - 5;
+
+/** Buffer reading failed */
+const int32_t ERR_READ_BUFFER = BASE_AUDIO_ERR_OFFSET - 6;
+
+/** Buffer writing failed */
+const int32_t ERR_WRITE_BUFFER = BASE_AUDIO_ERR_OFFSET - 7;
+
+/** Device not started */
+const int32_t ERR_NOT_STARTED = BASE_AUDIO_ERR_OFFSET - 8;
+
+/** Invalid Device handle */
+const int32_t ERR_INVALID_HANDLE = BASE_AUDIO_ERR_OFFSET - 9;
+
+/** unsupported operation */
+const int32_t ERR_NOT_SUPPORTED = BASE_AUDIO_ERR_OFFSET - 10;
+
+/** unsupported device */
+const int32_t ERR_DEVICE_NOT_SUPPORTED = BASE_AUDIO_ERR_OFFSET - 11;
+
+/** write operation failed */
+const int32_t ERR_WRITE_FAILED = BASE_AUDIO_ERR_OFFSET - 12;
+
+/** read operation failed */
+const int32_t ERR_READ_FAILED = BASE_AUDIO_ERR_OFFSET - 13;
+
+/** device init failed */
+const int32_t ERR_DEVICE_INIT = BASE_AUDIO_ERR_OFFSET - 14;
+
+/** Invalid data size that has been read */
+const int32_t ERR_INVALID_READ = BASE_AUDIO_ERR_OFFSET - 15;
+
+/** Invalid data size that has been written */
+const int32_t ERR_INVALID_WRITE = BASE_AUDIO_ERR_OFFSET - 16;
+
+/** set invalid index < 0 */
+const int32_t ERR_INVALID_INDEX = BASE_AUDIO_ERR_OFFSET - 17;
+
+/** Unknown error */
+const int32_t ERR_UNKNOWN = BASE_AUDIO_ERR_OFFSET - 200;
+} // namespace AudioStandard
+} // namespace OHOS
+#endif // AUDIO_ERRORS_H
diff --git a/frameworks/innerkitsimpl/libsnd/BUILD.gn b/frameworks/innerkitsimpl/libsnd/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..df184f0ab112d93087a947cc4062a9bf37c4c38b
--- /dev/null
+++ b/frameworks/innerkitsimpl/libsnd/BUILD.gn
@@ -0,0 +1,132 @@
+import("//build/ohos.gni")
+
+libsndfile_dir = "//third_party/libsnd"
+libsndfile_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/libsnd"
+
+config("sndfile_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$libsndfile_dir/src",
+ "$libsndfile_dir/include",
+ "$libsndfile_build_path/include",
+ "$libsndfile_dir/src/GSM610",
+ "$libsndfile_dir/src/G72x",
+ "$libsndfile_dir/src/ALAC",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ ]
+}
+
+ohos_source_set("sndfile_sources") {
+ sources = [
+ "$libsndfile_dir/src/common.c",
+ "$libsndfile_dir/src/file_io.c",
+ "$libsndfile_dir/src/command.c",
+ "$libsndfile_dir/src/pcm.c",
+ "$libsndfile_dir/src/ulaw.c",
+ "$libsndfile_dir/src/alaw.c",
+ "$libsndfile_dir/src/float32.c",
+ "$libsndfile_dir/src/double64.c",
+ "$libsndfile_dir/src/ima_adpcm.c",
+ "$libsndfile_dir/src/ms_adpcm.c",
+ "$libsndfile_dir/src/gsm610.c",
+ "$libsndfile_dir/src/dwvw.c",
+ "$libsndfile_dir/src/vox_adpcm.c",
+ "$libsndfile_dir/src/interleave.c",
+ "$libsndfile_dir/src/strings.c",
+ "$libsndfile_dir/src/dither.c",
+ "$libsndfile_dir/src/cart.c",
+ "$libsndfile_dir/src/broadcast.c",
+ "$libsndfile_dir/src/audio_detect.c",
+ "$libsndfile_dir/src/ima_oki_adpcm.c",
+ "$libsndfile_dir/src/alac.c",
+ "$libsndfile_dir/src/chunk.c",
+ "$libsndfile_dir/src/ogg.c",
+ "$libsndfile_dir/src/chanmap.c",
+ "$libsndfile_dir/src/id3.c",
+ "$libsndfile_dir/src/sndfile.c",
+ "$libsndfile_dir/src/aiff.c",
+ "$libsndfile_dir/src/au.c",
+ "$libsndfile_dir/src/avr.c",
+ "$libsndfile_dir/src/caf.c",
+ "$libsndfile_dir/src/dwd.c",
+ "$libsndfile_dir/src/flac.c",
+ "$libsndfile_dir/src/g72x.c",
+ "$libsndfile_dir/src/htk.c",
+ "$libsndfile_dir/src/ircam.c",
+ "$libsndfile_dir/src/macos.c",
+ "$libsndfile_dir/src/mat4.c",
+ "$libsndfile_dir/src/mat5.c",
+ "$libsndfile_dir/src/nist.c",
+ "$libsndfile_dir/src/paf.c",
+ "$libsndfile_dir/src/pvf.c",
+ "$libsndfile_dir/src/raw.c",
+ "$libsndfile_dir/src/rx2.c",
+ "$libsndfile_dir/src/sd2.c",
+ "$libsndfile_dir/src/sds.c",
+ "$libsndfile_dir/src/svx.c",
+ "$libsndfile_dir/src/txw.c",
+ "$libsndfile_dir/src/voc.c",
+ "$libsndfile_dir/src/wve.c",
+ "$libsndfile_dir/src/w64.c",
+ "$libsndfile_dir/src/wavlike.c",
+ "$libsndfile_dir/src/wav.c",
+ "$libsndfile_dir/src/xi.c",
+ "$libsndfile_dir/src/mpc2k.c",
+ "$libsndfile_dir/src/rf64.c",
+ "$libsndfile_dir/src/ogg_vorbis.c",
+ "$libsndfile_dir/src/ogg_speex.c",
+ "$libsndfile_dir/src/ogg_pcm.c",
+ "$libsndfile_dir/src/ogg_opus.c",
+ "$libsndfile_dir/src/ogg_vcomment.c",
+ "$libsndfile_dir/src/nms_adpcm.c",
+ #"$libsndfile_dir/src/mpeg.c",
+ #"$libsndfile_dir/src/mpeg_decode.c",
+ #"$libsndfile_dir/src/mpeg_l3_encode.c",
+ "$libsndfile_dir/src/GSM610/add.c",
+ "$libsndfile_dir/src/GSM610/code.c",
+ "$libsndfile_dir/src/GSM610/decode.c",
+ "$libsndfile_dir/src/GSM610/gsm_create.c",
+ "$libsndfile_dir/src/GSM610/gsm_decode.c",
+ "$libsndfile_dir/src/GSM610/gsm_destroy.c",
+ "$libsndfile_dir/src/GSM610/gsm_encode.c",
+ "$libsndfile_dir/src/GSM610/gsm_option.c",
+ "$libsndfile_dir/src/GSM610/long_term.c",
+ "$libsndfile_dir/src/GSM610/lpc.c",
+ "$libsndfile_dir/src/GSM610/preprocess.c",
+ "$libsndfile_dir/src/GSM610/rpe.c",
+ "$libsndfile_dir/src/GSM610/short_term.c",
+ "$libsndfile_dir/src/GSM610/table.c",
+ "$libsndfile_dir/src/G72x/g721.c",
+ "$libsndfile_dir/src/G72x/g723_16.c",
+ "$libsndfile_dir/src/G72x/g723_24.c",
+ "$libsndfile_dir/src/G72x/g723_40.c",
+ "$libsndfile_dir/src/G72x/g72x.c",
+ "$libsndfile_dir/src/ALAC/ALACBitUtilities.c",
+ "$libsndfile_dir/src/ALAC/ag_dec.c",
+ "$libsndfile_dir/src/ALAC/ag_enc.c",
+ "$libsndfile_dir/src/ALAC/dp_dec.c",
+ "$libsndfile_dir/src/ALAC/dp_enc.c",
+ "$libsndfile_dir/src/ALAC/matrix_dec.c",
+ "$libsndfile_dir/src/ALAC/matrix_enc.c",
+ "$libsndfile_dir/src/ALAC/alac_decoder.c",
+ "$libsndfile_dir/src/ALAC/alac_encoder.c",
+ ]
+
+ configs = [
+ ":sndfile_config",
+ ]
+}
+
+ohos_shared_library("sndfile") {
+ deps = [
+ ":sndfile_sources",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/libsnd/include/config.h b/frameworks/innerkitsimpl/libsnd/include/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3856c9658b179b4818268087286c3ab55707c60
--- /dev/null
+++ b/frameworks/innerkitsimpl/libsnd/include/config.h
@@ -0,0 +1,320 @@
+/* Set to 1 if the compile is GNU GCC. */
+#define COMPILER_IS_GCC 1
+
+/* Target processor clips on negative float to int conversion. */
+#define CPU_CLIPS_NEGATIVE 0
+
+/* Target processor clips on positive float to int conversion. */
+#define CPU_CLIPS_POSITIVE 0
+
+/* Target processor is big endian. */
+#define CPU_IS_BIG_ENDIAN 0
+
+/* Target processor is little endian. */
+#define CPU_IS_LITTLE_ENDIAN 1
+
+/* Set to 1 to enable experimental code. */
+#define ENABLE_EXPERIMENTAL_CODE 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ALSA_ASOUNDLIB_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_BYTESWAP_H 1
+
+/* Define to 1 if you have the `calloc' function. */
+#define HAVE_CALLOC 0
+
+/* Define to 1 if you have the `ceil' function. */
+#define HAVE_CEIL 0
+
+/* Set to 1 if S_IRGRP is defined. */
+#define HAVE_DECL_S_IRGRP 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_DIRECT_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_ENDIAN_H 1
+
+/* Will be set to 1 if flac, ogg and vorbis are available. */
+#define HAVE_EXTERNAL_XIPH_LIBS 0
+
+/* Will be set to 1 if lame and mpg123 are available. */
+#define HAVE_MPEG 0
+
+/* Define to 1 if you have the `floor' function. */
+#define HAVE_FLOOR 0
+
+/* Define to 1 if you have the `fmod' function. */
+#define HAVE_FMOD 0
+
+/* Define to 1 if you have the `free' function. */
+#define HAVE_FREE 0
+
+/* Define to 1 if you have the `fstat' function. */
+#define HAVE_FSTAT 1
+
+/* Define to 1 if you have the `fstat64' function. */
+#define HAVE_FSTAT64 1
+
+/* Define to 1 if you have the `fsync' function. */
+#define HAVE_FSYNC 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 0
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the `gmtime' function. */
+#define HAVE_GMTIME
+
+/* Define if you have the `gmtime_r' function. */
+#define HAVE_GMTIME_R
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_IO_H */
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_LOCALE_H 1
+
+/* Define if you have the `localtime' function. */
+#define HAVE_LOCALTIME
+
+/* Define if you have the `localtime_r' function. */
+#define HAVE_LOCALTIME_R
+
+/* Define if you have C99's lrint function. */
+#define HAVE_LRINT 1
+
+/* Define if you have C99's lrintf function. */
+#define HAVE_LRINTF 1
+
+/* Define to 1 if you have the `lround' function. */
+#define HAVE_LROUND 0
+
+/* Define to 1 if you have the `lseek' function. */
+#define HAVE_LSEEK 1
+
+/* Define to 1 if you have the `lseek64' function. */
+#define HAVE_LSEEK64 0
+
+/* Define to 1 if you have the `malloc' function. */
+#define HAVE_MALLOC 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 0
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 0
+
+/* Define to 1 if you have the `open' function. */
+#define HAVE_OPEN 1
+
+/* Define to 1 if you have the `pipe' function. */
+#define HAVE_PIPE 1
+
+/* Define to 1 if you have the `read' function. */
+#define HAVE_READ 1
+
+/* Define to 1 if you have the `realloc' function. */
+#define HAVE_REALLOC 0
+
+/* Define to 1 if you have the `setlocale' function. */
+#define HAVE_SETLOCALE 1
+
+/* Set to 1 if is available. */
+#define HAVE_SNDIO_H 0
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 0
+
+/* Set to 1 if you have libsqlite3. */
+#define HAVE_SQLITE3 1
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#define HAVE_SSIZE_T 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 0
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_IMMINTRIN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 0
+
+/* Define to 1 if you have the `waitpid' function. */
+#define HAVE_WAITPID 1
+
+/* Define to 1 if you have the `write' function. */
+#define HAVE_WRITE 1
+
+/* The darwin version, no-zero is valid */
+#define OSX_DARWIN_VERSION 0
+
+/* Set to 1 if compiling for OpenBSD */
+#define OS_IS_OPENBSD 0
+
+/* Set to 1 if compiling for Win32 */
+#define OS_IS_WIN32 0
+
+/* Set to 1 if SSE2 is enabled */
+/* #undef USE_SSE2 */
+
+/* Name of package */
+#define PACKAGE "libsndfile"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libsndfile"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libsndfile 1.0.31"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libsndfile"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.0.31"
+
+/* Set to maximum allowed value of sf_count_t type. */
+#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
+
+/* The size of `double', as computed by sizeof. */
+
+
+/* The size of `float', as computed by sizeof. */
+
+
+/* The size of `int', as computed by sizeof. */
+
+
+/* The size of `int64_t', as computed by sizeof. */
+#define SIZEOF_INT64_T 8
+
+/* The size of `loff_t', as computed by sizeof. */
+
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* The size of `long long', as computed by sizeof. */
+#define SIZEOF_LONG_LONG 8
+
+/* The size of `off64_t', as computed by sizeof. */
+
+
+/* The size of `off_t', as computed by sizeof. */
+#define SIZEOF_OFF_T 8
+
+/* Set to sizeof (long) if unknown. */
+#define SIZEOF_SF_COUNT_T 8
+
+/* The size of `short', as computed by sizeof. */
+
+
+/* The size of `size_t', as computed by sizeof. */
+
+
+/* The size of `ssize_t', as computed by sizeof. */
+#define SIZEOF_SSIZE_T 8
+
+/* The size of `void*', as computed by sizeof. */
+
+
+/* The size of `wchar_t', as computed by sizeof. */
+#define SIZEOF_WCHAR_T 4
+
+/* Set to long if unknown. */
+#define TYPEOF_SF_COUNT_T int64_t
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Set to 1 to use the native windows API */
+#define USE_WINDOWS_API 0
+
+/* Version number of package */
+#define VERSION "1.0.31"
+
+/* Set to 1 if windows DLL is being built. */
+#define WIN32_TARGET_DLL 0
+
+/* Target processor is big endian. */
+#define WORDS_BIGENDIAN 0
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Define to 1 if on MINIX. */
+#define _MINIX 0
+
+/* Define as `__inline' or '__inline__' if that's what the C compiler calls it, or to nothing if it is not supported. */
+/* #undef inline */
diff --git a/frameworks/innerkitsimpl/libsnd/include/sndfile.h b/frameworks/innerkitsimpl/libsnd/include/sndfile.h
new file mode 100755
index 0000000000000000000000000000000000000000..f0e65010e7e3db648d84193bfb0ecaea9bcf129c
--- /dev/null
+++ b/frameworks/innerkitsimpl/libsnd/include/sndfile.h
@@ -0,0 +1,817 @@
+/*
+ * Copyright (C) 1999-2016 Erik de Castro Lopo
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * sndfile.h -- system-wide definitions
+ *
+ * API documentation is in the doc/ directory of the source code tarball
+ * and at http://libsndfile.github.io/libsndfile/api.html.
+*/
+
+#ifndef SNDFILE_H
+#define SNDFILE_H
+
+/* This is the version 1.0.X header file. */
+#define SNDFILE_1
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* The following file types can be read and written.
+ * A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
+ * ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
+ * SF_FORMAT_SUBMASK can be used to separate the major and minor file
+ * types.
+*/
+
+enum {
+ /* Major formats. */
+ SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */
+ SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
+ SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
+ SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
+ SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
+ SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
+ SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
+ SF_FORMAT_VOC = 0x080000, /* VOC files. */
+ SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
+ SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
+ SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
+ SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
+ SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
+ SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
+ SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
+ SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
+ SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
+ SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
+ SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
+ SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
+ SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
+ SF_FORMAT_WVE = 0x190000, /* Psion WVE format */
+ SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */
+ SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */
+ SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */
+ SF_FORMAT_MPEG = 0x230000, /* MPEG-1/2 audio stream */
+ /* Subtypes from here on. */
+ SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
+ SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
+ SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
+ SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
+ SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
+ SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
+ SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
+ SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
+ SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
+ SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
+ SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
+ SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
+ SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
+ SF_FORMAT_NMS_ADPCM_16 = 0x0022, /* 16kbs NMS G721-variant encoding. */
+ SF_FORMAT_NMS_ADPCM_24 = 0x0023, /* 24kbs NMS G721-variant encoding. */
+ SF_FORMAT_NMS_ADPCM_32 = 0x0024, /* 32kbs NMS G721-variant encoding. */
+ SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
+ SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
+ SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
+ SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
+ SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
+ SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
+ SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
+ SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
+ SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
+ SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */
+ SF_FORMAT_OPUS = 0x0064, /* Xiph/Skype Opus encoding. */
+ SF_FORMAT_ALAC_16 = 0x0070, /* Apple Lossless Audio Codec (16 bit). */
+ SF_FORMAT_ALAC_20 = 0x0071, /* Apple Lossless Audio Codec (20 bit). */
+ SF_FORMAT_ALAC_24 = 0x0072, /* Apple Lossless Audio Codec (24 bit). */
+ SF_FORMAT_ALAC_32 = 0x0073, /* Apple Lossless Audio Codec (32 bit). */
+ SF_FORMAT_MPEG_LAYER_I = 0x0080, /* MPEG-1 Audio Layer I */
+ SF_FORMAT_MPEG_LAYER_II = 0x0081, /* MPEG-1 Audio Layer II */
+ SF_FORMAT_MPEG_LAYER_III = 0x0082, /* MPEG-2 Audio Layer III */
+ /* Endian-ness options. */
+ SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
+ SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
+ SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
+ SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
+ SF_FORMAT_SUBMASK = 0x0000FFFF,
+ SF_FORMAT_TYPEMASK = 0x0FFF0000,
+ SF_FORMAT_ENDMASK = 0x30000000
+};
+
+/*
+ * The following are the valid command numbers for the sf_command()
+ * interface. The use of these commands is documented in the file
+ * command.html in the doc directory of the source code distribution.
+*/
+enum {
+ SFC_GET_LIB_VERSION = 0x1000,
+ SFC_GET_LOG_INFO = 0x1001,
+ SFC_GET_CURRENT_SF_INFO = 0x1002,
+ SFC_GET_NORM_DOUBLE = 0x1010,
+ SFC_GET_NORM_FLOAT = 0x1011,
+ SFC_SET_NORM_DOUBLE = 0x1012,
+ SFC_SET_NORM_FLOAT = 0x1013,
+ SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
+ SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015,
+ SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
+ SFC_GET_SIMPLE_FORMAT = 0x1021,
+ SFC_GET_FORMAT_INFO = 0x1028,
+ SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
+ SFC_GET_FORMAT_MAJOR = 0x1031,
+ SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
+ SFC_GET_FORMAT_SUBTYPE = 0x1033,
+ SFC_CALC_SIGNAL_MAX = 0x1040,
+ SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
+ SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
+ SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
+ SFC_GET_SIGNAL_MAX = 0x1044,
+ SFC_GET_MAX_ALL_CHANNELS = 0x1045,
+ SFC_SET_ADD_PEAK_CHUNK = 0x1050,
+ SFC_UPDATE_HEADER_NOW = 0x1060,
+ SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
+ SFC_FILE_TRUNCATE = 0x1080,
+ SFC_SET_RAW_START_OFFSET = 0x1090,
+ /* Commands reserved for dithering, which is not implemented. */
+ SFC_SET_DITHER_ON_WRITE = 0x10A0,
+ SFC_SET_DITHER_ON_READ = 0x10A1,
+ SFC_GET_DITHER_INFO_COUNT = 0x10A2,
+ SFC_GET_DITHER_INFO = 0x10A3,
+ SFC_GET_EMBED_FILE_INFO = 0x10B0,
+ SFC_SET_CLIPPING = 0x10C0,
+ SFC_GET_CLIPPING = 0x10C1,
+ SFC_GET_CUE_COUNT = 0x10CD,
+ SFC_GET_CUE = 0x10CE,
+ SFC_SET_CUE = 0x10CF,
+ SFC_GET_INSTRUMENT = 0x10D0,
+ SFC_SET_INSTRUMENT = 0x10D1,
+ SFC_GET_LOOP_INFO = 0x10E0,
+ SFC_GET_BROADCAST_INFO = 0x10F0,
+ SFC_SET_BROADCAST_INFO = 0x10F1,
+ SFC_GET_CHANNEL_MAP_INFO = 0x1100,
+ SFC_SET_CHANNEL_MAP_INFO = 0x1101,
+ SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110,
+ /* Support for Wavex Ambisonics Format */
+ SFC_WAVEX_SET_AMBISONIC = 0x1200,
+ SFC_WAVEX_GET_AMBISONIC = 0x1201,
+ /*
+ * RF64 files can be set so that on-close, writable files that have less
+ * than 4GB of data in them are converted to RIFF/WAV, as per EBU
+ * recommendations.
+ */
+ SFC_RF64_AUTO_DOWNGRADE = 0x1210,
+ SFC_SET_VBR_ENCODING_QUALITY = 0x1300,
+ SFC_SET_COMPRESSION_LEVEL = 0x1301,
+ SFC_SET_OGG_PAGE_LATENCY_MS = 0x1302,
+ SFC_SET_OGG_PAGE_LATENCY = 0x1303,
+ SFC_GET_BITRATE_MODE = 0x1302,
+ SFC_SET_BITRATE_MODE = 0x1303,
+ /* Cart Chunk support */
+ SFC_SET_CART_INFO = 0x1400,
+ SFC_GET_CART_INFO = 0x1401,
+ /* Opus files original samplerate metadata */
+ SFC_SET_ORIGINAL_SAMPLERATE = 0x1500,
+ SFC_GET_ORIGINAL_SAMPLERATE = 0x1501,
+ /* Following commands for testing only. */
+ SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
+ /*
+ * These SFC_SET_ADD_* values are deprecated and will disappear at some
+ * time in the future. They are guaranteed to be here up to and
+ * including version 1.0.8 to avoid breakage of existing software.
+ * They currently do nothing and will continue to do nothing.
+ */
+ SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051,
+ SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
+ SFC_SET_ADD_DITHER_ON_READ = 0x1071
+};
+
+ /*
+ * String types that can be set and read from files. Not all file types
+ * support this and even the file types which support one, may not support
+ * all string types.
+ */
+enum {
+ SF_STR_TITLE = 0x01,
+ SF_STR_COPYRIGHT = 0x02,
+ SF_STR_SOFTWARE = 0x03,
+ SF_STR_ARTIST = 0x04,
+ SF_STR_COMMENT = 0x05,
+ SF_STR_DATE = 0x06,
+ SF_STR_ALBUM = 0x07,
+ SF_STR_LICENSE = 0x08,
+ SF_STR_TRACKNUMBER = 0x09,
+ SF_STR_GENRE = 0x10
+};
+
+/*
+ * Use the following as the start and end index when doing metadata
+ * transcoding.
+*/
+
+#define SF_STR_FIRST SF_STR_TITLE
+#define SF_STR_LAST SF_STR_GENRE
+
+enum {
+ /* True and false */
+ SF_FALSE = 0,
+ SF_TRUE = 1,
+ /* Modes for opening files. */
+ SFM_READ = 0x10,
+ SFM_WRITE = 0x20,
+ SFM_RDWR = 0x30,
+
+ SF_AMBISONIC_NONE = 0x40,
+ SF_AMBISONIC_B_FORMAT = 0x41
+};
+
+/* Public error values. These are guaranteed to remain unchanged for the duration
+ * of the library major version number.
+ * There are also a large number of private error numbers which are internal to
+ * the library which can change at any time.
+*/
+
+enum {
+ SF_ERR_NO_ERROR = 0,
+ SF_ERR_UNRECOGNISED_FORMAT = 1,
+ SF_ERR_SYSTEM = 2,
+ SF_ERR_MALFORMED_FILE = 3,
+ SF_ERR_UNSUPPORTED_ENCODING = 4
+};
+
+
+/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP).
+*/
+
+enum {
+ SF_CHANNEL_MAP_INVALID = 0,
+ SF_CHANNEL_MAP_MONO = 1,
+ SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */
+ SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */
+ SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */
+ SF_CHANNEL_MAP_FRONT_LEFT,
+ SF_CHANNEL_MAP_FRONT_RIGHT,
+ SF_CHANNEL_MAP_FRONT_CENTER,
+ SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */
+ SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */
+ SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */
+ SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */
+ SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
+ SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
+ SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
+ SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
+ SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */
+ SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */
+ SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */
+ SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */
+ SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */
+ SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */
+ SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */
+ SF_CHANNEL_MAP_AMBISONIC_B_W,
+ SF_CHANNEL_MAP_AMBISONIC_B_X,
+ SF_CHANNEL_MAP_AMBISONIC_B_Y,
+ SF_CHANNEL_MAP_AMBISONIC_B_Z,
+ SF_CHANNEL_MAP_MAX
+};
+
+/* Bitrate mode values (for use with SFC_GET/SET_BITRATE_MODE)
+*/
+enum {
+ SF_BITRATE_MODE_CONSTANT = 0,
+ SF_BITRATE_MODE_AVERAGE,
+ SF_BITRATE_MODE_VARIABLE
+};
+
+
+/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
+
+typedef struct sf_private_tag SNDFILE;
+
+/* The following typedef is system specific and is defined when libsndfile is
+ * compiled. sf_count_t will be a 64 bit value when the underlying OS allows
+ * 64 bit file offsets.
+ * On windows, we need to allow the same header file to be compiler by both GCC
+ * and the Microsoft compiler.
+*/
+
+typedef int64_t sf_count_t;
+#ifndef SF_COUNT_MAX
+#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
+#endif
+
+
+/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.
+ * On write, the SF_INFO structure is filled in by the user and passed into
+ * sf_open ().
+*/
+
+struct SF_INFO {
+ sf_count_t frames; /* Used to be called samples. Changed to avoid confusion. */
+ int samplerate;
+ int channels;
+ int format;
+ int sections;
+ int seekable;
+};
+
+typedef struct SF_INFO SF_INFO;
+
+/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
+ * file formats libsndfile supports using the sf_command () interface.
+ *
+ * Using this interface will allow applications to support new file formats
+ * and encoding types when libsndfile is upgraded, without requiring
+ * re-compilation of the application.
+ *
+ * Please consult the libsndfile documentation (particularly the information
+ * on the sf_command () interface) for examples of its use.
+*/
+
+typedef struct {
+ int format;
+ const char *name;
+ const char *extension;
+} SF_FORMAT_INFO;
+
+/*
+ * Enums and typedefs for adding dither on read and write.
+ * Reserved for future implementation.
+*/
+
+enum {
+ SFD_DEFAULT_LEVEL = 0,
+ SFD_CUSTOM_LEVEL = 0x40000000,
+ SFD_NO_DITHER = 500,
+ SFD_WHITE = 501,
+ SFD_TRIANGULAR_PDF = 502
+};
+
+typedef struct {
+ int type;
+ double level;
+ const char *name;
+} SF_DITHER_INFO;
+
+ /* Struct used to retrieve information about a file embedded within a
+ * larger file. See SFC_GET_EMBED_FILE_INFO.
+ */
+
+typedef struct {
+ sf_count_t offset;
+ sf_count_t length;
+} SF_EMBED_FILE_INFO;
+
+/*
+ * Struct used to retrieve cue marker information from a file
+*/
+
+typedef struct {
+ int32_t indx;
+ uint32_t position;
+ int32_t fcc_chunk;
+ int32_t chunk_start;
+ int32_t block_start;
+ uint32_t sample_offset;
+ char name [256];
+} SF_CUE_POINT;
+
+#define SF_CUES_VAR(count) \
+ struct \
+ { \
+ uint32_t cue_count; \
+ SF_CUE_POINT cue_points [count]; \
+ }
+
+typedef SF_CUES_VAR (100) SF_CUES;
+
+/*
+ * Structs used to retrieve music sample information from a file.
+*/
+
+enum {
+ /*
+ * The loop mode field in SF_INSTRUMENT will be one of the following.
+ */
+ SF_LOOP_NONE = 800,
+ SF_LOOP_FORWARD,
+ SF_LOOP_BACKWARD,
+ SF_LOOP_ALTERNATING
+};
+
+typedef struct {
+ int gain;
+ char basenote, detune;
+ char velocity_lo, velocity_hi;
+ char key_lo, key_hi;
+ int loop_count;
+
+ struct {
+ int mode;
+ uint32_t start;
+ uint32_t end;
+ uint32_t count;
+ } loops [16]; /* make variable in a sensible way */
+} SF_INSTRUMENT;
+
+/* Struct used to retrieve loop information from a file. */
+typedef struct {
+ short time_sig_num; /* any positive integer > 0 */
+ short time_sig_den; /* any positive power of 2 > 0 */
+ int loop_mode; /* see SF_LOOP enum */
+
+ int num_beats; /* this is NOT the amount of quarter notes !!! */
+ /* a full bar of 4/4 is 4 beats */
+ /* a full bar of 7/8 is 7 beats */
+
+ float bpm; /* suggestion, as it can be calculated using other fields: */
+ /* file's length, file's sampleRate and our time_sig_den */
+ /* -> bpms are always the amount of _quarter notes_ per minute */
+
+ int root_key; /* MIDI note, or -1 for None */
+ int future [6];
+} SF_LOOP_INFO;
+
+
+/* Struct used to retrieve broadcast (EBU) information from a file.
+ * Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
+*/
+#define SF_BROADCAST_INFO_VAR(coding_hist_size) \
+ struct \
+ { \
+ char description [256]; \
+ char originator [32]; \
+ char originator_reference [32]; \
+ char origination_date [10]; \
+ char origination_time [8]; \
+ uint32_t time_reference_low; \
+ uint32_t time_reference_high; \
+ short version; \
+ char umid [64]; \
+ int16_t loudness_value; \
+ int16_t loudness_range; \
+ int16_t max_true_peak_level; \
+ int16_t max_momentary_loudness; \
+ int16_t max_shortterm_loudness; \
+ char reserved [180]; \
+ uint32_t coding_history_size; \
+ char coding_history [coding_hist_size]; \
+ }
+
+/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */
+typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO;
+
+struct SF_CART_TIMER {
+ char usage [4];
+ int32_t value;
+};
+
+typedef struct SF_CART_TIMER SF_CART_TIMER;
+
+#define SF_CART_INFO_VAR(p_tag_text_size) \
+ struct \
+ { \
+ char version [4]; \
+ char title [64]; \
+ char artist [64]; \
+ char cut_id [64]; \
+ char client_id [64]; \
+ char category [64]; \
+ char classification [64]; \
+ char out_cue [64]; \
+ char start_date [10]; \
+ char start_time [8]; \
+ char end_date [10]; \
+ char end_time [8]; \
+ char producer_app_id [64]; \
+ char producer_app_version [64]; \
+ char user_def [64]; \
+ int32_t level_reference; \
+ SF_CART_TIMER post_timers [8]; \
+ char reserved [276]; \
+ char url [1024]; \
+ uint32_t tag_text_size; \
+ char tag_text [p_tag_text_size]; \
+ }
+
+typedef SF_CART_INFO_VAR (256) SF_CART_INFO;
+
+/* Virtual I/O functionality. */
+
+typedef sf_count_t (*sf_vio_get_filelen) (void *user_data);
+typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data);
+typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data);
+typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data);
+typedef sf_count_t (*sf_vio_tell) (void *user_data);
+
+struct SF_VIRTUAL_IO {
+ sf_vio_get_filelen get_filelen;
+ sf_vio_seek seek;
+ sf_vio_read read;
+ sf_vio_write write;
+ sf_vio_tell tell;
+};
+
+typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO;
+
+
+/* Open the specified file for read, write or both. On error, this will
+ * return a NULL pointer. To find the error number, pass a NULL SNDFILE
+ * to sf_strerror ().
+ * All calls to sf_open() should be matched with a call to sf_close().
+*/
+
+SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo);
+
+
+/* Use the existing file descriptor to create a SNDFILE object. If close_desc
+ * is TRUE, the file descriptor will be closed when sf_close() is called. If
+ * it is FALSE, the descriptor will not be closed.
+ * When passed a descriptor like this, the library will assume that the start
+ * of file header is at the current file offset. This allows sound files within
+ * larger container files to be read and/or written.
+ * On error, this will return a NULL pointer. To find the error number, pass a
+ * NULL SNDFILE to sf_strerror ().
+ * All calls to sf_open_fd() should be matched with a call to sf_close().
+
+*/
+
+SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc);
+
+SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data);
+
+
+/* sf_error () returns a error number which can be translated to a text
+ * string using sf_error_number().
+*/
+
+int sf_error (SNDFILE *sndfile);
+
+
+/* sf_strerror () returns to the caller a pointer to the current error message for
+ * the given SNDFILE.
+*/
+
+const char* sf_strerror (SNDFILE *sndfile);
+
+
+/* sf_error_number () allows the retrieval of the error string for each internal
+ * error number.
+ *
+*/
+
+const char* sf_error_number (int errnum);
+
+
+/* The following two error functions are deprecated but they will remain in the
+ * library for the foreseeable future. The function sf_strerror() should be used
+ * in their place.
+*/
+
+int sf_perror (SNDFILE *sndfile);
+int sf_error_str (SNDFILE *sndfile, char* str, size_t len);
+
+
+/* Allow the caller to retrieve information from or change aspects of the
+ * library behaviour.
+*/
+
+int sf_command (SNDFILE *sndfile, int command, void *data, int datasize);
+
+
+/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
+
+int sf_format_check (const SF_INFO *info);
+
+
+/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
+ * the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
+ * stdio.h function fseek ().
+ * An offset of zero with whence set to SEEK_SET will position the
+ * read / write pointer to the first data sample.
+ * On success sf_seek returns the current position in (multi-channel)
+ * samples from the start of the file.
+ * Please see the libsndfile documentation for moving the read pointer
+ * separately from the write pointer on files open in mode SFM_RDWR.
+ * On error all of these functions return -1.
+*/
+
+enum {
+ SF_SEEK_SET = SEEK_SET,
+ SF_SEEK_CUR = SEEK_CUR,
+ SF_SEEK_END = SEEK_END
+};
+
+sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence);
+
+/* Functions for retrieving and setting string data within sound files.
+ * Not all file types support this features; AIFF and WAV do. For both
+ * functions, the str_type parameter must be one of the SF_STR_* values
+ * defined above.
+ * On error, sf_set_string() returns non-zero while sf_get_string()
+ * returns NULL.
+*/
+
+int sf_set_string (SNDFILE *sndfile, int str_type, const char* str);
+
+const char* sf_get_string (SNDFILE *sndfile, int str_type);
+
+
+/* Return the library version string. */
+
+const char * sf_version_string (void);
+
+/* Return the current byterate at this point in the file. The byte rate in this
+ * case is the number of bytes per second of audio data. For instance, for a
+ * stereo, 18 bit PCM encoded file with an 16kHz sample rate, the byte rate
+ * would be 2 (stereo) * 2 (two bytes per sample) * 16000 => 64000 bytes/sec.
+ * For some file formats the returned value will be accurate and exact, for some
+ * it will be a close approximation, for some it will be the average bitrate for
+ * the whole file and for some it will be a time varying value that was accurate
+ * when the file was most recently read or written.
+ * To get the bitrate, multiple this value by 8.
+ * Returns -1 for unknown.
+*/
+int sf_current_byterate (SNDFILE *sndfile);
+
+/* Functions for reading/writing the waveform data of a sound file.
+*/
+
+sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes);
+sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes);
+
+/* Functions for reading and writing the data chunk in terms of frames.
+ * The number of items actually read/written = frames * number of channels.
+ * sf_xxxx_raw read/writes the raw data bytes from/to the file
+ * sf_xxxx_short passes data in the native short format
+ * sf_xxxx_int passes data in the native int format
+ * sf_xxxx_float passes data in the native float format
+ * sf_xxxx_double passes data in the native double format
+ * All of these read/write function return number of frames read/written.
+*/
+
+sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames);
+sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames);
+
+sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames);
+sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames);
+
+sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames);
+sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames);
+
+sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames);
+sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames);
+
+
+/* Functions for reading and writing the data chunk in terms of items.
+ * Otherwise similar to above.
+ * All of these read/write function return number of items read/written.
+*/
+
+sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items);
+sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items);
+
+sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items);
+sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items);
+
+sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items);
+sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items);
+
+sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items);
+sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items);
+
+
+/* Close the SNDFILE and clean up all memory allocations associated with this
+ * file.
+ * Returns 0 on success, or an error number.
+*/
+
+int sf_close (SNDFILE *sndfile);
+
+
+/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
+ * to force the writing of data to disk. If the file is opened SFM_READ
+ * no action is taken.
+*/
+
+void sf_write_sync (SNDFILE *sndfile);
+
+/* The function sf_wchar_open() is Windows Only!
+ * Open a file passing in a Windows Unicode filename. Otherwise, this is
+ * the same as sf_open().
+*/
+
+#ifdef _WIN32
+SNDFILE* sf_wchar_open (const wchar_t *wpath, int mode, SF_INFO *sfinfo);
+#endif
+
+/* Getting and setting of chunks from within a sound file.
+ *
+ * These functions allow the getting and setting of chunks within a sound file
+ * (for those formats which allow it).
+ *
+ * These functions fail safely. Specifically, they will not allow you to overwrite
+ * existing chunks or add extra versions of format specific reserved chunks but
+ * should allow you to retrieve any and all chunks (may not be implemented for
+ * all chunks or all file formats).
+*/
+
+struct SF_CHUNK_INFO {
+ char id [64]; /* The chunk identifier. */
+ unsigned id_size; /* The size of the chunk identifier. */
+ unsigned datalen; /* The size of that data. */
+ void *data; /* Pointer to the data. */
+};
+
+typedef struct SF_CHUNK_INFO SF_CHUNK_INFO;
+
+/* Set the specified chunk info (must be done before any audio data is written
+ * to the file). This will fail for format specific reserved chunks.
+ * The chunk_info->data pointer must be valid until the file is closed.
+ * Returns SF_ERR_NO_ERROR on success or non-zero on failure.
+*/
+int sf_set_chunk (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info);
+
+/*
+ * An opaque structure to an iterator over the all chunks of a given id
+*/
+typedef struct SF_CHUNK_ITERATOR SF_CHUNK_ITERATOR;
+
+/* Get an iterator for all chunks matching chunk_info.
+ * The iterator will point to the first chunk matching chunk_info.
+ * Chunks are matching, if (chunk_info->id) matches the first
+ * (chunk_info->id_size) bytes of a chunk found in the SNDFILE* handle.
+ * If chunk_info is NULL, an iterator to all chunks in the SNDFILE* handle
+ * is returned.
+ * The values of chunk_info->datalen and chunk_info->data are ignored.
+ * If no matching chunks are found in the sndfile, NULL is returned.
+ * The returned iterator will stay valid until one of the following occurs
+ * a) The sndfile is closed.
+ * b) A new chunk is added using sf_set_chunk().
+ * c) Another chunk iterator function is called on the same SNDFILE* handle
+ * that causes the iterator to be modified.
+ * The memory for the iterator belongs to the SNDFILE* handle and is freed when
+ * sf_close() is called.
+*/
+SF_CHUNK_ITERATOR * sf_get_chunk_iterator (SNDFILE * sndfile, const SF_CHUNK_INFO * chunk_info);
+
+/* Iterate through chunks by incrementing the iterator.
+ * Increments the iterator and returns a handle to the new one.
+ * After this call, iterator will no longer be valid, and you must use the
+ * newly returned handle from now on.
+ * The returned handle can be used to access the next chunk matching
+ * the criteria as defined in sf_get_chunk_iterator().
+ * If iterator points to the last chunk, this will free all resources
+ * associated with iterator and return NULL.
+ * The returned iterator will stay valid until sf_get_chunk_iterator_next
+ * is called again, the sndfile is closed or a new chunk us added.
+*/
+SF_CHUNK_ITERATOR * sf_next_chunk_iterator (SF_CHUNK_ITERATOR * iterator);
+
+/* Get the size of the specified chunk.
+ * If the specified chunk exists, the size will be returned in the
+ * datalen field of the SF_CHUNK_INFO struct.
+ * Additionally, the id of the chunk will be copied to the id
+ * field of the SF_CHUNK_INFO struct and it's id_size field will
+ * be updated accordingly.
+ * If the chunk doesn't exist chunk_info->datalen will be zero, and the
+ * id and id_size fields will be undefined.
+ * The function will return SF_ERR_NO_ERROR on success or non-zero on
+ * failure.
+*/
+int sf_get_chunk_size (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info);
+
+/* Get the specified chunk data.
+ * If the specified chunk exists, up to chunk_info->datalen bytes of
+ * the chunk data will be copied into the chunk_info->data buffer
+ * (allocated by the caller) and the chunk_info->datalen field
+ * updated to reflect the size of the data. The id and id_size
+ * field will be updated according to the retrieved chunk
+ * If the chunk doesn't exist chunk_info->datalen will be zero, and the
+ * id and id_size fields will be undefined.
+ * The function will return SF_ERR_NO_ERROR on success or non-zero on
+ * failure.
+*/
+int sf_get_chunk_data (const SF_CHUNK_ITERATOR * it, SF_CHUNK_INFO * chunk_info);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+#endif /* SNDFILE_H */
diff --git a/frameworks/innerkitsimpl/pulseaudio/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..86bfbf60f1fa03f2b831234c8a273258bd633804
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+libsndfile_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/libsnd"
+
+group("pulseaudio_packages") {
+ deps = [
+ # ":gen_config_header",
+ "$libsndfile_build_path:sndfile",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src:pa_daemon_config",
+ "$pulseaudio_build_path/src:pa_default_config",
+ "$pulseaudio_build_path/src:pa_client_config",
+ "$pulseaudio_build_path/src/pulse:pulse-simple",
+ "$pulseaudio_build_path/src/pulse:pulse-mainloop-glib",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ "$pulseaudio_build_path/src/pulsecore:protocol-native",
+ "$pulseaudio_build_path/src/pulsecore:cli",
+ "$pulseaudio_build_path/src/pulsecore:protocol-cli",
+ "$pulseaudio_build_path/src/daemon:pulseaudio",
+ "$pulseaudio_build_path/src/utils:pacmd",
+ "$pulseaudio_build_path/src/utils:pacat",
+ "$pulseaudio_build_path/src/utils:pactl",
+ "$pulseaudio_build_path/src/modules:modules",
+ "$pulseaudio_build_path/src/modules/hdi:module-hdi-sink",
+ "$pulseaudio_build_path/src/modules/hdi:module-hdi-source",
+ ]
+}
+
+action("gen_config_header") {
+ script = "$pulseaudio_build_path/ohos_paconfig.sh"
+
+ args = [ rebase_path("//third_party/pulseaudio", root_build_dir), rebase_path( "${target_gen_dir}/", root_build_dir),]
+
+ outputs = [ "${target_gen_dir}/config.h", ]
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/conf/client.conf b/frameworks/innerkitsimpl/pulseaudio/conf/client.conf
new file mode 100644
index 0000000000000000000000000000000000000000..9e40ae269bcde0baf52051925c5574e6774c9a13
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/conf/client.conf
@@ -0,0 +1,20 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+## Configuration file for PulseAudio clients. See pulse-client.conf(5) for
+## more information. Default values are commented out. Use either ; or # for
+## commenting.
+cookie-file = /data/local/.pulse_dir/cookie
+
diff --git a/frameworks/innerkitsimpl/pulseaudio/conf/daemon.conf b/frameworks/innerkitsimpl/pulseaudio/conf/daemon.conf
new file mode 100644
index 0000000000000000000000000000000000000000..8bcaf7cda669773c21155936fd2bb94024f9b69f
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/conf/daemon.conf
@@ -0,0 +1,91 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+## Configuration file for the PulseAudio daemon. See pulse-daemon.conf(5) for
+## more information. Default values are commented out. Use either ; or # for
+## commenting.
+
+; daemonize = no
+; fail = yes
+; allow-module-loading = yes
+; disallow-exit = yes
+disallow-exit = yes
+allow-exit = no
+; use-pid-file = yes
+; system-instance = no
+; local-server-type = user
+; enable-shm = yes
+; enable-memfd = yes
+; shm-size-bytes = 0 # setting this 0 will use the system-default, usually 64 MiB
+; lock-memory = no
+; cpu-limit = no
+
+; high-priority = yes
+; nice-level = -11
+
+; realtime-scheduling = yes
+; realtime-priority = 5
+
+exit-idle-time = -1
+; scache-idle-time = 20
+
+; dl-search-path = (depends on architecture)
+
+; load-default-script-file = yes
+; default-script-file =
+
+; log-target = auto
+; log-level = notice
+; log-meta = no
+; log-time = no
+; log-backtrace = 0
+
+; resample-method = speex-float-1
+; avoid-resampling = false
+; enable-remixing = yes
+; remixing-use-all-sink-channels = yes
+; enable-lfe-remixing = no
+; lfe-crossover-freq = 0
+
+flat-volumes = no
+
+; rlimit-fsize = -1
+; rlimit-data = -1
+; rlimit-stack = -1
+; rlimit-core = -1
+; rlimit-as = -1
+; rlimit-rss = -1
+; rlimit-nproc = -1
+; rlimit-nofile = 256
+; rlimit-memlock = -1
+; rlimit-locks = -1
+; rlimit-sigpending = -1
+; rlimit-msgqueue = -1
+; rlimit-nice = 31
+; rlimit-rtprio = 9
+; rlimit-rttime = 200000
+
+; default-sample-format = s16le
+; default-sample-rate = 44100
+; alternate-sample-rate = 48000
+; default-sample-channels = 2
+; default-channel-map = front-left,front-right
+
+; default-fragments = 4
+; default-fragment-size-msec = 25
+
+; enable-deferred-volume = yes
+deferred-volume-safety-margin-usec = 1
+; deferred-volume-extra-delay-usec = 0
diff --git a/frameworks/innerkitsimpl/pulseaudio/conf/default.pa b/frameworks/innerkitsimpl/pulseaudio/conf/default.pa
new file mode 100644
index 0000000000000000000000000000000000000000..1f08228fb4926b3093c179fa8751d098f17d059a
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/conf/default.pa
@@ -0,0 +1,34 @@
+#!/usr/bin/pulseaudio -nF
+#
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+# This startup script is used only if PulseAudio is started per-user
+# (i.e. not in system mode)
+
+.fail
+
+# Load mandatory modules
+load-module libmodule-cli-protocol-unix.z.so
+load-module libmodule-native-protocol-unix.z.so auth-cookie=/data/local/.pulse_dir/cookie
+
+### Load audio drivers statically
+### (it's probably better to not load these drivers manually, but instead
+### use module-udev-detect -- see below -- for doing this automatically)
+load-module libmodule-suspend-on-idle.z.so timeout=1
+
+### Make some devices default
+#set-default-sink output
+#set-default-source input
diff --git a/frameworks/innerkitsimpl/pulseaudio/include/config.h b/frameworks/innerkitsimpl/pulseaudio/include/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..219aee0cedac6071fc119df28c1458a3ef4e7c57
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/include/config.h
@@ -0,0 +1,285 @@
+/*
+ * Autogenerated by the Meson build system.
+ * Do not edit, your changes will be lost.
+ */
+
+#pragma once
+
+#define DESKTOPFILEDIR "/usr/local/share/applications"
+
+#define DISABLE_ORC 1
+
+#define ENABLE_LEGACY_DATABASE_ENTRY_FORMAT 1
+
+#define GETGROUPS_T gid_t
+
+#define GETTEXT_PACKAGE "pulseaudio"
+
+#define HAVE_ACCEPT4 1
+
+#define HAVE_ALSA 1
+
+#define HAVE_ALSA_UCM 1
+
+#define HAVE_ARPA_INET_H 1
+
+#define HAVE_ATOMIC_BUILTINS 1
+
+#define HAVE_ATOMIC_BUILTINS_MEMORY_MODEL 1
+
+#define HAVE_BYTESWAP_H 1
+
+#define HAVE_CLOCK_GETTIME 1
+
+#define HAVE_COREAUDIO 0
+
+#define HAVE_CTIME_R 1
+
+#define HAVE_DECL_ENVIRON 1
+
+#define HAVE_DECL_SOUND_PCM_READ_BITS 1
+
+#define HAVE_DECL_SOUND_PCM_READ_CHANNELS 1
+
+#define HAVE_DECL_SOUND_PCM_READ_RATE 1
+
+#define HAVE_DLADDR 1
+
+#define HAVE_DLFCN_H 1
+
+#define HAVE_FAST_64BIT_OPERATIONS 1
+
+#define HAVE_FCHMOD 1
+
+#define HAVE_FCHOWN 1
+
+#define HAVE_FORK 1
+
+#define HAVE_FSTAT 1
+
+#define HAVE_GETADDRINFO 1
+
+#define HAVE_GETGRGID_R 1
+
+#define HAVE_GETGRNAM_R 1
+
+#define HAVE_GETPWNAM_R 1
+
+#define HAVE_GETPWUID_R 1
+
+#define HAVE_GETTIMEOFDAY 1
+
+#define HAVE_GETUID 1
+
+#define HAVE_GRP_H 1
+
+#define HAVE_HAL_COMPAT 1
+
+#define HAVE_ICONV 1
+
+#define HAVE_IPV6 1
+
+#define HAVE_LANGINFO_H 1
+
+#define HAVE_LINUX_SOCKIOS_H 1
+
+#define HAVE_LOCALE_H 1
+
+#define HAVE_LRINTF 1
+
+#define HAVE_LSTAT 1
+
+#define HAVE_MEMFD_CREATE 1
+
+#define HAVE_MKFIFO 1
+
+#define HAVE_MLOCK 1
+
+/* Compiler supports mmx. */
+#define HAVE_MMX 1
+
+#define HAVE_NANOSLEEP 1
+
+#define HAVE_NETDB_H 1
+
+#define HAVE_NETINET_IN_H 1
+
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+#define HAVE_NETINET_IP_H 1
+
+#define HAVE_NETINET_TCP_H 1
+
+#define HAVE_OPEN64 1
+
+#define HAVE_OPENSSL 1
+
+#define HAVE_OSS_OUTPUT 1
+
+#define HAVE_OSS_WRAPPER 1
+
+#define HAVE_PCREPOSIX_H 1
+
+#define HAVE_PIPE 1
+
+#define HAVE_PIPE2 1
+
+#define HAVE_POLL_H 1
+
+#define HAVE_POSIX_FADVISE 1
+
+#define HAVE_POSIX_MADVISE 1
+
+#define HAVE_POSIX_MEMALIGN 1
+
+#define HAVE_PPOLL 1
+
+#define HAVE_PTHREAD 1
+
+#define HAVE_PTHREAD_GETNAME_NP 1
+
+#define HAVE_PTHREAD_PRIO_INHERIT 1
+
+#define HAVE_PTHREAD_SETAFFINITY_NP 1
+
+#define HAVE_PTHREAD_SETNAME_NP 1
+
+#define HAVE_PWD_H 1
+
+#define HAVE_READLINK 1
+
+#define HAVE_REGEX_H 1
+
+#define HAVE_RUNNING_FROM_BUILD_TREE 1
+
+#define HAVE_SCHED_H 1
+
+#define HAVE_SETEGID 1
+
+#define HAVE_SETEUID 1
+
+#define HAVE_SETPGID 1
+
+#define HAVE_SETREGID 1
+
+#define HAVE_SETRESGID 1
+
+#define HAVE_SETRESUID 1
+
+#define HAVE_SETREUID 1
+
+#define HAVE_SETSID 1
+
+#define HAVE_SIGACTION 1
+
+#define HAVE_SIGXCPU 1
+
+/* Compiler supports sse. */
+#define HAVE_SSE 1
+
+#define HAVE_STDINT_H 1
+
+#define HAVE_STD_BOOL 1
+
+#define HAVE_STRERROR_R 1
+
+#define HAVE_STRTOD_L 1
+
+#define HAVE_STRTOF 1
+
+#define HAVE_SYMLINK 1
+
+#define HAVE_SYSCONF 1
+
+#define HAVE_SYSLOG_H 1
+
+#define HAVE_SYS_EVENTFD_H 1
+
+#define HAVE_SYS_IOCTL_H 1
+
+#define HAVE_SYS_MMAN_H 1
+
+#define HAVE_SYS_PRCTL_H 1
+
+#define HAVE_SYS_RESOURCE_H 1
+
+#define HAVE_SYS_SELECT_H 1
+
+#define HAVE_SYS_SOCKET_H 1
+
+#define HAVE_SYS_SYSCALL_H 1
+
+#define HAVE_SYS_UIO_H 1
+
+#define HAVE_SYS_UN_H 1
+
+#define HAVE_SYS_WAIT_H 1
+
+#define HAVE_UNAME 1
+
+#define HAVE_WAVEOUT 0
+
+#define ICONV_CONST
+
+#define LIBICONV_PLUG 1
+
+#define MESON_BUILD 1
+
+#define PACKAGE "pulseaudio"
+
+#define PACKAGE_NAME "pulseaudio"
+
+#define PACKAGE_VERSION "14.0-271-g1a19"
+
+#define PA_ACCESS_GROUP "pulse-access"
+
+#define PA_ALSA_PATHS_DIR "/usr/local/share/pulseaudio/alsa-mixer/paths"
+
+#define PA_ALSA_PROFILE_SETS_DIR "/usr/local/share/pulseaudio/alsa-mixer/profile-sets"
+
+#define PA_API_VERSION 12
+
+#define PA_BINARY "/system/bin"
+
+#define PA_BUILDDIR "/home/workspace/pa/pulseaudio/confgure"
+
+#define PA_CFLAGS "Not yet supported on meson"
+
+#define PA_DEFAULT_CONFIG_DIR "/system/etc/pulse"
+
+#define PA_DEFAULT_CONFIG_DIR_UNQUOTED /usr/local/etc/pulse
+
+#define PA_DLSEARCHPATH "/system/lib"
+
+#define PA_INCDIR /usr/local/include
+
+#define PA_LIBDIR /usr/local/lib/x86_64-linux-gnu
+
+#define PA_MACHINE_ID "/usr/local/etc/machine-id"
+
+#define PA_MACHINE_ID_FALLBACK "/var/local/lib/dbus/machine-id"
+
+#define PA_MAJOR 14
+
+#define PA_MINOR 0
+
+#define PA_PROTOCOL_VERSION 35
+
+#define PA_SOEXT ".so"
+
+#define PA_SYSTEM_CONFIG_PATH "/var/local/lib/pulse"
+
+#define PA_SYSTEM_GROUP "pulse"
+
+#define PA_SYSTEM_RUNTIME_PATH "/var/local/run/pulse"
+
+#define PA_SYSTEM_STATE_PATH "/var/local/lib/pulse"
+
+#define PA_SYSTEM_USER "pulse"
+
+#define PULSEDSP_LOCATION /usr/local/lib/x86_64-linux-gnu/pulseaudio
+
+#define PULSE_LOCALEDIR "/usr/local/share/locale"
+
+#define top_srcdir /home/workspace/pa/pulseaudio
+
diff --git a/frameworks/innerkitsimpl/pulseaudio/include/ltdl.h b/frameworks/innerkitsimpl/pulseaudio/include/ltdl.h
new file mode 100644
index 0000000000000000000000000000000000000000..9ce4b7d3ea355c1df5f3a3581c70c5a515f2ff23
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/include/ltdl.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file stubs the functionality of
+ * libtool library used by pulseaudio.
+ */
+
+#include
+
+typedef void* lt_dlhandle;
+
+const char *lt_dlerror(void);
+const char* lt_dlgetsearchpath();
+int lt_dlclose(lt_dlhandle handle);
+lt_dlhandle lt_dlopenext(const char *filename);
+void* lt_dlsym(lt_dlhandle handle, const char *symbol);
diff --git a/frameworks/innerkitsimpl/pulseaudio/include/pulse/version.h b/frameworks/innerkitsimpl/pulseaudio/include/pulse/version.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4fda9325c5ed573e7d2cf967b0d7a787309dbb1
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/include/pulse/version.h
@@ -0,0 +1,70 @@
+#ifndef fooversionhfoo /*-*-C-*-*/
+#define fooversionhfoo
+
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+ Copyright 2006 Pierre Ossman for Cendio AB
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see .
+***/
+
+/* WARNING: Make sure to edit the real source file version.h.in! */
+
+#include
+
+/** \file
+ * Define header version */
+
+PA_C_DECL_BEGIN
+
+/** Return the version of the header files. Keep in mind that this is
+a macro and not a function, so it is impossible to get the pointer of
+it. */
+#define pa_get_headers_version() ("14.0.0")
+
+/** Return the version of the library the current application is
+ * linked to. */
+const char* pa_get_library_version(void);
+
+/** The current API version. Version 6 relates to Polypaudio
+ * 0.6. Prior versions (i.e. Polypaudio 0.5.1 and older) have
+ * PA_API_VERSION undefined. Please note that this is only ever
+ * increased on incompatible API changes! */
+#define PA_API_VERSION 12
+
+/** The current protocol version. Version 8 relates to Polypaudio
+ * 0.8/PulseAudio 0.9. */
+#define PA_PROTOCOL_VERSION 35
+
+/** The major version of PA. \since 0.9.15 */
+#define PA_MAJOR 14
+
+/** The minor version of PA. \since 0.9.15 */
+#define PA_MINOR 0
+
+/** The micro version of PA (will always be 0 from v1.0 onwards). \since 0.9.15 */
+#define PA_MICRO 0
+
+/** Evaluates to TRUE if the PulseAudio library version is equal or
+ * newer than the specified. \since 0.9.16 */
+#define PA_CHECK_VERSION(major,minor,micro) \
+ ((PA_MAJOR > (major)) || \
+ (PA_MAJOR == (major) && PA_MINOR > (minor)) || \
+ (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro)))
+
+PA_C_DECL_END
+
+#endif
diff --git a/frameworks/innerkitsimpl/pulseaudio/ohos_paconfig.sh b/frameworks/innerkitsimpl/pulseaudio/ohos_paconfig.sh
new file mode 100644
index 0000000000000000000000000000000000000000..cca462f023afe27c3274e0a0a05f67ac1356e66b
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/ohos_paconfig.sh
@@ -0,0 +1,75 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/bash
+
+PASRC_PATH=$1
+PASRC_OUT_PATH=$2
+
+function clean_pa_src() {
+ echo "Clean local generated files"
+ rm -rf ABOUT-NLS Makefile Makefile.in PulseAudioConfig.cmake PulseAudioConfigVersion.cmake aclocal.m4
+ rm -rf autom4te.cache/ build-aux/ config.h config.h.in config.h.in~ config.log config.status configure
+ rm -rf libpulse-mainloop-glib.pc libpulse-simple.pc libpulse.pc libtool stamp-h1
+}
+
+clean_pa_src
+
+sed -i 's/\.\/git-version-gen .tarball-version//g' configure.ac
+sed -i 's/\[m4_esyscmd()\],//g' configure.ac
+sed -i 's/src doxygen man po/src doxygen man #po/g' Makefile.am
+
+PA_CONFIG_OPTIONS="
+ --without-caps
+ --disable-alsa
+ --disable-x11
+ --disable-oss-output
+ --disable-coreaudio-output
+ --disable-alsa
+ --disable-esound
+ --disable-gsettings
+ --disable-dbus
+ --disable-udev
+ --disable-ipv6
+ --disable-openssl
+ --disable-avahi
+ --disable-jack
+"
+# We check for this here, because if pkg-config is not found in the
+# system, it's likely that the pkg.m4 macro file is also not present,
+# which will make PKG_PROG_PKG_CONFIG be undefined and the generated
+# configure file faulty.
+if ! pkg-config --version &>/dev/null; then
+ echo "pkg-config is required to bootstrap this program"
+
+fi
+# Other necessary programs
+if ! autopoint --version &>/dev/null ; then
+ echo "autopoint is required to bootstrap this program"
+
+fi
+
+autoreconf --force --install --verbose
+
+if test "x$NOCONFIGURE" = "x"; then
+ CFLAGS="$CFLAGS -g -O0" $PASRC_PATH/configure --enable-force-preopen ${PA_CONFIG_OPTIONS} && \
+ make clean
+fi
+
+sed -i 's/#define ENABLE_NLS 1//g' config.h
+sed -i 's/#define HAVE_SHM_OPEN 1//g' config.h
+sed -i 's/#define HAVE_RUNNING_FROM_BUILD_TREE 1//g' config.h
+sed -i 's/#define HAVE_CPUID_H 1//g' config.h
+sed -i 's/#define HAVE_EXECINFO_H 1//g' config.h
+sed -i 's/#define HAVE_MEMFD 1//g' config.h
+echo "#define PACKAGE_NAME \"pulseaudio\"" >> config.h
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..da8fac3376cf8f0a72865103e672a11046c78420
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/BUILD.gn
@@ -0,0 +1,150 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+libsndfile_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/libsnd"
+
+config("pulsecommon_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir/include",
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ "$pulseaudio_build_path/include",
+ "$libsndfile_build_path/include",
+ "$pulseaudio_dir/src/pulse",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-implicit-function-declaration",
+ "-Wno-unused-function",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ ]
+}
+
+ohos_source_set("pulsecommon_sources") {
+ sources = [
+ "$pulseaudio_dir/src/pulse/client-conf.c",
+ "$pulseaudio_dir/src/pulse/error.c",
+ "$pulseaudio_dir/src/pulse/fork-detect.c",
+ "$pulseaudio_dir/src/pulse/format.c",
+ "$pulseaudio_dir/src/pulse/json.c",
+ "$pulseaudio_dir/src/pulse/mainloop-api.c",
+ "$pulseaudio_dir/src/pulse/xmalloc.c",
+ "$pulseaudio_dir/src/pulse/proplist.c",
+ "$pulseaudio_dir/src/pulse/utf8.c",
+ "$pulseaudio_dir/src/pulse/channelmap.c",
+ "$pulseaudio_dir/src/pulse/sample.c",
+ "$pulseaudio_dir/src/pulse/util.c",
+ "$pulseaudio_dir/src/pulse/timeval.c",
+ "$pulseaudio_dir/src/pulse/rtclock.c",
+ "$pulseaudio_build_path/src/pulse/ohos_pa_volume.c",
+ "$pulseaudio_dir/src/pulsecore/authkey.c",
+ "$pulseaudio_dir/src/pulsecore/conf-parser.c",
+ "$pulseaudio_dir/src/pulsecore/core-error.c",
+ "$pulseaudio_dir/src/pulsecore/core-format.c",
+ "$pulseaudio_dir/src/pulsecore/core-rtclock.c",
+ "$pulseaudio_dir/src/pulsecore/core-util.c",
+ "$pulseaudio_dir/src/pulsecore/dynarray.c",
+ "$pulseaudio_dir/src/pulsecore/fdsem.c",
+ "$pulseaudio_dir/src/pulsecore/flist.c",
+ "$pulseaudio_dir/src/pulsecore/g711.c",
+ "$pulseaudio_dir/src/pulsecore/hashmap.c",
+ "$pulseaudio_dir/src/pulsecore/i18n.c",
+ "$pulseaudio_dir/src/pulsecore/idxset.c",
+ "$pulseaudio_dir/src/pulsecore/arpa-inet.c",
+ "$pulseaudio_dir/src/pulsecore/iochannel.c",
+ "$pulseaudio_dir/src/pulsecore/ioline.c",
+ "$pulseaudio_dir/src/pulsecore/ipacl.c",
+ "$pulseaudio_dir/src/pulsecore/lock-autospawn.c",
+ "$pulseaudio_dir/src/pulsecore/log.c",
+ "$pulseaudio_dir/src/pulsecore/ratelimit.c",
+ "$pulseaudio_dir/src/pulsecore/mcalign.c",
+ "$pulseaudio_dir/src/pulsecore/memblock.c",
+ "$pulseaudio_dir/src/pulsecore/memblockq.c",
+ "$pulseaudio_dir/src/pulsecore/memchunk.c",
+ "$pulseaudio_dir/src/pulsecore/native-common.c",
+ "$pulseaudio_dir/src/pulsecore/once.c",
+ "$pulseaudio_dir/src/pulsecore/packet.c",
+ "$pulseaudio_dir/src/pulsecore/parseaddr.c",
+ "$pulseaudio_dir/src/pulsecore/pdispatch.c",
+ "$pulseaudio_dir/src/pulsecore/pid.c",
+ "$pulseaudio_dir/src/pulsecore/pipe.c",
+ "$pulseaudio_dir/src/pulsecore/memtrap.c",
+ "$pulseaudio_dir/src/pulsecore/aupdate.c",
+ "$pulseaudio_dir/src/pulsecore/proplist-util.c",
+ "$pulseaudio_dir/src/pulsecore/pstream-util.c",
+ "$pulseaudio_dir/src/pulsecore/pstream.c",
+ "$pulseaudio_dir/src/pulsecore/queue.c",
+ "$pulseaudio_dir/src/pulsecore/random.c",
+ "$pulseaudio_dir/src/pulsecore/srbchannel.c",
+ "$pulseaudio_dir/src/pulsecore/sample-util.c",
+ "$pulseaudio_dir/src/pulsecore/shm.c",
+ "$pulseaudio_dir/src/pulsecore/bitset.c",
+ "$pulseaudio_dir/src/pulsecore/socket-client.c",
+ "$pulseaudio_dir/src/pulsecore/socket-server.c",
+ "$pulseaudio_dir/src/pulsecore/socket-util.c",
+ "$pulseaudio_dir/src/pulsecore/strbuf.c",
+ "$pulseaudio_dir/src/pulsecore/strlist.c",
+ "$pulseaudio_dir/src/pulsecore/tagstruct.c",
+ "$pulseaudio_dir/src/pulsecore/time-smoother.c",
+ "$pulseaudio_dir/src/pulsecore/tokenizer.c",
+ "$pulseaudio_dir/src/pulsecore/usergroup.c",
+ "$pulseaudio_dir/src/pulsecore/sndfile-util.c",
+ "$pulseaudio_dir/src/pulsecore/mutex-posix.c",
+ "$pulseaudio_dir/src/pulsecore/semaphore-posix.c",
+ "$pulseaudio_dir/src/pulsecore/thread-posix.c",
+ ]
+
+ configs = [ ":pulsecommon_config" ]
+}
+
+ohos_shared_library("pulsecommon") {
+ deps = [
+ ":pulsecommon_sources",
+ "$libsndfile_build_path:sndfile",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+ohos_prebuilt_etc("pa_daemon_config") {
+ source = "$pulseaudio_build_path/conf/daemon.conf"
+
+ subsystem_name = "multimedia"
+ module_install_dir = "etc/pulse"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_prebuilt_etc("pa_default_config") {
+ source = "$pulseaudio_build_path/conf/default.pa"
+ subsystem_name = "multimedia"
+ module_install_dir = "etc/pulse"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_prebuilt_etc("pa_client_config") {
+ source = "$pulseaudio_build_path/conf/client.conf"
+ subsystem_name = "multimedia"
+ module_install_dir = "etc/pulse"
+ part_name = "multimedia_audio_standard"
+}
+
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/daemon/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/daemon/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..89868e9edb9fd10c2a6e256a7a5f200f070b0e1c
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/daemon/BUILD.gn
@@ -0,0 +1,61 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+pulseaudio_dir = "//third_party/pulseaudio"
+
+config("daemon_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_build_path/include",
+ "$pulseaudio_dir/src/daemon",
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-function",
+ "-DHAVE_CONFIG_H",
+ "-DHAVE_UNISTD_H",
+ ]
+}
+
+ohos_source_set("pulseaudio_sources") {
+ sources = [
+ "$pulseaudio_dir/src/daemon/caps.c",
+ "$pulseaudio_dir/src/daemon/cmdline.c",
+ "$pulseaudio_dir/src/daemon/cpulimit.c",
+ "$pulseaudio_build_path/src/daemon/ohos_daemon-conf.c",
+ "$pulseaudio_build_path/src/daemon/ohos_pa_main.c",
+ ]
+
+ configs = [ ":daemon_config" ]
+}
+
+ohos_shared_library("pulseaudio") {
+ ldflags = [ "-ffast-math" ]
+ deps = [
+ ":pulseaudio_sources",
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ "$pulseaudio_build_path/src:pulsecommon",
+ ]
+
+ part_name = "multimedia_audio_standard"
+ subsystem_name = "multimedia"
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_daemon-conf.c b/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_daemon-conf.c
new file mode 100644
index 0000000000000000000000000000000000000000..4a6fe0b3d37e756cf0634953a799de29c5804e56
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_daemon-conf.c
@@ -0,0 +1,872 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+ Copyright 2006 Pierre Ossman for Cendio AB
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_SCHED_H
+#include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "daemon-conf.h"
+
+#define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa"
+#define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa"
+#define DEFAULT_SYSTEM_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "system.pa"
+
+#define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
+#define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
+
+#define ENV_SCRIPT_FILE "PULSE_SCRIPT"
+#define ENV_CONFIG_FILE "PULSE_CONFIG"
+#define ENV_DL_SEARCH_PATH "PULSE_DLPATH"
+
+static const pa_daemon_conf default_conf = {
+ .cmd = PA_CMD_DAEMON,
+ .daemonize = false,
+ .fail = true,
+ .high_priority = true,
+ .nice_level = -11,
+ .realtime_scheduling = true,
+ .realtime_priority = 5, /* Half of JACK's default rtprio */
+ .disallow_module_loading = false,
+ .disallow_exit = false,
+ .flat_volumes = false,
+ .rescue_streams = true,
+ .exit_idle_time = -1,
+ .scache_idle_time = 20,
+ .script_commands = NULL,
+ .dl_search_path = NULL,
+ .load_default_script_file = true,
+ .default_script_file = NULL,
+ .log_target = NULL,
+ .log_level = PA_LOG_NOTICE,
+ .log_backtrace = 0,
+ .log_meta = false,
+ .log_time = false,
+ .resample_method = PA_RESAMPLER_AUTO,
+ .avoid_resampling = false,
+ .disable_remixing = false,
+ .remixing_use_all_sink_channels = true,
+ .remixing_produce_lfe = false,
+ .remixing_consume_lfe = false,
+ .lfe_crossover_freq = 0,
+ .config_file = NULL,
+ .use_pid_file = true,
+ .system_instance = false,
+#ifdef HAVE_DBUS
+ .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
+#endif
+ .no_cpu_limit = true,
+ .disable_shm = false,
+ .disable_memfd = false,
+ .lock_memory = false,
+ .deferred_volume = true,
+ .default_n_fragments = 4,
+ .default_fragment_size_msec = 25,
+ .deferred_volume_safety_margin_usec = 8000,
+ .deferred_volume_extra_delay_usec = 0,
+ .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
+ .alternate_sample_rate = 48000,
+ .default_channel_map = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
+ .shm_size = 0
+#ifdef HAVE_SYS_RESOURCE_H
+ ,.rlimit_fsize = { .value = 0, .is_set = false },
+ .rlimit_data = { .value = 0, .is_set = false },
+ .rlimit_stack = { .value = 0, .is_set = false },
+ .rlimit_core = { .value = 0, .is_set = false }
+#ifdef RLIMIT_RSS
+ ,.rlimit_rss = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_NPROC
+ ,.rlimit_nproc = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_NOFILE
+ ,.rlimit_nofile = { .value = 256, .is_set = true }
+#endif
+#ifdef RLIMIT_MEMLOCK
+ ,.rlimit_memlock = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_AS
+ ,.rlimit_as = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_LOCKS
+ ,.rlimit_locks = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_SIGPENDING
+ ,.rlimit_sigpending = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ ,.rlimit_msgqueue = { .value = 0, .is_set = false }
+#endif
+#ifdef RLIMIT_NICE
+ ,.rlimit_nice = { .value = 31, .is_set = true } /* nice level of -11 */
+#endif
+#ifdef RLIMIT_RTPRIO
+ ,.rlimit_rtprio = { .value = 9, .is_set = true } /* One below JACK's default for the server */
+#endif
+#ifdef RLIMIT_RTTIME
+ ,.rlimit_rttime = { .value = 200*PA_USEC_PER_MSEC, .is_set = true } /* rtkit's limit is 200 ms */
+#endif
+#endif
+};
+
+pa_daemon_conf *pa_daemon_conf_new(void) {
+ pa_daemon_conf *c;
+
+ c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
+
+#ifdef OS_IS_WIN32
+ c->dl_search_path = pa_sprintf_malloc("%s" PA_PATH_SEP "lib" PA_PATH_SEP "pulse-%d.%d" PA_PATH_SEP "modules",
+ pa_win32_get_toplevel(NULL), PA_MAJOR, PA_MINOR);
+#else
+#ifdef HAVE_RUNNING_FROM_BUILD_TREE
+ if (pa_run_from_build_tree()) {
+ pa_log_notice("Detected that we are run from the build tree, fixing search path.");
+#ifdef MESON_BUILD
+ c->dl_search_path = pa_xstrdup(PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "modules");
+#else
+ c->dl_search_path = pa_xstrdup(PA_BUILDDIR);
+#endif // Endof #ifdef MESON_BUILD
+ } else
+#endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE
+ c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
+#endif // Endof #ifdef OS_IS_WIN32
+
+ return c;
+}
+
+void pa_daemon_conf_free(pa_daemon_conf *c) {
+ pa_assert(c);
+
+ pa_xfree(c->script_commands);
+ pa_xfree(c->dl_search_path);
+ pa_xfree(c->default_script_file);
+
+ if (c->log_target)
+ pa_log_target_free(c->log_target);
+
+ pa_xfree(c->config_file);
+ pa_xfree(c);
+}
+
+int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
+ pa_log_target *log_target = NULL;
+
+ pa_assert(c);
+ pa_assert(string);
+
+ if (!pa_streq(string, "auto")) {
+ log_target = pa_log_parse_target(string);
+
+ if (!log_target)
+ return -1;
+ }
+
+ c->log_target = log_target;
+
+ return 0;
+}
+
+int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
+ uint32_t u;
+ pa_assert(c);
+ pa_assert(string);
+
+ if (pa_atou(string, &u) >= 0) {
+ if (u >= PA_LOG_LEVEL_MAX)
+ return -1;
+
+ c->log_level = (pa_log_level_t) u;
+ } else if (pa_startswith(string, "debug"))
+ c->log_level = PA_LOG_DEBUG;
+ else if (pa_startswith(string, "info"))
+ c->log_level = PA_LOG_INFO;
+ else if (pa_startswith(string, "notice"))
+ c->log_level = PA_LOG_NOTICE;
+ else if (pa_startswith(string, "warn"))
+ c->log_level = PA_LOG_WARN;
+ else if (pa_startswith(string, "err"))
+ c->log_level = PA_LOG_ERROR;
+ else
+ return -1;
+
+ return 0;
+}
+
+int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
+ int m;
+ pa_assert(c);
+ pa_assert(string);
+
+ if ((m = pa_parse_resample_method(string)) < 0)
+ return -1;
+
+ c->resample_method = m;
+ return 0;
+}
+
+int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) {
+ pa_assert(c);
+ pa_assert(string);
+
+ if (pa_streq(string, "user"))
+ c->local_server_type = PA_SERVER_TYPE_USER;
+ else if (pa_streq(string, "system")) {
+ c->local_server_type = PA_SERVER_TYPE_SYSTEM;
+ } else if (pa_streq(string, "none")) {
+ c->local_server_type = PA_SERVER_TYPE_NONE;
+ } else
+ return -1;
+
+ return 0;
+}
+
+static int parse_log_target(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_daemon_conf_set_log_target(c, state->rvalue) < 0) {
+ pa_log(_("[%s:%u] Invalid log target '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int parse_log_level(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_daemon_conf_set_log_level(c, state->rvalue) < 0) {
+ pa_log(_("[%s:%u] Invalid log level '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int parse_resample_method(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_daemon_conf_set_resample_method(c, state->rvalue) < 0) {
+ pa_log(_("[%s:%u] Invalid resample method '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef HAVE_SYS_RESOURCE_H
+static int parse_rlimit(pa_config_parser_state *state) {
+ struct pa_rlimit *r;
+
+ pa_assert(state);
+
+ r = state->data;
+
+ if (state->rvalue[strspn(state->rvalue, "\t ")] == 0) {
+ /* Empty string */
+ r->is_set = 0;
+ r->value = 0;
+ } else {
+ int32_t k;
+ if (pa_atoi(state->rvalue, &k) < 0) {
+ pa_log(_("[%s:%u] Invalid rlimit '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+ r->is_set = k >= 0;
+ r->value = k >= 0 ? (rlim_t) k : 0;
+ }
+
+ return 0;
+}
+#endif
+
+static int parse_sample_format(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ pa_sample_format_t f;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if ((f = pa_parse_sample_format(state->rvalue)) < 0) {
+ pa_log(_("[%s:%u] Invalid sample format '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->default_sample_spec.format = f;
+ return 0;
+}
+
+static int parse_sample_rate(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ uint32_t r;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
+ pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->default_sample_spec.rate = r;
+ return 0;
+}
+
+static int parse_alternate_sample_rate(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ uint32_t r;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
+ pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->alternate_sample_rate = r;
+ return 0;
+}
+
+struct channel_conf_info {
+ pa_daemon_conf *conf;
+ bool default_sample_spec_set;
+ bool default_channel_map_set;
+};
+
+static int parse_sample_channels(pa_config_parser_state *state) {
+ struct channel_conf_info *i;
+ int32_t n;
+
+ pa_assert(state);
+
+ i = state->data;
+
+ if (pa_atoi(state->rvalue, &n) < 0 || !pa_channels_valid(n)) {
+ pa_log(_("[%s:%u] Invalid sample channels '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ i->conf->default_sample_spec.channels = (uint8_t) n;
+ i->default_sample_spec_set = true;
+ return 0;
+}
+
+static int parse_channel_map(pa_config_parser_state *state) {
+ struct channel_conf_info *i;
+
+ pa_assert(state);
+
+ i = state->data;
+
+ if (!pa_channel_map_parse(&i->conf->default_channel_map, state->rvalue)) {
+ pa_log(_("[%s:%u] Invalid channel map '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ i->default_channel_map_set = true;
+ return 0;
+}
+
+static int parse_fragments(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ int32_t n;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_atoi(state->rvalue, &n) < 0 || n < 2) {
+ pa_log(_("[%s:%u] Invalid number of fragments '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->default_n_fragments = (unsigned) n;
+ return 0;
+}
+
+static int parse_fragment_size_msec(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ int32_t n;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_atoi(state->rvalue, &n) < 0 || n < 1) {
+ pa_log(_("[%s:%u] Invalid fragment size '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->default_fragment_size_msec = (unsigned) n;
+ return 0;
+}
+
+static int parse_nice_level(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ int32_t level;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_atoi(state->rvalue, &level) < 0 || level < -20 || level > 19) {
+ pa_log(_("[%s:%u] Invalid nice level '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->nice_level = (int) level;
+ return 0;
+}
+
+static int parse_rtprio(pa_config_parser_state *state) {
+#if !defined(OS_IS_WIN32) && defined(HAVE_SCHED_H)
+ pa_daemon_conf *c;
+ int32_t rtprio;
+#endif
+
+ pa_assert(state);
+
+#ifdef OS_IS_WIN32
+ pa_log("[%s:%u] Realtime priority not available on win32.", state->filename, state->lineno);
+#else
+# ifdef HAVE_SCHED_H
+ c = state->data;
+
+ if (pa_atoi(state->rvalue, &rtprio) < 0 || rtprio < sched_get_priority_min(SCHED_FIFO) || rtprio > sched_get_priority_max(SCHED_FIFO)) {
+ pa_log("[%s:%u] Invalid realtime priority '%s'.", state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->realtime_priority = (int) rtprio;
+# endif
+#endif /* OS_IS_WIN32 */
+
+ return 0;
+}
+
+static int parse_disable_lfe_remix(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ int k;
+
+ pa_assert(state);
+ c = state->data;
+
+ if ((k = pa_parse_boolean(state->rvalue)) < 0) {
+ pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->remixing_produce_lfe = c->remixing_consume_lfe = !k;
+
+ pa_log("[%s:%u] Deprecated option 'disable-lfe-remixing' found.", state->filename, state->lineno);
+ pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
+ state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
+
+ return 0;
+}
+
+static int parse_enable_lfe_remix(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+ int k;
+
+ pa_assert(state);
+ c = state->data;
+
+ if ((k = pa_parse_boolean(state->rvalue)) < 0) {
+ pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ c->remixing_produce_lfe = c->remixing_consume_lfe = k;
+
+ pa_log("[%s:%u] Deprecated option 'enable-lfe-remixing' found.", state->filename, state->lineno);
+ pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
+ state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
+
+ return 0;
+}
+
+#ifdef HAVE_DBUS
+static int parse_server_type(pa_config_parser_state *state) {
+ pa_daemon_conf *c;
+
+ pa_assert(state);
+
+ c = state->data;
+
+ if (pa_daemon_conf_set_local_server_type(c, state->rvalue) < 0) {
+ pa_log(_("[%s:%u] Invalid server type '%s'."), state->filename, state->lineno, state->rvalue);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
+ int r = -1;
+ FILE *f = NULL;
+ struct channel_conf_info ci;
+ pa_config_item table[] = {
+ { "daemonize", pa_config_parse_bool, &c->daemonize, NULL },
+ { "fail", pa_config_parse_bool, &c->fail, NULL },
+ { "high-priority", pa_config_parse_bool, &c->high_priority, NULL },
+ { "realtime-scheduling", pa_config_parse_bool, &c->realtime_scheduling, NULL },
+ { "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading, NULL },
+ { "allow-module-loading", pa_config_parse_not_bool, &c->disallow_module_loading, NULL },
+ { "disallow-exit", pa_config_parse_bool, &c->disallow_exit, NULL },
+ { "allow-exit", pa_config_parse_not_bool, &c->disallow_exit, NULL },
+ { "use-pid-file", pa_config_parse_bool, &c->use_pid_file, NULL },
+ { "system-instance", pa_config_parse_bool, &c->system_instance, NULL },
+#ifdef HAVE_DBUS
+ { "local-server-type", parse_server_type, c, NULL },
+#endif
+ { "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL },
+ { "cpu-limit", pa_config_parse_not_bool, &c->no_cpu_limit, NULL },
+ { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL },
+ { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL },
+ { "enable-memfd", pa_config_parse_not_bool, &c->disable_memfd, NULL },
+ { "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL },
+ { "rescue-streams", pa_config_parse_bool, &c->rescue_streams, NULL },
+ { "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL },
+ { "enable-deferred-volume", pa_config_parse_bool, &c->deferred_volume, NULL },
+ { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time, NULL },
+ { "scache-idle-time", pa_config_parse_int, &c->scache_idle_time, NULL },
+ { "realtime-priority", parse_rtprio, c, NULL },
+ { "dl-search-path", pa_config_parse_string, &c->dl_search_path, NULL },
+ { "default-script-file", pa_config_parse_string, &c->default_script_file, NULL },
+ { "log-target", parse_log_target, c, NULL },
+ { "log-level", parse_log_level, c, NULL },
+ { "verbose", parse_log_level, c, NULL },
+ { "resample-method", parse_resample_method, c, NULL },
+ { "default-sample-format", parse_sample_format, c, NULL },
+ { "default-sample-rate", parse_sample_rate, c, NULL },
+ { "alternate-sample-rate", parse_alternate_sample_rate, c, NULL },
+ { "default-sample-channels", parse_sample_channels, &ci, NULL },
+ { "default-channel-map", parse_channel_map, &ci, NULL },
+ { "default-fragments", parse_fragments, c, NULL },
+ { "default-fragment-size-msec", parse_fragment_size_msec, c, NULL },
+ { "deferred-volume-safety-margin-usec",
+ pa_config_parse_unsigned, &c->deferred_volume_safety_margin_usec, NULL },
+ { "deferred-volume-extra-delay-usec",
+ pa_config_parse_int, &c->deferred_volume_extra_delay_usec, NULL },
+ { "nice-level", parse_nice_level, c, NULL },
+ { "avoid-resampling", pa_config_parse_bool, &c->avoid_resampling, NULL },
+ { "disable-remixing", pa_config_parse_bool, &c->disable_remixing, NULL },
+ { "enable-remixing", pa_config_parse_not_bool, &c->disable_remixing, NULL },
+ { "remixing-use-all-sink-channels",
+ pa_config_parse_bool, &c->remixing_use_all_sink_channels, NULL },
+ { "disable-lfe-remixing", parse_disable_lfe_remix, c, NULL },
+ { "enable-lfe-remixing", parse_enable_lfe_remix, c, NULL },
+ { "remixing-produce-lfe", pa_config_parse_bool, &c->remixing_produce_lfe, NULL },
+ { "remixing-consume-lfe", pa_config_parse_bool, &c->remixing_consume_lfe, NULL },
+ { "lfe-crossover-freq", pa_config_parse_unsigned, &c->lfe_crossover_freq, NULL },
+ { "load-default-script-file", pa_config_parse_bool, &c->load_default_script_file, NULL },
+ { "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL },
+ { "log-meta", pa_config_parse_bool, &c->log_meta, NULL },
+ { "log-time", pa_config_parse_bool, &c->log_time, NULL },
+ { "log-backtrace", pa_config_parse_unsigned, &c->log_backtrace, NULL },
+#ifdef HAVE_SYS_RESOURCE_H
+ { "rlimit-fsize", parse_rlimit, &c->rlimit_fsize, NULL },
+ { "rlimit-data", parse_rlimit, &c->rlimit_data, NULL },
+ { "rlimit-stack", parse_rlimit, &c->rlimit_stack, NULL },
+ { "rlimit-core", parse_rlimit, &c->rlimit_core, NULL },
+#ifdef RLIMIT_RSS
+ { "rlimit-rss", parse_rlimit, &c->rlimit_rss, NULL },
+#endif
+#ifdef RLIMIT_NOFILE
+ { "rlimit-nofile", parse_rlimit, &c->rlimit_nofile, NULL },
+#endif
+#ifdef RLIMIT_AS
+ { "rlimit-as", parse_rlimit, &c->rlimit_as, NULL },
+#endif
+#ifdef RLIMIT_NPROC
+ { "rlimit-nproc", parse_rlimit, &c->rlimit_nproc, NULL },
+#endif
+#ifdef RLIMIT_MEMLOCK
+ { "rlimit-memlock", parse_rlimit, &c->rlimit_memlock, NULL },
+#endif
+#ifdef RLIMIT_LOCKS
+ { "rlimit-locks", parse_rlimit, &c->rlimit_locks, NULL },
+#endif
+#ifdef RLIMIT_SIGPENDING
+ { "rlimit-sigpending", parse_rlimit, &c->rlimit_sigpending, NULL },
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ { "rlimit-msgqueue", parse_rlimit, &c->rlimit_msgqueue, NULL },
+#endif
+#ifdef RLIMIT_NICE
+ { "rlimit-nice", parse_rlimit, &c->rlimit_nice, NULL },
+#endif
+#ifdef RLIMIT_RTPRIO
+ { "rlimit-rtprio", parse_rlimit, &c->rlimit_rtprio, NULL },
+#endif
+#ifdef RLIMIT_RTTIME
+ { "rlimit-rttime", parse_rlimit, &c->rlimit_rttime, NULL },
+#endif
+#endif
+ { NULL, NULL, NULL, NULL },
+ };
+
+ pa_xfree(c->config_file);
+ c->config_file = NULL;
+
+ f = filename ?
+ pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
+ pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
+
+ if (!f && errno != ENOENT) {
+ pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
+ goto finish;
+ }
+
+ ci.default_channel_map_set = ci.default_sample_spec_set = false;
+ ci.conf = c;
+
+ r = f ? pa_config_parse(c->config_file, f, table, NULL, true, NULL) : 0;
+
+ if (r >= 0) {
+
+ /* Make sure that channel map and sample spec fit together */
+
+ if (ci.default_sample_spec_set &&
+ ci.default_channel_map_set &&
+ c->default_channel_map.channels != c->default_sample_spec.channels) {
+ pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels."));
+ r = -1;
+ goto finish;
+ } else if (ci.default_sample_spec_set)
+ pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
+ else if (ci.default_channel_map_set)
+ c->default_sample_spec.channels = c->default_channel_map.channels;
+ }
+
+finish:
+ if (f)
+ fclose(f);
+
+ return r;
+}
+
+int pa_daemon_conf_env(pa_daemon_conf *c) {
+ char *e;
+ pa_assert(c);
+
+ if ((e = getenv(ENV_DL_SEARCH_PATH))) {
+ pa_xfree(c->dl_search_path);
+ c->dl_search_path = pa_xstrdup(e);
+ }
+ if ((e = getenv(ENV_SCRIPT_FILE))) {
+ pa_xfree(c->default_script_file);
+ c->default_script_file = pa_xstrdup(e);
+ }
+
+ return 0;
+}
+
+const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) {
+ pa_assert(c);
+
+ if (!c->default_script_file) {
+ if (c->system_instance)
+ c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE);
+ else
+ c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE);
+ }
+
+ return c->default_script_file;
+}
+
+FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
+ FILE *f;
+ pa_assert(c);
+
+ if (!c->default_script_file) {
+ if (c->system_instance)
+ f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file);
+ else
+ f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
+ } else
+ f = pa_fopen_cloexec(c->default_script_file, "r");
+
+ return f;
+}
+
+char *pa_daemon_conf_dump(pa_daemon_conf *c) {
+ static const char* const log_level_to_string[] = {
+ [PA_LOG_DEBUG] = "debug",
+ [PA_LOG_INFO] = "info",
+ [PA_LOG_NOTICE] = "notice",
+ [PA_LOG_WARN] = "warning",
+ [PA_LOG_ERROR] = "error"
+ };
+
+#ifdef HAVE_DBUS
+ static const char* const server_type_to_string[] = {
+ [PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
+ [PA_SERVER_TYPE_USER] = "user",
+ [PA_SERVER_TYPE_SYSTEM] = "system",
+ [PA_SERVER_TYPE_NONE] = "none"
+ };
+#endif
+
+ pa_strbuf *s;
+ char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ char *log_target = NULL;
+
+ pa_assert(c);
+
+ s = pa_strbuf_new();
+
+ if (c->config_file)
+ pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);
+
+ pa_assert(c->log_level < PA_LOG_LEVEL_MAX);
+
+ if (c->log_target)
+ log_target = pa_log_target_to_string(c->log_target);
+
+ pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
+ pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
+ pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
+ pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level);
+ pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
+ pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
+ pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading));
+ pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit));
+ pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
+ pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
+#ifdef HAVE_DBUS
+ pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]);
+#endif
+ pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
+ pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
+ pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
+ pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams));
+ pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
+ pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
+ pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
+ pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
+ pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
+ pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
+ pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
+ pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
+ pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
+ pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling));
+ pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
+ pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
+ pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe));
+ pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe));
+ pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
+ pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
+ pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
+ pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate);
+ pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
+ pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
+ pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
+ pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
+ pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume));
+ pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec);
+ pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec);
+ pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
+ pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta));
+ pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time));
+ pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace);
+#ifdef HAVE_SYS_RESOURCE_H
+ pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
+ pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
+ pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
+ pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
+#ifdef RLIMIT_RSS
+ pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
+#endif
+#ifdef RLIMIT_AS
+ pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
+#endif
+#ifdef RLIMIT_NPROC
+ pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
+#endif
+#ifdef RLIMIT_NOFILE
+ pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
+#endif
+#ifdef RLIMIT_MEMLOCK
+ pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
+#endif
+#ifdef RLIMIT_LOCKS
+ pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
+#endif
+#ifdef RLIMIT_SIGPENDING
+ pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
+#endif
+#ifdef RLIMIT_NICE
+ pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
+#endif
+#ifdef RLIMIT_RTPRIO
+ pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
+#endif
+#ifdef RLIMIT_RTTIME
+ pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
+#endif
+#endif
+
+ pa_xfree(log_target);
+
+ return pa_strbuf_to_string_free(s);
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_pa_main.c b/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_pa_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..34525aac6f4780fc749c4adbd96d8eca5d98ccd8
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/daemon/ohos_pa_main.c
@@ -0,0 +1,1274 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+ Copyright 2006 Pierre Ossman for Cendio AB
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_SYS_MMAN_H
+#include
+#endif
+
+#ifdef HAVE_PWD_H
+#include
+#endif
+#ifdef HAVE_GRP_H
+#include
+#endif
+
+#ifdef HAVE_LIBWRAP
+#include
+#include
+#endif
+
+#ifdef HAVE_DBUS
+#include
+#endif
+
+#ifdef HAVE_SYSTEMD_DAEMON
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#ifdef HAVE_DBUS
+#include
+#endif
+#include
+
+#include "cmdline.h"
+#include "cpulimit.h"
+#include "daemon-conf.h"
+#include "dumpmodules.h"
+#include "caps.h"
+#include "ltdl-bind-now.h"
+#include "server-lookup.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* End of #ifdef __cplusplus */
+#ifdef DISABLE_LIBTOOL_PRELOAD
+/* FIXME: work around a libtool bug by making sure we have 2 elements. Bug has
+ * been reported: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29576 */
+const lt_dlsymlist lt_preloaded_symbols[] = {
+ { "@PROGRAM@", NULL },
+ { NULL, NULL }
+};
+#endif
+
+#ifdef HAVE_LIBWRAP
+/* Only one instance of these variables */
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+#endif
+
+#ifdef HAVE_OSS_WRAPPER
+/* padsp looks for this symbol in the running process and disables
+ * itself if it finds it and it is set to 7 (which is actually a bit
+ * mask). For details see padsp. */
+int __padsp_disabled__ = 7;
+#endif
+
+static void signal_callback(pa_mainloop_api* m, pa_signal_event *e, int sig, void *userdata) {
+ pa_module *module = NULL;
+
+ pa_log_info("Got signal %s.", pa_sig2str(sig));
+
+ switch (sig) {
+#ifdef SIGUSR1
+ case SIGUSR1:
+ pa_module_load(&module, userdata, "module-cli", NULL);
+ break;
+#endif
+
+#ifdef SIGUSR2
+ case SIGUSR2:
+ pa_module_load(&module, userdata, "module-cli-protocol-unix", NULL);
+ break;
+#endif
+
+#ifdef SIGHUP
+ case SIGHUP: {
+ char *c = pa_full_status_string(userdata);
+ pa_log_notice("%s", c);
+ pa_xfree(c);
+ return;
+ }
+#endif
+
+ case SIGINT:
+ case SIGTERM:
+ default:
+ pa_log_info("Exiting.");
+ m->quit(m, 0);
+ break;
+ }
+}
+
+#if defined(HAVE_PWD_H) && defined(HAVE_GRP_H)
+
+static int change_user(void) {
+ struct passwd *pw;
+ struct group * gr;
+ int r;
+
+ /* This function is called only in system-wide mode. It creates a
+ * runtime dir in /var/run/ with proper UID/GID and drops privs
+ * afterwards. */
+
+ if (!(pw = getpwnam(PA_SYSTEM_USER))) {
+ pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER);
+ return -1;
+ }
+
+ if (!(gr = getgrnam(PA_SYSTEM_GROUP))) {
+ pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP);
+ return -1;
+ }
+
+ pa_log_info("Found user '%s' (UID %lu) and group '%s' (GID %lu).",
+ PA_SYSTEM_USER, (unsigned long) pw->pw_uid,
+ PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid);
+
+ if (pw->pw_gid != gr->gr_gid) {
+ pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP);
+ return -1;
+ }
+
+ if (!pa_streq(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH))
+ pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH);
+
+ if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid, true) < 0) {
+ pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
+ return -1;
+ }
+
+ if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid, true) < 0) {
+ pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno));
+ return -1;
+ }
+
+ /* We don't create the config dir here, because we don't need to write to it */
+
+ if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
+ pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno));
+ return -1;
+ }
+
+#if defined(HAVE_SETRESGID)
+ r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid);
+#elif defined(HAVE_SETEGID)
+ if ((r = setgid(gr->gr_gid)) >= 0)
+ r = setegid(gr->gr_gid);
+#elif defined(HAVE_SETREGID)
+ r = setregid(gr->gr_gid, gr->gr_gid);
+#else
+#error "No API to drop privileges"
+#endif
+
+ if (r < 0) {
+ pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno));
+ return -1;
+ }
+
+#if defined(HAVE_SETRESUID)
+ r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
+#elif defined(HAVE_SETEUID)
+ if ((r = setuid(pw->pw_uid)) >= 0)
+ r = seteuid(pw->pw_uid);
+#elif defined(HAVE_SETREUID)
+ r = setreuid(pw->pw_uid, pw->pw_uid);
+#else
+#error "No API to drop privileges"
+#endif
+
+ if (r < 0) {
+ pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno));
+ return -1;
+ }
+
+ pa_drop_caps();
+
+ pa_set_env("USER", PA_SYSTEM_USER);
+ pa_set_env("USERNAME", PA_SYSTEM_USER);
+ pa_set_env("LOGNAME", PA_SYSTEM_USER);
+ pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH);
+
+ /* Relevant for pa_runtime_path() */
+ if (!getenv("PULSE_RUNTIME_PATH"))
+ pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH);
+
+ if (!getenv("PULSE_CONFIG_PATH"))
+ pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH);
+
+ if (!getenv("PULSE_STATE_PATH"))
+ pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH);
+
+ pa_log_info("Successfully changed user to \"" PA_SYSTEM_USER "\".");
+
+ return 0;
+}
+
+#else /* HAVE_PWD_H && HAVE_GRP_H */
+
+static int change_user(void) {
+ pa_log(_("System wide mode unsupported on this platform."));
+ return -1;
+}
+
+#endif /* HAVE_PWD_H && HAVE_GRP_H */
+
+#ifdef HAVE_SYS_RESOURCE_H
+
+static int set_one_rlimit(const pa_rlimit *r, int resource, const char *name) {
+ struct rlimit rl;
+ pa_assert(r);
+
+ if (!r->is_set)
+ return 0;
+
+ rl.rlim_cur = rl.rlim_max = r->value;
+
+ if (setrlimit(resource, &rl) < 0) {
+ pa_log_info("setrlimit(%s, (%u, %u)) failed: %s", name, (unsigned) r->value, (unsigned) r->value, pa_cstrerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static void set_all_rlimits(const pa_daemon_conf *conf) {
+ set_one_rlimit(&conf->rlimit_fsize, RLIMIT_FSIZE, "RLIMIT_FSIZE");
+ set_one_rlimit(&conf->rlimit_data, RLIMIT_DATA, "RLIMIT_DATA");
+ set_one_rlimit(&conf->rlimit_stack, RLIMIT_STACK, "RLIMIT_STACK");
+ set_one_rlimit(&conf->rlimit_core, RLIMIT_CORE, "RLIMIT_CORE");
+#ifdef RLIMIT_RSS
+ set_one_rlimit(&conf->rlimit_rss, RLIMIT_RSS, "RLIMIT_RSS");
+#endif
+#ifdef RLIMIT_NPROC
+ set_one_rlimit(&conf->rlimit_nproc, RLIMIT_NPROC, "RLIMIT_NPROC");
+#endif
+#ifdef RLIMIT_NOFILE
+ set_one_rlimit(&conf->rlimit_nofile, RLIMIT_NOFILE, "RLIMIT_NOFILE");
+#endif
+#ifdef RLIMIT_MEMLOCK
+ set_one_rlimit(&conf->rlimit_memlock, RLIMIT_MEMLOCK, "RLIMIT_MEMLOCK");
+#endif
+#ifdef RLIMIT_AS
+ set_one_rlimit(&conf->rlimit_as, RLIMIT_AS, "RLIMIT_AS");
+#endif
+#ifdef RLIMIT_LOCKS
+ set_one_rlimit(&conf->rlimit_locks, RLIMIT_LOCKS, "RLIMIT_LOCKS");
+#endif
+#ifdef RLIMIT_SIGPENDING
+ set_one_rlimit(&conf->rlimit_sigpending, RLIMIT_SIGPENDING, "RLIMIT_SIGPENDING");
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ set_one_rlimit(&conf->rlimit_msgqueue, RLIMIT_MSGQUEUE, "RLIMIT_MSGQUEUE");
+#endif
+#ifdef RLIMIT_NICE
+ set_one_rlimit(&conf->rlimit_nice, RLIMIT_NICE, "RLIMIT_NICE");
+#endif
+#ifdef RLIMIT_RTPRIO
+ set_one_rlimit(&conf->rlimit_rtprio, RLIMIT_RTPRIO, "RLIMIT_RTPRIO");
+#endif
+#ifdef RLIMIT_RTTIME
+ set_one_rlimit(&conf->rlimit_rttime, RLIMIT_RTTIME, "RLIMIT_RTTIME");
+#endif
+}
+#endif
+
+static char *check_configured_address(void) {
+ char *default_server = NULL;
+ pa_client_conf *c = pa_client_conf_new();
+
+ pa_client_conf_load(c, true, true);
+
+ if (c->default_server && *c->default_server)
+ default_server = pa_xstrdup(c->default_server);
+
+ pa_client_conf_free(c);
+
+ return default_server;
+}
+
+#ifdef HAVE_DBUS
+static pa_dbus_connection *register_dbus_name(pa_core *c, DBusBusType bus, const char* name) {
+ DBusError error;
+ pa_dbus_connection *conn;
+
+ dbus_error_init(&error);
+
+ if (!(conn = pa_dbus_bus_get(c, bus, &error)) || dbus_error_is_set(&error)) {
+ pa_log_warn("Unable to contact D-Bus: %s: %s", error.name, error.message);
+ goto fail;
+ }
+
+ if (dbus_bus_request_name(pa_dbus_connection_get(conn), name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ pa_log_debug("Got %s!", name);
+ return conn;
+ }
+
+ if (dbus_error_is_set(&error))
+ pa_log_error("Failed to acquire %s: %s: %s", name, error.name, error.message);
+ else
+ pa_log_error("D-Bus name %s already taken.", name);
+
+ /* PA cannot be started twice by the same user and hence we can
+ * ignore mostly the case that a name is already taken. */
+
+fail:
+ if (conn)
+ pa_dbus_connection_unref(conn);
+
+ dbus_error_free(&error);
+ return NULL;
+}
+#endif
+
+int ohos_pa_main(int argc, char *argv[]) {
+ pa_core *c = NULL;
+ pa_strbuf *buf = NULL;
+ pa_daemon_conf *conf = NULL;
+ pa_mainloop *mainloop = NULL;
+ char *s;
+ char *configured_address;
+ int r = 0, retval = 1, d = 0;
+ bool valid_pid_file = false;
+#ifdef HAVE_NO_OHOS
+ bool ltdl_init = false;
+#endif
+ int n_fds = 0, *passed_fds = NULL;
+ const char *e;
+#ifdef HAVE_FORK
+ int daemon_pipe[2] = { -1, -1 };
+ int daemon_pipe2[2] = { -1, -1 };
+#endif
+ int autospawn_fd = -1;
+ bool autospawn_locked = false;
+#ifdef HAVE_DBUS
+ pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */
+ pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */
+ pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */
+ bool start_server;
+#endif
+
+ pa_log_set_ident("pulseaudio");
+ pa_log_set_level(PA_LOG_NOTICE);
+ pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET);
+
+#if !defined(HAVE_BIND_NOW) && defined(__linux__) && defined(__OPTIMIZE__)
+ /*
+ Disable lazy relocations to make usage of external libraries
+ more deterministic for our RT threads. We abuse __OPTIMIZE__ as
+ a check whether we are a debug build or not. This all is
+ admittedly a bit snake-oilish.
+ */
+
+ if (!getenv("LD_BIND_NOW")) {
+ char *rp;
+ char *canonical_rp;
+
+ /* We have to execute ourselves, because the libc caches the
+ * value of $LD_BIND_NOW on initialization. */
+
+ pa_set_env("LD_BIND_NOW", "1");
+
+ if ((canonical_rp = pa_realpath(PA_BINARY))) {
+
+ if ((rp = pa_readlink("/proc/self/exe"))) {
+
+ if (pa_streq(rp, canonical_rp))
+ pa_assert_se(execv(rp, argv) == 0);
+ else
+ pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp);
+
+ pa_xfree(rp);
+
+ } else
+ pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?");
+
+ pa_xfree(canonical_rp);
+
+ } else
+ pa_log_warn("Couldn't canonicalize binary path, cannot self execute.");
+ }
+#endif
+
+#ifdef HAVE_SYSTEMD_DAEMON
+ n_fds = sd_listen_fds(0);
+ if (n_fds > 0) {
+ int i = n_fds;
+
+ passed_fds = pa_xnew(int, n_fds+2);
+ passed_fds[n_fds] = passed_fds[n_fds+1] = -1;
+ while (i--)
+ passed_fds[i] = SD_LISTEN_FDS_START + i;
+ }
+#endif
+
+ if (!passed_fds) {
+ n_fds = 0;
+ passed_fds = pa_xnew(int, 2);
+ passed_fds[0] = passed_fds[1] = -1;
+ }
+
+ if ((e = getenv("PULSE_PASSED_FD"))) {
+ int passed_fd = atoi(e);
+ if (passed_fd > 2)
+ passed_fds[n_fds] = passed_fd;
+ }
+
+ /* We might be autospawned, in which case have no idea in which
+ * context we have been started. Let's cleanup our execution
+ * context as good as possible */
+
+ pa_reset_personality();
+ pa_drop_root();
+#ifdef HAVE_NO_OHOS
+ pa_close_allv(passed_fds);
+ pa_xfree(passed_fds);
+#endif
+ pa_reset_sigs(-1);
+ pa_unblock_sigs(-1);
+ pa_reset_priority();
+
+ /* Load locale from the environment. */
+ setlocale(LC_ALL, "");
+
+ /* Set LC_NUMERIC to C so that floating point strings are consistently
+ * formatted and parsed across locales. */
+ setlocale(LC_NUMERIC, "C");
+
+ pa_init_i18n();
+
+ conf = pa_daemon_conf_new();
+
+ if (pa_daemon_conf_load(conf, NULL) < 0)
+ goto finish;
+
+ if (pa_daemon_conf_env(conf) < 0)
+ goto finish;
+
+ if (pa_cmdline_parse(conf, argc, argv, &d) < 0) {
+ pa_log(_("Failed to parse command line."));
+ goto finish;
+ }
+
+ if (conf->log_target)
+ pa_log_set_target(conf->log_target);
+ else {
+ pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL };
+ pa_log_set_target(&target);
+ }
+
+ pa_log_set_level(conf->log_level);
+ if (conf->log_meta)
+ pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET);
+ if (conf->log_time)
+ pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET);
+ pa_log_set_show_backtrace(conf->log_backtrace);
+
+#ifdef HAVE_DBUS
+ /* conf->system_instance and conf->local_server_type control almost the
+ * same thing; make them agree about what is requested. */
+ switch (conf->local_server_type) {
+ case PA_SERVER_TYPE_UNSET:
+ conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER;
+ break;
+ case PA_SERVER_TYPE_USER:
+ case PA_SERVER_TYPE_NONE:
+ conf->system_instance = false;
+ break;
+ case PA_SERVER_TYPE_SYSTEM:
+ conf->system_instance = true;
+ break;
+ default:
+ pa_assert_not_reached();
+ }
+
+ start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM);
+
+ if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) {
+ pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service."));
+ conf->system_instance = false;
+ }
+#endif
+
+#ifdef HAVE_NO_OHOS
+ LTDL_SET_PRELOADED_SYMBOLS();
+ pa_ltdl_init();
+ ltdl_init = true;
+
+ if (conf->dl_search_path)
+ lt_dlsetsearchpath(conf->dl_search_path);
+#endif
+
+#ifdef OS_IS_WIN32
+ {
+ WSADATA data;
+ WSAStartup(MAKEWORD(2, 0), &data);
+ }
+#endif
+
+ pa_random_seed();
+
+ switch (conf->cmd) {
+ case PA_CMD_DUMP_MODULES:
+#ifdef HAVE_NO_OHOS
+ pa_dump_modules(conf, argc-d, argv+d);
+#endif
+ retval = 0;
+ goto finish;
+
+ case PA_CMD_DUMP_CONF: {
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ s = pa_daemon_conf_dump(conf);
+ fputs(s, stdout);
+ pa_xfree(s);
+ retval = 0;
+ goto finish;
+ }
+
+ case PA_CMD_DUMP_RESAMPLE_METHODS: {
+ int i;
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ for (i = 0; i < PA_RESAMPLER_MAX; i++)
+ if (pa_resample_method_supported(i))
+ printf("%s\n", pa_resample_method_to_string(i));
+
+ retval = 0;
+ goto finish;
+ }
+
+ case PA_CMD_HELP :
+ pa_cmdline_help(argv[0]);
+ retval = 0;
+ goto finish;
+
+ case PA_CMD_VERSION :
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
+ retval = 0;
+ goto finish;
+
+ case PA_CMD_CHECK: {
+ pid_t pid;
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ if (pa_pid_file_check_running(&pid, "pulseaudio") < 0)
+ pa_log_info("Daemon not running");
+ else {
+ pa_log_info("Daemon running as PID %u", pid);
+ retval = 0;
+ }
+
+ goto finish;
+
+ }
+ case PA_CMD_KILL:
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0)
+ pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno));
+ else
+ retval = 0;
+
+ goto finish;
+
+ case PA_CMD_CLEANUP_SHM:
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+ if (pa_shm_cleanup() >= 0)
+ retval = 0;
+
+ goto finish;
+
+ default:
+ pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START);
+ }
+
+ if (d < argc) {
+ pa_log("Too many arguments.");
+ goto finish;
+ }
+
+#ifdef HAVE_GETUID
+ if (getuid() == 0 && !conf->system_instance)
+ pa_log_warn(_("This program is not intended to be run as root (unless --system is specified)."));
+#ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */
+ else if (getuid() != 0 && conf->system_instance) {
+ pa_log(_("Root privileges required."));
+ goto finish;
+ }
+#endif
+#endif /* HAVE_GETUID */
+
+ if (conf->cmd == PA_CMD_START && conf->system_instance) {
+ pa_log(_("--start not supported for system instances."));
+ goto finish;
+ }
+
+ if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) {
+ /* There is an server address in our config, but where did it come from?
+ * By default a standard X11 login will load module-x11-publish which will
+ * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end
+ * up hitting this code path. So we have to check to see if our configured_address
+ * is the same as the value that would go into this property so that we can
+ * recover (i.e. autospawn) from a crash.
+ */
+ char *ufn;
+ bool start_anyway = false;
+
+ if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) {
+ char *id;
+
+ if ((id = pa_machine_id())) {
+ pa_strlist *server_list;
+ char formatted_ufn[256];
+
+ pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn);
+ pa_xfree(id);
+
+ if ((server_list = pa_strlist_parse(configured_address))) {
+ char *u = NULL;
+
+ /* We only need to check the first server */
+ server_list = pa_strlist_pop(server_list, &u);
+ pa_strlist_free(server_list);
+
+ start_anyway = (u && pa_streq(formatted_ufn, u));
+ pa_xfree(u);
+ }
+ }
+ pa_xfree(ufn);
+ }
+
+ if (!start_anyway) {
+ pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address);
+ pa_xfree(configured_address);
+ retval = 0;
+ goto finish;
+ }
+
+ pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address);
+ pa_xfree(configured_address);
+ }
+
+ if (conf->system_instance && !conf->disallow_exit)
+ pa_log_warn(_("Running in system mode, but --disallow-exit not set."));
+
+ if (conf->system_instance && !conf->disallow_module_loading)
+ pa_log_warn(_("Running in system mode, but --disallow-module-loading not set."));
+
+ if (conf->system_instance && !conf->disable_shm) {
+ pa_log_notice(_("Running in system mode, forcibly disabling SHM mode."));
+ conf->disable_shm = true;
+ }
+
+ if (conf->system_instance && conf->exit_idle_time >= 0) {
+ pa_log_notice(_("Running in system mode, forcibly disabling exit idle time."));
+ conf->exit_idle_time = -1;
+ }
+
+ if (conf->cmd == PA_CMD_START) {
+ /* If we shall start PA only when it is not running yet, we
+ * first take the autospawn lock to make things
+ * synchronous. */
+
+ /* This locking and thread synchronisation code doesn't work reliably
+ * on kFreeBSD (Debian bug #705435), or in upstream FreeBSD ports
+ * (bug reference: ports/128947, patched in SVN r231972). */
+#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
+ if ((autospawn_fd = pa_autospawn_lock_init()) < 0) {
+ pa_log("Failed to initialize autospawn lock");
+ goto finish;
+ }
+
+ if ((pa_autospawn_lock_acquire(true) < 0)) {
+ pa_log("Failed to acquire autospawn lock");
+ goto finish;
+ }
+
+ autospawn_locked = true;
+#endif
+ }
+
+ if (conf->daemonize) {
+#ifdef HAVE_FORK
+ pid_t child;
+#endif
+
+ if (pa_stdio_acquire() < 0) {
+ pa_log(_("Failed to acquire stdio."));
+ goto finish;
+ }
+
+#ifdef HAVE_FORK
+ if (pipe(daemon_pipe) < 0) {
+ pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
+ goto finish;
+ }
+
+ if ((child = fork()) < 0) {
+ pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
+ pa_close_pipe(daemon_pipe);
+ goto finish;
+ }
+
+ if (child != 0) {
+ ssize_t n;
+ /* Father */
+
+ pa_assert_se(pa_close(daemon_pipe[1]) == 0);
+ daemon_pipe[1] = -1;
+
+ if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
+
+ if (n < 0)
+ pa_log(_("read() failed: %s"), pa_cstrerror(errno));
+
+ retval = 1;
+ }
+
+ if (retval)
+ pa_log(_("Daemon startup failed."));
+ else
+ pa_log_info("Daemon startup successful.");
+
+ goto finish;
+ }
+
+ if (autospawn_fd >= 0) {
+ /* The lock file is unlocked from the parent, so we need
+ * to close it in the child */
+
+ pa_autospawn_lock_release();
+ pa_autospawn_lock_done(true);
+
+ autospawn_locked = false;
+ autospawn_fd = -1;
+ }
+
+ pa_assert_se(pa_close(daemon_pipe[0]) == 0);
+ daemon_pipe[0] = -1;
+#endif
+
+ if (!conf->log_target) {
+#ifdef HAVE_SYSTEMD_JOURNAL
+ pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL };
+#else
+ pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL };
+#endif
+ pa_log_set_target(&target);
+ }
+
+#ifdef HAVE_SETSID
+ if (setsid() < 0) {
+ pa_log(_("setsid() failed: %s"), pa_cstrerror(errno));
+ goto finish;
+ }
+#endif
+
+#ifdef HAVE_FORK
+ /* We now are a session and process group leader. Let's fork
+ * again and let the father die, so that we'll become a
+ * process that can never acquire a TTY again, in a session and
+ * process group without leader */
+
+ if (pipe(daemon_pipe2) < 0) {
+ pa_log(_("pipe() failed: %s"), pa_cstrerror(errno));
+ goto finish;
+ }
+
+ if ((child = fork()) < 0) {
+ pa_log(_("fork() failed: %s"), pa_cstrerror(errno));
+ pa_close_pipe(daemon_pipe2);
+ goto finish;
+ }
+
+ if (child != 0) {
+ ssize_t n;
+ /* Father */
+
+ pa_assert_se(pa_close(daemon_pipe2[1]) == 0);
+ daemon_pipe2[1] = -1;
+
+ if ((n = pa_loop_read(daemon_pipe2[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) {
+
+ if (n < 0)
+ pa_log(_("read() failed: %s"), pa_cstrerror(errno));
+
+ retval = 1;
+ }
+
+ /* We now have to take care of signalling the first fork with
+ * the return value we've received from this fork... */
+ pa_assert(daemon_pipe[1] >= 0);
+
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
+ pa_close(daemon_pipe[1]);
+ daemon_pipe[1] = -1;
+
+ goto finish;
+ }
+
+ pa_assert_se(pa_close(daemon_pipe2[0]) == 0);
+ daemon_pipe2[0] = -1;
+
+ /* We no longer need the (first) daemon_pipe as it's handled in our child above */
+ pa_close_pipe(daemon_pipe);
+#endif
+
+#ifdef SIGTTOU
+ signal(SIGTTOU, SIG_IGN);
+#endif
+#ifdef SIGTTIN
+ signal(SIGTTIN, SIG_IGN);
+#endif
+#ifdef SIGTSTP
+ signal(SIGTSTP, SIG_IGN);
+#endif
+
+ pa_nullify_stdfds();
+ }
+
+ pa_set_env_and_record("PULSE_INTERNAL", "1");
+ pa_assert_se(chdir("/") == 0);
+ umask(0077);
+
+#ifdef HAVE_SYS_RESOURCE_H
+ set_all_rlimits(conf);
+#endif
+ pa_rtclock_hrtimer_enable();
+
+ if (conf->high_priority)
+ pa_raise_priority(conf->nice_level);
+
+ if (conf->system_instance)
+ if (change_user() < 0)
+ goto finish;
+
+ pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
+
+ pa_log_info("This is PulseAudio %s", PACKAGE_VERSION);
+ pa_log_debug("Compilation CFLAGS: %s", PA_CFLAGS);
+
+#ifdef HAVE_LIBSAMPLERATE
+ pa_log_warn("Compiled with DEPRECATED libsamplerate support!");
+#endif
+
+ s = pa_uname_string();
+ pa_log_debug("Running on host: %s", s);
+ pa_xfree(s);
+
+ pa_log_debug("Found %u CPUs.", pa_ncpus());
+
+ pa_log_info("Page size is %zu bytes", pa_page_size());
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+ pa_log_debug("Compiled with Valgrind support: yes");
+#else
+ pa_log_debug("Compiled with Valgrind support: no");
+#endif
+
+ pa_log_debug("Running in valgrind mode: %s", pa_yes_no(pa_in_valgrind()));
+
+ pa_log_debug("Running in VM: %s", pa_yes_no(pa_running_in_vm()));
+
+#ifdef HAVE_RUNNING_FROM_BUILD_TREE
+ pa_log_debug("Running from build tree: %s", pa_yes_no(pa_run_from_build_tree()));
+#else
+ pa_log_debug("Running from build tree: no");
+#endif
+
+#ifdef __OPTIMIZE__
+ pa_log_debug("Optimized build: yes");
+#else
+ pa_log_debug("Optimized build: no");
+#endif
+
+#ifdef NDEBUG
+ pa_log_debug("NDEBUG defined, all asserts disabled.");
+#elif defined(FASTPATH)
+ pa_log_debug("FASTPATH defined, only fast path asserts disabled.");
+#else
+ pa_log_debug("All asserts enabled.");
+#endif
+
+ if (!(s = pa_machine_id())) {
+ pa_log(_("Failed to get machine ID"));
+ goto finish;
+ }
+ pa_log_info("Machine ID is %s.", s);
+ pa_xfree(s);
+
+ if ((s = pa_session_id())) {
+ pa_log_info("Session ID is %s.", s);
+ pa_xfree(s);
+ }
+
+ if (!(s = pa_get_runtime_dir()))
+ goto finish;
+ pa_log_info("Using runtime directory %s.", s);
+ pa_xfree(s);
+
+ if (!(s = pa_get_state_dir()))
+ goto finish;
+ pa_log_info("Using state directory %s.", s);
+ pa_xfree(s);
+
+ pa_log_info("Using modules directory %s.", conf->dl_search_path);
+
+ pa_log_info("Running in system mode: %s", pa_yes_no(pa_in_system_mode()));
+
+ if (pa_in_system_mode())
+ pa_log_warn(_("OK, so you are running PA in system mode. Please make sure that you actually do want to do that.\n"
+ "Please read http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/WhatIsWrongWithSystemWide/ for an explanation why system mode is usually a bad idea."));
+
+ if (conf->use_pid_file) {
+ int z;
+ pa_pid_file_remove();
+ if ((z = pa_pid_file_create("pulseaudio")) != 0) {
+
+ if (conf->cmd == PA_CMD_START && z > 0) {
+ /* If we are already running and with are run in
+ * --start mode, then let's return this as success. */
+
+ retval = 0;
+ goto finish;
+ }
+
+ pa_log(_("pa_pid_file_create() failed."));
+ goto finish;
+ }
+
+ valid_pid_file = true;
+ }
+
+ pa_disable_sigpipe();
+
+ if (pa_rtclock_hrtimer())
+ pa_log_info("System supports high resolution timers");
+ else
+ pa_log_info("System appears to not support high resolution timers");
+
+ if (conf->lock_memory) {
+#if defined(HAVE_SYS_MMAN_H) && !defined(__ANDROID__)
+ if (mlockall(MCL_FUTURE) < 0)
+ pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno));
+ else
+ pa_log_info("Successfully locked process into memory.");
+#else
+ pa_log_warn("Memory locking requested but not supported on platform.");
+#endif
+ }
+
+ pa_memtrap_install();
+
+ pa_assert_se(mainloop = pa_mainloop_new());
+
+ if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm,
+ !conf->disable_shm && !conf->disable_memfd && pa_memfd_is_locally_supported(),
+ conf->shm_size))) {
+ pa_log(_("pa_core_new() failed."));
+ goto finish;
+ }
+
+ c->default_sample_spec = conf->default_sample_spec;
+ c->alternate_sample_rate = conf->alternate_sample_rate;
+ c->default_channel_map = conf->default_channel_map;
+ c->default_n_fragments = conf->default_n_fragments;
+ c->default_fragment_size_msec = conf->default_fragment_size_msec;
+ c->deferred_volume_safety_margin_usec = conf->deferred_volume_safety_margin_usec;
+ c->deferred_volume_extra_delay_usec = conf->deferred_volume_extra_delay_usec;
+ c->lfe_crossover_freq = conf->lfe_crossover_freq;
+ c->exit_idle_time = conf->exit_idle_time;
+ c->scache_idle_time = conf->scache_idle_time;
+ c->resample_method = conf->resample_method;
+ c->realtime_priority = conf->realtime_priority;
+ c->realtime_scheduling = conf->realtime_scheduling;
+ c->avoid_resampling = conf->avoid_resampling;
+ c->disable_remixing = conf->disable_remixing;
+ c->remixing_use_all_sink_channels = conf->remixing_use_all_sink_channels;
+ c->remixing_produce_lfe = conf->remixing_produce_lfe;
+ c->remixing_consume_lfe = conf->remixing_consume_lfe;
+ c->deferred_volume = conf->deferred_volume;
+ c->running_as_daemon = conf->daemonize;
+ c->disallow_exit = conf->disallow_exit;
+ c->flat_volumes = conf->flat_volumes;
+ c->rescue_streams = conf->rescue_streams;
+#ifdef HAVE_DBUS
+ c->server_type = conf->local_server_type;
+#endif
+
+ pa_core_check_idle(c);
+
+ c->state = PA_CORE_RUNNING;
+#ifdef HAVE_CPU_INFO
+ pa_cpu_init(&c->cpu_info);
+#endif
+ pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
+ pa_signal_new(SIGINT, signal_callback, c);
+ pa_signal_new(SIGTERM, signal_callback, c);
+#ifdef SIGUSR1
+ pa_signal_new(SIGUSR1, signal_callback, c);
+#endif
+#ifdef SIGUSR2
+ pa_signal_new(SIGUSR2, signal_callback, c);
+#endif
+#ifdef SIGHUP
+ pa_signal_new(SIGHUP, signal_callback, c);
+#endif
+
+ if (!conf->no_cpu_limit)
+ pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0);
+
+ buf = pa_strbuf_new();
+
+#ifdef HAVE_DBUS
+ pa_assert_se(dbus_threads_init_default());
+
+ if (start_server)
+#endif
+ {
+ const char *command_source = NULL;
+
+ if (conf->load_default_script_file) {
+ FILE *f;
+
+ if ((f = pa_daemon_conf_open_default_script_file(conf))) {
+ r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail);
+ fclose(f);
+ command_source = pa_daemon_conf_get_default_script_file(conf);
+ }
+ }
+
+ if (r >= 0) {
+ r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
+ command_source = _("command line arguments");
+ }
+
+ pa_log_error("%s", s = pa_strbuf_to_string_free(buf));
+ pa_xfree(s);
+
+ if (r < 0 && conf->fail) {
+ pa_log(_("Failed to initialize daemon due to errors while executing startup commands. Source of commands: %s"), command_source);
+ goto finish;
+ }
+
+ if (!c->modules || pa_idxset_size(c->modules) == 0) {
+ pa_log(_("Daemon startup without any loaded modules, refusing to work."));
+ goto finish;
+ }
+#ifdef HAVE_DBUS
+ } else {
+ /* When we just provide the D-Bus server lookup service, we don't want
+ * any modules to be loaded. We haven't loaded any so far, so one might
+ * think there's no way to contact the server, but receiving certain
+ * signals could still cause modules to load. */
+ conf->disallow_module_loading = true;
+#endif
+ }
+
+ /* We completed the initial module loading, so let's disable it
+ * from now on, if requested */
+ c->disallow_module_loading = conf->disallow_module_loading;
+
+#ifdef HAVE_DBUS
+ if (!conf->system_instance) {
+ if ((server_lookup = pa_dbusobj_server_lookup_new(c))) {
+ if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1")))
+ goto finish;
+ }
+ }
+
+ if (start_server)
+ server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server");
+#endif
+
+#ifdef HAVE_FORK
+ if (daemon_pipe2[1] >= 0) {
+ int ok = 0;
+ pa_loop_write(daemon_pipe2[1], &ok, sizeof(ok), NULL);
+ pa_close(daemon_pipe2[1]);
+ daemon_pipe2[1] = -1;
+ }
+#endif
+
+ pa_log_info("Daemon startup complete.");
+
+#ifdef HAVE_SYSTEMD_DAEMON
+ sd_notify(0, "READY=1");
+#endif
+
+ retval = 0;
+ if (pa_mainloop_run(mainloop, &retval) < 0)
+ goto finish;
+
+ pa_log_info("Daemon shutdown initiated.");
+
+#ifdef HAVE_SYSTEMD_DAEMON
+ sd_notify(0, "STOPPING=1");
+#endif
+
+finish:
+#ifdef HAVE_DBUS
+ if (server_bus)
+ pa_dbus_connection_unref(server_bus);
+ if (lookup_service_bus)
+ pa_dbus_connection_unref(lookup_service_bus);
+ if (server_lookup)
+ pa_dbusobj_server_lookup_free(server_lookup);
+#endif
+
+ if (autospawn_fd >= 0) {
+ if (autospawn_locked)
+ pa_autospawn_lock_release();
+
+ pa_autospawn_lock_done(false);
+ }
+
+ if (c) {
+ /* Ensure all the modules/samples are unloaded when the core is still ref'ed,
+ * as unlink callback hooks in modules may need the core to be ref'ed */
+ pa_module_unload_all(c);
+ pa_scache_free_all(c);
+
+ pa_core_unref(c);
+ pa_log_info("Daemon terminated.");
+ }
+
+ if (!conf->no_cpu_limit)
+ pa_cpu_limit_done();
+
+ pa_signal_done();
+
+#ifdef HAVE_FORK
+ /* If we have daemon_pipe[1] still open, this means we've failed after
+ * the first fork, but before the second. Therefore just write to it. */
+ if (daemon_pipe[1] >= 0)
+ pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL);
+ else if (daemon_pipe2[1] >= 0)
+ pa_loop_write(daemon_pipe2[1], &retval, sizeof(retval), NULL);
+
+ pa_close_pipe(daemon_pipe2);
+ pa_close_pipe(daemon_pipe);
+#endif
+
+ if (mainloop)
+ pa_mainloop_free(mainloop);
+
+ if (conf)
+ pa_daemon_conf_free(conf);
+
+ if (valid_pid_file)
+ pa_pid_file_remove();
+
+ /* This has no real purpose except making things valgrind-clean */
+ pa_unset_env_recorded();
+
+#ifdef OS_IS_WIN32
+ WSACleanup();
+#endif
+
+#ifdef HAVE_NO_OHOS
+ if (ltdl_init)
+ pa_ltdl_done();
+#endif
+
+#ifdef HAVE_DBUS
+ dbus_shutdown();
+#endif
+
+ return retval;
+}
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* End of #ifdef __cplusplus */
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/modules/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..f85914bd381bbb4c2e1a609ca8dc3f086ed9cd0c
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/BUILD.gn
@@ -0,0 +1,182 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+
+group("modules") {
+ deps = [
+ ":module-native-protocol-fd",
+ ":module-native-protocol-tcp",
+ ":module-native-protocol-unix",
+ ":module-cli-protocol-unix",
+ ":module-pipe-sink",
+ ":module-pipe-source",
+ ":module-suspend-on-idle"
+ ]
+}
+
+group("common_deps") {
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ ]
+}
+
+config("common_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir/src/modules",
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ "$pulseaudio_build_path/include",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ "-D__INCLUDED_FROM_PULSE_AUDIO",
+ ]
+}
+
+ohos_shared_library("module-native-protocol-fd") {
+ sources = [ "$pulseaudio_dir/src/modules/module-native-protocol-fd.c" ]
+ cflags = [ "-DPA_MODULE_NAME=libmodule_native_protocol_fd_z_so" ]
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+ configs = [ ":common_config" ]
+ deps = [
+ ":common_deps",
+ "$pulseaudio_build_path/src/pulsecore:protocol-native",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-native-protocol-tcp") {
+ sources = [ "$pulseaudio_dir/src/modules/module-protocol-stub.c" ]
+ cflags = [
+ "-DPA_MODULE_NAME=libmodule_native_protocol_tcp_z_so",
+ "-DUSE_PROTOCOL_NATIVE",
+ "-DUSE_TCP_SOCKETS",
+ ]
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+ configs = [ ":common_config" ]
+ deps = [
+ ":common_deps",
+ "$pulseaudio_build_path/src/pulsecore:protocol-native",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-native-protocol-unix") {
+ sources = [ "$pulseaudio_dir/src/modules/module-protocol-stub.c" ]
+ cflags = [
+ "-DPA_MODULE_NAME=libmodule_native_protocol_unix_z_so",
+ "-DUSE_PROTOCOL_NATIVE",
+ "-DUSE_UNIX_SOCKETS",
+ ]
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+ configs = [ ":common_config" ]
+ deps = [
+ ":common_deps",
+ "$pulseaudio_build_path/src/pulsecore:protocol-native",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-cli-protocol-unix") {
+ sources = [ "$pulseaudio_dir/src/modules/module-protocol-stub.c" ]
+ cflags = [
+ "-DPA_MODULE_NAME=libmodule_cli_protocol_unix_z_so",
+ "-DUSE_PROTOCOL_CLI",
+ "-DUSE_UNIX_SOCKETS",
+ ]
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+ configs = [ ":common_config" ]
+ deps = [
+ ":common_deps",
+ "$pulseaudio_build_path/src/pulsecore:protocol-cli",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-pipe-sink") {
+ sources = [ "$pulseaudio_dir/src/modules/module-pipe-sink.c" ]
+ cflags = [ "-DPA_MODULE_NAME=libmodule_pipe_sink_z_so" ]
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+ configs = [ ":common_config" ]
+ deps = [ ":common_deps" ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-pipe-source") {
+ sources = ["$pulseaudio_dir/src/modules/module-pipe-source.c",]
+ cflags = [ "-DPA_MODULE_NAME=libmodule_pipe_source_z_so" ]
+
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+
+ configs = [ ":common_config" ]
+ deps = [ ":common_deps" ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-suspend-on-idle") {
+ sources = ["$pulseaudio_dir/src/modules/module-suspend-on-idle.c",]
+ cflags = [ "-DPA_MODULE_NAME=libmodule_suspend_on_idle_z_so" ]
+
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+
+ configs = [ ":common_config" ]
+ deps = [ ":common_deps" ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..83fcf98202872511e159352036231b9992ffb3ef
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/BUILD.gn
@@ -0,0 +1,96 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+
+config("hdi_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ "$pulseaudio_build_path/include",
+ "//drivers/peripheral/audio/interfaces/include",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/common/include",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiocapturer/include",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiorenderer/include",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ "-D__INCLUDED_FROM_PULSE_AUDIO",
+ ]
+}
+
+ohos_shared_library("module-hdi-sink") {
+ sources = [
+ "$pulseaudio_build_path/src/modules/hdi/hdi_sink.c",
+ "$pulseaudio_build_path/src/modules/hdi/module_hdi_sink.c"
+ ]
+
+ configs = [ ":hdi_config" ]
+
+ cflags = [
+ "-DPA_MODULE_NAME=libmodule_hdi_sink_z_so",
+ ]
+
+ ldflags = [
+ "-Wl",
+ "--no-undefined",
+ ]
+
+ deps = [
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiorenderer:audio_renderer_sink",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("module-hdi-source") {
+ sources = [
+ "hdi_source.c",
+ "module_hdi_source.c"
+ ]
+
+ configs = [ ":hdi_config" ]
+
+ cflags = [
+ "-DPA_MODULE_NAME=libmodule_hdi_source_z_so",
+ ]
+
+ deps = [
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "//third_party/bounds_checking_function:libsec_static",
+ "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/audiocapturer:audio_capturer_source",
+ ]
+
+ external_deps = [
+ "hiviewdfx_hilog_native:libhilog",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_sink.c b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_sink.c
new file mode 100644
index 0000000000000000000000000000000000000000..cc9f7406568106102c0bc2595c266eae997972a1
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_sink.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DEFAULT_SINK_NAME "hdi_output"
+#define DEFAULT_AUDIO_DEVICE_NAME "Speaker"
+#define DEFAULT_BUFFER_SIZE 8192
+#define MAX_SINK_VOLUME_LEVEL 1.0
+
+struct Userdata {
+ size_t buffer_size;
+ size_t bytes_dropped;
+ pa_thread_mq thread_mq;
+ pa_memchunk memchunk;
+ pa_usec_t block_usec;
+ pa_usec_t timestamp;
+ pa_thread *thread;
+ pa_rtpoll *rtpoll;
+ pa_core *core;
+ pa_module *module;
+ pa_sink *sink;
+ pa_sample_spec ss;
+ pa_channel_map map;
+ bool isHDISinkInitialized;
+};
+
+static void UserdataFree(struct Userdata *u);
+static int32_t PrepareDevice(const pa_sample_spec *ss);
+
+static ssize_t RenderWrite(pa_memchunk *pchunk)
+{
+ size_t index, length;
+ ssize_t count = 0;
+ void *p = NULL;
+ int32_t ret;
+
+ pa_assert(pchunk);
+
+ index = pchunk->index;
+ length = pchunk->length;
+ p = pa_memblock_acquire(pchunk->memblock);
+ pa_assert(p);
+
+ while (true) {
+ uint64_t writeLen = 0;
+
+ ret = AudioRendererRenderFrame((char *) p + index, (uint64_t)length, &writeLen);
+ if (writeLen > length) {
+ pa_log_error("Error writeLen > actual bytes. Length: %u, Written: %llu bytes, %d ret",
+ length, writeLen, ret);
+ count = -1 - count;
+ break;
+ }
+ if (writeLen == 0) {
+ pa_log_error("Failed to render Length: %u, Written: %llu bytes, %d ret",
+ length, writeLen, ret);
+ count = -1 - count;
+ break;
+ } else {
+ pa_log_info("Success: outputting to audio renderer Length: %u, Written: %llu bytes, %d ret",
+ length, writeLen, ret);
+ count += writeLen;
+ index += writeLen;
+ length -= writeLen;
+ pa_log_info("Remaining bytes Length: %u", length);
+ if (length <= 0) {
+ break;
+ }
+ }
+ }
+ pa_memblock_release(pchunk->memblock);
+
+ return count;
+}
+
+static void ProcessRenderUseTiming(struct Userdata *u, pa_usec_t now)
+{
+ size_t dropped;
+ size_t consumed = 0;
+
+ pa_assert(u);
+
+ // Fill the buffer up the latency size
+ while (u->timestamp < now + u->block_usec) {
+ ssize_t written = 0;
+ pa_memchunk chunk;
+
+ pa_sink_render(u->sink, u->sink->thread_info.max_request, &chunk);
+
+ pa_assert(chunk.length > 0);
+
+ if ((written = RenderWrite(&chunk)) < 0)
+ written = -1 - written;
+
+ pa_memblock_unref(chunk.memblock);
+
+ u->timestamp += pa_bytes_to_usec(chunk.length, &u->sink->sample_spec);
+
+ dropped = chunk.length - written;
+
+ if (u->bytes_dropped != 0 && dropped != chunk.length) {
+ pa_log_debug("HDI-sink continuously dropped %zu bytes", u->bytes_dropped);
+ u->bytes_dropped = 0;
+ }
+
+ if (u->bytes_dropped == 0 && dropped != 0)
+ pa_log_debug("HDI-sink just dropped %zu bytes", dropped);
+
+ u->bytes_dropped += dropped;
+
+ consumed += chunk.length;
+
+ if (consumed >= u->sink->thread_info.max_request)
+ break;
+ }
+}
+
+static void ThreadFuncUseTiming(void *userdata)
+{
+ struct Userdata *u = userdata;
+
+ pa_assert(u);
+
+ pa_log_debug("Thread (use timing) starting up");
+ pa_thread_mq_install(&u->thread_mq);
+
+ u->timestamp = pa_rtclock_now();
+
+ while (true) {
+ pa_usec_t now = 0;
+ int ret;
+
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
+ now = pa_rtclock_now();
+
+ if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
+ pa_sink_process_rewind(u->sink, 0);
+
+ // Render some data and drop it immediately
+ if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
+ if (u->timestamp <= now)
+ ProcessRenderUseTiming(u, now);
+
+ pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp);
+ } else
+ pa_rtpoll_set_timer_disabled(u->rtpoll);
+
+ // Hmm, nothing to do. Let's sleep
+ if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
+ goto fail;
+
+ if (ret == 0) {
+ goto finish;
+ }
+ }
+
+fail:
+ // If this was no regular exit from the loop we have to continue
+ // processing messages until we received PA_MESSAGE_SHUTDOWN
+ pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE,
+ u->module, 0, NULL, NULL);
+ pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
+
+finish:
+ pa_log_debug("Thread (use timing) shutting down");
+}
+
+static void SinkUpdateRequestedLatencyCb(pa_sink *s)
+{
+ struct Userdata *u = NULL;
+ size_t nbytes;
+
+ pa_sink_assert_ref(s);
+ pa_assert_se(u = s->userdata);
+
+ u->block_usec = pa_sink_get_requested_latency_within_thread(s);
+
+ if (u->block_usec == (pa_usec_t) - 1)
+ u->block_usec = s->thread_info.max_latency;
+
+ nbytes = pa_usec_to_bytes(u->block_usec, &s->sample_spec);
+ pa_sink_set_max_request_within_thread(s, nbytes);
+}
+
+// Called from IO context
+static int SinkProcessMsg(pa_msgobject *o, int code, void *data, int64_t offset,
+ pa_memchunk *chunk)
+{
+ struct Userdata *u = PA_SINK(o)->userdata;
+ switch (code) {
+ case PA_SINK_MESSAGE_GET_LATENCY: {
+ int64_t latency;
+ uint32_t hdiLatency;
+
+ // Tries to fetch latency from HDI else will make an estimate based
+ // on samples to be rendered based on the timestamp and current time
+ if (AudioRendererSinkGetLatency(&hdiLatency) == 0) {
+ latency = (PA_USEC_PER_MSEC * hdiLatency);
+ } else {
+ pa_usec_t now = pa_rtclock_now();
+ latency = (now - u->timestamp);
+ }
+
+ *((int64_t *)data) = latency;
+ return 0;
+ }
+ default:
+ break;
+ }
+ return pa_sink_process_msg(o, code, data, offset, chunk);
+}
+
+// Called from the IO thread.
+static int SinkSetStateInIoThreadCb(pa_sink *s, pa_sink_state_t newState,
+ pa_suspend_cause_t newSuspendCause)
+{
+ struct Userdata *u = NULL;
+
+ pa_assert(s);
+ pa_assert_se(u = s->userdata);
+
+ if (s->thread_info.state == PA_SINK_SUSPENDED || s->thread_info.state == PA_SINK_INIT) {
+ if (PA_SINK_IS_OPENED(newState)) {
+ u->timestamp = pa_rtclock_now();
+ if (!u->isHDISinkInitialized) {
+ pa_log("Reinitializing HDI rendering device with rate: %d, channels: %d", u->ss.rate, u->ss.channels);
+ if (PrepareDevice(&u->ss) < 0) {
+ pa_log_error("HDI renderer reinitialization failed");
+ } else {
+ u->isHDISinkInitialized = true;
+ pa_log("Successfully reinitialized HDI renderer");
+ }
+ }
+ }
+ } else if (PA_SINK_IS_OPENED(s->thread_info.state)) {
+ if (newState == PA_SINK_SUSPENDED) {
+ // Continuously dropping data (clear counter on entering suspended state.
+ if (u->bytes_dropped != 0) {
+ pa_log_debug("HDI-sink continuously dropping data - clear statistics (%zu -> 0 bytes dropped)",
+ u->bytes_dropped);
+ u->bytes_dropped = 0;
+ }
+ if (u->isHDISinkInitialized) {
+ AudioRendererSinkStop();
+ AudioRendererSinkDeInit();
+ u->isHDISinkInitialized = false;
+ pa_log("Deinitialized HDI renderer");
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int32_t PrepareDevice(const pa_sample_spec *ss)
+{
+ AudioSinkAttr sample_attrs;
+ int32_t ret;
+
+ sample_attrs.format = AUDIO_FORMAT_PCM_16_BIT;
+ sample_attrs.sampleRate = ss->rate;
+ sample_attrs.channel = ss->channels;
+ sample_attrs.volume = MAX_SINK_VOLUME_LEVEL;
+
+ ret = AudioRendererSinkInit(&sample_attrs);
+ if (ret != 0) {
+ pa_log_error("audiorenderer Init failed!");
+ return -1;
+ }
+
+ ret = AudioRendererSinkStart();
+ if (ret != 0) {
+ pa_log_error("audiorenderer control start failed!");
+ AudioRendererSinkDeInit();
+ return -1;
+ }
+
+ ret = AudioRendererSinkSetVolume(MAX_SINK_VOLUME_LEVEL, MAX_SINK_VOLUME_LEVEL);
+ if (ret != 0) {
+ pa_log_error("audiorenderer set volume failed!");
+ AudioRendererSinkStop();
+ AudioRendererSinkDeInit();
+ return -1;
+ }
+
+ return 0;
+}
+
+static pa_sink* PaHdiSinkInit(struct Userdata *u, pa_modargs *ma, const char *driver)
+{
+ pa_sink_new_data data;
+ pa_module *m;
+ pa_sink *sink = NULL;
+
+ m = u->module;
+ u->ss = m->core->default_sample_spec;
+ u->map = m->core->default_channel_map;
+ if (pa_modargs_get_sample_spec_and_channel_map(ma, &u->ss, &u->map, PA_CHANNEL_MAP_DEFAULT) < 0) {
+ pa_log("Failed to parse sample specification and channel map");
+ goto fail;
+ }
+
+ pa_log("Initializing HDI rendering device with rate: %d, channels: %d", u->ss.rate, u->ss.channels);
+ if (PrepareDevice(&u->ss) < 0)
+ goto fail;
+
+ u->isHDISinkInitialized = true;
+ pa_log("Initialization of HDI rendering device completed");
+ pa_sink_new_data_init(&data);
+ data.driver = driver;
+ data.module = m;
+
+ pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME));
+ pa_sink_new_data_set_sample_spec(&data, &u->ss);
+ pa_sink_new_data_set_channel_map(&data, &u->map);
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, DEFAULT_AUDIO_DEVICE_NAME);
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "HDI sink is %s",
+ DEFAULT_AUDIO_DEVICE_NAME);
+
+ if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
+ pa_log("Invalid properties");
+ pa_sink_new_data_done(&data);
+ goto fail;
+ }
+
+ sink = pa_sink_new(m->core, &data,
+ PA_SINK_HARDWARE | PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY);
+ pa_sink_new_data_done(&data);
+
+ return sink;
+
+fail:
+ return NULL;
+}
+
+pa_sink *PaHdiSinkNew(pa_module *m, pa_modargs *ma, const char *driver)
+{
+ struct Userdata *u = NULL;
+ char *threadName = NULL;
+
+ pa_assert(m);
+ pa_assert(ma);
+
+ u = pa_xnew0(struct Userdata, 1);
+ u->core = m->core;
+ u->module = m;
+
+ pa_memchunk_reset(&u->memchunk);
+ u->rtpoll = pa_rtpoll_new();
+
+ if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) {
+ pa_log("pa_thread_mq_init() failed.");
+ goto fail;
+ }
+
+ u->sink = PaHdiSinkInit(u, ma, driver);
+ if (!u->sink) {
+ pa_log("Failed to create sink object");
+ goto fail;
+ }
+
+ u->sink->parent.process_msg = SinkProcessMsg;
+ u->sink->set_state_in_io_thread = SinkSetStateInIoThreadCb;
+ u->sink->update_requested_latency = SinkUpdateRequestedLatencyCb;
+ u->sink->userdata = u;
+
+ pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq);
+ pa_sink_set_rtpoll(u->sink, u->rtpoll);
+
+ u->bytes_dropped = 0;
+ u->buffer_size = DEFAULT_BUFFER_SIZE;
+ if (pa_modargs_get_value_u32(ma, "buffer_size", &u->buffer_size) < 0) {
+ pa_log("Failed to parse buffer_size argument.");
+ goto fail;
+ }
+
+ u->block_usec = pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec);
+ pa_sink_set_latency_range(u->sink, 0, u->block_usec);
+ pa_sink_set_max_request(u->sink, u->buffer_size);
+
+ threadName = pa_sprintf_malloc("hdi-sink-playback");
+ if (!(u->thread = pa_thread_new(threadName, ThreadFuncUseTiming, u))) {
+ pa_log("Failed to create thread.");
+ goto fail;
+ }
+ pa_xfree(threadName);
+ threadName = NULL;
+
+ pa_sink_put(u->sink);
+
+ return u->sink;
+fail:
+ pa_xfree(threadName);
+
+ if (u) {
+ UserdataFree(u);
+ }
+
+ return NULL;
+}
+
+static void UserdataFree(struct Userdata *u)
+{
+ pa_assert(u);
+
+ if (u->sink)
+ pa_sink_unlink(u->sink);
+
+ if (u->thread) {
+ pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+ pa_thread_free(u->thread);
+ }
+
+ pa_thread_mq_done(&u->thread_mq);
+
+ if (u->sink)
+ pa_sink_unref(u->sink);
+
+ if (u->memchunk.memblock)
+ pa_memblock_unref(u->memchunk.memblock);
+
+ if (u->rtpoll)
+ pa_rtpoll_free(u->rtpoll);
+
+ AudioRendererSinkStop();
+ AudioRendererSinkDeInit();
+
+ pa_xfree(u);
+}
+
+void PaHdiSinkFree(pa_sink *s)
+{
+ struct Userdata *u = NULL;
+
+ pa_sink_assert_ref(s);
+ pa_assert_se(u = s->userdata);
+
+ UserdataFree(u);
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_source.c b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_source.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b14c5f875342610af5a76cde062fd44c9ee38a4
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/hdi_source.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include "media_log.h"
+
+#define DEFAULT_SOURCE_NAME "hdi_input"
+#define DEFAULT_AUDIO_DEVICE_NAME "Internal Mic"
+
+#define DEFAULT_BUFFER_SIZE (1024 * 16)
+#define MAX_VOLUME_VALUE 15.0
+#define DEFAULT_LEFT_VOLUME MAX_VOLUME_VALUE
+#define DEFAULT_RIGHT_VOLUME MAX_VOLUME_VALUE
+#define MAX_LATENCY_USEC (PA_USEC_PER_SEC * 2)
+#define MIN_LATENCY_USEC 500
+#define AUDIO_POINT_NUM 1024
+#define AUDIO_FRAME_NUM_IN_BUF 30
+
+struct userdata {
+ pa_core *core;
+ pa_module *module;
+ pa_source *source;
+ pa_thread *thread;
+ pa_thread_mq thread_mq;
+ pa_rtpoll *rtpoll;
+ size_t buffer_size;
+ pa_usec_t block_usec;
+ pa_usec_t timestamp;
+ AudioSourceAttr attrs;
+ // A flag to signal us to prevent silent record during bootup
+ bool IsReady;
+ bool IsCapturerInit;
+};
+
+static int pa_capturer_init(struct userdata *u);
+static void pa_capturer_exit(void);
+
+static void userdata_free(struct userdata *u) {
+ pa_assert(u);
+ if (u->source)
+ pa_source_unlink(u->source);
+
+ if (u->thread) {
+ pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
+ pa_thread_free(u->thread);
+ }
+
+ pa_thread_mq_done(&u->thread_mq);
+
+ if (u->source)
+ pa_source_unref(u->source);
+
+ if (u->rtpoll)
+ pa_rtpoll_free(u->rtpoll);
+
+ AudioCapturerSourceStop();
+ AudioCapturerSourceDeInit();
+ pa_xfree(u);
+}
+
+static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
+ struct userdata *u = PA_SOURCE(o)->userdata;
+
+ switch (code) {
+ case PA_SOURCE_MESSAGE_GET_LATENCY: {
+ pa_usec_t now;
+ now = pa_rtclock_now();
+ *((int64_t*) data) = (int64_t)now - (int64_t)u->timestamp;
+ return 0;
+ }
+ default: {
+ pa_log("source_process_msg default case");
+ return pa_source_process_msg(o, code, data, offset, chunk);
+ }
+ }
+}
+
+/* Called from the IO thread. */
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
+ struct userdata *u = NULL;
+ pa_assert(s);
+ pa_assert_se(u = s->userdata);
+ if (s->thread_info.state == PA_SOURCE_SUSPENDED || s->thread_info.state == PA_SOURCE_INIT) {
+ if (PA_SOURCE_IS_OPENED(new_state))
+ u->timestamp = pa_rtclock_now();
+ }
+
+ return 0;
+}
+
+static pa_hook_result_t source_output_fixate_hook_cb(pa_core *c, pa_source_output_new_data *data,
+ struct userdata *u) {
+ int ret;
+ MEDIA_DEBUG_LOG("HDI Source: Detected source output");
+ pa_assert(data);
+ pa_assert(u);
+
+ if (!strcmp(u->source->name, data->source->name)) {
+ // Signal Ready when a Source Output is connected
+ if (!u->IsReady)
+ u->IsReady = true;
+
+ ret = pa_capturer_init(u);
+ if (ret != 0) {
+ MEDIA_DEBUG_LOG("HDI Source: Cannot initialize Capturer! ret=%d", ret);
+ return PA_HOOK_OK;
+ }
+
+ u->timestamp = pa_rtclock_now();
+ pa_source_suspend(u->source, false, PA_SUSPEND_IDLE);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static pa_hook_result_t source_output_move_finish_hook_cb(pa_core *c, pa_source_output *output, struct userdata *u) {
+ int ret;
+
+ MEDIA_DEBUG_LOG("HDI Source: Detected source move finish");
+ pa_assert(output);
+ pa_assert(u);
+
+ if (!strcmp(output->source->name, u->source->name)) {
+ // Signal Ready when a source output is connected
+ if (!u->IsReady)
+ u->IsReady = true;
+
+ ret = pa_capturer_init(u);
+ if (ret != 0) {
+ pa_log_error("HDI Source: Cannot initialize capturer! ret=%d", ret);
+ return PA_HOOK_OK;
+ }
+
+ u->timestamp = pa_rtclock_now();
+ pa_source_suspend(u->source, false, PA_SUSPEND_IDLE);
+ }
+
+ return PA_HOOK_OK;
+}
+
+static void thread_func(void *userdata) {
+ struct userdata *u = userdata;
+ bool timer_elapsed = false;
+
+ pa_assert(u);
+
+ if (u->core->realtime_scheduling)
+ pa_thread_make_realtime(u->core->realtime_priority);
+
+ pa_thread_mq_install(&u->thread_mq);
+ u->timestamp = pa_rtclock_now();
+ MEDIA_DEBUG_LOG("HDI Source: u->timestamp : %{public}llu", u->timestamp);
+
+ while(true) {
+ int ret = 0;
+ uint64_t requestBytes;
+ uint64_t replyBytes = 0;
+ void *p = NULL;
+
+ if (PA_SOURCE_IS_OPENED(u->source->thread_info.state) &&
+ (u->source->thread_info.state != PA_SOURCE_SUSPENDED) && u->IsReady && u->IsCapturerInit) {
+ pa_usec_t now;
+ pa_memchunk chunk;
+
+ now = pa_rtclock_now();
+ MEDIA_DEBUG_LOG("HDI Source: now: %{public}llu timer_elapsed: %{public}d", now, timer_elapsed);
+
+ if (timer_elapsed && (chunk.length = pa_usec_to_bytes(now - u->timestamp, &u->source->sample_spec)) > 0) {
+ chunk.length = u->buffer_size;
+ MEDIA_DEBUG_LOG("HDI Source: chunk.length = u->buffer_size: %{public}zu", chunk.length);
+ chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length);
+ pa_assert(chunk.memblock);
+ p = pa_memblock_acquire(chunk.memblock);
+ pa_assert(p);
+
+ requestBytes = pa_memblock_get_length(chunk.memblock);
+ AudioCapturerSourceFrame((char *) p, (uint64_t)requestBytes, &replyBytes);
+
+ pa_memblock_release(chunk.memblock);
+ MEDIA_DEBUG_LOG("HDI Source: request bytes: %{public}llu, replyBytes: %{public}llu", requestBytes, replyBytes);
+ if(replyBytes > requestBytes) {
+ MEDIA_ERR_LOG("HDI Source: Error replyBytes > requestBytes. Requested data Length: %{public}llu, Read: %{public}llu bytes, %{public}d ret", requestBytes, replyBytes, ret);
+ pa_memblock_unref(chunk.memblock);
+ break;
+ }
+
+ if (replyBytes == 0) {
+ MEDIA_ERR_LOG("HDI Source: Failed to read, Requested data Length: %{public}llu bytes,"
+ " Read: %{public}llu bytes, %{public}d ret", requestBytes, replyBytes, ret);
+ pa_memblock_unref(chunk.memblock);
+ break;
+ }
+
+ chunk.index = 0;
+ chunk.length = replyBytes;
+ pa_source_post(u->source, &chunk);
+ pa_memblock_unref(chunk.memblock);
+ u->timestamp += pa_bytes_to_usec(chunk.length, &u->source->sample_spec);
+ MEDIA_INFO_LOG("HDI Source: new u->timestamp : %{public}llu", u->timestamp);
+ }
+
+ pa_rtpoll_set_timer_absolute(u->rtpoll, u->timestamp + u->block_usec);
+ } else {
+ if (u->IsCapturerInit) {
+ u->IsCapturerInit = false;
+ pa_capturer_exit();
+ MEDIA_INFO_LOG("HDI Source: Capturer exit done");
+ }
+
+ pa_rtpoll_set_timer_disabled(u->rtpoll);
+ MEDIA_INFO_LOG("HDI Source: pa_rtpoll_set_timer_disabled done ");
+ }
+
+ /* Hmm, nothing to do. Let's sleep */
+ if ((ret = pa_rtpoll_run(u->rtpoll)) < 0) {
+ /* If this was no regular exit from the loop we have to continue
+ * processing messages until we received PA_MESSAGE_SHUTDOWN */
+ MEDIA_INFO_LOG("HDI Source: pa_rtpoll_run ret:%{public}d failed", ret );
+ pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module,
+ 0, NULL, NULL);
+ pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
+ return;
+ }
+
+ timer_elapsed = pa_rtpoll_timer_elapsed(u->rtpoll);
+
+ if (ret == 0) {
+ return;
+ }
+ }
+}
+
+static int pa_capturer_init(struct userdata *u) {
+ int ret;
+
+ ret = AudioCapturerSourceInit(&u->attrs);
+ if (ret != 0) {
+ MEDIA_INFO_LOG("Audio capturer init failed!");
+ return ret;
+ }
+
+ ret = AudioCapturerSourceStart();
+ if (ret != 0) {
+ MEDIA_INFO_LOG("Audio capturer start failed!");
+ goto fail;
+ }
+
+ ret = AudioCapturerSourceSetVolume(DEFAULT_LEFT_VOLUME, DEFAULT_RIGHT_VOLUME);
+ if (ret != 0) {
+ MEDIA_INFO_LOG("audio capturer set volume failed!");
+ goto fail;
+ }
+
+ u->IsCapturerInit = true;
+ return ret;
+
+fail:
+ pa_capturer_exit();
+ return ret;
+}
+
+static void pa_capturer_exit() {
+ AudioCapturerSourceStop();
+ AudioCapturerSourceDeInit();
+}
+
+pa_source *pa_hdi_source_new(pa_module *m, pa_modargs *ma, const char*driver) {
+ struct userdata *u = NULL;
+ pa_sample_spec ss;
+ char *thread_name = NULL;
+ pa_channel_map map;
+ pa_source_new_data data;
+ int ret;
+
+ pa_assert(m);
+ pa_assert(ma);
+
+ ss = m->core->default_sample_spec;
+ map = m->core->default_channel_map;
+
+ /* Override with modargs if provided */
+ if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
+ MEDIA_INFO_LOG("Failed to parse sample specification and channel map");
+ goto fail;
+ }
+
+ u = pa_xnew0(struct userdata, 1);
+ u->core = m->core;
+ u->module = m;
+ u->rtpoll = pa_rtpoll_new();
+
+ // Set IsReady to false at start. will be made true when a Source Output is connected
+ u->IsReady = false;
+
+ if (pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll) < 0) {
+ MEDIA_INFO_LOG("pa_thread_mq_init() failed.");
+ goto fail;
+ }
+
+ u->buffer_size = DEFAULT_BUFFER_SIZE;
+ u->attrs.format = AUDIO_FORMAT_PCM_16_BIT;
+ u->attrs.channel = ss.channels;
+ u->attrs.sampleRate = ss.rate;
+ MEDIA_INFO_LOG("AudioDeviceCreateCapture format: %{public}d, channel: %{public}d, sampleRate: %{public}d",
+ u->attrs.format, u->attrs.channel, u->attrs.sampleRate);
+ ret = pa_capturer_init(u);
+ if (ret != 0) {
+ goto fail;
+ }
+
+ pa_source_new_data_init(&data);
+ data.driver = __FILE__;
+ data.module = m;
+ pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME));
+ pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, DEFAULT_AUDIO_DEVICE_NAME);
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "HDI source %s", DEFAULT_AUDIO_DEVICE_NAME);
+ pa_source_new_data_set_sample_spec(&data, &ss);
+ pa_source_new_data_set_channel_map(&data, &map);
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long)u->buffer_size);
+
+ if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
+ MEDIA_INFO_LOG("Invalid properties");
+ pa_source_new_data_done(&data);
+ goto fail;
+ }
+
+ u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE | PA_SOURCE_LATENCY);
+ pa_source_new_data_done(&data);
+
+ if (!u->source) {
+ MEDIA_INFO_LOG("Failed to create source object");
+ goto fail;
+ }
+
+ u->source->parent.process_msg = source_process_msg;
+ u->source->set_state_in_io_thread = source_set_state_in_io_thread_cb;
+ u->source->userdata = u;
+
+ pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
+ pa_source_set_rtpoll(u->source, u->rtpoll);
+
+ if (pa_modargs_get_value_u32(ma, "buffer_size", &u->buffer_size) < 0) {
+ MEDIA_INFO_LOG("Failed to parse buffer_size argument.");
+ goto fail;
+ }
+
+ u->block_usec = pa_bytes_to_usec(u->buffer_size, &u->source->sample_spec);
+ pa_source_set_latency_range(u->source, 0, u->block_usec);
+ u->source->thread_info.max_rewind = pa_usec_to_bytes(u->block_usec, &u->source->sample_spec);
+
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_NORMAL,
+ (pa_hook_cb_t) source_output_fixate_hook_cb, u);
+ pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], PA_HOOK_NORMAL,
+ (pa_hook_cb_t) source_output_move_finish_hook_cb, u);
+
+ thread_name = pa_sprintf_malloc("hdi-source-record");
+ if (!(u->thread = pa_thread_new(thread_name, thread_func, u))) {
+ MEDIA_INFO_LOG("Failed to create hdi-source-record thread!");
+ goto fail;
+ }
+
+ pa_xfree(thread_name);
+ thread_name = NULL;
+ pa_source_put(u->source);
+ return u->source;
+
+fail:
+ pa_xfree(thread_name);
+
+ if (u->IsCapturerInit)
+ pa_capturer_exit();
+
+ if (u)
+ userdata_free(u);
+
+ return NULL;
+}
+
+void pa_hdi_source_free(pa_source *s) {
+ struct userdata *u;
+ pa_source_assert_ref(s);
+ pa_assert_se(u = s->userdata);
+ userdata_free(u);
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_sink.c b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_sink.c
new file mode 100644
index 0000000000000000000000000000000000000000..f47aa9ed2fa57d4186563edcf4f75a1bed39db3a
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_sink.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+
+pa_sink* PaHdiSinkNew(pa_module *m, pa_modargs *ma, const char *driver);
+void PaHdiSinkFree(pa_sink *s);
+
+PA_MODULE_AUTHOR("OpenHarmony");
+PA_MODULE_DESCRIPTION("OpenHarmony HDI Sink");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(false);
+PA_MODULE_USAGE(
+ "sink_name= "
+ "sink_properties= "
+ "format= "
+ "rate= "
+ "channels= "
+ "channel_map= "
+ "buffer_size="
+ );
+
+static const char * const VALID_MODARGS[] = {
+ "sink_name",
+ "sink_properties",
+ "format",
+ "rate",
+ "channels",
+ "channel_map",
+ "buffer_size",
+ NULL
+};
+
+int pa__init(pa_module *m)
+{
+ pa_modargs *ma = NULL;
+
+ pa_assert(m);
+
+ if (!(ma = pa_modargs_new(m->argument, VALID_MODARGS))) {
+ pa_log("Failed to parse module arguments");
+ goto fail;
+ }
+
+ if (!(m->userdata = PaHdiSinkNew(m, ma, __FILE__))) {
+ goto fail;
+ }
+
+ pa_modargs_free(ma);
+
+ return 0;
+
+fail:
+ if (ma) {
+ pa_modargs_free(ma);
+ }
+
+ pa__done(m);
+
+ return -1;
+}
+
+int pa__get_n_used(pa_module *m)
+{
+ pa_sink *sink = NULL;
+
+ pa_assert(m);
+ pa_assert_se(sink = m->userdata);
+
+ return pa_sink_linked_by(sink);
+}
+
+void pa__done(pa_module *m)
+{
+ pa_sink *sink = NULL;
+
+ pa_assert(m);
+
+ if ((sink = m->userdata)) {
+ PaHdiSinkFree(sink);
+ }
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_source.c b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_source.c
new file mode 100644
index 0000000000000000000000000000000000000000..4e8760c937f138f9ad2e11f8f5130fffe858de00
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/modules/hdi/module_hdi_source.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+
+#include
+#include
+#include
+#include
+
+pa_source* pa_hdi_source_new(pa_module *m, pa_modargs *ma, const char*driver);
+
+void pa_hdi_source_free(pa_source *s);
+
+PA_MODULE_AUTHOR("OpenHarmony");
+PA_MODULE_DESCRIPTION("OpenHarmony HDI Source");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(false);
+PA_MODULE_USAGE(
+ "source_name= "
+ "source_properties= "
+ "format= "
+ "rate= "
+ "channels= "
+ "channel_map="
+ "buffer_size="
+ );
+
+static const char * const VALID_MODARGS[] = {
+ "source_name",
+ "source_properties",
+ "format",
+ "rate",
+ "channels",
+ "channel_map",
+ "buffer_size",
+ NULL
+};
+
+int pa__init(pa_module *m)
+{
+ pa_modargs *ma = NULL;
+
+ pa_assert(m);
+
+ if (!(ma = pa_modargs_new(m->argument, VALID_MODARGS))) {
+ pa_log("Failed to parse module arguments");
+ goto fail;
+ }
+
+ if (!(m->userdata = pa_hdi_source_new(m, ma, __FILE__)))
+ goto fail;
+
+ pa_modargs_free(ma);
+
+ return 0;
+
+fail:
+
+ if (ma)
+ pa_modargs_free(ma);
+
+ pa__done(m);
+
+ return -1;
+}
+
+int pa__get_n_used(pa_module *m)
+{
+ pa_source *source = NULL;
+
+ pa_assert(m);
+ pa_assert_se(source = m->userdata);
+
+ return pa_source_linked_by(source);
+}
+
+void pa__done(pa_module*m)
+{
+ pa_source *source = NULL;
+
+ pa_assert(m);
+
+ if ((source = m->userdata))
+ pa_hdi_source_free(source);
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/pulse/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/pulse/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..797695996b6c234a39a11963313bfd75d8aff35b
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/pulse/BUILD.gn
@@ -0,0 +1,113 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+
+config("pulse_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir/src/pulse",
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ "$pulseaudio_build_path/include",
+ "//third_party/glib/glib",
+ "//third_party/glib",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-implicit-function-declaration",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ ]
+}
+
+ohos_source_set("pulse_sources") {
+ sources = [
+ "$pulseaudio_dir/src/pulse/channelmap.c",
+ "$pulseaudio_dir/src/pulse/context.c",
+ "$pulseaudio_dir/src/pulse/direction.c",
+ "$pulseaudio_dir/src/pulse/error.c",
+ "$pulseaudio_dir/src/pulse/ext-device-manager.c",
+ "$pulseaudio_dir/src/pulse/ext-device-restore.c",
+ "$pulseaudio_dir/src/pulse/ext-stream-restore.c",
+ "$pulseaudio_dir/src/pulse/format.c",
+ "$pulseaudio_dir/src/pulse/internal.h",
+ "$pulseaudio_dir/src/pulse/introspect.c",
+ "$pulseaudio_dir/src/pulse/mainloop-api.c",
+ "$pulseaudio_dir/src/pulse/mainloop-signal.c",
+ "$pulseaudio_dir/src/pulse/mainloop.c",
+ "$pulseaudio_dir/src/pulse/operation.c",
+ "$pulseaudio_dir/src/pulse/proplist.c",
+ "$pulseaudio_dir/src/pulse/rtclock.c",
+ "$pulseaudio_dir/src/pulse/sample.c",
+ "$pulseaudio_dir/src/pulse/scache.c",
+ "$pulseaudio_dir/src/pulse/stream.c",
+ "$pulseaudio_dir/src/pulse/subscribe.c",
+ "$pulseaudio_dir/src/pulse/thread-mainloop.c",
+ "$pulseaudio_dir/src/pulse/timeval.c",
+ "$pulseaudio_dir/src/pulse/utf8.c",
+ "$pulseaudio_dir/src/pulse/util.c",
+ "$pulseaudio_build_path/src/pulse/ohos_pa_volume.c",
+ "$pulseaudio_dir/src/pulse/xmalloc.c",
+ ]
+
+ configs = [
+ ":pulse_config",
+ ]
+}
+
+ohos_shared_library("pulse") {
+ deps = [
+ ":pulse_sources",
+ "$pulseaudio_build_path/src:pulsecommon",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("pulse-simple") {
+ sources = [ "$pulseaudio_dir/src/pulse/simple.c" ]
+
+ configs = [ ":pulse_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulse:pulse",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("pulse-mainloop-glib") {
+ sources = [ "$pulseaudio_build_path/src/pulse/ohos_glib-mainloop.c" ]
+
+ configs = [ ":pulse_config" ]
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "//third_party/glib:glib",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_glib-mainloop.c b/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_glib-mainloop.c
new file mode 100644
index 0000000000000000000000000000000000000000..82c45713fd2bcdfd454b41dbceb9fa2a5c97ef7d
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_glib-mainloop.c
@@ -0,0 +1,661 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include "glib-mainloop.h"
+
+struct pa_io_event {
+ pa_glib_mainloop *mainloop;
+ int dead;
+
+ GPollFD poll_fd;
+ int poll_fd_added;
+
+ pa_io_event_cb_t callback;
+ void *userdata;
+ pa_io_event_destroy_cb_t destroy_callback;
+
+ PA_LLIST_FIELDS(pa_io_event);
+};
+
+struct pa_time_event {
+ pa_glib_mainloop *mainloop;
+ int dead;
+
+ int enabled;
+ struct timeval timeval;
+
+ pa_time_event_cb_t callback;
+ void *userdata;
+ pa_time_event_destroy_cb_t destroy_callback;
+
+ PA_LLIST_FIELDS(pa_time_event);
+};
+
+struct pa_defer_event {
+ pa_glib_mainloop *mainloop;
+ int dead;
+
+ int enabled;
+
+ pa_defer_event_cb_t callback;
+ void *userdata;
+ pa_defer_event_destroy_cb_t destroy_callback;
+
+ PA_LLIST_FIELDS(pa_defer_event);
+};
+
+struct pa_glib_mainloop {
+ GSource source;
+
+ pa_mainloop_api api;
+ GMainContext *context;
+
+ PA_LLIST_HEAD(pa_io_event, io_events);
+ PA_LLIST_HEAD(pa_time_event, time_events);
+ PA_LLIST_HEAD(pa_defer_event, defer_events);
+
+ int n_enabled_defer_events, n_enabled_time_events;
+ int io_events_please_scan, time_events_please_scan, defer_events_please_scan;
+
+ pa_time_event *cached_next_time_event;
+};
+
+static void cleanup_io_events(pa_glib_mainloop *g, int force) {
+ pa_io_event *e;
+
+ e = g->io_events;
+ while (e) {
+ pa_io_event *n = e->next;
+
+ if (!force && g->io_events_please_scan <= 0)
+ break;
+
+ if (force || e->dead) {
+ PA_LLIST_REMOVE(pa_io_event, g->io_events, e);
+
+ if (e->dead) {
+ g_assert(g->io_events_please_scan > 0);
+ g->io_events_please_scan--;
+ }
+
+ if (e->poll_fd_added)
+ g_source_remove_poll(&g->source, &e->poll_fd);
+
+ if (e->destroy_callback)
+ e->destroy_callback(&g->api, e, e->userdata);
+
+ pa_xfree(e);
+ }
+
+ e = n;
+ }
+
+ g_assert(g->io_events_please_scan == 0);
+}
+
+static void cleanup_time_events(pa_glib_mainloop *g, int force) {
+ pa_time_event *e;
+
+ e = g->time_events;
+ while (e) {
+ pa_time_event *n = e->next;
+
+ if (!force && g->time_events_please_scan <= 0)
+ break;
+
+ if (force || e->dead) {
+ PA_LLIST_REMOVE(pa_time_event, g->time_events, e);
+
+ if (e->dead) {
+ g_assert(g->time_events_please_scan > 0);
+ g->time_events_please_scan--;
+ }
+
+ if (!e->dead && e->enabled) {
+ g_assert(g->n_enabled_time_events > 0);
+ g->n_enabled_time_events--;
+ }
+
+ if (e->destroy_callback)
+ e->destroy_callback(&g->api, e, e->userdata);
+
+ pa_xfree(e);
+ }
+
+ e = n;
+ }
+
+ g_assert(g->time_events_please_scan == 0);
+}
+
+static void cleanup_defer_events(pa_glib_mainloop *g, int force) {
+ pa_defer_event *e;
+
+ e = g->defer_events;
+ while (e) {
+ pa_defer_event *n = e->next;
+
+ if (!force && g->defer_events_please_scan <= 0)
+ break;
+
+ if (force || e->dead) {
+ PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e);
+
+ if (e->dead) {
+ g_assert(g->defer_events_please_scan > 0);
+ g->defer_events_please_scan--;
+ }
+
+ if (!e->dead && e->enabled) {
+ g_assert(g->n_enabled_defer_events > 0);
+ g->n_enabled_defer_events--;
+ }
+
+ if (e->destroy_callback)
+ e->destroy_callback(&g->api, e, e->userdata);
+
+ pa_xfree(e);
+ }
+
+ e = n;
+ }
+
+ g_assert(g->defer_events_please_scan == 0);
+}
+
+static gushort map_flags_to_glib(pa_io_event_flags_t flags) {
+ return (gushort)
+ ((flags & PA_IO_EVENT_INPUT ? G_IO_IN : 0) |
+ (flags & PA_IO_EVENT_OUTPUT ? G_IO_OUT : 0) |
+ (flags & PA_IO_EVENT_ERROR ? G_IO_ERR : 0) |
+ (flags & PA_IO_EVENT_HANGUP ? G_IO_HUP : 0));
+}
+
+static pa_io_event_flags_t map_flags_from_glib(gushort flags) {
+ return
+ (flags & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
+ (flags & G_IO_OUT ? PA_IO_EVENT_OUTPUT : 0) |
+ (flags & G_IO_ERR ? PA_IO_EVENT_ERROR : 0) |
+ (flags & G_IO_HUP ? PA_IO_EVENT_HANGUP : 0);
+}
+
+static pa_io_event* glib_io_new(
+ pa_mainloop_api*m,
+ int fd,
+ pa_io_event_flags_t f,
+ pa_io_event_cb_t cb,
+ void *userdata) {
+
+ pa_io_event *e;
+ pa_glib_mainloop *g;
+
+ g_assert(m);
+ g_assert(m->userdata);
+ g_assert(fd >= 0);
+ g_assert(cb);
+
+ g = m->userdata;
+
+ e = pa_xnew(pa_io_event, 1);
+ e->mainloop = g;
+ e->dead = 0;
+
+ e->poll_fd.fd = fd;
+ e->poll_fd.events = map_flags_to_glib(f);
+ e->poll_fd.revents = 0;
+
+ e->callback = cb;
+ e->userdata = userdata;
+ e->destroy_callback = NULL;
+
+ PA_LLIST_PREPEND(pa_io_event, g->io_events, e);
+
+ g_source_add_poll(&g->source, &e->poll_fd);
+ e->poll_fd_added = 1;
+
+ return e;
+}
+
+static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->poll_fd.events = map_flags_to_glib(f);
+}
+
+static void glib_io_free(pa_io_event*e) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->dead = 1;
+ e->mainloop->io_events_please_scan++;
+
+ if (e->poll_fd_added) {
+ g_source_remove_poll(&e->mainloop->source, &e->poll_fd);
+ e->poll_fd_added = 0;
+ }
+}
+
+static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->destroy_callback = cb;
+}
+
+/* Time sources */
+
+static pa_time_event* glib_time_new(
+ pa_mainloop_api*m,
+ const struct timeval *tv,
+ pa_time_event_cb_t cb,
+ void *userdata) {
+
+ pa_glib_mainloop *g;
+ pa_time_event *e;
+
+ g_assert(m);
+ g_assert(m->userdata);
+ g_assert(cb);
+
+ g = m->userdata;
+
+ e = pa_xnew(pa_time_event, 1);
+ e->mainloop = g;
+ e->dead = 0;
+
+ if ((e->enabled = !!tv)) {
+ e->timeval = *tv;
+ g->n_enabled_time_events++;
+
+ if (g->cached_next_time_event) {
+ g_assert(g->cached_next_time_event->enabled);
+
+ if (pa_timeval_cmp(tv, &g->cached_next_time_event->timeval) < 0)
+ g->cached_next_time_event = e;
+ }
+ }
+
+ e->callback = cb;
+ e->userdata = userdata;
+ e->destroy_callback = NULL;
+
+ PA_LLIST_PREPEND(pa_time_event, g->time_events, e);
+
+ return e;
+}
+
+static void glib_time_restart(pa_time_event*e, const struct timeval *tv) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ if (e->enabled && !tv) {
+ g_assert(e->mainloop->n_enabled_time_events > 0);
+ e->mainloop->n_enabled_time_events--;
+ } else if (!e->enabled && tv)
+ e->mainloop->n_enabled_time_events++;
+
+ if ((e->enabled = !!tv))
+ e->timeval = *tv;
+
+ if (e->mainloop->cached_next_time_event == e)
+ e->mainloop->cached_next_time_event = NULL;
+
+ if (e->mainloop->cached_next_time_event && e->enabled) {
+ g_assert(e->mainloop->cached_next_time_event->enabled);
+
+ if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
+ e->mainloop->cached_next_time_event = e;
+ }
+}
+
+static void glib_time_free(pa_time_event *e) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->dead = 1;
+ e->mainloop->time_events_please_scan++;
+
+ if (e->enabled)
+ e->mainloop->n_enabled_time_events--;
+
+ if (e->mainloop->cached_next_time_event == e)
+ e->mainloop->cached_next_time_event = NULL;
+}
+
+static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->destroy_callback = cb;
+}
+
+/* Deferred sources */
+
+static pa_defer_event* glib_defer_new(
+ pa_mainloop_api*m,
+ pa_defer_event_cb_t cb,
+ void *userdata) {
+
+ pa_defer_event *e;
+ pa_glib_mainloop *g;
+
+ g_assert(m);
+ g_assert(m->userdata);
+ g_assert(cb);
+
+ g = m->userdata;
+
+ e = pa_xnew(pa_defer_event, 1);
+ e->mainloop = g;
+ e->dead = 0;
+
+ e->enabled = 1;
+ g->n_enabled_defer_events++;
+
+ e->callback = cb;
+ e->userdata = userdata;
+ e->destroy_callback = NULL;
+
+ PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e);
+ return e;
+}
+
+static void glib_defer_enable(pa_defer_event *e, int b) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ if (e->enabled && !b) {
+ g_assert(e->mainloop->n_enabled_defer_events > 0);
+ e->mainloop->n_enabled_defer_events--;
+ } else if (!e->enabled && b)
+ e->mainloop->n_enabled_defer_events++;
+
+ e->enabled = b;
+}
+
+static void glib_defer_free(pa_defer_event *e) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->dead = 1;
+ e->mainloop->defer_events_please_scan++;
+
+ if (e->enabled) {
+ g_assert(e->mainloop->n_enabled_defer_events > 0);
+ e->mainloop->n_enabled_defer_events--;
+ }
+}
+
+static void glib_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb) {
+ g_assert(e);
+ g_assert(!e->dead);
+
+ e->destroy_callback = cb;
+}
+
+/* quit() */
+
+static void glib_quit(pa_mainloop_api*a, int retval) {
+
+ g_warning("quit() ignored");
+
+ /* NOOP */
+}
+
+static pa_time_event* find_next_time_event(pa_glib_mainloop *g) {
+ pa_time_event *t, *n = NULL;
+ g_assert(g);
+
+ if (g->cached_next_time_event)
+ return g->cached_next_time_event;
+
+ for (t = g->time_events; t; t = t->next) {
+
+ if (t->dead || !t->enabled)
+ continue;
+
+ if (!n || pa_timeval_cmp(&t->timeval, &n->timeval) < 0) {
+ n = t;
+
+ /* Shortcut for tv = { 0, 0 } */
+ if (n->timeval.tv_sec <= 0)
+ break;
+ }
+ }
+
+ g->cached_next_time_event = n;
+ return n;
+}
+
+static void scan_dead(pa_glib_mainloop *g) {
+ g_assert(g);
+
+ if (g->io_events_please_scan)
+ cleanup_io_events(g, 0);
+
+ if (g->time_events_please_scan)
+ cleanup_time_events(g, 0);
+
+ if (g->defer_events_please_scan)
+ cleanup_defer_events(g, 0);
+}
+
+static gboolean prepare_func(GSource *source, gint *timeout) {
+ pa_glib_mainloop *g = (pa_glib_mainloop*) source;
+
+ g_assert(g);
+ g_assert(timeout);
+
+ scan_dead(g);
+
+ if (g->n_enabled_defer_events) {
+ *timeout = 0;
+ return TRUE;
+ } else if (g->n_enabled_time_events) {
+ pa_time_event *t;
+ gint64 now;
+ struct timeval tvnow;
+ pa_usec_t usec;
+
+ t = find_next_time_event(g);
+ g_assert(t);
+
+ now = g_get_real_time();
+ tvnow.tv_sec = now / 1000000;
+ tvnow.tv_usec = now % 1000000;
+
+ if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
+ *timeout = 0;
+ return TRUE;
+ }
+ usec = pa_timeval_diff(&t->timeval, &tvnow);
+ *timeout = (gint) (usec / 1000);
+ } else
+ *timeout = -1;
+
+ return FALSE;
+}
+static gboolean check_func(GSource *source) {
+ pa_glib_mainloop *g = (pa_glib_mainloop*) source;
+ pa_io_event *e;
+
+ g_assert(g);
+
+ if (g->n_enabled_defer_events)
+ return TRUE;
+ else if (g->n_enabled_time_events) {
+ pa_time_event *t;
+ gint64 now;
+ struct timeval tvnow;
+
+ t = find_next_time_event(g);
+ g_assert(t);
+ now = g_get_real_time();
+ tvnow.tv_sec = now / 1000000;
+ tvnow.tv_usec = now % 1000000;
+
+ if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0)
+ return TRUE;
+ }
+
+ for (e = g->io_events; e; e = e->next)
+ if (!e->dead && e->poll_fd.revents != 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer userdata) {
+ pa_glib_mainloop *g = (pa_glib_mainloop*) source;
+ pa_io_event *e;
+
+ g_assert(g);
+
+ if (g->n_enabled_defer_events) {
+ pa_defer_event *d;
+
+ for (d = g->defer_events; d; d = d->next) {
+ if (d->dead || !d->enabled)
+ continue;
+
+ break;
+ }
+
+ g_assert(d);
+
+ d->callback(&g->api, d, d->userdata);
+ return TRUE;
+ }
+
+ if (g->n_enabled_time_events) {
+ gint64 now;
+ struct timeval tvnow;
+ pa_time_event *t;
+
+ t = find_next_time_event(g);
+ g_assert(t);
+ now = g_get_real_time();
+ tvnow.tv_sec = now / 1000000;
+ tvnow.tv_usec = now % 1000000;
+
+ if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
+
+ /* Disable time event */
+ glib_time_restart(t, NULL);
+
+ t->callback(&g->api, t, &t->timeval, t->userdata);
+ return TRUE;
+ }
+ }
+
+ for (e = g->io_events; e; e = e->next)
+ if (!e->dead && e->poll_fd.revents != 0) {
+ e->callback(&g->api, e, e->poll_fd.fd, map_flags_from_glib(e->poll_fd.revents), e->userdata);
+ e->poll_fd.revents = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static const pa_mainloop_api vtable = {
+ .userdata = NULL,
+
+ .io_new = glib_io_new,
+ .io_enable = glib_io_enable,
+ .io_free = glib_io_free,
+ .io_set_destroy = glib_io_set_destroy,
+
+ .time_new = glib_time_new,
+ .time_restart = glib_time_restart,
+ .time_free = glib_time_free,
+ .time_set_destroy = glib_time_set_destroy,
+
+ .defer_new = glib_defer_new,
+ .defer_enable = glib_defer_enable,
+ .defer_free = glib_defer_free,
+ .defer_set_destroy = glib_defer_set_destroy,
+
+ .quit = glib_quit,
+};
+
+pa_glib_mainloop *pa_glib_mainloop_new(GMainContext *c) {
+ pa_glib_mainloop *g;
+
+ static GSourceFuncs source_funcs = {
+ prepare_func,
+ check_func,
+ dispatch_func,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop));
+ g_main_context_ref(g->context = c ? c : g_main_context_default());
+
+ g->api = vtable;
+ g->api.userdata = g;
+
+ PA_LLIST_HEAD_INIT(pa_io_event, g->io_events);
+ PA_LLIST_HEAD_INIT(pa_time_event, g->time_events);
+ PA_LLIST_HEAD_INIT(pa_defer_event, g->defer_events);
+
+ g->n_enabled_defer_events = g->n_enabled_time_events = 0;
+ g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0;
+
+ g->cached_next_time_event = NULL;
+
+ g_source_attach(&g->source, g->context);
+ g_source_set_can_recurse(&g->source, FALSE);
+
+ return g;
+}
+
+void pa_glib_mainloop_free(pa_glib_mainloop* g) {
+ g_assert(g);
+
+ cleanup_io_events(g, 1);
+ cleanup_defer_events(g, 1);
+ cleanup_time_events(g, 1);
+
+ g_main_context_unref(g->context);
+ g_source_destroy(&g->source);
+ g_source_unref(&g->source);
+}
+
+pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) {
+ g_assert(g);
+
+ return &g->api;
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_pa_volume.c b/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_pa_volume.c
new file mode 100644
index 0000000000000000000000000000000000000000..88feeff22f5835f26af474f8986e1f0cde6ab978
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/pulse/ohos_pa_volume.c
@@ -0,0 +1,1007 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License,
+ or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "volume.h"
+
+int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
+ int i;
+ pa_assert(a);
+ pa_assert(b);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), 0);
+
+ if (PA_UNLIKELY(a == b))
+ return 1;
+
+ pa_return_val_if_fail(pa_cvolume_valid(b), 0);
+
+ if (a->channels != b->channels)
+ return 0;
+
+ for (i = 0; i < a->channels; i++)
+ if (a->values[i] != b->values[i])
+ return 0;
+
+ return 1;
+}
+
+pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
+ unsigned c;
+
+ pa_assert(a);
+
+ a->channels = 0;
+
+ for (c = 0; c < PA_CHANNELS_MAX; c++)
+ a->values[c] = PA_VOLUME_INVALID;
+
+ return a;
+}
+
+pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
+ int i;
+
+ pa_assert(a);
+ pa_assert(pa_channels_valid(channels));
+
+ a->channels = (uint8_t) channels;
+
+ for (i = 0; i < a->channels; i++)
+ /* Clamp in case there is stale data that exceeds the current
+ * PA_VOLUME_MAX */
+ a->values[i] = PA_CLAMP_VOLUME(v);
+
+ return a;
+}
+
+pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
+ uint64_t sum = 0;
+ unsigned c;
+
+ pa_assert(a);
+ pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
+
+ for (c = 0; c < a->channels; c++)
+ sum += a->values[c];
+
+ sum /= a->channels;
+
+ return (pa_volume_t) sum;
+}
+
+pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
+ uint64_t sum = 0;
+ unsigned c, n;
+
+ pa_assert(a);
+
+ if (!cm)
+ return pa_cvolume_avg(a);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
+
+ for (c = n = 0; c < a->channels; c++) {
+
+ if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
+ continue;
+
+ sum += a->values[c];
+ n ++;
+ }
+
+ if (n > 0)
+ sum /= n;
+
+ return (pa_volume_t) sum;
+}
+
+pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
+ pa_volume_t m = PA_VOLUME_MUTED;
+ unsigned c;
+
+ pa_assert(a);
+ pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
+
+ for (c = 0; c < a->channels; c++)
+ if (a->values[c] > m)
+ m = a->values[c];
+
+ return m;
+}
+
+pa_volume_t pa_cvolume_min(const pa_cvolume *a) {
+ pa_volume_t m = PA_VOLUME_MAX;
+ unsigned c;
+
+ pa_assert(a);
+ pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
+
+ for (c = 0; c < a->channels; c++)
+ if (a->values[c] < m)
+ m = a->values[c];
+
+ return m;
+}
+
+pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
+ pa_volume_t m = PA_VOLUME_MUTED;
+ unsigned c;
+
+ pa_assert(a);
+
+ if (!cm)
+ return pa_cvolume_max(a);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
+
+ for (c = 0; c < a->channels; c++) {
+
+ if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
+ continue;
+
+ if (a->values[c] > m)
+ m = a->values[c];
+ }
+
+ return m;
+}
+
+pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
+ pa_volume_t m = PA_VOLUME_MAX;
+ unsigned c;
+
+ pa_assert(a);
+
+ if (!cm)
+ return pa_cvolume_min(a);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
+
+ for (c = 0; c < a->channels; c++) {
+
+ if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
+ continue;
+
+ if (a->values[c] < m)
+ m = a->values[c];
+ }
+
+ return m;
+}
+
+pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
+ uint64_t result;
+
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
+
+ /* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
+
+ result = ((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM;
+
+ if (result > (uint64_t)PA_VOLUME_MAX)
+ pa_log_warn("pa_sw_volume_multiply: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
+
+ return (pa_volume_t) PA_CLAMP_VOLUME(result);
+}
+
+pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
+ uint64_t result;
+
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
+
+ if (b <= PA_VOLUME_MUTED)
+ return 0;
+
+ result = ((uint64_t) a * (uint64_t) PA_VOLUME_NORM + (uint64_t) b / 2ULL) / (uint64_t) b;
+
+ if (result > (uint64_t)PA_VOLUME_MAX)
+ pa_log_warn("pa_sw_volume_divide: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
+
+ return (pa_volume_t) PA_CLAMP_VOLUME(result);
+}
+
+/* Amplitude, not power */
+static double linear_to_dB(double v) {
+ return 20.0 * log10(v);
+}
+
+static double dB_to_linear(double v) {
+ return pow(10.0, v / 20.0);
+}
+
+pa_volume_t pa_sw_volume_from_dB(double dB) {
+#ifdef __MUSL__
+ if (dB == -INFINITY || dB <= PA_DECIBEL_MININFTY)
+ return PA_VOLUME_MUTED;
+#else
+ if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
+ return PA_VOLUME_MUTED;
+#endif // __MUSL__
+
+ return pa_sw_volume_from_linear(dB_to_linear(dB));
+}
+
+double pa_sw_volume_to_dB(pa_volume_t v) {
+
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), PA_DECIBEL_MININFTY);
+
+ if (v <= PA_VOLUME_MUTED)
+ return PA_DECIBEL_MININFTY;
+
+ return linear_to_dB(pa_sw_volume_to_linear(v));
+}
+
+pa_volume_t pa_sw_volume_from_linear(double v) {
+
+ if (v <= 0.0)
+ return PA_VOLUME_MUTED;
+
+ /*
+ * We use a cubic mapping here, as suggested and discussed here:
+ *
+ * http://www.robotplanet.dk/audio/audio_gui_design/
+ * http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-May/thread.html#23151
+ *
+ * We make sure that the conversion to linear and back yields the
+ * same volume value! That's why we need the lround() below!
+ */
+
+ return (pa_volume_t) PA_CLAMP_VOLUME((uint64_t) lround(cbrt(v) * PA_VOLUME_NORM));
+}
+
+double pa_sw_volume_to_linear(pa_volume_t v) {
+ double f;
+
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0.0);
+
+ if (v <= PA_VOLUME_MUTED)
+ return 0.0;
+
+ if (v == PA_VOLUME_NORM)
+ return 1.0;
+
+ f = ((double) v / PA_VOLUME_NORM);
+
+ return f*f*f;
+}
+
+char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
+ unsigned channel;
+ bool first = true;
+ char *e;
+
+ pa_assert(s);
+ pa_assert(l > 0);
+ pa_assert(c);
+
+ pa_init_i18n();
+
+ if (!pa_cvolume_valid(c)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ *(e = s) = 0;
+
+ for (channel = 0; channel < c->channels && l > 1; channel++) {
+ l -= pa_snprintf(e, l, "%s%u: %3u%%",
+ first ? "" : " ",
+ channel,
+ (unsigned)(((uint64_t)c->values[channel] * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
+
+ e = strchr(e, 0);
+ first = false;
+ }
+
+ return s;
+}
+
+char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
+ pa_assert(s);
+ pa_assert(l > 0);
+
+ pa_init_i18n();
+
+ if (!PA_VOLUME_IS_VALID(v)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ pa_snprintf(s, l, "%3u%%", (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
+ return s;
+}
+
+char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
+ unsigned channel;
+ bool first = true;
+ char *e;
+
+ pa_assert(s);
+ pa_assert(l > 0);
+ pa_assert(c);
+
+ pa_init_i18n();
+
+ if (!pa_cvolume_valid(c)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ *(e = s) = 0;
+
+ for (channel = 0; channel < c->channels && l > 1; channel++) {
+ double f = pa_sw_volume_to_dB(c->values[channel]);
+
+#ifdef __MUSL__
+ l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
+ first ? "" : " ",
+ channel,
+ f == -INFINITY || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
+#else
+ l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
+ first ? "" : " ",
+ channel,
+ isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
+#endif // __MUSL__
+
+ e = strchr(e, 0);
+ first = false;
+ }
+
+ return s;
+}
+
+char *pa_cvolume_snprint_verbose(char *s, size_t l, const pa_cvolume *c, const pa_channel_map *map, int print_dB) {
+ char *current = s;
+ bool first = true;
+
+ pa_assert(s);
+ pa_assert(l > 0);
+ pa_assert(c);
+
+ pa_init_i18n();
+
+ if (!pa_cvolume_valid(c)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ pa_assert(!map || (map->channels == c->channels));
+ pa_assert(!map || pa_channel_map_valid(map));
+
+ current[0] = 0;
+
+ for (unsigned channel = 0; channel < c->channels && l > 1; channel++) {
+ char channel_position[32];
+ size_t bytes_printed;
+ char buf[PA_VOLUME_SNPRINT_VERBOSE_MAX];
+
+ if (map)
+ pa_snprintf(channel_position, sizeof(channel_position), "%s", pa_channel_position_to_string(map->map[channel]));
+ else
+ pa_snprintf(channel_position, sizeof(channel_position), "%u", channel);
+
+ bytes_printed = pa_snprintf(current, l, "%s%s: %s",
+ first ? "" : ", ",
+ channel_position,
+ pa_volume_snprint_verbose(buf, sizeof(buf), c->values[channel], print_dB));
+ l -= bytes_printed;
+ current += bytes_printed;
+ first = false;
+ }
+
+ return s;
+}
+
+char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
+ double f;
+
+ pa_assert(s);
+ pa_assert(l > 0);
+
+ pa_init_i18n();
+
+ if (!PA_VOLUME_IS_VALID(v)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ f = pa_sw_volume_to_dB(v);
+#ifdef __MUSL__
+ pa_snprintf(s, l, "%0.2f dB", f == -INFINITY || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
+#else
+ pa_snprintf(s, l, "%0.2f dB", isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
+#endif // __MUSL__
+
+ return s;
+}
+
+char *pa_volume_snprint_verbose(char *s, size_t l, pa_volume_t v, int print_dB) {
+ char dB[PA_SW_VOLUME_SNPRINT_DB_MAX];
+
+ pa_assert(s);
+ pa_assert(l > 0);
+
+ pa_init_i18n();
+
+ if (!PA_VOLUME_IS_VALID(v)) {
+ pa_snprintf(s, l, _("(invalid)"));
+ return s;
+ }
+
+ pa_snprintf(s, l, "%" PRIu32 " / %3u%%%s%s",
+ v,
+ (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM),
+ print_dB ? " / " : "",
+ print_dB ? pa_sw_volume_snprint_dB(dB, sizeof(dB), v) : "");
+
+ return s;
+}
+
+int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
+ unsigned c;
+ pa_assert(a);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), 0);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0);
+
+ for (c = 0; c < a->channels; c++)
+ if (a->values[c] != v)
+ return 0;
+
+ return 1;
+}
+
+pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+ pa_assert(b);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
+
+ dest->channels = PA_MIN(a->channels, b->channels);
+
+ for (i = 0; i < dest->channels; i++)
+ dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
+
+ return dest;
+}
+
+pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
+
+ for (i = 0; i < a->channels; i++)
+ dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
+
+ dest->channels = (uint8_t) i;
+
+ return dest;
+}
+
+pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+ pa_assert(b);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
+
+ dest->channels = PA_MIN(a->channels, b->channels);
+
+ for (i = 0; i < dest->channels; i++)
+ dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
+
+ return dest;
+}
+
+pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
+
+ for (i = 0; i < a->channels; i++)
+ dest->values[i] = pa_sw_volume_divide(a->values[i], b);
+
+ dest->channels = (uint8_t) i;
+
+ return dest;
+}
+
+int pa_cvolume_valid(const pa_cvolume *v) {
+ unsigned c;
+
+ pa_assert(v);
+
+ if (!pa_channels_valid(v->channels))
+ return 0;
+
+ for (c = 0; c < v->channels; c++)
+ if (!PA_VOLUME_IS_VALID(v->values[c]))
+ return 0;
+
+ return 1;
+}
+
+static bool on_left(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LEFT);
+}
+
+static bool on_right(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_RIGHT);
+}
+
+static bool on_center(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_CENTER);
+}
+
+static bool on_hfe(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_HFE);
+}
+
+static bool on_lfe(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LFE);
+}
+
+static bool on_front(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_FRONT);
+}
+
+static bool on_rear(pa_channel_position_t p) {
+ return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_REAR);
+}
+
+pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
+ int a, b;
+ pa_cvolume result;
+
+ pa_assert(v);
+ pa_assert(from);
+ pa_assert(to);
+
+ pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
+
+ if (pa_channel_map_equal(from, to))
+ return v;
+
+ result.channels = to->channels;
+
+ for (b = 0; b < to->channels; b++) {
+ pa_volume_t k = 0;
+ int n = 0;
+
+ for (a = 0; a < from->channels; a++)
+ if (from->map[a] == to->map[b]) {
+ k += v->values[a];
+ n ++;
+ }
+
+ if (n <= 0) {
+ for (a = 0; a < from->channels; a++)
+ if ((on_left(from->map[a]) && on_left(to->map[b])) ||
+ (on_right(from->map[a]) && on_right(to->map[b])) ||
+ (on_center(from->map[a]) && on_center(to->map[b])) ||
+ (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
+
+ k += v->values[a];
+ n ++;
+ }
+ }
+
+ if (n <= 0)
+ k = pa_cvolume_avg(v);
+ else
+ k /= n;
+
+ result.values[b] = k;
+ }
+
+ *v = result;
+ return v;
+}
+
+int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
+
+ pa_assert(v);
+ pa_assert(ss);
+
+ pa_return_val_if_fail(pa_cvolume_valid(v), 0);
+ pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
+
+ return v->channels == ss->channels;
+}
+
+int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) {
+ pa_assert(v);
+ pa_assert(cm);
+
+ pa_return_val_if_fail(pa_cvolume_valid(v), 0);
+ pa_return_val_if_fail(pa_channel_map_valid(cm), 0);
+
+ return v->channels == cm->channels;
+}
+
+/*
+ * Returns the average volume of l and r, where l and r are two disjoint sets of channels
+ * (e g left and right, or front and rear).
+ */
+static void get_avg(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *l, pa_volume_t *r,
+ bool (*on_l)(pa_channel_position_t), bool (*on_r)(pa_channel_position_t)) {
+ int c;
+ pa_volume_t left = 0, right = 0;
+ unsigned n_left = 0, n_right = 0;
+
+ pa_assert(v);
+ pa_assert(map);
+ pa_assert(map->channels == v->channels);
+ pa_assert(l);
+ pa_assert(r);
+
+ for (c = 0; c < map->channels; c++) {
+ if (on_l(map->map[c])) {
+ left += v->values[c];
+ n_left++;
+ } else if (on_r(map->map[c])) {
+ right += v->values[c];
+ n_right++;
+ }
+ }
+
+ if (n_left <= 0)
+ *l = PA_VOLUME_NORM;
+ else
+ *l = left / n_left;
+
+ if (n_right <= 0)
+ *r = PA_VOLUME_NORM;
+ else
+ *r = right / n_right;
+}
+
+float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
+ pa_volume_t left, right;
+
+ pa_assert(v);
+ pa_assert(map);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
+
+ if (!pa_channel_map_can_balance(map))
+ return 0.0f;
+
+ get_avg(map, v, &left, &right, on_left, on_right);
+
+ if (left == right)
+ return 0.0f;
+
+ /* 1.0, 0.0 => -1.0
+ 0.0, 1.0 => 1.0
+ 0.0, 0.0 => 0.0
+ 0.5, 0.5 => 0.0
+ 1.0, 0.5 => -0.5
+ 1.0, 0.25 => -0.75
+ 0.75, 0.25 => -0.66
+ 0.5, 0.25 => -0.5 */
+
+ if (left > right)
+ return -1.0f + ((float) right / (float) left);
+ else
+ return 1.0f - ((float) left / (float) right);
+}
+
+static pa_cvolume* set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance,
+ bool (*on_l)(pa_channel_position_t), bool (*on_r)(pa_channel_position_t)) {
+
+ pa_volume_t left, nleft, right, nright, m;
+ unsigned c;
+
+ get_avg(map, v, &left, &right, on_l, on_r);
+
+ m = PA_MAX(left, right);
+
+ if (new_balance <= 0) {
+ nright = (new_balance + 1.0f) * m;
+ nleft = m;
+ } else {
+ nleft = (1.0f - new_balance) * m;
+ nright = m;
+ }
+
+ for (c = 0; c < map->channels; c++) {
+ if (on_l(map->map[c])) {
+ if (left == 0)
+ v->values[c] = nleft;
+ else
+ v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nleft) / (uint64_t) left);
+ } else if (on_r(map->map[c])) {
+ if (right == 0)
+ v->values[c] = nright;
+ else
+ v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nright) / (uint64_t) right);
+ }
+ }
+
+ return v;
+}
+
+
+pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
+ pa_assert(map);
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+ pa_return_val_if_fail(new_balance >= -1.0f, NULL);
+ pa_return_val_if_fail(new_balance <= 1.0f, NULL);
+
+ if (!pa_channel_map_can_balance(map))
+ return v;
+
+ return set_balance(v, map, new_balance, on_left, on_right);
+}
+
+pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
+ unsigned c;
+ pa_volume_t t = 0;
+
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
+
+ t = pa_cvolume_max(v);
+
+ if (t <= PA_VOLUME_MUTED)
+ return pa_cvolume_set(v, v->channels, max);
+
+ for (c = 0; c < v->channels; c++)
+ v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
+
+ return v;
+}
+
+pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
+ unsigned c;
+ pa_volume_t t = 0;
+
+ pa_assert(v);
+
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
+
+ if (!cm)
+ return pa_cvolume_scale(v, max);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL);
+
+ t = pa_cvolume_max_mask(v, cm, mask);
+
+ if (t <= PA_VOLUME_MUTED)
+ return pa_cvolume_set(v, v->channels, max);
+
+ for (c = 0; c < v->channels; c++)
+ v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
+
+ return v;
+}
+
+float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
+ pa_volume_t rear, front;
+
+ pa_assert(v);
+ pa_assert(map);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
+
+ if (!pa_channel_map_can_fade(map))
+ return 0.0f;
+
+ get_avg(map, v, &rear, &front, on_rear, on_front);
+
+ if (front == rear)
+ return 0.0f;
+
+ if (rear > front)
+ return -1.0f + ((float) front / (float) rear);
+ else
+ return 1.0f - ((float) rear / (float) front);
+}
+
+pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) {
+ pa_assert(map);
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+ pa_return_val_if_fail(new_fade >= -1.0f, NULL);
+ pa_return_val_if_fail(new_fade <= 1.0f, NULL);
+
+ if (!pa_channel_map_can_fade(map))
+ return v;
+
+ return set_balance(v, map, new_fade, on_rear, on_front);
+}
+
+float pa_cvolume_get_lfe_balance(const pa_cvolume *v, const pa_channel_map *map) {
+ pa_volume_t hfe, lfe;
+
+ pa_assert(v);
+ pa_assert(map);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
+
+ if (!pa_channel_map_can_lfe_balance(map))
+ return 0.0f;
+
+ get_avg(map, v, &hfe, &lfe, on_hfe, on_lfe);
+
+ if (hfe == lfe)
+ return 0.0f;
+
+ if (hfe > lfe)
+ return -1.0f + ((float) lfe / (float) hfe);
+ else
+ return 1.0f - ((float) hfe / (float) lfe);
+}
+
+pa_cvolume* pa_cvolume_set_lfe_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
+ pa_assert(map);
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+ pa_return_val_if_fail(new_balance >= -1.0f, NULL);
+ pa_return_val_if_fail(new_balance <= 1.0f, NULL);
+
+ if (!pa_channel_map_can_lfe_balance(map))
+ return v;
+
+ return set_balance(v, map, new_balance, on_hfe, on_lfe);
+}
+
+pa_cvolume* pa_cvolume_set_position(
+ pa_cvolume *cv,
+ const pa_channel_map *map,
+ pa_channel_position_t t,
+ pa_volume_t v) {
+
+ unsigned c;
+ bool good = false;
+
+ pa_assert(cv);
+ pa_assert(map);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
+ pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), NULL);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == t) {
+ cv->values[c] = v;
+ good = true;
+ }
+
+ return good ? cv : NULL;
+}
+
+pa_volume_t pa_cvolume_get_position(
+ const pa_cvolume *cv,
+ const pa_channel_map *map,
+ pa_channel_position_t t) {
+
+ unsigned c;
+ pa_volume_t v = PA_VOLUME_MUTED;
+
+ pa_assert(cv);
+ pa_assert(map);
+
+ pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
+ pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == t)
+ if (cv->values[c] > v)
+ v = cv->values[c];
+
+ return v;
+}
+
+pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
+ unsigned i;
+
+ pa_assert(dest);
+ pa_assert(a);
+ pa_assert(b);
+
+ pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+ pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
+
+ dest->channels = PA_MIN(a->channels, b->channels);
+
+ for (i = 0; i < dest->channels; i++)
+ dest->values[i] = PA_MAX(a->values[i], b->values[i]);
+
+ return dest;
+}
+
+pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) {
+ pa_volume_t m;
+
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(inc), NULL);
+
+ m = pa_cvolume_max(v);
+
+ if (m >= limit - inc)
+ m = limit;
+ else
+ m += inc;
+
+ return pa_cvolume_scale(v, m);
+}
+
+pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
+ return pa_cvolume_inc_clamp(v, inc, PA_VOLUME_MAX);
+}
+
+pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
+ pa_volume_t m;
+
+ pa_assert(v);
+
+ pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+ pa_return_val_if_fail(PA_VOLUME_IS_VALID(dec), NULL);
+
+ m = pa_cvolume_max(v);
+
+ if (m <= PA_VOLUME_MUTED + dec)
+ m = PA_VOLUME_MUTED;
+ else
+ m -= dec;
+
+ return pa_cvolume_scale(v, m);
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..80737bb00d46f6f042d00f12bab1084e5a8ee366
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/BUILD.gn
@@ -0,0 +1,182 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+libsndfile_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/libsnd"
+
+config("pulsecore_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir",
+ "$pulseaudio_dir/src",
+ "$pulseaudio_build_path/include",
+ "$pulseaudio_build_path/src",
+ "//third_party/glib/glib",
+ "//third_party/glib",
+ "$libsndfile_build_path/include",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-implicit-function-declaration",
+ "-Wno-unused-function",
+ "-Wno-uninitialized",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ "-D__INCLUDED_FROM_PULSE_AUDIO",
+ ]
+}
+
+ohos_source_set("pulsecore_sources") {
+ sources = [
+ "$pulseaudio_build_path/src/pulsecore/ltdl-stub.c",
+ "$pulseaudio_dir/src/pulsecore/asyncmsgq.c",
+ "$pulseaudio_dir/src/pulsecore/asyncq.c",
+ "$pulseaudio_dir/src/pulsecore/auth-cookie.c",
+ "$pulseaudio_dir/src/pulsecore/card.c",
+ "$pulseaudio_dir/src/pulsecore/cli-command.c",
+ "$pulseaudio_dir/src/pulsecore/cli-text.c",
+ "$pulseaudio_dir/src/pulsecore/client.c",
+ "$pulseaudio_dir/src/pulsecore/core-scache.c",
+ "$pulseaudio_dir/src/pulsecore/core-subscribe.c",
+ "$pulseaudio_dir/src/pulsecore/core.c",
+ #"$pulseaudio_dir/src/pulsecore/cpu.c",
+ "$pulseaudio_dir/src/pulsecore/cpu-arm.c",
+ #"$pulseaudio_dir/src/pulsecore/cpu-orc.c",
+ #"$pulseaudio_dir/src/pulsecore/cpu-x86.c",
+ "$pulseaudio_dir/src/pulsecore/device-port.c",
+ "$pulseaudio_dir/src/pulsecore/database.c",
+ "$pulseaudio_dir/src/pulsecore/database-simple.c",
+ "$pulseaudio_dir/src/pulsecore/ffmpeg/resample2.c",
+ "$pulseaudio_dir/src/pulsecore/filter/biquad.c",
+ "$pulseaudio_dir/src/pulsecore/filter/crossover.c",
+ "$pulseaudio_dir/src/pulsecore/filter/lfe-filter.c",
+ "$pulseaudio_dir/src/pulsecore/hook-list.c",
+ "$pulseaudio_dir/src/pulsecore/ltdl-helper.c",
+ "$pulseaudio_dir/src/pulsecore/message-handler.c",
+ "$pulseaudio_dir/src/pulsecore/mix.c",
+ "$pulseaudio_dir/src/pulsecore/modargs.c",
+ "$pulseaudio_dir/src/pulsecore/modinfo.c",
+ "$pulseaudio_dir/src/pulsecore/module.c",
+ "$pulseaudio_dir/src/pulsecore/msgobject.c",
+ "$pulseaudio_dir/src/pulsecore/namereg.c",
+ "$pulseaudio_dir/src/pulsecore/object.c",
+ "$pulseaudio_dir/src/pulsecore/play-memblockq.c",
+ "$pulseaudio_dir/src/pulsecore/play-memchunk.c",
+ "$pulseaudio_dir/src/pulsecore/remap.c",
+ "$pulseaudio_dir/src/pulsecore/resampler.c",
+ "$pulseaudio_dir/src/pulsecore/resampler/ffmpeg.c",
+ "$pulseaudio_dir/src/pulsecore/resampler/peaks.c",
+ "$pulseaudio_dir/src/pulsecore/resampler/trivial.c",
+ "$pulseaudio_dir/src/pulsecore/rtpoll.c",
+ "$pulseaudio_dir/src/pulsecore/sconv-s16be.c",
+ "$pulseaudio_dir/src/pulsecore/sconv-s16le.c",
+ "$pulseaudio_dir/src/pulsecore/sconv.c",
+ "$pulseaudio_dir/src/pulsecore/shared.c",
+ "$pulseaudio_dir/src/pulsecore/sink.c",
+ "$pulseaudio_dir/src/pulsecore/sink-input.c",
+ "$pulseaudio_dir/src/pulsecore/sioman.c",
+ "$pulseaudio_dir/src/pulsecore/sound-file-stream.c",
+ "$pulseaudio_dir/src/pulsecore/sound-file.c",
+ "$pulseaudio_dir/src/pulsecore/source.c",
+ "$pulseaudio_dir/src/pulsecore/source-output.c",
+ "$pulseaudio_dir/src/pulsecore/start-child.c",
+ "$pulseaudio_dir/src/pulsecore/stream-util.c",
+ "$pulseaudio_dir/src/pulsecore/svolume_arm.c",
+ "$pulseaudio_dir/src/pulsecore/svolume_c.c",
+ "$pulseaudio_dir/src/pulsecore/svolume_mmx.c",
+ "$pulseaudio_dir/src/pulsecore/svolume_sse.c",
+ "$pulseaudio_dir/src/pulsecore/thread-mq.c",
+ ]
+
+ configs = [ ":pulsecore_config" ]
+}
+
+ohos_shared_library("pulsecore") {
+ deps = [
+ ":pulsecore_sources",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$libsndfile_build_path:sndfile",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+config("modules_internal_lib_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_build_path/include",
+ "$pulseaudio_dir/src",
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-function",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ "-D__INCLUDED_FROM_PULSE_AUDIO",
+ ]
+}
+
+ohos_shared_library("cli") {
+ sources = [ "$pulseaudio_dir/src/pulsecore/cli.c" ]
+
+ configs = [ ":modules_internal_lib_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("protocol-cli") {
+ sources = [ "$pulseaudio_dir/src/pulsecore/protocol-cli.c" ]
+
+ configs = [ ":modules_internal_lib_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ "$pulseaudio_build_path/src/pulsecore:cli",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_shared_library("protocol-native") {
+ sources = [ "$pulseaudio_dir/src/pulsecore/protocol-native.c" ]
+
+ configs = [ ":modules_internal_lib_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$pulseaudio_build_path/src/pulsecore:pulsecore",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/ltdl-stub.c b/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/ltdl-stub.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce239ab9b8ef4a8b822326f58214da872cc3ab67
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/pulsecore/ltdl-stub.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include
+#include "ltdl.h"
+#include
+
+#define SYSTEM_LIB_PATH "/system/lib/"
+
+lt_dlhandle lt_dlopenext(const char *filename) {
+ pa_assert(filename);
+ return (dlopen(filename, RTLD_NOW));
+}
+
+void* lt_dlsym(lt_dlhandle handle, const char *symbol) {
+ pa_assert(handle);
+ pa_assert(symbol);
+
+ return (dlsym(handle, symbol));
+}
+
+int lt_dlclose(lt_dlhandle handle) {
+ pa_assert(handle);
+ return (dlclose(handle));
+}
+
+const char *lt_dlerror(void) {
+ return dlerror();
+}
+
+const char* lt_dlgetsearchpath() {
+ const char* path = SYSTEM_LIB_PATH;
+ return path;
+}
diff --git a/frameworks/innerkitsimpl/pulseaudio/src/utils/BUILD.gn b/frameworks/innerkitsimpl/pulseaudio/src/utils/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..39a40462bbddff84667a8a5f979779c14a07c201
--- /dev/null
+++ b/frameworks/innerkitsimpl/pulseaudio/src/utils/BUILD.gn
@@ -0,0 +1,85 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+pulseaudio_dir = "//third_party/pulseaudio"
+pulseaudio_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/pulseaudio"
+libsndfile_build_path = "//foundation/multimedia/audio_standard/frameworks/innerkitsimpl/libsnd"
+
+config("pulseutils_config") {
+ visibility = [ ":*" ]
+
+ include_dirs = [
+ "$pulseaudio_dir",
+ "$pulseaudio_build_path/src",
+ "$pulseaudio_build_path/include",
+ "$pulseaudio_dir/src",
+ "$libsndfile_build_path/include",
+ ]
+
+ cflags = [
+ "-Wall",
+ "-Werror",
+ "-Wno-implicit-function-declaration",
+ "-DHAVE_CONFIG_H",
+ "-D_GNU_SOURCE",
+ ]
+}
+
+ohos_executable("pacat") {
+
+ sources = [ "$pulseaudio_dir/src/utils/pacat.c" ]
+
+ configs = [ ":pulseutils_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$libsndfile_build_path:sndfile",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_executable("pactl") {
+ sources = [ "$pulseaudio_dir/src/utils/pactl.c" ]
+
+ configs = [ ":pulseutils_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src:pulsecommon",
+ "$libsndfile_build_path:sndfile",
+ ]
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
+
+ohos_executable("pacmd") {
+
+ install_enable = true
+
+ sources = [ "$pulseaudio_dir/src/utils/pacmd.c" ]
+
+ configs = [ ":pulseutils_config" ]
+
+ deps = [
+ "$pulseaudio_build_path/src/pulse:pulse",
+ "$pulseaudio_build_path/src:pulsecommon",
+ ]
+
+ subsystem_name = "multimedia"
+ part_name = "multimedia_audio_standard"
+}
diff --git a/frameworks/innerkitsimpl/test/BUILD.gn b/frameworks/innerkitsimpl/test/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..5fa4016c5a04bbfc91691b7f6e3fbf3d20805a32
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+group("audio_test") {
+ testonly = true
+
+ deps = [
+ "moduletest/renderer_test:moduletest",
+ "moduletest/recorder_test:audio_recorder_module_test",
+ "moduletest/audiopolicy:audio_policy_module_test"
+ ]
+}
diff --git a/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/include/audio_policy_test.h b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/include/audio_policy_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..472f942660496fcd4c8f7474354f7281ee2638dc
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/include/audio_policy_test.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+namespace OHOS {
+namespace AudioStandard {
+namespace V1_0 {
+using namespace std;
+using namespace testing;
+
+struct PolicyParam {
+ float volume;
+ AudioStreamType streamType;
+ AudioRingerMode ringerMode;
+ AudioStandard::DeviceType deviceType;
+ AudioStandard::AudioDeviceDescriptor::DeviceFlag deviceFlag;
+ AudioStandard::AudioDeviceDescriptor::DeviceRole deviceRole;
+ bool active;
+ bool mute;
+ string key;
+ string value;
+};
+
+class AudioPolicyTest : public TestWithParam {
+public:
+ AudioPolicyTest() {}
+
+ virtual ~AudioPolicyTest() {}
+
+ // SetUpTestCase: Called before all test cases
+ static void SetUpTestCase(void);
+ // TearDownTestCase: Called after all test case
+ static void TearDownTestCase(void);
+ // SetUp: Called before each test cases
+ void SetUp(void) override;
+ // TearDown: Called after each test cases
+ void TearDown(void) override;
+};
+}
+}
+}
diff --git a/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/src/audio_policy_test.cpp b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/src/audio_policy_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f2d5fb8efa3b6e300b7e54f098234e61974dc36e
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/1.0/src/audio_policy_test.cpp
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "audio_policy_test.h"
+#include "audio_system_manager.h"
+
+using namespace std;
+using namespace OHOS::AudioStandard;
+using namespace testing::ext;
+
+namespace OHOS {
+namespace AudioStandard {
+namespace V1_0 {
+void AudioPolicyTest::SetUpTestCase(void)
+{
+ ASSERT_NE(nullptr, AudioSystemManager::GetInstance());
+}
+
+void AudioPolicyTest::TearDownTestCase(void) {}
+
+void AudioPolicyTest::SetUp(void) {}
+
+void AudioPolicyTest::TearDown(void) {}
+
+namespace {
+const PolicyParam VOLUME_PARAMS[] = {
+ {
+ .volume = 0.5,
+ .streamType = STREAM_MUSIC
+ },
+ {
+ .volume = 0.5,
+ .streamType = STREAM_RING
+ }
+};
+
+const PolicyParam MUTE_PARAMS[] = {
+ {
+ .streamType = STREAM_MUSIC,
+ .mute = true
+ },
+ {
+ .streamType = STREAM_MUSIC,
+ .mute = false
+ }
+};
+
+const PolicyParam STREAM_PARAMS[] = {
+ {
+ .streamType = STREAM_MUSIC,
+ .active = true
+ },
+ {
+ .streamType = STREAM_RING,
+ .active = false
+ }
+};
+
+const PolicyParam DEVICE_PARAMS[] = {
+ {
+ .deviceType = SPEAKER,
+ .active = true
+ },
+ {
+ .deviceType = MIC,
+ .active = true
+ },
+ {
+ .deviceType = BLUETOOTH_A2DP,
+ .active = true
+ },
+ {
+ .deviceType = BLUETOOTH_A2DP,
+ .active = false
+ },
+ {
+ .deviceType = BLUETOOTH_SCO,
+ .active = true
+ },
+ {
+ .deviceType = BLUETOOTH_SCO,
+ .active = false
+ },
+ {
+ .deviceType = MIC,
+ .active = true
+ },
+ {
+ .deviceType = BLUETOOTH_SCO,
+ .active = true
+ },
+ {
+ .deviceType = SPEAKER,
+ .active = true
+ },
+ {
+ .deviceType = BLUETOOTH_A2DP,
+ .active = true
+ },
+};
+
+const PolicyParam RINGER_MODE_PARAMS[] = {
+ {
+ .ringerMode = RINGER_MODE_NORMAL
+ },
+ {
+ .ringerMode = RINGER_MODE_SILENT
+ },
+ {
+ .ringerMode = RINGER_MODE_VIBRATE
+ },
+};
+
+const PolicyParam MIC_MUTE_PARAMS[] = {
+ {
+ .mute = true
+ },
+ {
+ .mute = false
+ }
+};
+
+const PolicyParam VOLUME_RANGE_PARAMS[] = {
+ {
+ .streamType = STREAM_MUSIC
+ },
+ {
+ .streamType = STREAM_RING
+ }
+};
+
+const PolicyParam AUDIO_PARAMS[] = {
+ {
+ .key = "sampling_rate",
+ .value = "8000"
+ },
+ {
+ .key = "sampling_rate",
+ .value = "44100"
+ },
+ {
+ .key = "sampling_rate",
+ .value = "96000"
+ }
+};
+
+const PolicyParam DEVICES_PARAMS[] = {
+ {
+ .deviceType = MIC,
+ .deviceFlag = AudioDeviceDescriptor::DeviceFlag::INPUT_DEVICES_FLAG,
+ .deviceRole = AudioDeviceDescriptor::DeviceRole::INPUT_DEVICE
+ },
+ {
+ .deviceType = SPEAKER,
+ .deviceFlag = AudioDeviceDescriptor::DeviceFlag::OUTPUT_DEVICES_FLAG,
+ .deviceRole = AudioDeviceDescriptor::DeviceRole::OUTPUT_DEVICE
+ }
+};
+} // namespace
+
+/*
+ * Set Volume
+ *
+ */
+class AudioPolicySetVolumeTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicySetVolumeTest, SetVolume, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ float volume = params.volume;
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetVolume(volumeType, volume));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SetVolume,
+ AudioPolicySetVolumeTest,
+ ValuesIn(VOLUME_PARAMS));
+
+/*
+ * Get Volume
+ *
+ */
+
+class AudioPolicyGetVolumeTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyGetVolumeTest, GetVolume, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ float volume = params.volume;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetVolume(volumeType, volume));
+ EXPECT_EQ(volume, AudioSystemManager::GetInstance()->GetVolume(volumeType));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetVolume,
+ AudioPolicyGetVolumeTest,
+ ValuesIn(VOLUME_PARAMS));
+
+/*
+ * Set Mute
+ *
+ */
+class AudioPolicySetMuteTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicySetMuteTest, SetMute, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ bool mute = params.mute;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetMute(volumeType, mute));
+}
+
+
+INSTANTIATE_TEST_CASE_P(
+ SetMute,
+ AudioPolicySetMuteTest,
+ ValuesIn(MUTE_PARAMS));
+
+/*
+ * Is Mute
+ *
+ */
+class AudioPolicyGetMuteTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyGetMuteTest, IsStreamMute, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ bool mute = params.mute;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetMute(volumeType, mute));
+ EXPECT_EQ(mute, AudioSystemManager::GetInstance()->IsStreamMute(volumeType));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ IsStreamMute,
+ AudioPolicyGetMuteTest,
+ ValuesIn(MUTE_PARAMS));
+
+/*
+ * Is Stream Active
+ *
+ */
+class AudioPolicyIsStreamActiveTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyIsStreamActiveTest, IsStreamActive, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+
+ // review this code
+ EXPECT_EQ(params.active, AudioSystemManager::GetInstance()->IsStreamActive(volumeType));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ IsStreamActive,
+ AudioPolicyIsStreamActiveTest,
+ ValuesIn(STREAM_PARAMS));
+
+/*
+ * Set Device Active
+ *
+ */
+class AudioPolicySetDeviceActiveTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicySetDeviceActiveTest, SetDeviceActive, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioDeviceDescriptor::DeviceType deviceType = static_cast(params.deviceType);
+ bool active = params.active;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetDeviceActive(deviceType, active));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SetDeviceActive,
+ AudioPolicySetDeviceActiveTest,
+ ValuesIn(DEVICE_PARAMS));
+
+/*
+ * Is Device Active
+ *
+ */
+
+class AudioPolicyIsDeviceActiveTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyIsDeviceActiveTest, IsDeviceActive, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioDeviceDescriptor::DeviceType deviceType = static_cast(params.deviceType);
+ bool active = params.active;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetDeviceActive(deviceType, active));
+ EXPECT_EQ(active, AudioSystemManager::GetInstance()->IsDeviceActive(deviceType));
+}
+
+
+INSTANTIATE_TEST_CASE_P(
+ IsDeviceActive,
+ AudioPolicyIsDeviceActiveTest,
+ ValuesIn(DEVICE_PARAMS));
+
+/*
+ * Set Ringer Mode
+ *
+ */
+class AudioPolicySetRingerModeTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicySetRingerModeTest, SetRingerMode, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioRingerMode ringerMode = params.ringerMode;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetRingerMode(ringerMode));
+}
+
+
+INSTANTIATE_TEST_CASE_P(
+ SetRingerMode,
+ AudioPolicySetRingerModeTest,
+ ValuesIn(RINGER_MODE_PARAMS));
+
+/*
+ * Get Ringer Mode
+ *
+ */
+
+class AudioPolicyGetRingerModeTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyGetRingerModeTest, GetRingerMode, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioRingerMode ringerMode = params.ringerMode;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetRingerMode(ringerMode));
+ EXPECT_EQ(ringerMode, AudioSystemManager::GetInstance()->GetRingerMode());
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetRingerMode,
+ AudioPolicyGetRingerModeTest,
+ ValuesIn(RINGER_MODE_PARAMS));
+
+
+/*
+ * Set microphone mute
+ *
+ */
+class AudioPolicySetMicrophoneMuteTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicySetMicrophoneMuteTest, SetMicrophoneMute, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ bool mute = params.mute;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetMicrophoneMute(mute));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SetMicrophoneMute,
+ AudioPolicySetMicrophoneMuteTest,
+ ValuesIn(MIC_MUTE_PARAMS));
+
+/*
+ * Is Microphone Mute
+ *
+ */
+class AudioPolicyGetMicrophoneMuteTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyGetMicrophoneMuteTest, IsMicrophoneMute, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ bool mute = params.mute;
+
+ EXPECT_EQ(MEDIA_OK, AudioSystemManager::GetInstance()->SetMicrophoneMute(mute));
+ EXPECT_EQ(mute, AudioSystemManager::GetInstance()->IsMicrophoneMute());
+}
+
+INSTANTIATE_TEST_CASE_P(
+ IsMicrophoneMute,
+ AudioPolicyGetMicrophoneMuteTest,
+ ValuesIn(MIC_MUTE_PARAMS));
+
+/*
+ * Check volume range
+ *
+ */
+class AudioPolicyVolumeRangeTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyVolumeRangeTest, GetMaxVolume, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ EXPECT_EQ(1.0, AudioSystemManager::GetInstance()->GetMaxVolume(volumeType));
+}
+
+HWTEST_P(AudioPolicyVolumeRangeTest, GetMinVolume, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::AudioVolumeType volumeType
+ = static_cast(params.streamType);
+ EXPECT_EQ(0, AudioSystemManager::GetInstance()->GetMinVolume(volumeType));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetMaxVolume,
+ AudioPolicyVolumeRangeTest,
+ ValuesIn(VOLUME_RANGE_PARAMS));
+
+INSTANTIATE_TEST_CASE_P(
+ GetMinVolume,
+ AudioPolicyVolumeRangeTest,
+ ValuesIn(VOLUME_RANGE_PARAMS));
+
+/*
+ * Check volume range
+ *
+ */
+class AudioPolicyAudioParameterTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyAudioParameterTest, SetAudioParameter, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::GetInstance()->SetAudioParameter(params.key, params.value);
+ EXPECT_EQ(params.value, AudioSystemManager::GetInstance()->GetAudioParameter(params.key));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ SetAudioParameter,
+ AudioPolicyAudioParameterTest,
+ ValuesIn(AUDIO_PARAMS));
+
+HWTEST_P(AudioPolicyAudioParameterTest, GetAudioParameter, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioSystemManager::GetInstance()->SetAudioParameter(params.key, params.value);
+ EXPECT_EQ(params.value, AudioSystemManager::GetInstance()->GetAudioParameter(params.key));
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetAudioParameter,
+ AudioPolicyAudioParameterTest,
+ ValuesIn(AUDIO_PARAMS));
+
+/*
+ * Check volume range
+ *
+ */
+class AudioPolicyGetDevicesTest : public AudioPolicyTest {};
+
+HWTEST_P(AudioPolicyGetDevicesTest, GetDevices, TestSize.Level1)
+{
+ PolicyParam params = GetParam();
+ AudioDeviceDescriptor::DeviceFlag deviceFlag = static_cast(params.deviceFlag);
+ AudioDeviceDescriptor::DeviceType deviceType = static_cast(params.deviceType);
+ AudioDeviceDescriptor::DeviceRole deviceRole = static_cast(params.deviceRole);
+ vector> audioDeviceDescriptors
+ = AudioSystemManager::GetInstance()->GetDevices(deviceFlag);
+ sptr audioDeviceDescriptor = audioDeviceDescriptors[0];
+ EXPECT_EQ(deviceType, audioDeviceDescriptor->deviceType_);
+ EXPECT_EQ(deviceRole, audioDeviceDescriptor->deviceRole_);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ GetDevices,
+ AudioPolicyGetDevicesTest,
+ ValuesIn(DEVICES_PARAMS));
+}
+}
+}
diff --git a/frameworks/innerkitsimpl/test/moduletest/audiopolicy/BUILD.gn b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..f1f218de0fb36b5e7bcde8754bec6cfd85c22577
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/audiopolicy/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/test.gni")
+
+module_output_path = "audio_standard/audio_policy"
+
+group("moduletest") {
+ testonly = true
+
+ deps = [
+ ":audio_policy_module_test",
+ ]
+}
+
+ohos_moduletest("audio_policy_module_test") {
+ module_out_path = module_output_path
+ include_dirs = [
+ "./1.0/include",
+ "//foundation/multimedia/audio_standard/interfaces/innerkits/native/audiomanager/include",
+ "//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
+ ]
+
+ sources = [
+ "1.0/src/audio_policy_test.cpp",
+ ]
+
+ deps = [
+ "//foundation/multimedia/audio_standard/interfaces/innerkits/native/audiomanager:audio_client",
+ "//utils/native/base:utils",
+ ]
+}
diff --git a/frameworks/innerkitsimpl/test/moduletest/recorder_test/BUILD.gn b/frameworks/innerkitsimpl/test/moduletest/recorder_test/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..2eb2888b5a746b2ac818901a84bc1c394deebcc1
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/recorder_test/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright (C) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/test.gni")
+
+module_output_path = "audio_standard/audio_recorder"
+
+ohos_moduletest("audio_recorder_module_test") {
+ module_out_path = module_output_path
+ include_dirs = [
+ "./include",
+ "//foundation/multimedia/audio_standard/interfaces/innerkits/native/audiocommon/include",
+ ]
+
+ sources = [
+ "src/audio_recorder_module_test.cpp",
+ ]
+
+ deps = [
+ "//foundation/multimedia/audio_standard/interfaces/innerkits/native/audiorecorder:audio_recorder",
+ ]
+}
diff --git a/frameworks/innerkitsimpl/test/moduletest/recorder_test/include/audio_recorder_module_test.h b/frameworks/innerkitsimpl/test/moduletest/recorder_test/include/audio_recorder_module_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..a5a11c8d90bcf5d073d41271c8a27f8597d7d958
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/recorder_test/include/audio_recorder_module_test.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "audio_recorder.h"
+#include "gtest/gtest.h"
+
+namespace OHOS {
+namespace AudioStandard {
+class AudioRecorderModuleTest : public testing::Test {
+public:
+ // SetUpTestCase: Called before all test cases
+ static void SetUpTestCase(void);
+ // TearDownTestCase: Called after all test case
+ static void TearDownTestCase(void);
+ // SetUp: Called before each test cases
+ void SetUp(void);
+ // TearDown: Called after each test cases
+ void TearDown(void);
+ // Init Recorder
+ static int32_t InitializeRecorder(std::unique_ptr &audioRecorder);
+};
+} // namespace AudioStandard
+} // namespace OHOS
diff --git a/frameworks/innerkitsimpl/test/moduletest/recorder_test/src/audio_recorder_module_test.cpp b/frameworks/innerkitsimpl/test/moduletest/recorder_test/src/audio_recorder_module_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bc6446867db33902830ca1178f45d17265483e8f
--- /dev/null
+++ b/frameworks/innerkitsimpl/test/moduletest/recorder_test/src/audio_recorder_module_test.cpp
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "audio_recorder_module_test.h"
+
+
+#include "audio_info.h"
+#include "audio_recorder.h"
+
+using namespace std;
+using namespace testing::ext;
+
+namespace OHOS {
+namespace AudioStandard {
+namespace {
+ const string AUDIO_RECORD_FILE1 = "/data/audioreordtest_blocking.pcm";
+ const string AUDIO_RECORD_FILE2 = "/data/audioreordtest_nonblocking.pcm";
+ const string AUDIO_RECORD_FILE3 = "/data/audioreordtest_out.pcm";
+ const int32_t READ_BUFFERS_COUNT = 128;
+ const int32_t VALUE_ZERO = 0;
+ const int32_t SUCCESS = 0;
+} // namespace
+
+void AudioRecorderModuleTest::SetUpTestCase(void) {}
+void AudioRecorderModuleTest::TearDownTestCase(void) {}
+void AudioRecorderModuleTest::SetUp(void) {}
+void AudioRecorderModuleTest::TearDown(void) {}
+
+int32_t AudioRecorderModuleTest::InitializeRecorder(unique_ptr &audioRecorder)
+{
+ AudioRecorderParams recorderParams;
+ recorderParams.audioSampleFormat = SAMPLE_S16LE;
+ recorderParams.samplingRate = SAMPLE_RATE_44100;
+ recorderParams.audioChannel = STEREO;
+ recorderParams.audioEncoding = ENCODING_PCM;
+
+ return audioRecorder->SetParams(recorderParams);
+}
+
+/**
+* @tc.name : Test GetSupportedFormats API
+* @tc.number: Auido_Recorder_GetSupportedFormats_001
+* @tc.desc : test GetSupportedFormats interface, Returns supported Formats on success.
+*/
+HWTEST(AudioRecorderModuleTest, Auido_Recorder_GetSupportedFormats_001, TestSize.Level1)
+{
+ vector supportedFormatList = AudioRecorder::GetSupportedFormats();
+ EXPECT_EQ(AUDIO_SUPPORTED_FORMATS.size(), supportedFormatList.size());
+}
+
+/**
+* @tc.name : Test GetSupportedChannels API
+* @tc.number: Auido_Recorder_GetSupportedChannels_001
+* @tc.desc : test GetSupportedChannels interface, Returns supported Channels on success.
+*/
+HWTEST(AudioRecorderModuleTest, Auido_Recorder_GetSupportedChannels_001, TestSize.Level1)
+{
+ vector supportedChannelList = AudioRecorder::GetSupportedChannels();
+ EXPECT_EQ(AUDIO_SUPPORTED_CHANNELS.size(), supportedChannelList.size());
+}
+
+/**
+* @tc.name : Test GetSupportedEncodingTypes API
+* @tc.number: Auido_Recorder_GetSupportedEncodingTypes_001
+* @tc.desc : test GetSupportedEncodingTypes interface, Returns supported Encoding types on success.
+*/
+HWTEST(AudioRecorderModuleTest, Auido_Recorder_GetSupportedEncodingTypes_001, TestSize.Level1)
+{
+ vector