• 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     };
359     auto napiAsyntask = std::make_shared<ConcreteTask>();
360     if (napiAsyntask == nullptr) {
361         CLOGE("Create NapiAsyncTask failed");
362         return GetUndefinedValue(env);
363     }
364 
365     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
366         constexpr size_t expectedArgc = 1;
367         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
368             NapiErrors::errcode_[ERR_INVALID_PARAM]);
369         napi_valuetype expectedTypes[expectedArgc] = { napi_string };
370         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
371         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
372             NapiErrors::errcode_[ERR_INVALID_PARAM]);
373         napiAsyntask->deviceId_ = ParseString(env, argv[0]);
374     };
375     napiAsyntask->GetJSInfo(env, info, inputParser);
376     auto executor = [napiAsyntask]() {
377         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
378         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
379             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
380         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
381         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
382             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
383         int32_t ret = castSession->RemoveDevice(napiAsyntask->deviceId_);
384         if (ret != CAST_ENGINE_SUCCESS) {
385             if (ret == ERR_NO_PERMISSION) {
386                 napiAsyntask->errMessage = "RemoveDevice failed : no permission";
387             } else if (ret == ERR_INVALID_PARAM) {
388                 napiAsyntask->errMessage = "RemoveDevice failed : invalid parameters";
389             } else {
390                 napiAsyntask->errMessage = "RemoveDevice failed : native server exception";
391             }
392             napiAsyntask->status = napi_generic_failure;
393             napiAsyntask->errCode = NapiErrors::errcode_[ret];
394         }
395     };
396 
397     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
398     return NapiAsyncWork::Enqueue(env, napiAsyntask, "RemoveDevice", executor, complete);
399 }
400 
GetSessionId(napi_env env,napi_callback_info info)401 napi_value NapiCastSession::GetSessionId(napi_env env, napi_callback_info info)
402 {
403     CLOGD("Start to get sessionId in");
404     struct ConcreteTask : public NapiAsyncTask {
405         string sessionId_;
406     };
407     auto napiAsyntask = std::make_shared<ConcreteTask>();
408     if (napiAsyntask == nullptr) {
409         CLOGE("Create NapiAsyncTask failed");
410         return GetUndefinedValue(env);
411     }
412 
413     napiAsyntask->GetJSInfo(env, info);
414     auto executor = [napiAsyntask]() {
415         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
416         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
417             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
418         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
419         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
420             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
421         int32_t ret = castSession->GetSessionId(napiAsyntask->sessionId_);
422         if (ret != CAST_ENGINE_SUCCESS) {
423             if (ret == ERR_NO_PERMISSION) {
424                 napiAsyntask->errMessage = "GetSessionId failed : no permission";
425             } else {
426                 napiAsyntask->errMessage = "GetSessionId failed : native server exception";
427             }
428             napiAsyntask->status = napi_generic_failure;
429             napiAsyntask->errCode = NapiErrors::errcode_[ret];
430         }
431     };
432 
433     auto complete = [env, napiAsyntask](napi_value &output) {
434         napiAsyntask->status =
435             napi_create_string_utf8(env, napiAsyntask->sessionId_.c_str(), NAPI_AUTO_LENGTH, &output);
436         CHECK_STATUS_RETURN_VOID(napiAsyntask, "napi_create_string_utf8 failed",
437             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
438     };
439     return NapiAsyncWork::Enqueue(env, napiAsyntask, "GetSessionId", executor, complete);
440 }
441 
SetSessionProperty(napi_env env,napi_callback_info info)442 napi_value NapiCastSession::SetSessionProperty(napi_env env, napi_callback_info info)
443 {
444     CLOGD("Start to set sessionProperty in");
445     struct ConcreteTask : public NapiAsyncTask {
446         CastSessionProperty castSessionProperty_;
447     };
448     auto napiAsyntask = std::make_shared<ConcreteTask>();
449     if (napiAsyntask == nullptr) {
450         CLOGE("Create NapiAsyncTask failed");
451         return GetUndefinedValue(env);
452     }
453 
454     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
455         constexpr size_t expectedArgc = 1;
456         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
457             NapiErrors::errcode_[ERR_INVALID_PARAM]);
458         napi_valuetype expectedTypes[expectedArgc] = { napi_object };
459         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
460         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
461             NapiErrors::errcode_[ERR_INVALID_PARAM]);
462         napiAsyntask->castSessionProperty_ = GetCastSessionPropertyFromJS(env, argv[0]);
463     };
464     napiAsyntask->GetJSInfo(env, info, inputParser);
465     auto executor = [napiAsyntask]() {
466         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
467         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
468             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
469         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
470         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
471             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
472         int32_t ret = castSession->SetSessionProperty(napiAsyntask->castSessionProperty_);
473         if (ret != CAST_ENGINE_SUCCESS) {
474             if (ret == ERR_NO_PERMISSION) {
475                 napiAsyntask->errMessage = "SetSessionProperty failed : no permission";
476             } else if (ret == ERR_INVALID_PARAM) {
477                 napiAsyntask->errMessage = "SetSessionProperty failed : invalid parameters";
478             } else {
479                 napiAsyntask->errMessage = "SetSessionProperty failed : native server exception";
480             }
481             napiAsyntask->status = napi_generic_failure;
482             napiAsyntask->errCode = NapiErrors::errcode_[ret];
483         }
484     };
485 
486     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
487     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetSessionProperty", executor, complete);
488 }
489 
CreateMirrorPlayer(napi_env env,napi_callback_info info)490 napi_value NapiCastSession::CreateMirrorPlayer(napi_env env, napi_callback_info info)
491 {
492     CLOGD("Start to create mirror Player");
493     struct ConcreteTask : public NapiAsyncTask {
494         shared_ptr<IMirrorPlayer> player_;
495     };
496     auto napiAsyntask = std::make_shared<ConcreteTask>();
497     if (napiAsyntask == nullptr) {
498         CLOGE("Create NapiAsyncTask failed");
499         return GetUndefinedValue(env);
500     }
501 
502     napiAsyntask->GetJSInfo(env, info);
503     auto executor = [napiAsyntask]() {
504         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
505         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
506             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
507         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
508         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
509             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
510         int32_t ret = castSession->CreateMirrorPlayer(napiAsyntask->player_);
511         if (ret != CAST_ENGINE_SUCCESS) {
512             if (ret == ERR_NO_PERMISSION) {
513                 napiAsyntask->errMessage = "CreateMirrorPlayer failed : no permission";
514             } else {
515                 napiAsyntask->errMessage = "CreateMirrorPlayer failed : native server exception";
516             }
517             napiAsyntask->status = napi_generic_failure;
518             napiAsyntask->errCode = NapiErrors::errcode_[ret];
519         }
520     };
521 
522     auto complete = [napiAsyntask](napi_value &output) {
523         napiAsyntask->status =
524             NapiMirrorPlayer::CreateNapiMirrorPlayer(napiAsyntask->env, napiAsyntask->player_, output);
525         CHECK_STATUS_RETURN_VOID(napiAsyntask, "convert native object to javascript object failed",
526             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
527     };
528     return NapiAsyncWork::Enqueue(env, napiAsyntask, "CreateMirrorPlayer", executor, complete);
529 }
530 
CreateStreamPlayer(napi_env env,napi_callback_info info)531 napi_value NapiCastSession::CreateStreamPlayer(napi_env env, napi_callback_info info)
532 {
533     CLOGD("Start to create Stream Player");
534     struct ConcreteTask : public NapiAsyncTask {
535         shared_ptr<IStreamPlayer> player_;
536     };
537     auto napiAsyntask = std::make_shared<ConcreteTask>();
538     if (napiAsyntask == nullptr) {
539         CLOGE("Create NapiAsyncTask failed");
540         return GetUndefinedValue(env);
541     }
542 
543     napiAsyntask->GetJSInfo(env, info);
544     auto executor = [napiAsyntask]() {
545         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
546         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
547             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
548         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
549         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
550             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
551         int32_t ret = castSession->CreateStreamPlayer(napiAsyntask->player_);
552         if (ret != CAST_ENGINE_SUCCESS) {
553             if (ret == ERR_NO_PERMISSION) {
554                 napiAsyntask->errMessage = "CreateStreamPlayer failed : no permission";
555             } else {
556                 napiAsyntask->errMessage = "CreateStreamPlayer failed : native server exception";
557             }
558             napiAsyntask->status = napi_generic_failure;
559             napiAsyntask->errCode = NapiErrors::errcode_[ret];
560         }
561     };
562 
563     auto complete = [napiAsyntask](napi_value &output) {
564         napiAsyntask->status =
565             NapiStreamPlayer::CreateNapiStreamPlayer(napiAsyntask->env, napiAsyntask->player_, output);
566         CHECK_STATUS_RETURN_VOID(napiAsyntask, "convert native object to javascript object failed",
567             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
568     };
569     return NapiAsyncWork::Enqueue(env, napiAsyntask, "CreateStreamPlayer", executor, complete);
570 }
571 
SetCastMode(napi_env env,napi_callback_info info)572 napi_value NapiCastSession::SetCastMode(napi_env env, napi_callback_info info)
573 {
574     CLOGD("Start to set cast mode in");
575     struct ConcreteTask : public NapiAsyncTask {
576         CastMode castMode_;
577         string jsonParam_;
578     };
579     auto napiAsyntask = std::make_shared<ConcreteTask>();
580     if (napiAsyntask == nullptr) {
581         CLOGE("Create NapiAsyncTask failed");
582         return GetUndefinedValue(env);
583     }
584 
585     auto inputParser = [env, napiAsyntask](size_t argc, napi_value *argv) {
586         constexpr size_t expectedArgc = 2;
587         CHECK_ARGS_RETURN_VOID(napiAsyntask, argc == expectedArgc, "invalid arguments",
588             NapiErrors::errcode_[ERR_INVALID_PARAM]);
589         napi_valuetype expectedTypes[expectedArgc] = { napi_number, napi_string };
590         bool isParamsTypeValid = CheckJSParamsType(env, argv, expectedArgc, expectedTypes);
591         CHECK_ARGS_RETURN_VOID(napiAsyntask, isParamsTypeValid, "invalid arguments",
592             NapiErrors::errcode_[ERR_INVALID_PARAM]);
593         napiAsyntask->castMode_ = static_cast<CastMode>(ParseInt32(env, argv[0]));
594         napiAsyntask->jsonParam_ = ParseString(env, argv[1]);
595     };
596     napiAsyntask->GetJSInfo(env, info, inputParser);
597     auto executor = [napiAsyntask]() {
598         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
599         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
600             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
601         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
602         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
603             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
604         int32_t ret = castSession->SetCastMode(napiAsyntask->castMode_, napiAsyntask->jsonParam_);
605         if (ret != CAST_ENGINE_SUCCESS) {
606             if (ret == ERR_NO_PERMISSION) {
607                 napiAsyntask->errMessage = "SetCastMode failed : no permission";
608             } else if (ret == ERR_INVALID_PARAM) {
609                 napiAsyntask->errMessage = "SetCastMode failed : invalid parameters";
610             } else {
611                 napiAsyntask->errMessage = "SetCastMode failed : native server exception";
612             }
613             napiAsyntask->status = napi_generic_failure;
614             napiAsyntask->errCode = NapiErrors::errcode_[ret];
615         }
616     };
617 
618     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
619     return NapiAsyncWork::Enqueue(env, napiAsyntask, "SetCastMode", executor, complete);
620 }
621 
Release(napi_env env,napi_callback_info info)622 napi_value NapiCastSession::Release(napi_env env, napi_callback_info info)
623 {
624     CLOGD("Start to release in");
625     auto napiAsyntask = std::make_shared<NapiAsyncTask>();
626     if (napiAsyntask == nullptr) {
627         CLOGE("Create NapiAsyncTask failed");
628         return GetUndefinedValue(env);
629     }
630     napiAsyntask->GetJSInfo(env, info);
631 
632     auto executor = [napiAsyntask]() {
633         auto *napiSession = reinterpret_cast<NapiCastSession *>(napiAsyntask->native);
634         CHECK_ARGS_RETURN_VOID(napiAsyntask, napiSession != nullptr, "napiSession is null",
635             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
636         shared_ptr<ICastSession> castSession = napiSession->GetCastSession();
637         CHECK_ARGS_RETURN_VOID(napiAsyntask, castSession, "ICastSession is null",
638             NapiErrors::errcode_[CAST_ENGINE_ERROR]);
639         int32_t ret = castSession->Release();
640         if (ret == CAST_ENGINE_SUCCESS) {
641             napiSession->Reset();
642         } else if (ret == ERR_NO_PERMISSION) {
643             napiAsyntask->errMessage = "Release failed : no permission";
644             napiAsyntask->status = napi_generic_failure;
645             napiAsyntask->errCode = NapiErrors::errcode_[ret];
646         } else {
647             napiAsyntask->errMessage = "Release failed : native server exception";
648             napiAsyntask->status = napi_generic_failure;
649             napiAsyntask->errCode = NapiErrors::errcode_[ret];
650         }
651     };
652 
653     auto complete = [env](napi_value &output) { output = GetUndefinedValue(env); };
654     return NapiAsyncWork::Enqueue(env, napiAsyntask, "Release", executor, complete);
655 }
656 
NapiListenerGetter()657 std::shared_ptr<NapiCastSessionListener> NapiCastSession::NapiListenerGetter()
658 {
659     return listener_;
660 }
661 
NapiListenerSetter(std::shared_ptr<NapiCastSessionListener> listener)662 void NapiCastSession::NapiListenerSetter(std::shared_ptr<NapiCastSessionListener> listener)
663 {
664     listener_ = listener;
665 }
666 } // namespace CastEngineClient
667 } // namespace CastEngine
668 } // namespace OHOS