• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023-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  * Description: supply napi interface realization for cast mirror player.
15  * Author: zhangjingnan
16  * Create: 2023-5-27
17  */
18 
19 #include <memory>
20 #include "napi/native_api.h"
21 #include "napi/native_node_api.h"
22 #include "cast_engine_log.h"
23 #include "cast_engine_common.h"
24 #include "oh_remote_control_event.h"
25 #include "i_mirror_player.h"
26 #include "napi_castengine_utils.h"
27 #include "napi_mirror_player.h"
28 #include "napi_async_work.h"
29 
30 using namespace OHOS::CastEngine::CastEngineClient;
31 using namespace std;
32 
33 namespace OHOS {
34 namespace CastEngine {
35 namespace CastEngineClient {
36 DEFINE_CAST_ENGINE_LABEL("Cast-Napi-MirrorPlayer");
37 
38 thread_local napi_ref NapiMirrorPlayer::consRef_ = nullptr;
39 
DefineMirrorPlayerJSClass(napi_env env)40 void NapiMirrorPlayer::DefineMirrorPlayerJSClass(napi_env env)
41 {
42     napi_property_descriptor NapiMirrorPlayerDesc[] = {
43         DECLARE_NAPI_FUNCTION("play", Play),
44         DECLARE_NAPI_FUNCTION("pause", Pause),
45         DECLARE_NAPI_FUNCTION("setAppInfo", SetAppInfo),
46         DECLARE_NAPI_FUNCTION("setSurface", SetSurface),
47         DECLARE_NAPI_FUNCTION("release", Release),
48         DECLARE_NAPI_FUNCTION("resizeVirtualScreen", ResizeVirtualScreen)
49     };
50 
51     napi_value mirrorPlayer = nullptr;
52     constexpr int initialRefCount = 1;
53     napi_status status = napi_define_class(env, "mirrorPlayer", NAPI_AUTO_LENGTH, NapiMirrorPlayerConstructor, nullptr,
54         sizeof(NapiMirrorPlayerDesc) / sizeof(NapiMirrorPlayerDesc[0]), NapiMirrorPlayerDesc, &mirrorPlayer);
55     if (status != napi_ok) {
56         CLOGE("napi_define_class failed");
57         return;
58     }
59     status = napi_create_reference(env, mirrorPlayer, initialRefCount, &consRef_);
60     if (status != napi_ok) {
61         CLOGE("DefineMirrorPlayerJSClass napi_create_reference failed");
62     }
63 }
64 
NapiMirrorPlayerConstructor(napi_env env,napi_callback_info info)65 napi_value NapiMirrorPlayer::NapiMirrorPlayerConstructor(napi_env env, napi_callback_info info)
66 {
67     CLOGD("NapiMirrorPlayer start to construct in");
68     napi_value thisVar = nullptr;
69     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
70     CLOGD("NapiMirrorPlayer construct successfully");
71     return thisVar;
72 }
73 
CreateNapiMirrorPlayer(napi_env env,shared_ptr<IMirrorPlayer> player,napi_value & out)74 napi_status NapiMirrorPlayer::CreateNapiMirrorPlayer(napi_env env, shared_ptr<IMirrorPlayer> player, napi_value &out)
75 {
76     CLOGD("Start to create napiMirrorPlayer in");
77     napi_value result = nullptr;
78     napi_value constructor = nullptr;
79     if (consRef_ == nullptr || player == nullptr) {
80         CLOGE("CreateNapiMirrorPlayer input is null");
81         return napi_generic_failure;
82     }
83     napi_status status = napi_get_reference_value(env, consRef_, &constructor);
84     if (status != napi_ok || constructor == nullptr) {
85         CLOGE("CreateNapiMirrorPlayer napi_get_reference_value failed");
86         return napi_generic_failure;
87     }
88 
89     constexpr size_t argc = 0;
90     status = napi_new_instance(env, constructor, argc, nullptr, &result);
91     if (status != napi_ok) {
92         CLOGE("CreateNapiMirrorPlayer napi_new_instance failed");
93         return napi_generic_failure;
94     }
95 
96     NapiMirrorPlayer *napiMirrorPlayer = new NapiMirrorPlayer(player);
97     if (napiMirrorPlayer == nullptr) {
98         CLOGE("NapiMirrorPlayer is nullptr");
99         return napi_generic_failure;
100     }
101     auto finalize = [](napi_env env, void *data, void *hint) {
102         NapiMirrorPlayer *player = reinterpret_cast<NapiMirrorPlayer *>(data);
103         if (player != nullptr) {
104             CLOGI("Session deconstructed");
105             delete player;
106             player = nullptr;
107         }
108     };
109     if (napi_wrap(env, result, napiMirrorPlayer, finalize, nullptr, nullptr) != napi_ok) {
110         CLOGE("CreateNapiMirrorPlayer napi_wrap failed");
111         delete napiMirrorPlayer;
112         napiMirrorPlayer = nullptr;
113         return napi_generic_failure;
114     }
115     out = result;
116     CLOGD("Create napiMirrorPlayer successfully");
117     return napi_ok;
118 }
119 
Play(napi_env env,napi_callback_info info)120 napi_value NapiMirrorPlayer::Play(napi_env env, napi_callback_info info)
121 {
122     CLOGD("Start to play in");
123     struct ConcreteTask : public NapiAsyncTask {
124         string deviceId_;
125     };
126     auto napiAsyntask = std::make_shared<ConcreteTask>();
127     if (napiAsyntask == nullptr) {
128         CLOGE("Create NapiAsyncTask failed");
129         return GetUndefinedValue(env);
130     }
131 
132     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
133         constexpr size_t expectedArgc = 1;
134         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
135             NapiErrors::errcode_[ERR_INVALID_PARAM]);
136         napi_valuetype expectedTypes[expectedArgc] = { napi_string };
137         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
138         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
139             NapiErrors::errcode_[ERR_INVALID_PARAM]);
140         napiAsyntask->deviceId_ = ParseString(env, argv[0]);
141     };
142     napiAsyntask->GetJSInfo(env, info, inputParser);
143     auto executor = [napiAsyntask]() {
144         auto *napiPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
145         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiPlayer != nullptr, "napiPlayer is null",
146             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
147         shared_ptr<IMirrorPlayer> mirrorPlayer = napiPlayer->GetMirrorPlayer();
148         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
149             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
150         int32_t ret = mirrorPlayer->Play(napiAsyntask->deviceId_);
151         if (ret != CAST_ENGINE_SUCCESS) {
152             if (ret == ERR_NO_PERMISSION) {
153                 napiAsyntask->errMessage = "Play failed : no permission";
154             } else {
155                 napiAsyntask->errMessage = "Play failed : native server exception";
156             }
157             napiAsyntask->status = napi_generic_failure;
158             napiAsyntask->errCode = NapiErrors::errcode_[ret];
159         }
160     };
161 
162     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
163     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Play", executor, complete);
164 }
165 
Pause(napi_env env,napi_callback_info info)166 napi_value NapiMirrorPlayer::Pause(napi_env env, napi_callback_info info)
167 {
168     CLOGD("Start to pause in");
169     struct ConcreteTask : public NapiAsyncTask {
170         string deviceId_;
171     };
172     auto napiAsyntask = std::make_shared<ConcreteTask>();
173     if (napiAsyntask == nullptr) {
174         CLOGE("Create NapiAsyncTask failed");
175         return GetUndefinedValue(env);
176     }
177 
178     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
179         constexpr size_t expectedArgc = 1;
180         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
181             NapiErrors::errcode_[ERR_INVALID_PARAM]);
182         napi_valuetype expectedTypes[expectedArgc] = { napi_string };
183         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
184         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
185             NapiErrors::errcode_[ERR_INVALID_PARAM]);
186         napiAsyntask->deviceId_ = ParseString(env, argv[0]);
187     };
188     napiAsyntask->GetJSInfo(env, info, inputParser);
189     auto executor = [napiAsyntask]() {
190         auto *napiPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
191         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiPlayer != nullptr, "napiPlayer is null",
192             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
193         shared_ptr<IMirrorPlayer> mirrorPlayer = napiPlayer->GetMirrorPlayer();
194         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
195             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
196         int32_t ret = mirrorPlayer->Pause(napiAsyntask->deviceId_);
197         if (ret != CAST_ENGINE_SUCCESS) {
198             if (ret == ERR_NO_PERMISSION) {
199                 napiAsyntask->errMessage = "Pause failed : no permission";
200             } else {
201                 napiAsyntask->errMessage = "Pause failed : native server exception";
202             }
203             napiAsyntask->status = napi_generic_failure;
204             napiAsyntask->errCode = NapiErrors::errcode_[ret];
205         }
206     };
207 
208     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
209     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Pause", executor, complete);
210 }
211 
SetSurface(napi_env env,napi_callback_info info)212 napi_value NapiMirrorPlayer::SetSurface(napi_env env, napi_callback_info info)
213 {
214     CLOGD("Start to set surface in");
215     struct ConcreteTask : public NapiAsyncTask {
216         string surfaceId_;
217     };
218     auto napiAsyntask = std::make_shared<ConcreteTask>();
219     if (napiAsyntask == nullptr) {
220         CLOGE("Create NapiAsyncTask failed");
221         return GetUndefinedValue(env);
222     }
223 
224     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
225         constexpr size_t expectedArgc = 1;
226         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
227             NapiErrors::errcode_[ERR_INVALID_PARAM]);
228         napi_valuetype expectedTypes[expectedArgc] = { napi_string };
229         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
230         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
231             NapiErrors::errcode_[ERR_INVALID_PARAM]);
232         napiAsyntask->surfaceId_ = ParseString(env, argv[0]);
233     };
234     napiAsyntask->GetJSInfo(env, info, inputParser);
235     auto executor = [napiAsyntask]() {
236         auto *napiPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
237         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiPlayer != nullptr, "napiPlayer is null",
238             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
239         shared_ptr<IMirrorPlayer> mirrorPlayer = napiPlayer->GetMirrorPlayer();
240         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
241             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
242         int32_t ret = mirrorPlayer->SetSurface(napiAsyntask->surfaceId_);
243         if (ret != CAST_ENGINE_SUCCESS) {
244             if (ret == ERR_NO_PERMISSION) {
245                 napiAsyntask->errMessage = "SetSurface failed : no permission";
246             } else {
247                 napiAsyntask->errMessage = "SetSurface failed : native server exception";
248             }
249             napiAsyntask->status = napi_generic_failure;
250             napiAsyntask->errCode = NapiErrors::errcode_[ret];
251         }
252     };
253 
254     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
255     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetSurface", executor, complete);
256 }
257 
SetAppInfo(napi_env env,napi_callback_info info)258 napi_value NapiMirrorPlayer::SetAppInfo(napi_env env, napi_callback_info info)
259 {
260     CLOGD("Start to set appInfo in");
261     struct ConcreteTask : public NapiAsyncTask {
262         int32_t appUid;
263         uint32_t appTokenId;
264         int32_t appPid;
265     };
266     auto napiAsyntask = std::make_shared<ConcreteTask>();
267     if (napiAsyntask == nullptr) {
268         CLOGE("Create NapiAsyncTask failed");
269         return GetUndefinedValue(env);
270     }
271 
272     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
273         constexpr size_t expectedArgc = 3;
274         napi_valuetype expectedTypes[expectedArgc] = { napi_number,  napi_number, napi_number};
275         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
276         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
277             NapiErrors::errcode_[ERR_INVALID_PARAM]);
278         napiAsyntask->appUid = ParseInt32(env, argv[0]);
279         napiAsyntask->appTokenId = static_cast<uint32_t>(ParseInt32(env, argv[1]));
280         napiAsyntask->appPid = ParseInt32(env, argv[2]);
281     };
282 
283     napiAsyntask->GetJSInfo(env, info, inputParser);
284     auto executor = [napiAsyntask]() {
285         auto *napiPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
286         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiPlayer != nullptr, "napiPlayer is null",
287             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
288         shared_ptr<IMirrorPlayer> mirrorPlayer = napiPlayer->GetMirrorPlayer();
289         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
290             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
291         CLOGI("SetAppInfo in");
292         int32_t ret = mirrorPlayer->SetAppInfo({napiAsyntask->appUid, napiAsyntask->appTokenId, napiAsyntask->appPid});
293         CLOGI("SetAppInfo out");
294         if (ret != CAST_ENGINE_SUCCESS) {
295             if (ret == ERR_NO_PERMISSION) {
296                 napiAsyntask->errMessage = "SetAppInfo failed : no permission";
297             } else {
298                 napiAsyntask->errMessage = "SetAppInfo failed : native server exception";
299             }
300             napiAsyntask->status = napi_generic_failure;
301             napiAsyntask->errCode = NapiErrors::errcode_[ret];
302         }
303     };
304     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
305     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetAppInfo", executor, complete);
306 }
307 
Release(napi_env env,napi_callback_info info)308 napi_value NapiMirrorPlayer::Release(napi_env env, napi_callback_info info)
309 {
310     CLOGD("Start to release in");
311     auto napiAsyntask = std::make_shared<NapiAsyncTask>();
312     if (napiAsyntask == nullptr) {
313         CLOGE("Create NapiAsyncTask failed");
314         return GetUndefinedValue(env);
315     }
316     napiAsyntask->GetJSInfo(env, info);
317 
318     auto executor = [napiAsyntask]() {
319         auto *napiPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
320         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiPlayer != nullptr, "napiPlayer is null",
321             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
322         shared_ptr<IMirrorPlayer> mirrorPlayer = napiPlayer->GetMirrorPlayer();
323         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
324             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
325         int32_t ret = mirrorPlayer->Release();
326         if (ret == CAST_ENGINE_SUCCESS) {
327             napiPlayer->Reset();
328         } else if (ret == ERR_NO_PERMISSION) {
329             napiAsyntask->errMessage = "Release failed : no permission";
330             napiAsyntask->status = napi_generic_failure;
331             napiAsyntask->errCode = NapiErrors::errcode_[ret];
332         } else {
333             napiAsyntask->errMessage = "Release failed : native server exception";
334             napiAsyntask->status = napi_generic_failure;
335             napiAsyntask->errCode = NapiErrors::errcode_[ret];
336         }
337     };
338 
339     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
340     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Release", executor, complete);
341 }
342 
ResizeVirtualScreen(napi_env env,napi_callback_info info)343 napi_value NapiMirrorPlayer::ResizeVirtualScreen(napi_env env, napi_callback_info info)
344 {
345     struct ConcreteTask : public NapiAsyncTask {
346         uint32_t width_;
347         uint32_t height_;
348     };
349     auto napiAsyntask = std::make_shared<ConcreteTask>();
350     if (napiAsyntask == nullptr) {
351         CLOGE("Create NapiAsyncTask failed");
352         return GetUndefinedValue(env);
353     }
354 
355     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
356         constexpr size_t expectedArgc = 2;
357         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
358                                NapiErrors::errcode_[ERR_INVALID_PARAM]);
359         napi_valuetype expectedTypes[expectedArgc] = { napi_number, napi_number };
360         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
361         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
362                                NapiErrors::errcode_[ERR_INVALID_PARAM]);
363         napiAsyntask->width_ = ParseUint32(env, argv[0]);
364         napiAsyntask->height_ = ParseUint32(env, argv[1]);
365     };
366     napiAsyntask->GetJSInfo(env, info, inputParser);
367     auto executor = [napiAsyntask]() {
368         auto *napiMirrorPlayer = reinterpret_cast<NapiMirrorPlayer *>(napiAsyntask->native);
369         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiMirrorPlayer != nullptr, "napiMirrorPlayer is null",
370                                NapiErrors::errcode_[CAST_ENGINE_ERROR]);
371         std::shared_ptr<IMirrorPlayer> mirrorPlayer = napiMirrorPlayer->GetMirrorPlayer();
372         CHECK_ARGS_RETURN_VOID(napiAsyntask, mirrorPlayer, "IMirrorPlayer is null",
373                                NapiErrors::errcode_[CAST_ENGINE_ERROR]);
374         int32_t ret = mirrorPlayer->ResizeVirtualScreen(napiAsyntask->width_, napiAsyntask->height_);
375         if (ret != CAST_ENGINE_SUCCESS) {
376             if (ret == ERR_NO_PERMISSION) {
377                 napiAsyntask->errMessage = "ResizeVirtualScreen failed : no permission";
378             } else if (ret == ERR_INVALID_PARAM) {
379                 napiAsyntask->errMessage = "ResizeVirtualScreen failed : invalid parameters";
380             } else {
381                 napiAsyntask->errMessage = "ResizeVirtualScreen failed : native server exception";
382             }
383             napiAsyntask->status = napi_generic_failure;
384             napiAsyntask->errCode = NapiErrors::errcode_[ret];
385         }
386     };
387 
388     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
389     return NapiAsyncWork::Enqueue(env, napiAsyntask, "ResizeVirtualScreen", executor, complete);
390 }
391 } // namespace CastEngineClient
392 } // namespace CastEngine
393 } // namespace OHOS