1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "audio_renderer_info_napi.h"
17 #include "system_sound_log.h"
18 
19 using namespace std;
20 
21 namespace {
22 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "AudioRendererInfoNapi"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 thread_local napi_ref AudioRendererInfoNapi::sConstructor_ = nullptr;
28 unique_ptr<AudioStandard::AudioRendererInfo> AudioRendererInfoNapi::sAudioRendererInfo_ = nullptr;
29 
AudioRendererInfoNapi()30 AudioRendererInfoNapi::AudioRendererInfoNapi() : env_(nullptr) {}
31 
32 AudioRendererInfoNapi::~AudioRendererInfoNapi() = default;
33 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)34 void AudioRendererInfoNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
35 {
36     if (nativeObject != nullptr) {
37         auto obj = static_cast<AudioRendererInfoNapi *>(nativeObject);
38         delete obj;
39         obj = nullptr;
40     }
41 }
42 
Init(napi_env env,napi_value exports)43 napi_value AudioRendererInfoNapi::Init(napi_env env, napi_value exports)
44 {
45     napi_status status;
46     napi_value constructor;
47     napi_value result = nullptr;
48     napi_get_undefined(env, &result);
49     int32_t refCount = 1;
50 
51     napi_property_descriptor audio_renderer_info_properties[] = {
52         DECLARE_NAPI_GETTER_SETTER("content", GetContentType, SetContentType),
53         DECLARE_NAPI_GETTER_SETTER("usage", GetStreamUsage, SetStreamUsage),
54         DECLARE_NAPI_GETTER_SETTER("rendererFlags", GetRendererFlags, SetRendererFlags)
55     };
56 
57     status = napi_define_class(env, AUDIO_RENDERER_INFO_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
58         nullptr, sizeof(audio_renderer_info_properties) / sizeof(audio_renderer_info_properties[0]),
59         audio_renderer_info_properties, &constructor);
60     if (status != napi_ok) {
61         return result;
62     }
63 
64     status = napi_create_reference(env, constructor, refCount, &sConstructor_);
65     if (status == napi_ok) {
66         status = napi_set_named_property(env, exports, AUDIO_RENDERER_INFO_NAPI_CLASS_NAME.c_str(),
67                                          constructor);
68         if (status == napi_ok) {
69             return exports;
70         }
71     }
72     MEDIA_LOGE("Failure in AudioRendererInfoNapi::Init()");
73 
74     return result;
75 }
76 
Construct(napi_env env,napi_callback_info info)77 napi_value AudioRendererInfoNapi::Construct(napi_env env, napi_callback_info info)
78 {
79     napi_status status;
80     napi_value jsThis = nullptr;
81     size_t argCount = 0;
82 
83     status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
84     if (status == napi_ok) {
85         unique_ptr<AudioRendererInfoNapi> obj = make_unique<AudioRendererInfoNapi>();
86         if (obj != nullptr) {
87             obj->env_ = env;
88             obj->audioRendererInfo_ = move(sAudioRendererInfo_);
89             status = napi_wrap(env, jsThis, static_cast<void *>(obj.get()),
90                                AudioRendererInfoNapi::Destructor, nullptr, nullptr);
91             if (status == napi_ok) {
92                 obj.release();
93                 return jsThis;
94             }
95         }
96     }
97     MEDIA_LOGE("Failed in AudioRendererInfoNapi::Construct()!");
98     napi_get_undefined(env, &jsThis);
99 
100     return jsThis;
101 }
102 
CreateAudioRendererInfoWrapper(napi_env env,unique_ptr<AudioStandard::AudioRendererInfo> & audioRendererInfo)103 napi_value AudioRendererInfoNapi::CreateAudioRendererInfoWrapper(napi_env env,
104     unique_ptr<AudioStandard::AudioRendererInfo> &audioRendererInfo)
105 {
106     napi_status status;
107     napi_value result = nullptr;
108     napi_value constructor;
109 
110     status = napi_get_reference_value(env, sConstructor_, &constructor);
111     if (status == napi_ok) {
112         sAudioRendererInfo_ = move(audioRendererInfo);
113         status = napi_new_instance(env, constructor, 0, nullptr, &result);
114         sAudioRendererInfo_.release();
115         if (status == napi_ok) {
116             return result;
117         }
118     }
119     MEDIA_LOGE("Failed in CreateAudioRendererInfoWrapper, %{public}d", status);
120 
121     napi_get_undefined(env, &result);
122 
123     return result;
124 }
125 
GetContentType(napi_env env,napi_callback_info info)126 napi_value AudioRendererInfoNapi::GetContentType(napi_env env, napi_callback_info info)
127 {
128     napi_status status;
129     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
130     size_t argc = 0;
131     napi_value jsThis = nullptr;
132     AudioStandard::ContentType contentType;
133     napi_value jsResult = nullptr;
134     napi_get_undefined(env, &jsResult);
135 
136     status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
137     if (status != napi_ok || jsThis == nullptr) {
138         MEDIA_LOGE("Get content type fail to napi_get_cb_info");
139         return jsResult;
140     }
141 
142     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
143     if (status == napi_ok) {
144         contentType = audioRendererInfoNapi->audioRendererInfo_->contentType;
145         status = napi_create_int32(env, contentType, &jsResult);
146         if (status == napi_ok) {
147             return jsResult;
148         }
149     }
150 
151     return jsResult;
152 }
153 
SetContentType(napi_env env,napi_callback_info info)154 napi_value AudioRendererInfoNapi::SetContentType(napi_env env, napi_callback_info info)
155 {
156     napi_status status;
157     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
158     size_t argc = 1;
159     napi_value args[1] = { nullptr };
160     napi_value jsThis = nullptr;
161     int32_t contentType = 0;
162     napi_value jsResult = nullptr;
163     napi_get_undefined(env, &jsResult);
164 
165     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
166     if (status != napi_ok || jsThis == nullptr || argc < 1) {
167         MEDIA_LOGE("SetContentType: napi_get_cb_info failed");
168         return jsResult;
169     }
170 
171     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
172     if (status == napi_ok) {
173         napi_valuetype valueType = napi_undefined;
174         if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
175             MEDIA_LOGE("SetContentType: wrong data type");
176             return jsResult;
177         }
178     }
179 
180     status = napi_get_value_int32(env, args[0], &contentType);
181     if (status == napi_ok) {
182         audioRendererInfoNapi->audioRendererInfo_->contentType = static_cast<AudioStandard::ContentType>(contentType);
183     }
184 
185     return jsResult;
186 }
187 
GetStreamUsage(napi_env env,napi_callback_info info)188 napi_value AudioRendererInfoNapi::GetStreamUsage(napi_env env, napi_callback_info info)
189 {
190     napi_status status;
191     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
192     size_t argc = 0;
193     napi_value jsThis = nullptr;
194     AudioStandard::StreamUsage usage;
195     napi_value jsResult = nullptr;
196     napi_get_undefined(env, &jsResult);
197 
198     status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
199     if (status != napi_ok || jsThis == nullptr) {
200         MEDIA_LOGE("Get stream usage fail to napi_get_cb_info");
201         return jsResult;
202     }
203 
204     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
205     if (status == napi_ok && audioRendererInfoNapi->audioRendererInfo_ != nullptr) {
206         usage = audioRendererInfoNapi->audioRendererInfo_->streamUsage;
207         status = napi_create_int32(env, usage, &jsResult);
208         if (status == napi_ok) {
209             return jsResult;
210         }
211     }
212 
213     return jsResult;
214 }
215 
SetStreamUsage(napi_env env,napi_callback_info info)216 napi_value AudioRendererInfoNapi::SetStreamUsage(napi_env env, napi_callback_info info)
217 {
218     napi_status status;
219     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
220     size_t argc = 1;
221     napi_value args[1] = { nullptr };
222     napi_value jsThis = nullptr;
223     int32_t streamUsage = 0;
224     napi_value jsResult = nullptr;
225     napi_get_undefined(env, &jsResult);
226 
227     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
228     if (status != napi_ok || jsThis == nullptr || argc < 1) {
229         MEDIA_LOGE("SetStreamUsage: napi_get_cb_info failed");
230         return jsResult;
231     }
232 
233     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
234     if (status != napi_ok) {
235         MEDIA_LOGE("SetStreamUsage: napi_unwrap failed");
236         return jsResult;
237     }
238 
239     napi_valuetype valueType = napi_undefined;
240     if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
241         MEDIA_LOGE("SetStreamUsage: wrong data type");
242         return jsResult;
243     }
244 
245     status = napi_get_value_int32(env, args[0], &streamUsage);
246     if (status == napi_ok) {
247         audioRendererInfoNapi->audioRendererInfo_->streamUsage = static_cast<AudioStandard::StreamUsage>(streamUsage);
248     }
249 
250     return jsResult;
251 }
252 
GetRendererFlags(napi_env env,napi_callback_info info)253 napi_value AudioRendererInfoNapi::GetRendererFlags(napi_env env, napi_callback_info info)
254 {
255     napi_status status;
256     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
257     size_t argc = 0;
258     napi_value jsThis = nullptr;
259     napi_value jsResult = nullptr;
260     napi_get_undefined(env, &jsResult);
261 
262     status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
263     if (status != napi_ok || jsThis == nullptr) {
264         MEDIA_LOGE("Get renderer flag fail to napi_get_cb_info");
265         return jsResult;
266     }
267 
268     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
269     if (status == napi_ok) {
270         status = napi_create_int32(env, audioRendererInfoNapi->audioRendererInfo_->rendererFlags,
271                                    &jsResult);
272         if (status == napi_ok) {
273             return jsResult;
274         }
275     }
276 
277     return jsResult;
278 }
279 
SetRendererFlags(napi_env env,napi_callback_info info)280 napi_value AudioRendererInfoNapi::SetRendererFlags(napi_env env, napi_callback_info info)
281 {
282     napi_status status;
283     AudioRendererInfoNapi *audioRendererInfoNapi = nullptr;
284     size_t argc = 1;
285     napi_value args[1] = { nullptr };
286     napi_value jsThis = nullptr;
287     int32_t rendererFlags;
288     napi_value jsResult = nullptr;
289     napi_get_undefined(env, &jsResult);
290 
291     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
292     if (status != napi_ok || jsThis == nullptr || argc < 1) {
293         MEDIA_LOGE("get renderer flag fail to napi_get_cb_info");
294         return jsResult;
295     }
296 
297     status = napi_unwrap(env, jsThis, (void **)&audioRendererInfoNapi);
298     if (status == napi_ok) {
299         napi_valuetype valueType = napi_undefined;
300         if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
301             MEDIA_LOGE("get renderer flag fail: wrong data type");
302             return jsResult;
303         }
304     }
305 
306     status = napi_get_value_int32(env, args[0], &rendererFlags);
307     if (status == napi_ok) {
308         audioRendererInfoNapi->audioRendererInfo_->rendererFlags = rendererFlags;
309     }
310 
311     return jsResult;
312 }
313 }  // namespace Media
314 }  // namespace OHOS
315