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_avcontroller_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 {
NapiAVControllerCallback()27 NapiAVControllerCallback::NapiAVControllerCallback()
28 {
29 SLOGI("construct");
30 }
31
~NapiAVControllerCallback()32 NapiAVControllerCallback::~NapiAVControllerCallback()
33 {
34 SLOGI("destroy");
35 }
36
HandleEvent(int32_t event)37 void NapiAVControllerCallback::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 NapiAVControllerCallback::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 NapiAVControllerCallback::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
86 template<typename T>
HandleEvent(int32_t event,const int32_t firstParam,const T & secondParam)87 void NapiAVControllerCallback::HandleEvent(int32_t event, const int32_t firstParam, const T& secondParam)
88 {
89 std::lock_guard<std::mutex> lockGuard(lock_);
90 if (callbacks_[event].empty()) {
91 SLOGE("not register callback event=%{public}d", event);
92 return;
93 }
94 for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
95 asyncCallback_->Call(*ref, [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
96 argc = NapiUtils::ARGC_TWO;
97 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
98 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
99 status = NapiUtils::SetValue(env, secondParam, argv[1]);
100 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
101 });
102 }
103 }
104
OnSessionDestroy()105 void NapiAVControllerCallback::OnSessionDestroy()
106 {
107 HandleEvent(EVENT_SESSION_DESTROY);
108 }
109
OnPlaybackStateChange(const AVPlaybackState & state)110 void NapiAVControllerCallback::OnPlaybackStateChange(const AVPlaybackState& state)
111 {
112 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnPlaybackStateChange");
113 HandleEvent(EVENT_PLAYBACK_STATE_CHANGE, state);
114 }
115
OnMetaDataChange(const AVMetaData & data)116 void NapiAVControllerCallback::OnMetaDataChange(const AVMetaData& data)
117 {
118 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnMetaDataChange");
119 HandleEvent(EVENT_META_DATA_CHANGE, data);
120 }
121
OnActiveStateChange(bool isActive)122 void NapiAVControllerCallback::OnActiveStateChange(bool isActive)
123 {
124 HandleEvent(EVENT_ACTIVE_STATE_CHANGE, isActive);
125 }
126
OnValidCommandChange(const std::vector<int32_t> & cmds)127 void NapiAVControllerCallback::OnValidCommandChange(const std::vector<int32_t>& cmds)
128 {
129 std::vector<std::string> stringCmds = NapiControlCommand::ConvertCommands(cmds);
130 HandleEvent(EVENT_VALID_COMMAND_CHANGE, stringCmds);
131 }
132
OnOutputDeviceChange(const int32_t connectionState,const OutputDeviceInfo & info)133 void NapiAVControllerCallback::OnOutputDeviceChange(const int32_t connectionState, const OutputDeviceInfo& info)
134 {
135 HandleEvent(EVENT_OUTPUT_DEVICE_CHANGE, connectionState, info);
136 }
137
OnSessionEventChange(const std::string & event,const AAFwk::WantParams & args)138 void NapiAVControllerCallback::OnSessionEventChange(const std::string& event, const AAFwk::WantParams& args)
139 {
140 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnSessionEventChange");
141 HandleEvent(EVENT_SESSION_EVENT_CHANGE, event, args);
142 }
143
OnQueueItemsChange(const std::vector<AVQueueItem> & items)144 void NapiAVControllerCallback::OnQueueItemsChange(const std::vector<AVQueueItem>& items)
145 {
146 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnQueueItemsChange");
147 HandleEvent(EVENT_QUEUE_ITEMS_CHANGE, items);
148 }
149
OnQueueTitleChange(const std::string & title)150 void NapiAVControllerCallback::OnQueueTitleChange(const std::string& title)
151 {
152 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnQueueTitleChange");
153 HandleEvent(EVENT_QUEUE_TITLE_CHANGE, title);
154 }
155
OnExtrasChange(const AAFwk::WantParams & extras)156 void NapiAVControllerCallback::OnExtrasChange(const AAFwk::WantParams& extras)
157 {
158 AVSESSION_TRACE_SYNC_START("NapiAVControllerCallback::OnExtrasChange");
159 HandleEvent(EVENT_EXTRAS_CHANGE, extras);
160 }
161
AddCallback(napi_env env,int32_t event,napi_value callback)162 napi_status NapiAVControllerCallback::AddCallback(napi_env env, int32_t event, napi_value callback)
163 {
164 std::lock_guard<std::mutex> lockGuard(lock_);
165 napi_ref ref = nullptr;
166
167 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
168 napi_generic_failure, "get callback reference failed");
169 CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
170 napi_status status = napi_create_reference(env, callback, NapiUtils::ARGC_ONE, &ref);
171 if (status != napi_ok) {
172 SLOGE("napi_create_reference failed");
173 return status;
174 }
175 if (asyncCallback_ == nullptr) {
176 asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
177 if (asyncCallback_ == nullptr) {
178 SLOGE("no memory");
179 return napi_generic_failure;
180 }
181 }
182 callbacks_[event].push_back(ref);
183 return napi_ok;
184 }
185
RemoveCallback(napi_env env,int32_t event,napi_value callback)186 napi_status NapiAVControllerCallback::RemoveCallback(napi_env env, int32_t event, napi_value callback)
187 {
188 std::lock_guard<std::mutex> lockGuard(lock_);
189 if (callback == nullptr) {
190 SLOGD("Remove callback, the callback is nullptr");
191 for (auto callbackRef = callbacks_[event].begin(); callbackRef != callbacks_[event].end(); ++callbackRef) {
192 napi_status ret = napi_delete_reference(env, *callbackRef);
193 CHECK_AND_RETURN_RET_LOG(ret == napi_ok, ret, "delete callback reference failed");
194 *callbackRef = nullptr;
195 }
196 callbacks_[event].clear();
197 return napi_ok;
198 }
199 napi_ref ref = nullptr;
200 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
201 napi_generic_failure, "get callback reference failed");
202 CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
203 callbacks_[event].remove(ref);
204 return napi_delete_reference(env, ref);
205 }
206 }
207