• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 #undef LOG_TAG
16 #define LOG_TAG "ModuleHdiSource"
17 
18 #include <config.h>
19 #include <pulsecore/log.h>
20 #include <pulsecore/modargs.h>
21 #include <pulsecore/module.h>
22 #include <pulsecore/source.h>
23 #include <stddef.h>
24 #include <stdbool.h>
25 
26 #include <pulsecore/core.h>
27 #include <pulsecore/core-util.h>
28 #include <pulsecore/namereg.h>
29 
30 #include "securec.h"
31 #include "audio_hdi_log.h"
32 #include "audio_enhance_chain_adapter.h"
33 #include "source_userdata.h"
34 #include "common/hdi_adapter_info.h"
35 
36 pa_source *PaHdiSourceNew(pa_module *m, pa_modargs *ma, const char *driver);
37 void PaHdiSourceFree(pa_source *s);
38 
39 PA_MODULE_AUTHOR("OpenHarmony");
40 PA_MODULE_DESCRIPTION("OpenHarmony HDI Source");
41 PA_MODULE_VERSION(PACKAGE_VERSION);
42 PA_MODULE_LOAD_ONCE(false);
43 PA_MODULE_USAGE(
44         "source_name=<name for the source> "
45         "device_class=<name for the device class> "
46         "source_properties=<properties for the source> "
47         "format=<sample format> "
48         "rate=<sample rate> "
49         "channels=<number of channels> "
50         "channel_map=<channel map>"
51         "buffer_size=<custom buffer size>"
52         "file_path=<file path for data reading>"
53         "adapter_name=<primary>"
54         "open_mic_speaker<open mic>"
55         "network_id<device network id>"
56         "device_type<device type or port>"
57         "source_type<source type or port>"
58     );
59 
60 static const char * const VALID_MODARGS[] = {
61     "source_name",
62     "device_class",
63     "source_properties",
64     "format",
65     "rate",
66     "channels",
67     "channel_map",
68     "buffer_size",
69     "file_path",
70     "adapter_name",
71     "open_mic_speaker",
72     "network_id",
73     "device_type",
74     "source_type",
75     "ec_type",
76     "ec_adapter",
77     "ec_sampling_rate",
78     "ec_format",
79     "ec_channels",
80     "open_mic_ref",
81     "mic_ref_rate",
82     "mic_ref_format",
83     "mic_ref_channels",
84     "default_adapter_enable",
85     NULL
86 };
87 
IncreaseScenekeyCount(pa_hashmap * sceneMap,const char * key)88 static void IncreaseScenekeyCount(pa_hashmap *sceneMap, const char *key)
89 {
90     if (sceneMap == NULL) {
91         return;
92     }
93     uint32_t *num = NULL;
94     if ((num = (uint32_t *)pa_hashmap_get(sceneMap, key)) != NULL) {
95         (*num)++;
96     } else {
97         char *sceneKey;
98         sceneKey = strdup(key);
99         if (sceneKey != NULL) {
100             num = pa_xnew0(uint32_t, 1);
101             *num = 1;
102             if (pa_hashmap_put(sceneMap, sceneKey, num) != 0) {
103                 AUDIO_ERR_LOG("pa_hashmap_put failed");
104                 free(sceneKey);
105                 pa_xfree(num);
106             }
107         }
108     }
109 }
110 
DecreaseScenekeyCount(pa_hashmap * sceneMap,const char * key)111 static bool DecreaseScenekeyCount(pa_hashmap *sceneMap, const char *key)
112 {
113     if (sceneMap == NULL) {
114         return false;
115     }
116     uint32_t *num = NULL;
117     if ((num = (uint32_t *)pa_hashmap_get(sceneMap, key)) != NULL) {
118         (*num)--;
119         if (*num == 0) {
120             pa_hashmap_remove_and_free(sceneMap, key);
121             return true;
122         }
123     }
124     return false;
125 }
126 
ConvertPaFormat(pa_sample_format_t paFormat)127 static enum AudioSampleFormatIntf ConvertPaFormat(pa_sample_format_t paFormat)
128 {
129     enum AudioSampleFormatIntf format;
130     switch (paFormat) {
131         case PA_SAMPLE_U8:
132             format = SAMPLE_U8;
133             break;
134         case PA_SAMPLE_S16LE:
135         case PA_SAMPLE_S16BE:
136             format = SAMPLE_S16;
137             break;
138         case PA_SAMPLE_S24LE:
139         case PA_SAMPLE_S24BE:
140             format = SAMPLE_S24;
141             break;
142         case PA_SAMPLE_S32LE:
143         case PA_SAMPLE_S32BE:
144             format = SAMPLE_S32;
145             break;
146         default:
147             format = SAMPLE_S16;
148             break;
149     }
150 
151     return format;
152 }
153 
SetResampler(pa_source_output * so,const char * sceneKey,const struct Userdata * u,const struct AlgoSpecs * algoSpecs)154 static void SetResampler(pa_source_output *so, const char *sceneKey, const struct Userdata *u,
155     const struct AlgoSpecs *algoSpecs)
156 {
157     pa_hashmap *preResamplerMap = (pa_hashmap *)u->sceneToPreResamplerMap;
158     pa_hashmap *ecResamplerMap = (pa_hashmap *)u->sceneToEcResamplerMap;
159     pa_hashmap *micRefResamplerMap = (pa_hashmap *)u->sceneToMicRefResamplerMap;
160     if (!pa_sample_spec_equal(&so->source->sample_spec, &algoSpecs->micSpec)) {
161         AUDIO_INFO_LOG("SOURCE spec:%{public}u_%{public}u_%{public}u ALGO spec:%{public}u_%{public}u_%{public}u",
162             so->source->sample_spec.rate, (uint32_t)so->source->sample_spec.channels,
163             (uint32_t)ConvertPaFormat(so->source->sample_spec.format),
164             algoSpecs->micSpec.rate,  (uint32_t)algoSpecs->micSpec.channels,
165             (uint32_t)ConvertPaFormat(algoSpecs->micSpec.format));
166         pa_resampler *preResampler = pa_resampler_new(so->source->core->mempool,
167             &so->source->sample_spec, &so->source->channel_map,
168             &algoSpecs->micSpec, &so->source->channel_map,
169             so->source->core->lfe_crossover_freq,
170             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
171         pa_hashmap_put(preResamplerMap, pa_xstrdup(sceneKey), preResampler);
172         pa_resampler *postResampler = pa_resampler_new(so->source->core->mempool,
173             &algoSpecs->micSpec, &so->source->channel_map,
174             &so->sample_spec, &so->source->channel_map,
175             so->source->core->lfe_crossover_freq,
176             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
177         so->thread_info.resampler = postResampler;
178     }
179     if ((u->ecType != EC_NONE) && (algoSpecs->ecSpec.rate != 0) &&
180         (!pa_sample_spec_equal(&u->ecSpec, &algoSpecs->ecSpec))) {
181         AUDIO_INFO_LOG("EC SOURCE spec:%{public}u_%{public}u_%{public}u ALGO spec:%{public}u_%{public}u_%{public}u",
182             u->ecSpec.rate, (uint32_t)u->ecSpec.channels, (uint32_t)ConvertPaFormat(u->ecSpec.format),
183             algoSpecs->ecSpec.rate,  (uint32_t)algoSpecs->ecSpec.channels,
184             (uint32_t)ConvertPaFormat(algoSpecs->ecSpec.format));
185         pa_resampler *ecResampler = pa_resampler_new(so->source->core->mempool,
186             &u->ecSpec, &so->source->channel_map,
187             &algoSpecs->ecSpec, &so->source->channel_map,
188             so->source->core->lfe_crossover_freq,
189             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
190         pa_hashmap_put(ecResamplerMap, pa_xstrdup(sceneKey), ecResampler);
191     }
192     if ((u->micRef == REF_ON) && (algoSpecs->micRefSpec.rate != 0) &&
193         (!pa_sample_spec_equal(&u->micRefSpec, &algoSpecs->micRefSpec))) {
194         AUDIO_INFO_LOG("MIC REF SOURCE spec:%{public}u_%{public}u_%{public}u ALGO:%{public}u_%{public}u_%{public}u",
195             u->micRefSpec.rate, (uint32_t)u->micRefSpec.channels, (uint32_t)ConvertPaFormat(u->micRefSpec.format),
196             algoSpecs->micRefSpec.rate,  (uint32_t)algoSpecs->micRefSpec.channels,
197             (uint32_t)ConvertPaFormat(algoSpecs->micRefSpec.format));
198         pa_resampler *micRefResampler = pa_resampler_new(so->source->core->mempool,
199             &u->micRefSpec, &so->source->channel_map,
200             &algoSpecs->micRefSpec, &so->source->channel_map,
201             so->source->core->lfe_crossover_freq,
202             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
203         pa_hashmap_put(micRefResamplerMap, pa_xstrdup(sceneKey), micRefResampler);
204     }
205 }
206 
SetDefaultResampler(pa_source_output * so,const pa_sample_spec * algoConfig,struct Userdata * u)207 static void SetDefaultResampler(pa_source_output *so, const pa_sample_spec *algoConfig, struct Userdata *u)
208 {
209     if (!pa_sample_spec_equal(&so->source->sample_spec, algoConfig)) {
210         if (u->defaultSceneResampler) {
211             pa_resampler_free(u->defaultSceneResampler);
212         }
213         AUDIO_INFO_LOG("default SOURCE:%{public}u_%{public}u_%{public}u ALGO:%{public}u_%{public}u_%{public}u",
214             so->source->sample_spec.rate, (uint32_t)so->source->sample_spec.channels,
215             (uint32_t)ConvertPaFormat(so->source->sample_spec.format),
216             algoConfig->rate,  (uint32_t)algoConfig->channels,
217             (uint32_t)ConvertPaFormat(algoConfig->format));
218         u->defaultSceneResampler = pa_resampler_new(so->source->core->mempool,
219             &so->source->sample_spec, &so->source->channel_map,
220             algoConfig, &so->source->channel_map,
221             so->source->core->lfe_crossover_freq,
222             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
223         pa_resampler *postResampler = pa_resampler_new(so->source->core->mempool,
224             algoConfig, &so->source->channel_map,
225             &so->sample_spec, &so->source->channel_map,
226             so->source->core->lfe_crossover_freq,
227             PA_RESAMPLER_AUTO, PA_RESAMPLER_VARIABLE_RATE);
228         so->thread_info.resampler = postResampler;
229     }
230 }
231 
GetByteSizeByFormat(enum AudioSampleFormatIntf format)232 static uint32_t GetByteSizeByFormat(enum AudioSampleFormatIntf format)
233 {
234     uint32_t byteSize = 0;
235     switch (format) {
236         case SAMPLE_U8:
237             byteSize = BYTE_SIZE_SAMPLE_U8;
238             break;
239         case SAMPLE_S16:
240             byteSize = BYTE_SIZE_SAMPLE_S16;
241             break;
242         case SAMPLE_S24:
243             byteSize = BYTE_SIZE_SAMPLE_S24;
244             break;
245         case SAMPLE_S32:
246             byteSize = BYTE_SIZE_SAMPLE_S32;
247             break;
248         default:
249             byteSize = BYTE_SIZE_SAMPLE_S16;
250             break;
251     }
252     return byteSize;
253 }
254 
InitDeviceAttrAdapter(struct DeviceAttrAdapter * deviceAttrAdapter,struct Userdata * u)255 static void InitDeviceAttrAdapter(struct DeviceAttrAdapter *deviceAttrAdapter, struct Userdata *u)
256 {
257     deviceAttrAdapter->micRate = u->attrs.sampleRate;
258     deviceAttrAdapter->micChannels = u->attrs.channel;
259     deviceAttrAdapter->micFormat = GetByteSizeByFormat(u->attrs.format);
260     deviceAttrAdapter->needEc = false;
261     deviceAttrAdapter->needMicRef = false;
262     if (u->ecType != EC_NONE) {
263         deviceAttrAdapter->needEc = true;
264         deviceAttrAdapter->ecRate = u->ecSamplingRate;
265         deviceAttrAdapter->ecChannels = u->ecChannels;
266         deviceAttrAdapter->ecFormat = GetByteSizeByFormat(u->ecFormat);
267     } else {
268         deviceAttrAdapter->ecRate = 0;
269         deviceAttrAdapter->ecChannels = 0;
270         deviceAttrAdapter->ecFormat = 0;
271     }
272     if (u->micRef == REF_ON) {
273         deviceAttrAdapter->needMicRef = true;
274         deviceAttrAdapter->micRefRate = u->micRefRate;
275         deviceAttrAdapter->micRefChannels = u->micRefChannels;
276         deviceAttrAdapter->micRefFormat = GetByteSizeByFormat(u->micRefFormat);
277     } else {
278         deviceAttrAdapter->micRefRate = 0;
279         deviceAttrAdapter->micRefChannels = 0;
280         deviceAttrAdapter->micRefFormat = 0;
281     }
282 }
283 
GetAlgoSpecs(uint64_t sceneKeyCode,struct AlgoSpecs * algoSpecs)284 static pa_hook_result_t GetAlgoSpecs(uint64_t sceneKeyCode, struct AlgoSpecs *algoSpecs)
285 {
286     pa_sample_spec_init(&algoSpecs->micSpec);
287     pa_sample_spec_init(&algoSpecs->ecSpec);
288     pa_sample_spec_init(&algoSpecs->micRefSpec);
289 
290     if (EnhanceChainManagerGetAlgoConfig(sceneKeyCode, &algoSpecs->micSpec, &algoSpecs->ecSpec,
291         &algoSpecs->micRefSpec) != 0) {
292         AUDIO_ERR_LOG("Get algo config failed");
293         return PA_HOOK_OK;
294     }
295     return PA_HOOK_OK;
296 }
297 
HandleSourceOutputPut(pa_source_output * so,struct Userdata * u)298 static pa_hook_result_t HandleSourceOutputPut(pa_source_output *so, struct Userdata *u)
299 {
300     const char *sceneType = pa_proplist_gets(so->proplist, "scene.type");
301     if (sceneType == NULL) {
302         sceneType = "";
303     }
304     const char *sceneBypass = pa_proplist_gets(so->proplist, "scene.bypass");
305     if (pa_safe_streq(sceneBypass, DEFAULT_SCENE_BYPASS)) {
306         AUDIO_INFO_LOG("scene:%{public}s has been set to bypass", sceneType);
307         return PA_HOOK_OK;
308     }
309     uint32_t captureId = u->captureId;
310     uint32_t renderId = u->renderId;
311     uint64_t sceneTypeCode = 0;
312     if (GetSceneTypeCode(sceneType, &sceneTypeCode) != 0) {
313         AUDIO_ERR_LOG("scenetype:%{public}s GetSceneTypeCode failed", sceneType);
314         pa_proplist_sets(so->proplist, "scene.bypass", DEFAULT_SCENE_BYPASS);
315         return PA_HOOK_OK;
316     }
317     uint64_t sceneKeyCode = 0;
318     AUDIO_INFO_LOG("sceneTypeCode = %{public}" PRIu64 ", captureId = %{public}u, renderId = %{public}u",
319         sceneTypeCode, captureId, renderId);
320     sceneKeyCode = (sceneTypeCode << SCENE_TYPE_OFFSET) + (captureId << CAPTURER_ID_OFFSET) + renderId;
321     struct DeviceAttrAdapter deviceAttrAdapter;
322     InitDeviceAttrAdapter(&deviceAttrAdapter, u);
323     int32_t ret = EnhanceChainManagerCreateCb(sceneKeyCode, &deviceAttrAdapter);
324     if (ret < 0) {
325         AUDIO_INFO_LOG("Create EnhanceChain failed, set to bypass");
326         pa_proplist_sets(so->proplist, "scene.bypass", DEFAULT_SCENE_BYPASS);
327         return PA_HOOK_OK;
328     }
329     struct AlgoSpecs algoSpecs;
330     GetAlgoSpecs(sceneKeyCode, &algoSpecs);
331     // default chain
332     if (ret > 0) {
333         SetDefaultResampler(so, &algoSpecs.micSpec, u);
334         pa_proplist_sets(so->proplist, "scene.default", "1");
335     } else {
336         char sceneKey[MAX_SCENE_NAME_LEN];
337         if (sprintf_s(sceneKey, sizeof(sceneKey), "%lu", sceneKeyCode) < 0) {
338             AUDIO_ERR_LOG("sprintf from sceneKeyCode to sceneKey failed");
339             return PA_HOOK_OK;
340         }
341         IncreaseScenekeyCount(u->sceneToCountMap, sceneKey);
342         SetResampler(so, sceneKey, u, &algoSpecs);
343     }
344     EnhanceChainManagerInitEnhanceBuffer();
345     return PA_HOOK_OK;
346 }
347 
HandleSourceOutputUnlink(pa_source_output * so,struct Userdata * u)348 static pa_hook_result_t HandleSourceOutputUnlink(pa_source_output *so, struct Userdata *u)
349 {
350     const char *sceneType = pa_proplist_gets(so->proplist, "scene.type");
351     if (sceneType == NULL) {
352         sceneType = "";
353     }
354     const char *sceneBypass = pa_proplist_gets(so->proplist, "scene.bypass");
355     if (pa_safe_streq(sceneBypass, DEFAULT_SCENE_BYPASS)) {
356         AUDIO_INFO_LOG("scene:%{public}s has been set to bypass, do not need release", sceneType);
357         return PA_HOOK_OK;
358     }
359     uint32_t captureId = u->captureId;
360     uint32_t renderId = u->renderId;
361     uint64_t sceneTypeCode = 0;
362     if (GetSceneTypeCode(sceneType, &sceneTypeCode) != 0) {
363         AUDIO_ERR_LOG("scenetype:%{public}s GetSceneTypeCode failed", sceneType);
364         return PA_HOOK_OK;
365     }
366     uint64_t sceneKeyCode = 0;
367     sceneKeyCode = (sceneTypeCode << SCENE_TYPE_OFFSET) + (captureId << CAPTURER_ID_OFFSET) + renderId;
368     EnhanceChainManagerReleaseCb(sceneKeyCode);
369     char sceneKey[MAX_SCENE_NAME_LEN];
370     if (sprintf_s(sceneKey, sizeof(sceneKey), "%lu", sceneKeyCode) < 0) {
371         AUDIO_ERR_LOG("sprintf from sceneKeyCode to sceneKey failed");
372         return PA_HOOK_OK;
373     }
374     if (!pa_safe_streq(pa_proplist_gets(so->proplist, "scene.default"), "1") &&
375         DecreaseScenekeyCount(u->sceneToCountMap, sceneKey)) {
376         pa_hashmap_remove_and_free(u->sceneToPreResamplerMap, sceneKey);
377         pa_hashmap_remove_and_free(u->sceneToEcResamplerMap, sceneKey);
378         pa_hashmap_remove_and_free(u->sceneToMicRefResamplerMap, sceneKey);
379     }
380     return PA_HOOK_OK;
381 }
382 
CheckIfAvailSource(pa_source_output * so,struct Userdata * u)383 static pa_hook_result_t CheckIfAvailSource(pa_source_output *so, struct Userdata *u)
384 {
385     pa_source *soSource = so->source;
386     pa_source *thisSource = u->source;
387     if (soSource == NULL || thisSource == NULL) {
388         return PA_HOOK_CANCEL;
389     }
390     if (soSource->index != thisSource->index) {
391         AUDIO_INFO_LOG("NOT correspondant SOURCE %{public}s AND %{public}s.", soSource->name, thisSource->name);
392         return PA_HOOK_CANCEL;
393     }
394     return PA_HOOK_OK;
395 }
396 
SourceOutputPutCb(const pa_core * c,pa_source_output * so,struct Userdata * u)397 static pa_hook_result_t SourceOutputPutCb(const pa_core *c, pa_source_output *so, struct Userdata *u)
398 {
399     CHECK_AND_RETURN_RET_LOG(u != NULL, PA_HOOK_OK, "Get Userdata failed! userdata is NULL");
400     CHECK_AND_RETURN_RET_LOG(c != NULL, PA_HOOK_OK, "pa core is null");
401     CHECK_AND_RETURN_RET_LOG(so != NULL, PA_HOOK_OK, "so is NULL");
402 
403     const char *sessionID = pa_proplist_gets(so->proplist, "stream.sessionID");
404     if (sessionID == NULL) {
405         sessionID = "";
406     }
407     AUDIO_INFO_LOG("Trigger SourceOutputPutCb sessionID:%{public}s", sessionID);
408 
409     if (CheckIfAvailSource(so, u) == PA_HOOK_CANCEL) {
410         return PA_HOOK_OK;
411     }
412     return HandleSourceOutputPut(so, u);
413 }
414 
SourceOutputUnlinkCb(const pa_core * c,pa_source_output * so,struct Userdata * u)415 static pa_hook_result_t SourceOutputUnlinkCb(const pa_core *c, pa_source_output *so, struct Userdata *u)
416 {
417     CHECK_AND_RETURN_RET_LOG(u != NULL, PA_HOOK_OK, "Get Userdata failed! userdata is NULL");
418     CHECK_AND_RETURN_RET_LOG(c != NULL, PA_HOOK_OK, "pa core is null");
419     CHECK_AND_RETURN_RET_LOG(so != NULL, PA_HOOK_OK, "so is NULL");
420 
421     const char *sessionID = pa_proplist_gets(so->proplist, "stream.sessionID");
422     if (sessionID == NULL) {
423         sessionID = "";
424     }
425     AUDIO_INFO_LOG("Trigger SourceOutputUnlinkCb sessionID:%{public}s", sessionID);
426 
427     if (CheckIfAvailSource(so, u) == PA_HOOK_CANCEL) {
428         return PA_HOOK_OK;
429     }
430     return HandleSourceOutputUnlink(so, u);
431 }
432 
SourceOutputMoveStartCb(const pa_core * c,pa_source_output * so,struct Userdata * u)433 static pa_hook_result_t SourceOutputMoveStartCb(const pa_core *c, pa_source_output *so, struct Userdata *u)
434 {
435     CHECK_AND_RETURN_RET_LOG(u != NULL, PA_HOOK_OK, "Get Userdata failed! userdata is NULL");
436     CHECK_AND_RETURN_RET_LOG(c != NULL, PA_HOOK_OK, "pa core is null");
437     CHECK_AND_RETURN_RET_LOG(so != NULL, PA_HOOK_OK, "so is NULL");
438 
439     const char *sessionID = pa_proplist_gets(so->proplist, "stream.sessionID");
440     if (sessionID == NULL) {
441         sessionID = "";
442     }
443     AUDIO_INFO_LOG("Trigger SourceOutputMoveStartCb sessionID:%{public}s", sessionID);
444 
445     if (CheckIfAvailSource(so, u) == PA_HOOK_CANCEL) {
446         return PA_HOOK_OK;
447     }
448     return HandleSourceOutputUnlink(so, u);
449 }
450 
SourceOutputMoveFinishCb(const pa_core * c,pa_source_output * so,struct Userdata * u)451 static pa_hook_result_t SourceOutputMoveFinishCb(const pa_core *c, pa_source_output *so, struct Userdata *u)
452 {
453     CHECK_AND_RETURN_RET_LOG(u != NULL, PA_HOOK_OK, "Get Userdata failed! userdata is NULL");
454     CHECK_AND_RETURN_RET_LOG(c != NULL, PA_HOOK_OK, "pa core is null");
455     CHECK_AND_RETURN_RET_LOG(so != NULL, PA_HOOK_OK, "so is NULL");
456 
457     const char *sessionID = pa_proplist_gets(so->proplist, "stream.sessionID");
458     if (sessionID == NULL) {
459         sessionID = "";
460     }
461     AUDIO_INFO_LOG("Trigger SourceOutputMoveFinishCb sessionID:%{public}s", sessionID);
462 
463     if (CheckIfAvailSource(so, u) == PA_HOOK_CANCEL) {
464         return PA_HOOK_OK;
465     }
466     return HandleSourceOutputPut(so, u);
467 }
468 
pa__init(pa_module * m)469 int pa__init(pa_module *m)
470 {
471     pa_modargs *ma = NULL;
472 
473     CHECK_AND_RETURN_RET_LOG(m != NULL, PA_HOOK_OK, "pa core is null");
474 
475     if (!(ma = pa_modargs_new(m->argument, VALID_MODARGS))) {
476         AUDIO_ERR_LOG("Failed to parse module arguments");
477         goto fail;
478     }
479 
480     if (!(m->userdata = PaHdiSourceNew(m, ma, __FILE__))) {
481         AUDIO_ERR_LOG("Failed to PaHdiSourceNew");
482         goto fail;
483     }
484     pa_source *source = (pa_source *)m->userdata;
485 
486     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_PUT], PA_HOOK_LATE,
487         (pa_hook_cb_t)SourceOutputPutCb, source->userdata);
488     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK], PA_HOOK_LATE,
489         (pa_hook_cb_t)SourceOutputUnlinkCb, source->userdata);
490     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], PA_HOOK_LATE,
491         (pa_hook_cb_t)SourceOutputMoveFinishCb, source->userdata);
492     pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], PA_HOOK_LATE,
493         (pa_hook_cb_t)SourceOutputMoveStartCb, source->userdata);
494 
495     pa_source_put(source);
496     pa_modargs_free(ma);
497 
498     return 0;
499 
500 fail:
501 
502     if (ma) {
503         pa_modargs_free(ma);
504     }
505 
506     pa__done(m);
507 
508     return -1;
509 }
510 
pa__get_n_used(pa_module * m)511 int pa__get_n_used(pa_module *m)
512 {
513     CHECK_AND_RETURN_RET_LOG(m != NULL, PA_HOOK_OK, "pa core is null");
514 
515     pa_source *source = m->userdata;
516 
517     CHECK_AND_RETURN_RET_LOG(source != NULL, 0, "source is null");
518 
519     return pa_source_linked_by(source);
520 }
521 
ReleaseAllChains(struct Userdata * u)522 static void ReleaseAllChains(struct Userdata *u)
523 {
524     void *state = NULL;
525     uint32_t *sceneKeyNum;
526     const void *sceneKey;
527     while ((sceneKeyNum = pa_hashmap_iterate(u->sceneToCountMap, &state, &sceneKey))) {
528         uint64_t sceneKeyCode = (uint64_t)strtoul((char *)sceneKey, NULL, BASE_TEN);
529         for (uint32_t count = 0; count < *sceneKeyNum; count++) {
530             EnhanceChainManagerReleaseCb(sceneKeyCode);
531         }
532     }
533 }
534 
pa__done(pa_module * m)535 void pa__done(pa_module *m)
536 {
537     pa_source *source = NULL;
538 
539     CHECK_AND_RETURN_LOG(m != NULL, "pa core is null");
540 
541     if ((source = m->userdata)) {
542         struct Userdata *u = (struct Userdata *)source->userdata;
543         if (u != NULL) {
544             AUDIO_INFO_LOG("Release all enhChains on [%{public}s]", source->name);
545             ReleaseAllChains(u);
546         }
547         PaHdiSourceFree(source);
548         m->userdata = NULL;
549     }
550 }