1 /*
2 * Copyright (c) 2024 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 "cj_avsession_cast_controller_impl.h"
17
18 #include <cstddef>
19 #include <cstdint>
20 #include <optional>
21 #include <vector>
22 #include <string>
23
24 #include "want.h"
25 #include "avqueue_item.h"
26 #include "avsession_log.h"
27 #include "avsession_manager.h"
28 #include "avcast_controller.h"
29 #include "cj_avsession_utils.h"
30 #include "cj_avsession_prototypes.h"
31
32 namespace OHOS::AVSession {
33
34 constexpr int32_t CJ_CAST_CONTROLLER_PLAYBACK_STATE_CHANGE = 0;
35 constexpr int32_t CJ_CAST_CONTROLLER_MEDIAI_ITEM_CHANGE = 1;
36 constexpr int32_t CJ_CAST_CONTROLLER_PLAY_NEXT = 2;
37 constexpr int32_t CJ_CAST_CONTROLLER_PLAY_PREVIOUS = 3;
38 constexpr int32_t CJ_CAST_CONTROLLER_REQUEST_PLAY = 4;
39 constexpr int32_t CJ_CAST_CONTROLLER_END_OF_STREAM = 5;
40 constexpr int32_t CJ_CAST_CONTROLLER_SEEK_DONE = 6;
41 constexpr int32_t CJ_CAST_CONTROLLER_VALID_COMMAND_CHANGE = 7;
42 constexpr int32_t CJ_CAST_CONTROLLER_VALID_ERROR = 8;
43 constexpr int32_t CJ_CAST_CONTROLLER_VALID_REQUEST = 9;
44
45 std::map<std::string, std::shared_ptr<CJAVCastControllerImpl>> CJAVCastControllerImpl::ControllerList_ = {};
46 std::mutex CJAVCastControllerImpl::controllerListMutex_;
47 std::mutex CJAVCastControllerImpl::callbackMutex_;
48
CJAVCastControllerImpl(std::shared_ptr<AVCastController> & nativeController,const std::string & sessionId)49 CJAVCastControllerImpl::CJAVCastControllerImpl(
50 std::shared_ptr<AVCastController>& nativeController, const std::string& sessionId)
51 {
52 sessionId_ = sessionId;
53 controller_ = nativeController;
54 }
55
~CJAVCastControllerImpl()56 CJAVCastControllerImpl::~CJAVCastControllerImpl() {}
57
CJAVCastControllerInvalidImpl()58 CJAVCastControllerInvalidImpl::CJAVCastControllerInvalidImpl() {}
~CJAVCastControllerInvalidImpl()59 CJAVCastControllerInvalidImpl::~CJAVCastControllerInvalidImpl() {}
60
GetInstance(const std::string & sessionId)61 std::shared_ptr<CJAVCastControllerBase> CJAVCastControllerImpl::GetInstance(const std::string &sessionId)
62 {
63 std::lock_guard<std::mutex> lock(controllerListMutex_);
64 if (ControllerList_.count(sessionId) == 1) {
65 return std::static_pointer_cast<CJAVCastControllerBase>(ControllerList_[sessionId]);
66 }
67 return std::static_pointer_cast<CJAVCastControllerBase>(CJ_CAST_CONTROLLER_INVALID_IMPL);
68 }
69
NewInstance(std::shared_ptr<AVCastController> & nativeController,const std::string & sessionId)70 std::shared_ptr<CJAVCastControllerImpl> CJAVCastControllerImpl::NewInstance(
71 std::shared_ptr<AVCastController> &nativeController, const std::string& sessionId)
72 {
73 struct CJAVCastControllerImplInner: public CJAVCastControllerImpl {
74 CJAVCastControllerImplInner(std::shared_ptr<AVCastController>& nativeController, const std::string& sessionId)
75 : CJAVCastControllerImpl(nativeController, sessionId) {}
76 };
77 auto controller = std::make_shared<CJAVCastControllerImplInner>(nativeController, sessionId);
78 std::lock_guard<std::mutex> lock(controllerListMutex_);
79 ControllerList_[sessionId] = controller;
80 return controller;
81 }
82
SetCastPlaybackStateFilter(CParameters * extras)83 int32_t CJAVCastControllerImpl::SetCastPlaybackStateFilter(CParameters* extras)
84 {
85 AVPlaybackState::PlaybackStateMaskType mask;
86 if (extras == nullptr) {
87 SLOGE("filter provided is nullptr!");
88 return AVSESSION_ERROR;
89 } else {
90 if (extras->valueType != I32_PTR_TYPE) {
91 SLOGE("Expect CastPlaybackStateFilter Kind is 'int32_t array', but actual is %{public}d",
92 extras->valueType);
93 return AVSESSION_ERROR;
94 }
95 if (extras->value == nullptr || extras->size == 0) {
96 SLOGE("No filter is provided to set!");
97 return AVSESSION_ERROR;
98 }
99 auto head = static_cast<int32_t *>(extras->value);
100 for (int i = 0; i < extras->size; i++) {
101 if (head[i] == AVPlaybackState::PLAYBACK_KEY_MAX) {
102 mask.set();
103 break;
104 } else {
105 mask.set(head[i]);
106 }
107 }
108 }
109 return controller_->SetCastPlaybackFilter(mask);
110 }
111
SubscribeCallback(int32_t type,CParameters * extras,DoCallFunc doCall)112 int32_t CJAVCastControllerImpl::SubscribeCallback(int32_t type, CParameters* extras, DoCallFunc doCall)
113 {
114 std::lock_guard<std::mutex> lock(callbackMutex_);
115 if (!callback_) {
116 callback_ = std::make_shared<CJAVCastControllerCallback>();
117 callback_->AddCallback(doCall);
118 controller_->RegisterCallback(callback_);
119 }
120 switch (type) {
121 case CJ_CAST_CONTROLLER_PLAYBACK_STATE_CHANGE:
122 SetCastPlaybackStateFilter(extras);
123 break;
124
125 case CJ_CAST_CONTROLLER_MEDIAI_ITEM_CHANGE:
126 case CJ_CAST_CONTROLLER_PLAY_NEXT:
127 case CJ_CAST_CONTROLLER_PLAY_PREVIOUS:
128 case CJ_CAST_CONTROLLER_REQUEST_PLAY:
129 case CJ_CAST_CONTROLLER_END_OF_STREAM:
130 case CJ_CAST_CONTROLLER_SEEK_DONE:
131 case CJ_CAST_CONTROLLER_VALID_COMMAND_CHANGE:
132 case CJ_CAST_CONTROLLER_VALID_ERROR:
133 case CJ_CAST_CONTROLLER_VALID_REQUEST:
134 break;
135
136 default:
137 SLOGE("INVALID CALLBACK TYPE:No callback is subscribed!");
138 return AVSESSION_ERROR;
139 }
140 return CJNO_ERROR;
141 }
142
Start(CAVQueueItem & item)143 int32_t CJAVCastControllerImpl::Start(CAVQueueItem& item)
144 {
145 auto call = [&](AVQueueItem& native) {
146 return controller_->Start(native);
147 };
148 return CJAVSessionSetterCStruct<AVQueueItem, CAVQueueItem>(call, item, "Start");
149 }
Prepare(CAVQueueItem & item)150 int32_t CJAVCastControllerImpl::Prepare(CAVQueueItem& item)
151 {
152 auto call = [&](AVQueueItem& native) {
153 return controller_->Prepare(native);
154 };
155 return CJAVSessionSetterCStruct<AVQueueItem, CAVQueueItem>(call, item, "Prepare");
156 }
157
SendControlCommand(CAVSessionCommand & command)158 int32_t CJAVCastControllerImpl::SendControlCommand(CAVSessionCommand& command)
159 {
160 auto call = [&](AVCastControlCommand& native) {
161 return controller_->SendControlCommand(native);
162 };
163 return CJAVSessionSetterCStruct<AVCastControlCommand, CAVSessionCommand>(call, command, "SendControlCommand");
164 }
165
GetAVPlaybackState(CAVPlaybackState & avPlaybackState)166 int32_t CJAVCastControllerImpl::GetAVPlaybackState(CAVPlaybackState& avPlaybackState)
167 {
168 auto call = [&](AVPlaybackState& native) {
169 return controller_->GetCastAVPlaybackState(native);
170 };
171 return CJControllerGetterCStruct<AVPlaybackState, CAVPlaybackState>(call, avPlaybackState, "GetAVPlaybackState");
172 }
173
GetCurrentItem(CAVQueueItem & item)174 int32_t CJAVCastControllerImpl::GetCurrentItem(CAVQueueItem& item)
175 {
176 auto call = [&](AVQueueItem& native) {
177 return controller_->GetCurrentItem(native);
178 };
179 return CJControllerGetterCStruct<AVQueueItem, CAVQueueItem>(call, item, "GetCurrentItem");
180 }
181
GetValidCommands(CArray & commands)182 int32_t CJAVCastControllerImpl::GetValidCommands(CArray& commands)
183 {
184 auto call = [&](std::vector<int32_t>& native) {
185 return controller_->GetValidCommands(native);
186 };
187 return CJControllerGetterCStruct<std::vector<int32_t>, CArray>(call, commands, "GetValidCommands");
188 }
189
Release()190 int32_t CJAVCastControllerImpl::Release()
191 {
192 auto call = [&]() {
193 return controller_->Destroy();
194 };
195 return CJExecMethod(call, "Release");
196 }
197
ProcessMediaKeyResponse(char * & assetId,CArray & response)198 int32_t CJAVCastControllerImpl::ProcessMediaKeyResponse(char*& assetId, CArray& response)
199 {
200 std::string native(assetId);
201 std::vector<uint8_t> native2;
202 int ret = convertCJStructToNative(response, native2);
203 if (ret != CJNO_ERROR) {
204 SLOGE("ProcessMediaKeyResponse failed:%{public}d", ret);
205 return ret;
206 }
207 ret = controller_->ProcessMediaKeyResponse(native, native2);
208 if (ret != AVSESSION_SUCCESS) {
209 SLOGE("ProcessMediaKeyResponse failed:%{public}d", ret);
210 }
211 return ret;
212 }
213 } // namespace OHOS::AVSession