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