• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "napi_avcast_controller_callback.h"
17 #include "avsession_log.h"
18 #include "avsession_trace.h"
19 #include "napi_control_command.h"
20 #include "napi_meta_data.h"
21 #include "napi_playback_state.h"
22 #include "napi_media_description.h"
23 #include "napi_queue_item.h"
24 #include "napi_utils.h"
25 
26 namespace OHOS::AVSession {
NapiAVCastControllerCallback()27 NapiAVCastControllerCallback::NapiAVCastControllerCallback()
28 {
29     SLOGI("construct");
30 }
31 
~NapiAVCastControllerCallback()32 NapiAVCastControllerCallback::~NapiAVCastControllerCallback()
33 {
34     SLOGI("destroy");
35 }
36 
HandleEvent(int32_t event)37 void NapiAVCastControllerCallback::HandleEvent(int32_t event)
38 {
39     std::lock_guard<std::mutex> lockGuard(lock_);
40     if (callbacks_[event].empty()) {
41         SLOGE("not register callback event=%{public}d", event);
42         return;
43     }
44     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
45         asyncCallback_->Call(*ref);
46     }
47 }
48 
49 template<typename T>
HandleEvent(int32_t event,const T & param)50 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const T& param)
51 {
52     std::lock_guard<std::mutex> lockGuard(lock_);
53     if (callbacks_[event].empty()) {
54         SLOGE("not register callback event=%{public}d", event);
55         return;
56     }
57     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
58         asyncCallback_->Call(*ref, [param](napi_env env, int& argc, napi_value *argv) {
59             argc = NapiUtils::ARGC_ONE;
60             auto status = NapiUtils::SetValue(env, param, *argv);
61             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
62         });
63     }
64 }
65 
66 template<typename T>
HandleEvent(int32_t event,const std::string & firstParam,const T & secondParam)67 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const std::string& firstParam, const T& secondParam)
68 {
69     std::lock_guard<std::mutex> lockGuard(lock_);
70     if (callbacks_[event].empty()) {
71         SLOGE("not register callback event=%{public}d", event);
72         return;
73     }
74     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
75         asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
76             argc = NapiUtils::ARGC_TWO;
77             auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
78             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
79             status = NapiUtils::SetValue(env, secondParam, argv[1]);
80             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
81         });
82     }
83 }
84 
85 template<typename T>
HandleEvent(int32_t event,const int32_t firstParam,const T & secondParam)86 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const int32_t firstParam, const T& secondParam)
87 {
88     std::lock_guard<std::mutex> lockGuard(lock_);
89     if (callbacks_[event].empty()) {
90         SLOGE("not register callback event=%{public}d", event);
91         return;
92     }
93     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
94         asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
95             argc = NapiUtils::ARGC_TWO;
96             auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
97             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
98             status = NapiUtils::SetValue(env, secondParam, argv[1]);
99             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
100         });
101     }
102 }
103 
HandleEvent(int32_t event,const int32_t firstParam,const int32_t secondParam,const int32_t thirdParam)104 void NapiAVCastControllerCallback::HandleEvent(int32_t event,
105     const int32_t firstParam, const int32_t secondParam, const int32_t thirdParam)
106 {
107     std::lock_guard<std::mutex> lockGuard(lock_);
108     if (callbacks_[event].empty()) {
109         SLOGE("not register callback event=%{public}d", event);
110         return;
111     }
112     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
113         asyncCallback_->Call(*ref, [firstParam, secondParam, thirdParam](napi_env env, int& argc, napi_value *argv) {
114             argc = NapiUtils::ARGC_TWO;
115             auto status = NapiUtils::SetValue(env, firstParam, argv[NapiUtils::ARGV_FIRST]);
116             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
117             status = NapiUtils::SetValue(env, secondParam, argv[NapiUtils::ARGV_SECOND]);
118             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
119             status = NapiUtils::SetValue(env, thirdParam, argv[NapiUtils::ARGV_THIRD]);
120             CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
121         });
122     }
123 }
124 
HandleErrorEvent(int32_t event,const int32_t errorCode,const std::string & errorMsg)125 void NapiAVCastControllerCallback::HandleErrorEvent(int32_t event, const int32_t errorCode,
126     const std::string& errorMsg)
127 {
128     std::lock_guard<std::mutex> lockGuard(lock_);
129     if (callbacks_[event].empty()) {
130         SLOGE("not register callback event=%{public}d", event);
131         return;
132     }
133     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
134         asyncCallback_->Call(*ref, [errorCode, errorMsg](napi_env env, int& argc, napi_value *argv) {
135             napi_status status = napi_create_object(env, argv);
136             CHECK_RETURN_VOID((status == napi_ok) && (argv != nullptr), "create object failed");
137 
138             napi_value property = nullptr;
139             status = NapiUtils::SetValue(env, errorCode, property);
140             CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
141             status = napi_set_named_property(env, *argv, "code", property);
142             CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
143 
144             status = NapiUtils::SetValue(env, errorMsg, property);
145             CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
146             status = napi_set_named_property(env, *argv, "message", property);
147             CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
148         });
149     }
150 }
151 
OnCastPlaybackStateChange(const AVPlaybackState & state)152 void NapiAVCastControllerCallback::OnCastPlaybackStateChange(const AVPlaybackState& state)
153 {
154     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnCastPlaybackStateChange");
155     SLOGI("Start handle OnCastPlaybackStateChange event");
156     HandleEvent(EVENT_CAST_PLAYBACK_STATE_CHANGE, state);
157 }
158 
OnMediaItemChange(const AVQueueItem & avQueueItem)159 void NapiAVCastControllerCallback::OnMediaItemChange(const AVQueueItem& avQueueItem)
160 {
161     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnMediaItemChange");
162     SLOGI("Start handle OnCastPlaybackStateChange event");
163     HandleEvent(EVENT_CAST_MEDIA_ITEM_CHANGE, avQueueItem);
164 }
165 
OnPlayNext()166 void NapiAVCastControllerCallback::OnPlayNext()
167 {
168     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayNext");
169     SLOGI("Start handle OnPlayNext event");
170     HandleEvent(EVENT_CAST_PLAY_NEXT);
171 }
172 
OnPlayPrevious()173 void NapiAVCastControllerCallback::OnPlayPrevious()
174 {
175     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayPrevious");
176     SLOGI("Start handle OnPlayPrevious event");
177     HandleEvent(EVENT_CAST_PLAY_PREVIOUS);
178 }
179 
OnSeekDone(const int32_t seekNumber)180 void NapiAVCastControllerCallback::OnSeekDone(const int32_t seekNumber)
181 {
182     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnSeekDone");
183     SLOGI("Start handle OnSeekDone event");
184     HandleEvent(EVENT_CAST_SEEK_DONE, seekNumber);
185 }
186 
OnVideoSizeChange(const int32_t width,const int32_t height)187 void NapiAVCastControllerCallback::OnVideoSizeChange(const int32_t width, const int32_t height)
188 {
189     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnVideoSizeChange");
190     SLOGI("Start handle OnVideoSizeChange event");
191     HandleEvent(EVENT_CAST_VIDEO_SIZE_CHANGE, width, height);
192 }
193 
OnPlayerError(const int32_t errorCode,const std::string & errorMsg)194 void NapiAVCastControllerCallback::OnPlayerError(const int32_t errorCode, const std::string& errorMsg)
195 {
196     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayerError");
197     SLOGI("Start handle OnPlayerError event");
198     MediaServiceExtErrCodeAPI9 jsErr;
199     if (MSERRCODE_INFOS.count(static_cast<MediaServiceErrCode>(errorCode)) != 0 &&
200         MSERRCODE_TO_EXTERRORCODEAPI9.count(static_cast<MediaServiceErrCode>(errorCode)) != 0) {
201         jsErr = MSERRCODE_TO_EXTERRORCODEAPI9.at(static_cast<MediaServiceErrCode>(errorCode));
202     } else {
203         SLOGW("Can not match error code, use default");
204         // If error not in map, need add error and should not return default MSERR_EXT_API9_IO.
205         jsErr = MSERR_EXT_API9_IO;
206     }
207     SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
208     HandleErrorEvent(EVENT_CAST_ERROR, static_cast<int32_t>(jsErr), errorMsg);
209 }
210 
OnEndOfStream(const int32_t isLooping)211 void NapiAVCastControllerCallback::OnEndOfStream(const int32_t isLooping)
212 {
213     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnEndOfStream");
214     SLOGI("Start handle OnEndOfStream event");
215     HandleEvent(EVENT_CAST_END_OF_STREAM, isLooping);
216 }
217 
AddCallback(napi_env env,int32_t event,napi_value callback)218 napi_status NapiAVCastControllerCallback::AddCallback(napi_env env, int32_t event, napi_value callback)
219 {
220     std::lock_guard<std::mutex> lockGuard(lock_);
221     napi_ref ref = nullptr;
222 
223     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
224         napi_generic_failure, "get callback reference failed");
225     CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
226     napi_status status = napi_create_reference(env, callback, NapiUtils::ARGC_ONE, &ref);
227     if (status != napi_ok) {
228         SLOGE("napi_create_reference failed");
229         return status;
230     }
231     if (asyncCallback_ == nullptr) {
232         asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
233         if (asyncCallback_ == nullptr) {
234             SLOGE("no memory");
235             return napi_generic_failure;
236         }
237     }
238     callbacks_[event].push_back(ref);
239     return napi_ok;
240 }
241 
RemoveCallback(napi_env env,int32_t event,napi_value callback)242 napi_status NapiAVCastControllerCallback::RemoveCallback(napi_env env, int32_t event, napi_value callback)
243 {
244     std::lock_guard<std::mutex> lockGuard(lock_);
245     if (callback == nullptr) {
246         SLOGD("Remove callback, the callback is nullptr");
247         for (auto callbackRef = callbacks_[event].begin(); callbackRef != callbacks_[event].end(); ++callbackRef) {
248             napi_status ret = napi_delete_reference(env, *callbackRef);
249             CHECK_AND_RETURN_RET_LOG(ret == napi_ok, ret, "delete callback reference failed");
250             *callbackRef = nullptr;
251         }
252         callbacks_[event].clear();
253         return napi_ok;
254     }
255     napi_ref ref = nullptr;
256     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
257         napi_generic_failure, "get callback reference failed");
258     CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
259     callbacks_[event].remove(ref);
260     return napi_delete_reference(env, ref);
261 }
262 }
263