1 /*
2 * Copyright (c) 2022-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_avsession_callback.h"
17 #include "avsession_log.h"
18 #include "napi_utils.h"
19 #include "avsession_trace.h"
20
21 namespace OHOS::AVSession {
NapiAVSessionCallback()22 NapiAVSessionCallback::NapiAVSessionCallback()
23 {
24 SLOGI("construct");
25 }
26
~NapiAVSessionCallback()27 NapiAVSessionCallback::~NapiAVSessionCallback()
28 {
29 SLOGI("destroy");
30 }
31
HandleEvent(int32_t event)32 void NapiAVSessionCallback::HandleEvent(int32_t event)
33 {
34 std::lock_guard<std::mutex> lockGuard(lock_);
35 if (callbacks_[event].empty()) {
36 SLOGE("not register callback event=%{public}d", event);
37 return;
38 }
39 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
40 asyncCallback_->Call(*ref);
41 }
42 }
43
44 template<typename T>
HandleEvent(int32_t event,const T & param)45 void NapiAVSessionCallback::HandleEvent(int32_t event, const T& param)
46 {
47 std::lock_guard<std::mutex> lockGuard(lock_);
48 if (callbacks_[event].empty()) {
49 SLOGE("not register callback event=%{public}d", event);
50 return;
51 }
52 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
53 asyncCallback_->Call(*ref, [param](napi_env env, int& argc, napi_value* argv) {
54 argc = NapiUtils::ARGC_ONE;
55 NapiUtils::SetValue(env, param, *argv);
56 });
57 }
58 }
59
60 template<typename T>
HandleEvent(int32_t event,const std::string & firstParam,const T & secondParam)61 void NapiAVSessionCallback::HandleEvent(int32_t event, const std::string& firstParam, const T& secondParam)
62 {
63 std::lock_guard<std::mutex> lockGuard(lock_);
64 if (callbacks_[event].empty()) {
65 SLOGE("Not register callback event: %{public}d", event);
66 return;
67 }
68 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
69 asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
70 argc = NapiUtils::ARGC_TWO;
71 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
72 CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid");
73 status = NapiUtils::SetValue(env, secondParam, argv[1]);
74 CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid");
75 });
76 }
77 }
78
79 template<typename T>
HandleEvent(int32_t event,const int32_t firstParam,const T & secondParam)80 void NapiAVSessionCallback::HandleEvent(int32_t event, const int32_t firstParam, const T& secondParam)
81 {
82 std::lock_guard<std::mutex> lockGuard(lock_);
83 if (callbacks_[event].empty()) {
84 SLOGE("Not register callback event: %{public}d", event);
85 return;
86 }
87 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
88 asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
89 argc = NapiUtils::ARGC_TWO;
90 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
91 CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set first param invalid");
92 status = NapiUtils::SetValue(env, secondParam, argv[1]);
93 CHECK_RETURN_VOID(status == napi_ok, "AVSessionCallback set second param invalid");
94 });
95 }
96 }
97
OnPlay()98 void NapiAVSessionCallback::OnPlay()
99 {
100 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnPlay");
101 HandleEvent(EVENT_PLAY);
102 }
103
OnPause()104 void NapiAVSessionCallback::OnPause()
105 {
106 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnPause");
107 HandleEvent(EVENT_PAUSE);
108 }
109
OnStop()110 void NapiAVSessionCallback::OnStop()
111 {
112 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnStop");
113 HandleEvent(EVENT_STOP);
114 }
115
OnPlayNext()116 void NapiAVSessionCallback::OnPlayNext()
117 {
118 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnPlayNext");
119 HandleEvent(EVENT_PLAY_NEXT);
120 }
121
OnPlayPrevious()122 void NapiAVSessionCallback::OnPlayPrevious()
123 {
124 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnPlayPrevious");
125 HandleEvent(EVENT_PLAY_PREVIOUS);
126 }
127
OnFastForward()128 void NapiAVSessionCallback::OnFastForward()
129 {
130 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnFastForward");
131 HandleEvent(EVENT_FAST_FORWARD);
132 }
133
OnRewind()134 void NapiAVSessionCallback::OnRewind()
135 {
136 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnRewind");
137 HandleEvent(EVENT_REWIND);
138 }
139
OnSeek(int64_t time)140 void NapiAVSessionCallback::OnSeek(int64_t time)
141 {
142 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnSeek");
143 HandleEvent(EVENT_SEEK, time);
144 }
145
OnSetSpeed(double speed)146 void NapiAVSessionCallback::OnSetSpeed(double speed)
147 {
148 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnSetSpeed");
149 HandleEvent(EVENT_SET_SPEED, speed);
150 }
151
OnSetLoopMode(int32_t loopMode)152 void NapiAVSessionCallback::OnSetLoopMode(int32_t loopMode)
153 {
154 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnSetLoopMode");
155 HandleEvent(EVENT_SET_LOOP_MODE, loopMode);
156 }
157
OnToggleFavorite(const std::string & assertId)158 void NapiAVSessionCallback::OnToggleFavorite(const std::string& assertId)
159 {
160 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnToggleFavorite");
161 HandleEvent(EVENT_TOGGLE_FAVORITE, assertId);
162 }
163
OnMediaKeyEvent(const MMI::KeyEvent & keyEvent)164 void NapiAVSessionCallback::OnMediaKeyEvent(const MMI::KeyEvent& keyEvent)
165 {
166 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnMediaKeyEvent");
167 HandleEvent(EVENT_MEDIA_KEY_EVENT, std::make_shared<MMI::KeyEvent>(keyEvent));
168 }
169
OnOutputDeviceChange(const int32_t connectionState,const OutputDeviceInfo & outputDeviceInfo)170 void NapiAVSessionCallback::OnOutputDeviceChange(const int32_t connectionState,
171 const OutputDeviceInfo& outputDeviceInfo)
172 {
173 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnOutputDeviceChange");
174 HandleEvent(EVENT_OUTPUT_DEVICE_CHANGE, connectionState, outputDeviceInfo);
175 }
176
OnCommonCommand(const std::string & commonCommand,const AAFwk::WantParams & commandArgs)177 void NapiAVSessionCallback::OnCommonCommand(const std::string& commonCommand, const AAFwk::WantParams& commandArgs)
178 {
179 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnCommonCommand");
180 HandleEvent(EVENT_SEND_COMMON_COMMAND, commonCommand, commandArgs);
181 }
182
OnSkipToQueueItem(int32_t itemId)183 void NapiAVSessionCallback::OnSkipToQueueItem(int32_t itemId)
184 {
185 AVSESSION_TRACE_SYNC_START("NapiAVSessionCallback::OnSkipToQueueItem");
186 HandleEvent(EVENT_SKIP_TO_QUEUE_ITEM, itemId);
187 }
188
AddCallback(napi_env env,int32_t event,napi_value callback)189 napi_status NapiAVSessionCallback::AddCallback(napi_env env, int32_t event, napi_value callback)
190 {
191 SLOGI("Add callback %{public}d", event);
192 std::lock_guard<std::mutex> lockGuard(lock_);
193 napi_ref ref = nullptr;
194 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
195 napi_generic_failure, "get callback reference failed");
196 CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
197 napi_status status = napi_create_reference(env, callback, NapiUtils::ARGC_ONE, &ref);
198 if (status != napi_ok) {
199 SLOGE("napi_create_reference failed");
200 return status;
201 }
202 if (asyncCallback_ == nullptr) {
203 asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
204 if (asyncCallback_ == nullptr) {
205 SLOGE("no memory");
206 return napi_generic_failure;
207 }
208 }
209 callbacks_[event].push_back(ref);
210 return napi_ok;
211 }
212
RemoveCallback(napi_env env,int32_t event,napi_value callback)213 napi_status NapiAVSessionCallback::RemoveCallback(napi_env env, int32_t event, napi_value callback)
214 {
215 SLOGI("Remove callback %{public}d", event);
216 std::lock_guard<std::mutex> lockGuard(lock_);
217 if (callback == nullptr) {
218 for (auto callbackRef = callbacks_[event].begin(); callbackRef != callbacks_[event].end(); ++callbackRef) {
219 napi_status ret = napi_delete_reference(env, *callbackRef);
220 CHECK_AND_RETURN_RET_LOG(napi_ok == ret, ret, "delete callback reference failed");
221 }
222 callbacks_[event].clear();
223 return napi_ok;
224 }
225 napi_ref ref = nullptr;
226 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
227 napi_generic_failure, "get callback reference failed");
228 CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
229 callbacks_[event].remove(ref);
230 return napi_delete_reference(env, ref);
231 }
232
IsCallbacksEmpty(int32_t event)233 bool NapiAVSessionCallback::IsCallbacksEmpty(int32_t event)
234 {
235 return callbacks_[event].empty();
236 }
237 }
238