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 "ringtone_options_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, "RingtoneOptionsNapi"};
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 thread_local napi_ref RingtoneOptionsNapi::sConstructor_ = nullptr;
28 
29 float RingtoneOptionsNapi::sVolume_ = 1;
30 bool RingtoneOptionsNapi::sLoop_ = true;
31 
RingtoneOptionsNapi()32 RingtoneOptionsNapi::RingtoneOptionsNapi()
33     : env_(nullptr) {
34 }
35 
36 RingtoneOptionsNapi::~RingtoneOptionsNapi() = default;
37 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)38 void RingtoneOptionsNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
39 {
40     if (nativeObject != nullptr) {
41         auto obj = static_cast<RingtoneOptionsNapi *>(nativeObject);
42         delete obj;
43         obj = nullptr;
44     }
45 }
46 
Init(napi_env env,napi_value exports)47 napi_value RingtoneOptionsNapi::Init(napi_env env, napi_value exports)
48 {
49     napi_status status;
50     napi_value constructor;
51     napi_value result = nullptr;
52     napi_get_undefined(env, &result);
53 
54     napi_property_descriptor ringtone_options_properties[] = {
55         DECLARE_NAPI_GETTER_SETTER("volume", GetVolume, SetVolume),
56         DECLARE_NAPI_GETTER_SETTER("loop", GetLoop, SetLoop)
57     };
58 
59     status = napi_define_class(env, RINGTONE_OPTIONS_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
60                                nullptr, sizeof(ringtone_options_properties) / sizeof(ringtone_options_properties[0]),
61                                ringtone_options_properties, &constructor);
62     if (status != napi_ok) {
63         return result;
64     }
65 
66     status = napi_create_reference(env, constructor, 1, &sConstructor_);
67     if (status == napi_ok) {
68         status = napi_set_named_property(env, exports, RINGTONE_OPTIONS_NAPI_CLASS_NAME.c_str(),
69                                          constructor);
70         if (status == napi_ok) {
71             return exports;
72         }
73     }
74     MEDIA_LOGE("Failure in RingtoneOptionsNapi::Init()");
75 
76     return result;
77 }
78 
Construct(napi_env env,napi_callback_info info)79 napi_value RingtoneOptionsNapi::Construct(napi_env env, napi_callback_info info)
80 {
81     napi_status status;
82     napi_value jsThis = nullptr;
83     size_t argCount = 0;
84 
85     status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
86     if (status == napi_ok) {
87         unique_ptr<RingtoneOptionsNapi> obj = make_unique<RingtoneOptionsNapi>();
88         if (obj != nullptr) {
89             obj->env_ = env;
90             obj->volume_ = sVolume_;
91             obj->loop_ = sLoop_;
92             status = napi_wrap(env, jsThis, static_cast<void*>(obj.get()),
93                                RingtoneOptionsNapi::Destructor, nullptr, nullptr);
94             if (status == napi_ok) {
95                 obj.release();
96                 return jsThis;
97             }
98         }
99     }
100 
101     MEDIA_LOGE("Failed in RingtoneOptionsNapi::Construct()!");
102     napi_get_undefined(env, &jsThis);
103 
104     return jsThis;
105 }
106 
CreateRingtoneOptionsWrapper(napi_env env,float volume,bool loop)107 napi_value RingtoneOptionsNapi::CreateRingtoneOptionsWrapper(napi_env env, float volume, bool loop)
108 {
109     napi_status status;
110     napi_value result = nullptr;
111     napi_value constructor;
112 
113     status = napi_get_reference_value(env, sConstructor_, &constructor);
114     if (status == napi_ok) {
115         sVolume_ = volume;
116         sLoop_ = loop;
117         status = napi_new_instance(env, constructor, 0, nullptr, &result);
118         if (status == napi_ok) {
119             return result;
120         }
121     }
122     MEDIA_LOGE("Failed in CreateRingtoneOptionsWrapper, %{public}d", status);
123 
124     napi_get_undefined(env, &result);
125 
126     return result;
127 }
128 
GetVolume(napi_env env,napi_callback_info info)129 napi_value RingtoneOptionsNapi::GetVolume(napi_env env, napi_callback_info info)
130 {
131     napi_status status;
132     RingtoneOptionsNapi *ringtoneOptionsNapi = nullptr;
133     size_t argc = 0;
134     napi_value jsThis = nullptr;
135     napi_value jsResult = nullptr;
136     napi_get_undefined(env, &jsResult);
137 
138     status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
139     if (status != napi_ok || jsThis == nullptr) {
140         MEDIA_LOGE("Get volume: failed for napi_get_cb_info");
141         return jsResult;
142     }
143 
144     status = napi_unwrap(env, jsThis, (void **)&ringtoneOptionsNapi);
145     if (status == napi_ok) {
146         status = napi_create_double(env, ringtoneOptionsNapi->volume_, &jsResult);
147         if (status == napi_ok) {
148             return jsResult;
149         }
150     }
151 
152     return jsResult;
153 }
154 
SetVolume(napi_env env,napi_callback_info info)155 napi_value RingtoneOptionsNapi::SetVolume(napi_env env, napi_callback_info info)
156 {
157     napi_status status;
158     RingtoneOptionsNapi *ringtoneOptionsNapi = nullptr;
159     size_t argc = 1;
160     napi_value args[1] = { nullptr };
161     napi_value jsThis = nullptr;
162     double volume;
163     napi_value jsResult = nullptr;
164     napi_get_undefined(env, &jsResult);
165 
166     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
167     if (status != napi_ok || jsThis == nullptr || argc < 1) {
168         MEDIA_LOGE("SetVolume: failed for napi_get_cb_info");
169         return jsResult;
170     }
171 
172     status = napi_unwrap(env, jsThis, (void **)&ringtoneOptionsNapi);
173     if (status == napi_ok) {
174         napi_valuetype valueType = napi_undefined;
175         if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_number) {
176             MEDIA_LOGE("Setvolume: failed for wrong data type");
177             return jsResult;
178         }
179     }
180 
181     status = napi_get_value_double(env, args[0], &volume);
182     if (status == napi_ok) {
183         ringtoneOptionsNapi->volume_ = (float)volume;
184     }
185 
186     return jsResult;
187 }
188 
GetLoop(napi_env env,napi_callback_info info)189 napi_value RingtoneOptionsNapi::GetLoop(napi_env env, napi_callback_info info)
190 {
191     napi_status status;
192     RingtoneOptionsNapi *ringtoneOptionsNapi = nullptr;
193     size_t argc = 0;
194     napi_value jsThis = nullptr;
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("GetLoop: failed for napi_get_cb_info");
201         return jsResult;
202     }
203 
204     status = napi_unwrap(env, jsThis, (void **)&ringtoneOptionsNapi);
205     if (status == napi_ok) {
206         status = napi_get_boolean(env, ringtoneOptionsNapi->loop_, &jsResult);
207         if (status == napi_ok) {
208             return jsResult;
209         }
210     }
211 
212     return jsResult;
213 }
214 
SetLoop(napi_env env,napi_callback_info info)215 napi_value RingtoneOptionsNapi::SetLoop(napi_env env, napi_callback_info info)
216 {
217     napi_status status;
218     RingtoneOptionsNapi *ringtoneOptionsNapi = nullptr;
219     size_t argc = 1;
220     napi_value args[1] = { nullptr };
221     napi_value jsThis = nullptr;
222     bool loop = false;
223     napi_value jsResult = nullptr;
224     napi_get_undefined(env, &jsResult);
225 
226     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
227     if (status != napi_ok || jsThis == nullptr || argc < 1) {
228         MEDIA_LOGE("SetLoop: failed for napi_get_cb_info");
229         return jsResult;
230     }
231 
232     status = napi_unwrap(env, jsThis, (void **)&ringtoneOptionsNapi);
233     if (status == napi_ok) {
234         napi_valuetype valueType = napi_undefined;
235         if (napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_boolean) {
236             MEDIA_LOGE("SetLoop: failed for wrong data type");
237             return jsResult;
238         }
239     }
240 
241     status = napi_get_value_bool(env, args[0], &loop);
242     if (status == napi_ok) {
243         ringtoneOptionsNapi->loop_ = loop;
244     }
245 
246     return jsResult;
247 }
248 }  // namespace Media
249 }  // namespace OHOS
250