• 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 session.
15  * Author: zhangjingnan
16  * Create: 2022-7-11
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_cast_session.h"
26 #include "cast_session_manager.h"
27 #include "napi_castengine_utils.h"
28 #include "napi_cast_session_listener.h"
29 #include "napi_cast_session.h"
30 #include "napi_stream_player.h"
31 #include "napi_mirror_player.h"
32 #include "napi_async_work.h"
33 
34 using namespace OHOS::CastEngine::CastEngineClient;
35 using namespace std;
36 
37 namespace OHOS {
38 namespace CastEngine {
39 namespace CastEngineClient {
40 DEFINE_CAST_ENGINE_LABEL("Cast-Napi-Session");
41 
42 thread_local napi_ref NapiCastSession::consRef_ = nullptr;
43 
44 std::map<std::string, std::pair<NapiCastSession::OnEventHandlerType,
45     NapiCastSession::OffEventHandlerType>>
46     NapiCastSession::eventHandlers_ = {
47     { "event", { OnInnerEvent, OffInnerEvent } },
48     { "deviceState", { OnDeviceState, OffDeviceState } }
49 };
50 
DefineCastSessionJSClass(napi_env env)51 void NapiCastSession::DefineCastSessionJSClass(napi_env env)
52 {
53     napi_property_descriptor NapiCastSessionDesc[] = {
54         DECLARE_NAPI_FUNCTION("on", OnEvent),
55         DECLARE_NAPI_FUNCTION("off", OffEvent),
56         DECLARE_NAPI_FUNCTION("addDevice", AddDevice),
57         DECLARE_NAPI_FUNCTION("removeDevice", RemoveDevice),
58         DECLARE_NAPI_FUNCTION("getSessionId", GetSessionId),
59         DECLARE_NAPI_FUNCTION("setSessionProperty", SetSessionProperty),
60         DECLARE_NAPI_FUNCTION("createMirrorPlayer", CreateMirrorPlayer),
61         DECLARE_NAPI_FUNCTION("createStreamPlayer", CreateStreamPlayer),
62         DECLARE_NAPI_FUNCTION("setCastMode", SetCastMode),
63         DECLARE_NAPI_FUNCTION("release", Release)
64     };
65 
66     napi_value castSession = nullptr;
67     constexpr int initialRefCount = 1;
68     napi_status status = napi_define_class(env, "castSession", NAPI_AUTO_LENGTH, NapiCastSessionConstructor, nullptr,
69         sizeof(NapiCastSessionDesc) / sizeof(NapiCastSessionDesc[0]), NapiCastSessionDesc, &castSession);
70     if (status != napi_ok) {
71         CLOGE("napi_define_class failed");
72         return;
73     }
74     status = napi_create_reference(env, castSession, initialRefCount, &consRef_);
75     if (status != napi_ok) {
76         CLOGE("DefineCastSessionJSClass napi_create_reference failed");
77     }
78 }
79 
NapiCastSessionConstructor(napi_env env,napi_callback_info info)80 napi_value NapiCastSession::NapiCastSessionConstructor(napi_env env, napi_callback_info info)
81 {
82     CLOGD("NapiCastSession start to construct in");
83     napi_value thisVar = nullptr;
84     NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr));
85     CLOGD("NapiCastSession construct successfully");
86     return thisVar;
87 }
88 
CreateNapiCastSession(napi_env env,shared_ptr<ICastSession> session,napi_value & out)89 napi_status NapiCastSession::CreateNapiCastSession(napi_env env, shared_ptr<ICastSession> session, napi_value &out)
90 {
91     CLOGD("Start to create napiCastSession in");
92     napi_value result = nullptr;
93     napi_value constructor = nullptr;
94     if (consRef_ == nullptr || session == nullptr) {
95         CLOGE("CreateNapiCastSession input is null");
96         return napi_generic_failure;
97     }
98     napi_status status = napi_get_reference_value(env, consRef_, &constructor);
99     if (status != napi_ok || constructor == nullptr) {
100         CLOGE("CreateNapiCastSession napi_get_reference_value failed");
101         return napi_generic_failure;
102     }
103 
104     constexpr size_t argc = 0;
105     status = napi_new_instance(env, constructor, argc, nullptr, &result);
106     if (status != napi_ok) {
107         CLOGE("CreateNapiCastSession napi_new_instance failed");
108         return napi_generic_failure;
109     }
110 
111     NapiCastSession *napiCastSession = new NapiCastSession(session);
112     if (napiCastSession == nullptr) {
113         CLOGE("NapiCastSession is nullptr");
114         return napi_generic_failure;
115     }
116     auto finalize = [](napi_env env, void *data, void *hint) {
117         NapiCastSession *session = reinterpret_cast<NapiCastSession *>(data);
118         if (session != nullptr) {
119             CLOGI("Session deconstructed");
120             delete session;
121             session = nullptr;
122         }
123     };
124     if (napi_wrap(env, result, napiCastSession, finalize, nullptr, nullptr) != napi_ok) {
125         CLOGE("CreateNapiCastSession napi_wrap failed");
126         delete napiCastSession;
127         napiCastSession = nullptr;
128         return napi_generic_failure;
129     }
130     out = result;
131     CLOGD("Create napiCastSession successfully");
132     return napi_ok;
133 }
134 
GetNapiCastSession(napi_env env,napi_callback_info info)135 NapiCastSession *NapiCastSession::GetNapiCastSession(napi_env env, napi_callback_info info)
136 {
137     napi_value thisVar = nullptr;
138     NAPI_CALL_BASE(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr), nullptr);
139 
140     NapiCastSession *napiCastSession = nullptr;
141     NAPI_CALL_BASE(env, napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiCastSession)), nullptr);
142     if (napiCastSession == nullptr) {
143         CLOGE("napi_unwrap napiStreamPlayer is null");
144         return nullptr;
145     }
146 
147     return napiCastSession;
148 }
149 
OnEvent(napi_env env,napi_callback_info info)150 napi_value NapiCastSession::OnEvent(napi_env env, napi_callback_info info)
151 {
152     constexpr size_t expectedArgc = 2;
153     napi_value argv[expectedArgc] = { 0 };
154     napi_valuetype expectedTypes[expectedArgc] = { napi_string, napi_function };
155     if (!GetJSFuncParams(env, info, argv, expectedArgc, expectedTypes)) {
156         return GetUndefinedValue(env);
157     }
158     std::string eventName = ParseString(env, argv[0]);
159     NapiCastSession *napiSession = GetNapiCastSession(env, info);
160     if (napiSession == nullptr) {
161         CLOGE("napiSession is null");
162         return GetUndefinedValue(env);
163     }
164     auto it = eventHandlers_.find(eventName);
165     if (it == eventHandlers_.end()) {
166         CLOGE("event name invalid");
167         return GetUndefinedValue(env);
168     }
169 
170     if (RegisterNativeSessionListener(napiSession) == napi_generic_failure) {
171         return GetUndefinedValue(env);
172     }
173     if (it->second.first(env, argv[1], napiSession) != napi_ok) {
174         CLOGE("event name invalid");
175     }
176 
177     return GetUndefinedValue(env);
178 }
179 
OffEvent(napi_env env,napi_callback_info info)180 napi_value NapiCastSession::OffEvent(napi_env env, napi_callback_info info)
181 {
182     constexpr size_t expectedArgc = 2;
183     napi_value argv[expectedArgc] = { 0 };
184     napi_valuetype expectedTypes[expectedArgc] = { napi_string, napi_function};
185     if (!GetJSFuncParams(env, info, argv, expectedArgc, expectedTypes)) {
186         return GetUndefinedValue(env);
187     }
188 
189     std::string eventName = ParseString(env, argv[0]);
190     auto it = eventHandlers_.find(eventName);
191     if (it == eventHandlers_.end()) {
192         CLOGE("event name invalid");
193         return GetUndefinedValue(env);
194     }
195     NapiCastSession *napiSession = GetNapiCastSession(env, info);
196     if (napiSession == nullptr) {
197         CLOGE("napiSession is null");
198         return GetUndefinedValue(env);
199     }
200     if (it->second.second(env, argv[1], napiSession) != napi_ok) {
201         CLOGE("event name invalid");
202     }
203 
204     return GetUndefinedValue(env);
205 }
206 
RegisterNativeSessionListener(NapiCastSession * napiSession)207 napi_status NapiCastSession::RegisterNativeSessionListener(NapiCastSession *napiSession)
208 {
209     if (napiSession == nullptr) {
210         CLOGE("napiSession is null");
211         return napi_generic_failure;
212     }
213     if (napiSession->NapiListenerGetter()) {
214         return napi_ok;
215     }
216     auto session = napiSession->GetCastSession();
217     if (!session) {
218         CLOGE("Session is null");
219         return napi_generic_failure;
220     }
221 
222     auto listener = std::make_shared<NapiCastSessionListener>();
223     if (!listener) {
224         CLOGE("Failed to malloc session listener");
225         return napi_generic_failure;
226     }
227     int32_t ret = session->RegisterListener(listener);
228     if (ret != CAST_ENGINE_SUCCESS) {
229         CLOGE("native register session listener failed");
230         return napi_generic_failure;
231     }
232     napiSession->NapiListenerSetter(listener);
233 
234     return napi_ok;
235 }
236 
OnInnerEvent(napi_env env,napi_value callback,NapiCastSession * napiSession)237 napi_status NapiCastSession::OnInnerEvent(napi_env env, napi_value callback, NapiCastSession *napiSession)
238 {
239     if (napiSession == nullptr) {
240         CLOGE("napiSession is null");
241         return napi_generic_failure;
242     }
243     if (!napiSession->NapiListenerGetter()) {
244         CLOGE("cast session manager callback is null");
245         return napi_generic_failure;
246     }
247     if (napiSession->NapiListenerGetter()->AddCallback(env, NapiCastSessionListener::EVENT_ON_EVENT,
248         callback) != napi_ok) {
249         return napi_generic_failure;
250     }
251     return napi_ok;
252 }
253 
OnDeviceState(napi_env env,napi_value callback,NapiCastSession * napiSession)254 napi_status NapiCastSession::OnDeviceState(napi_env env, napi_value callback, NapiCastSession *napiSession)
255 {
256     if (napiSession == nullptr) {
257         CLOGE("napiSession is null");
258         return napi_generic_failure;
259     }
260     if (!napiSession->NapiListenerGetter()) {
261         CLOGE("cast session manager callback is null");
262         return napi_generic_failure;
263     }
264     if (napiSession->NapiListenerGetter()->AddCallback(env, NapiCastSessionListener::EVENT_DEVICE_STATE,
265         callback) != napi_ok) {
266         return napi_generic_failure;
267     }
268     return napi_ok;
269 }
270 
OffInnerEvent(napi_env env,napi_value callback,NapiCastSession * napiSession)271 napi_status NapiCastSession::OffInnerEvent(napi_env env, napi_value callback, NapiCastSession *napiSession)
272 {
273     if (napiSession == nullptr) {
274         CLOGE("napiSession is null");
275         return napi_generic_failure;
276     }
277     if (!napiSession->NapiListenerGetter()) {
278         CLOGE("cast session manager callback is null");
279         return napi_generic_failure;
280     }
281     if (napiSession->NapiListenerGetter()->RemoveCallback(env, NapiCastSessionListener::EVENT_ON_EVENT,
282         callback) != napi_ok) {
283         return napi_generic_failure;
284     }
285     return napi_ok;
286 }
287 
OffDeviceState(napi_env env,napi_value callback,NapiCastSession * napiSession)288 napi_status NapiCastSession::OffDeviceState(napi_env env, napi_value callback, NapiCastSession *napiSession)
289 {
290     if (napiSession == nullptr) {
291         CLOGE("napiSession is null");
292         return napi_generic_failure;
293     }
294     if (!napiSession->NapiListenerGetter()) {
295         CLOGE("cast session manager callback is null");
296         return napi_generic_failure;
297     }
298     if (napiSession->NapiListenerGetter()->RemoveCallback(env, NapiCastSessionListener::EVENT_DEVICE_STATE,
299         callback) != napi_ok) {
300         return napi_generic_failure;
301     }
302     return napi_ok;
303 }
304 
AddDevice(napi_env env,napi_callback_info info)305 napi_value NapiCastSession::AddDevice(napi_env env, napi_callback_info info)
306 {
307     CLOGD("Start to add device in");
308     struct ConcreteTask : public NapiAsyncTask {
309         CastRemoteDevice castRemoteDevice_;
310     };
311     auto napiAsyntask = std::make_shared<ConcreteTask>();
312     if (napiAsyntask == nullptr) {
313         CLOGE("Create NapiAsyncTask failed");
314         return GetUndefinedValue(env);
315     }
316 
317     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
318         constexpr size_t expectedArgc = 1;
319         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
320             NapiErrors::errcode_[ERR_INVALID_PARAM]);
321         napi_valuetype expectedTypes[expectedArgc] = { napi_object };
322         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
323         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
324             NapiErrors::errcode_[ERR_INVALID_PARAM]);
325         napiAsyntask->castRemoteDevice_ = GetCastRemoteDeviceFromJS(env, argv[0]);
326     };
327     napiAsyntask->GetJSInfo(env, info, inputParser);
328     auto executor = [napiAsyntask]() {
329         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
330         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
331             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
332         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
333         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
334             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
335         int32_t ret = castSession->AddDevice(napiAsyntask->castRemoteDevice_);
336         if (ret != CAST_ENGINE_SUCCESS) {
337             if (ret == ERR_NO_PERMISSION) {
338                 napiAsyntask->errMessage = "AddDevice failed : no permission";
339             } else if (ret == ERR_INVALID_PARAM) {
340                 napiAsyntask->errMessage = "AddDevice failed : invalid parameters";
341             } else {
342                 napiAsyntask->errMessage = "AddDevice failed : native server exception";
343             }
344             napiAsyntask->status = napi_generic_failure;
345             napiAsyntask->errCode = NapiErrors::errcode_[ret];
346         }
347     };
348 
349     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
350     return NapiAsyncWork::Enqueue(env, napiAsyntask, "AddDevice", executor, complete);
351 }
352 
RemoveDevice(napi_env env,napi_callback_info info)353 napi_value NapiCastSession::RemoveDevice(napi_env env, napi_callback_info info)
354 {
355     CLOGD("Start to remove device in");
356     struct ConcreteTask : public NapiAsyncTask {
357         string deviceId_;
358         DeviceRemoveAction actionType_;
359     };
360     auto napiAsyntask = std::make_shared<ConcreteTask>();
361     if (napiAsyntask == nullptr) {
362         CLOGE("Create NapiAsyncTask failed");
363         return GetUndefinedValue(env);
364     }
365 
366     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
367         constexpr size_t expectedArgcDeviceId = 1;
368         constexpr size_t expectedArgcType = 2;
369         CHECK_ARGS_RETURN_VOID(napiAsyntask, (argc == expectedArgcDeviceId || argc == expectedArgcType),
370             "invalid arguments", NapiErrors::errcode_[ERR_INVALID_PARAM]);
371         napi_valuetype expectedTypes[expectedArgcType] = {napi_string, napi_number};
372         bool isParamsTypeValid = CheckJSParamsType(env, argv, argc, expectedTypes);
373         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
374             NapiErrors::errcode_[ERR_INVALID_PARAM]);
375         napiAsyntask->deviceId_ = ParseString(env, argv[0]);
376         napiAsyntask->actionType_ = (argc == expectedArgcType) ?
377             static_cast<DeviceRemoveAction>(ParseInt32(env, argv[1])) : DeviceRemoveAction::ACTION_DISCONNECT;
378     };
379     napiAsyntask->GetJSInfo(env, info, inputParser);
380     auto executor = [napiAsyntask]() {
381         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
382         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
383             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
384         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
385         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
386             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
387         int32_t ret = castSession->RemoveDevice(napiAsyntask->deviceId_);
388         if (ret != CAST_ENGINE_SUCCESS) {
389             if (ret == ERR_NO_PERMISSION) {
390                 napiAsyntask->errMessage = "RemoveDevice failed : no permission";
391             } else if (ret == ERR_INVALID_PARAM) {
392                 napiAsyntask->errMessage = "RemoveDevice failed : invalid parameters";
393             } else {
394                 napiAsyntask->errMessage = "RemoveDevice failed : native server exception";
395             }
396             napiAsyntask->status = napi_generic_failure;
397             napiAsyntask->errCode = NapiErrors::errcode_[ret];
398         }
399     };
400 
401     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
402     return NapiAsyncWork::Enqueue(env, napiAsyntask, "RemoveDevice", executor, complete);
403 }
404 
GetSessionId(napi_env env,napi_callback_info info)405 napi_value NapiCastSession::GetSessionId(napi_env env, napi_callback_info info)
406 {
407     CLOGD("Start to get sessionId in");
408     struct ConcreteTask : public NapiAsyncTask {
409         string sessionId_;
410     };
411     auto napiAsyntask = std::make_shared<ConcreteTask>();
412     if (napiAsyntask == nullptr) {
413         CLOGE("Create NapiAsyncTask failed");
414         return GetUndefinedValue(env);
415     }
416 
417     napiAsyntask->GetJSInfo(env, info);
418     auto executor = [napiAsyntask]() {
419         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
420         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
421             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
422         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
423         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
424             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
425         int32_t ret = castSession->GetSessionId(napiAsyntask->sessionId_);
426         if (ret != CAST_ENGINE_SUCCESS) {
427             if (ret == ERR_NO_PERMISSION) {
428                 napiAsyntask->errMessage = "GetSessionId failed : no permission";
429             } else {
430                 napiAsyntask->errMessage = "GetSessionId failed : native server exception";
431             }
432             napiAsyntask->status = napi_generic_failure;
433             napiAsyntask->errCode = NapiErrors::errcode_[ret];
434         }
435     };
436 
437     auto complete = [env, napiAsyntask](napi_value &output) {
438         napiAsyntask->status =
439             napi_create_string_utf8(env, napiAsyntask->sessionId_.c_str(), NAPI_AUTO_LENGTH, &output);
440         CHECK_STATUS_RETURN_VOID(napiAsyntask, "napi_create_string_utf8 failed",
441             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
442     };
443     return NapiAsyncWork::Enqueue(env, napiAsyntask, "GetSessionId", executor, complete);
444 }
445 
SetSessionProperty(napi_env env,napi_callback_info info)446 napi_value NapiCastSession::SetSessionProperty(napi_env env, napi_callback_info info)
447 {
448     CLOGD("Start to set sessionProperty in");
449     struct ConcreteTask : public NapiAsyncTask {
450         CastSessionProperty castSessionProperty_;
451     };
452     auto napiAsyntask = std::make_shared<ConcreteTask>();
453     if (napiAsyntask == nullptr) {
454         CLOGE("Create NapiAsyncTask failed");
455         return GetUndefinedValue(env);
456     }
457 
458     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
459         constexpr size_t expectedArgc = 1;
460         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
461             NapiErrors::errcode_[ERR_INVALID_PARAM]);
462         napi_valuetype expectedTypes[expectedArgc] = { napi_object };
463         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
464         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
465             NapiErrors::errcode_[ERR_INVALID_PARAM]);
466         napiAsyntask->castSessionProperty_ = GetCastSessionPropertyFromJS(env, argv[0]);
467     };
468     napiAsyntask->GetJSInfo(env, info, inputParser);
469     auto executor = [napiAsyntask]() {
470         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
471         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
472             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
473         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
474         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
475             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
476         int32_t ret = castSession->SetSessionProperty(napiAsyntask->castSessionProperty_);
477         if (ret != CAST_ENGINE_SUCCESS) {
478             if (ret == ERR_NO_PERMISSION) {
479                 napiAsyntask->errMessage = "SetSessionProperty failed : no permission";
480             } else if (ret == ERR_INVALID_PARAM) {
481                 napiAsyntask->errMessage = "SetSessionProperty failed : invalid parameters";
482             } else {
483                 napiAsyntask->errMessage = "SetSessionProperty failed : native server exception";
484             }
485             napiAsyntask->status = napi_generic_failure;
486             napiAsyntask->errCode = NapiErrors::errcode_[ret];
487         }
488     };
489 
490     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
491     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetSessionProperty", executor, complete);
492 }
493 
CreateMirrorPlayer(napi_env env,napi_callback_info info)494 napi_value NapiCastSession::CreateMirrorPlayer(napi_env env, napi_callback_info info)
495 {
496     CLOGD("Start to create mirror Player");
497     struct ConcreteTask : public NapiAsyncTask {
498         shared_ptr<IMirrorPlayer> player_;
499     };
500     auto napiAsyntask = std::make_shared<ConcreteTask>();
501     if (napiAsyntask == nullptr) {
502         CLOGE("Create NapiAsyncTask failed");
503         return GetUndefinedValue(env);
504     }
505 
506     napiAsyntask->GetJSInfo(env, info);
507     auto executor = [napiAsyntask]() {
508         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
509         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
510             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
511         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
512         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
513             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
514         int32_t ret = castSession->CreateMirrorPlayer(napiAsyntask->player_);
515         if (ret != CAST_ENGINE_SUCCESS) {
516             if (ret == ERR_NO_PERMISSION) {
517                 napiAsyntask->errMessage = "CreateMirrorPlayer failed : no permission";
518             } else {
519                 napiAsyntask->errMessage = "CreateMirrorPlayer failed : native server exception";
520             }
521             napiAsyntask->status = napi_generic_failure;
522             napiAsyntask->errCode = NapiErrors::errcode_[ret];
523         }
524     };
525 
526     auto complete = [napiAsyntask](napi_value &output) {
527         napiAsyntask->status =
528             NapiMirrorPlayer::CreateNapiMirrorPlayer(napiAsyntask->env, napiAsyntask->player_, output);
529         CHECK_STATUS_RETURN_VOID(napiAsyntask, "convert native object to javascript object failed",
530             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
531     };
532     return NapiAsyncWork::Enqueue(env, napiAsyntask, "CreateMirrorPlayer", executor, complete);
533 }
534 
CreateStreamPlayer(napi_env env,napi_callback_info info)535 napi_value NapiCastSession::CreateStreamPlayer(napi_env env, napi_callback_info info)
536 {
537     CLOGD("Start to create Stream Player");
538     struct ConcreteTask : public NapiAsyncTask {
539         shared_ptr<IStreamPlayer> player_;
540     };
541     auto napiAsyntask = std::make_shared<ConcreteTask>();
542     if (napiAsyntask == nullptr) {
543         CLOGE("Create NapiAsyncTask failed");
544         return GetUndefinedValue(env);
545     }
546 
547     napiAsyntask->GetJSInfo(env, info);
548     auto executor = [napiAsyntask]() {
549         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
550         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
551             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
552         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
553         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
554             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
555         int32_t ret = castSession->CreateStreamPlayer(napiAsyntask->player_);
556         if (ret != CAST_ENGINE_SUCCESS) {
557             if (ret == ERR_NO_PERMISSION) {
558                 napiAsyntask->errMessage = "CreateStreamPlayer failed : no permission";
559             } else {
560                 napiAsyntask->errMessage = "CreateStreamPlayer failed : native server exception";
561             }
562             napiAsyntask->status = napi_generic_failure;
563             napiAsyntask->errCode = NapiErrors::errcode_[ret];
564         }
565     };
566 
567     auto complete = [napiAsyntask](napi_value &output) {
568         napiAsyntask->status =
569             NapiStreamPlayer::CreateNapiStreamPlayer(napiAsyntask->env, napiAsyntask->player_, output);
570         CHECK_STATUS_RETURN_VOID(napiAsyntask, "convert native object to javascript object failed",
571             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
572     };
573     return NapiAsyncWork::Enqueue(env, napiAsyntask, "CreateStreamPlayer", executor, complete);
574 }
575 
SetCastMode(napi_env env,napi_callback_info info)576 napi_value NapiCastSession::SetCastMode(napi_env env, napi_callback_info info)
577 {
578     CLOGD("Start to set cast mode in");
579     struct ConcreteTask : public NapiAsyncTask {
580         CastMode castMode_;
581         string jsonParam_;
582     };
583     auto napiAsyntask = std::make_shared<ConcreteTask>();
584     if (napiAsyntask == nullptr) {
585         CLOGE("Create NapiAsyncTask failed");
586         return GetUndefinedValue(env);
587     }
588 
589     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
590         constexpr size_t expectedArgc = 2;
591         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
592             NapiErrors::errcode_[ERR_INVALID_PARAM]);
593         napi_valuetype expectedTypes[expectedArgc] = { napi_number, napi_string };
594         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
595         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
596             NapiErrors::errcode_[ERR_INVALID_PARAM]);
597         napiAsyntask->castMode_ = static_cast<CastMode>(ParseInt32(env, argv[0]));
598         napiAsyntask->jsonParam_ = ParseString(env, argv[1]);
599     };
600     napiAsyntask->GetJSInfo(env, info, inputParser);
601     auto executor = [napiAsyntask]() {
602         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
603         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
604             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
605         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
606         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
607             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
608         int32_t ret = castSession->SetCastMode(napiAsyntask->castMode_, napiAsyntask->jsonParam_);
609         if (ret != CAST_ENGINE_SUCCESS) {
610             if (ret == ERR_NO_PERMISSION) {
611                 napiAsyntask->errMessage = "SetCastMode failed : no permission";
612             } else if (ret == ERR_INVALID_PARAM) {
613                 napiAsyntask->errMessage = "SetCastMode failed : invalid parameters";
614             } else {
615                 napiAsyntask->errMessage = "SetCastMode failed : native server exception";
616             }
617             napiAsyntask->status = napi_generic_failure;
618             napiAsyntask->errCode = NapiErrors::errcode_[ret];
619         }
620     };
621 
622     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
623     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetCastMode", executor, complete);
624 }
625 
Release(napi_env env,napi_callback_info info)626 napi_value NapiCastSession::Release(napi_env env, napi_callback_info info)
627 {
628     CLOGD("Start to release in");
629     auto napiAsyntask = std::make_shared<NapiAsyncTask>();
630     if (napiAsyntask == nullptr) {
631         CLOGE("Create NapiAsyncTask failed");
632         return GetUndefinedValue(env);
633     }
634     napiAsyntask->GetJSInfo(env, info);
635 
636     auto executor = [napiAsyntask]() {
637         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
638         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
639             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
640         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
641         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
642             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
643         int32_t ret = castSession->Release();
644         if (ret == CAST_ENGINE_SUCCESS) {
645             napiSession->Reset();
646         } else if (ret == ERR_NO_PERMISSION) {
647             napiAsyntask->errMessage = "Release failed : no permission";
648             napiAsyntask->status = napi_generic_failure;
649             napiAsyntask->errCode = NapiErrors::errcode_[ret];
650         } else {
651             napiAsyntask->errMessage = "Release failed : native server exception";
652             napiAsyntask->status = napi_generic_failure;
653             napiAsyntask->errCode = NapiErrors::errcode_[ret];
654         }
655     };
656 
657     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
658     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Release", executor, complete);
659 }
660 
NapiListenerGetter()661 std::shared_ptr<NapiCastSessionListener> NapiCastSession::NapiListenerGetter()
662 {
663     return listener_;
664 }
665 
NapiListenerSetter(std::shared_ptr<NapiCastSessionListener> listener)666 void NapiCastSession::NapiListenerSetter(std::shared_ptr<NapiCastSessionListener> listener)
667 {
668     listener_ = listener;
669 }
670 } // namespace CastEngineClient
671 } // namespace CastEngine
672 } // namespace OHOS