1 /*
2 * Copyright (c) 2020-2021 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 "liteplayer_state_machine.h"
17 #include "liteplayer.h"
18 #include "liteplayer_comm.h"
19 #include "hi_liteplayer_err.h"
20
21 namespace OHOS {
22 namespace Media {
23
24 namespace {
25 /*****************************************************************************
26 status table of operation, false is not support
27 *******************************************************************/
28 const bool LITEPLAY_STATE[PLAYERCONTROL_MSG_BUTT][PLAY_STATUS_BUTT] = {
29 /* idle, init, prepare play, tplay, pause, err */
30 { false, false, true, false, false, false, false }, /* setMedia */
31 { true, true, true, true, true, true, true }, /* regCallbk */
32 { true, true, false, false, false, false, false }, /* setsrc_fd */
33 { true, true, false, false, false, false, false }, /* setsrc_uri */
34 { true, true, false, false, false, false, false }, /* setsrc_stream */
35 { false, true, true, false, false, false, false }, /* prepare */
36 { false, false, true, true, true, true, false }, /* play */
37 { false, false, true, true, true, true, false }, /* seek */
38 { false, false, false, true, false, true, false }, /* pause */
39 { false, false, false, true, true, false, false }, /* tplay */
40 { true, true, true, true, true, true, true }, /* stop */
41 { false, false, true, true, true, true, false }, /* getInfo */
42 { true, false, false, true, true, true, false }, /* handledata */
43 { true, true, true, true, true, true, true }, /* Error */
44 { false, true, true, true, true, true, false }, /* setVolume */
45 { true, true, true, true, true, true, true }, /* invoke */
46 { true, true, true, false, false, false, false }, /* set audio stream type */
47 };
48
49 struct PlayerControlStatusMap {
50 PlayerStatus state;
51 const std::string stateName;
52 };
53
54 const PlayerControlStatusMap LITEPLAY_STATEMAP[PLAY_STATUS_BUTT] = {
55 { PLAY_STATUS_IDLE, "idle" },
56 { PLAY_STATUS_INIT, "init" },
57 { PLAY_STATUS_PREPARED, "prepare" },
58 { PLAY_STATUS_PLAY, "play" },
59 { PLAY_STATUS_TPLAY, "tplay" },
60 { PLAY_STATUS_PAUSE, "pause" },
61 { PLAY_STATUS_ERR, "error" },
62 };
63 }
64
65 #define CHECK_NULL_RETURN(value, ret, printfString) \
66 do { \
67 if (value == nullptr) { \
68 MEDIA_ERR_LOG( "playerStateMachine %s \n", printfString ? printfString : " "); \
69 return ret; \
70 } \
71 } while (0)
72
StateConvert2Enum(const std::string stateName)73 PlayerStatus StateConvert2Enum(const std::string stateName)
74 {
75 bool isFound = false;
76 uint32_t i = 0;
77
78 for (; i < PLAY_STATUS_BUTT; i++) {
79 if (stateName == LITEPLAY_STATEMAP[i].stateName) {
80 isFound = true;
81 break;
82 }
83 }
84 if (isFound == false) {
85 MEDIA_ERR_LOG("could not find respond state :%s", stateName.c_str());
86 return PLAY_STATUS_BUTT;
87 }
88 return LITEPLAY_STATEMAP[i].state;
89 }
90
StateEnum2Name(PlayerStatus state)91 static std::string StateEnum2Name(PlayerStatus state)
92 {
93 return LITEPLAY_STATEMAP[state].stateName;
94 }
95
~PlayerControlState()96 PlayerControlState::~PlayerControlState()
97 {
98 }
99
Enter()100 int PlayerControlState::Enter()
101 {
102 PlayerStatus playerStatus = StateConvert2Enum(Name());
103 CHECK_NULL_RETURN(playerControlHandle_, HI_ERR_PLAYERCONTROL_NULL_PTR, "handle null");
104 playerControlHandle_->StateChangeCallback(playerStatus);
105 MEDIA_DEBUG_LOG( "enter state: %s\n", Name().c_str());
106 return HI_SUCCESS;
107 }
108
Exit()109 int PlayerControlState::Exit()
110 {
111 MEDIA_DEBUG_LOG( "exit state: %s", Name().c_str());
112 return HI_SUCCESS;
113 }
114
FindTransition(int event)115 HiState *PlayerControlState::FindTransition(int event)
116 {
117 HiState *dstState = HiState::FindTransition(event);
118 return dstState;
119 }
120
HandleMessage(const MsgInfo & msgInfo)121 int PlayerControlState::HandleMessage(const MsgInfo& msgInfo)
122 {
123 int32_t ret = HI_SUCCESS;
124
125 CHECK_NULL_RETURN(curState_, HI_ERR_PLAYERCONTROL_NULL_PTR, "curState null");
126 if (!curState_->EventValidAtCurState((PlayerControlMsgType)msgInfo.what)) {
127 MEDIA_ERR_LOG( "invalid event :%d at current state: %s", msgInfo.what,
128 Name().c_str());
129 return HI_ERR_PLAYERCONTROL_ILLEGAL_STATE_ACTION;
130 }
131 CHECK_NULL_RETURN(playerControlHandle_, HI_ERR_PLAYERCONTROL_NULL_PTR, "handle null");
132 switch (msgInfo.what) {
133 case PLAYERCONTROL_MSG_REGCALLBACK:
134 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
135 ret = playerControlHandle_->DoRegCallback(*reinterpret_cast<PlayerCtrlCallbackParam *>(msgInfo.msgData));
136 break;
137 case PLAYERCONTROL_MSG_SET_DATASOURCE_URI:
138 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
139 ret = playerControlHandle_->DoSetDataSource(reinterpret_cast<const char *>(msgInfo.msgData));
140 break;
141 case PLAYERCONTROL_MSG_SET_DATASOURCE_FD:
142 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
143 ret = playerControlHandle_->DoSetDataSource(*reinterpret_cast<const int *>(msgInfo.msgData));
144 break;
145 case PLAYERCONTROL_MSG_SET_DATASOURCE_STREAM:
146 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
147 ret = playerControlHandle_->DoSetDataSource(*reinterpret_cast<BufferStream *>(msgInfo.msgData));
148 break;
149 case PLAYERCONTROL_MSG_SETATTR:
150 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
151 ret = playerControlHandle_->DoSetMedia(*reinterpret_cast<PlayerControlStreamAttr *>(msgInfo.msgData));
152 break;
153 case PLAYERCONTROL_MSG_PAUSE:
154 ret = playerControlHandle_->DoPause();
155 break;
156 case PLAYERCONTROL_MSG_TPLAY:
157 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
158 ret = playerControlHandle_->DoTPlay(*reinterpret_cast<TplayAttr *>(msgInfo.msgData));
159 break;
160 case PLAYERCONTROL_MSG_PREPARE:
161 ret = playerControlHandle_->DoPrepare();
162 break;
163 case PLAYERCONTROL_MSG_PLAY:
164 ret = playerControlHandle_->DoPlay();
165 break;
166 case PLAYERCONTROL_MSG_SET_VOLUME:
167 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
168 ret = playerControlHandle_->DoSetVolume(*reinterpret_cast<VolumeAttr *>(msgInfo.msgData));
169 break;
170 case PLAYERCONTROL_MSG_HANDLEDATA:
171 ret = HI_SUCCESS;
172 break;
173 case PLAYERCONTROL_MSG_STOP:
174 ret = playerControlHandle_->DoStop();
175 break;
176 case PLAYERCONTROL_MSG_SEEK:
177 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
178 ret = playerControlHandle_->DoSeek(*reinterpret_cast<int64_t *>(msgInfo.msgData));
179 break;
180 case PLAYERCONTROL_MSG_GETFILEINFO:
181 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
182 ret = playerControlHandle_->DoGetFileInfo(*reinterpret_cast<FormatFileInfo *>(msgInfo.msgData));
183 break;
184 case PLAYERCONTROL_MSG_INVOKE:
185 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
186 ret = playerControlHandle_->DoInvoke(*reinterpret_cast<InvokeParameter *>(msgInfo.msgData));
187 break;
188 case PLAYERCONTROL_MSG_SET_AUDIOSTREAM_TYPE:
189 CHECK_NULL_RETURN(msgInfo.msgData, HI_ERR_PLAYERCONTROL_NULL_PTR, "msgData null");
190 ret = playerControlHandle_->DoSetAudioStreamType(*reinterpret_cast<int32_t *>(msgInfo.msgData));
191 break;
192 default:
193 ret = HI_ERR_PLAYERCONTROL_ILLEGAL_PARAM;
194 break;
195 }
196
197 return ret;
198 }
199
OnEventHandled(const HiStateMachine & curState,int event,int result)200 void PlayerControlSMObserver::OnEventHandled(const HiStateMachine &curState, int event, int result)
201 {
202 (void)curState;
203 if ((result == HI_ERR_PLAYERCONTROL_ILLEGAL_STATE_ACTION) && (event == PLAYERCONTROL_MSG_SEEK) &&
204 (playerControlHandle_ != nullptr)) {
205 playerControlHandle_->NotifyError(PLAYERCONTROL_ERROR_ILLEGAL_STATEACTION);
206 }
207 }
208
~PlayerControlSMObserver()209 PlayerControlSMObserver::~PlayerControlSMObserver()
210 {
211 }
212
PlayerControlStateMachine(PlayerControlHandle & handle)213 PlayerControlStateMachine::PlayerControlStateMachine(PlayerControlHandle& handle)
214 : HiStateMachine(), playerControlHandle_(&handle), stateIdle_(nullptr), stateInit_(nullptr),
215 statePrepare_(nullptr), statePlay_(nullptr), stateTPlay_(nullptr),
216 statePause_(nullptr), stateError_(nullptr)
217 {
218 }
219
~PlayerControlStateMachine()220 PlayerControlStateMachine::~PlayerControlStateMachine()
221 {
222 (void)Deinit();
223 }
224
CreateStates()225 int32_t PlayerControlStateMachine::CreateStates()
226 {
227 CHECK_NULL_RETURN(playerControlHandle_, HI_ERR_PLAYERCONTROL_NULL_PTR, "handle null");
228 stateIdle_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
229 StateEnum2Name(PLAY_STATUS_IDLE));
230 if (stateIdle_ == nullptr) {
231 MEDIA_ERR_LOG( "new stateIdle_ failed");
232 return HI_ERR_PLAYERCONTROL_MEM_MALLOC;
233 }
234 stateInit_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
235 StateEnum2Name(PLAY_STATUS_INIT));
236 if (stateInit_ == nullptr) {
237 MEDIA_ERR_LOG( "new stateInit_ failed");
238 goto DESTROY;
239 }
240 statePrepare_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
241 StateEnum2Name(PLAY_STATUS_PREPARED));
242 if (statePrepare_ == nullptr) {
243 MEDIA_ERR_LOG( "new statePrepare_ failed");
244 goto DESTROY;
245 }
246 statePlay_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
247 StateEnum2Name(PLAY_STATUS_PLAY));
248 if (statePlay_ == nullptr) {
249 MEDIA_ERR_LOG( "new statePlay_ failed");
250 goto DESTROY;
251 }
252 stateTPlay_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
253 StateEnum2Name(PLAY_STATUS_TPLAY));
254 if (stateTPlay_ == nullptr) {
255 MEDIA_ERR_LOG( "new stateTPlay_ failed");
256 goto DESTROY;
257 }
258 statePause_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
259 StateEnum2Name(PLAY_STATUS_PAUSE));
260 if (statePause_ == nullptr) {
261 MEDIA_ERR_LOG( "new statePause_ failed");
262 goto DESTROY;
263 }
264 stateError_ = new(std::nothrow) PlayerControlState(*playerControlHandle_, *this,
265 StateEnum2Name(PLAY_STATUS_ERR));
266 if (stateError_ == nullptr) {
267 MEDIA_ERR_LOG( "new stateError_ failed");
268 goto DESTROY;
269 }
270 return HI_SUCCESS;
271 DESTROY:
272 DestroyStates();
273 return HI_ERR_PLAYERCONTROL_MEM_MALLOC;
274 }
275
DestroyStates()276 void PlayerControlStateMachine::DestroyStates()
277 {
278 if (stateIdle_ != nullptr) {
279 delete stateIdle_;
280 stateIdle_ = nullptr;
281 }
282 if (stateInit_ != nullptr) {
283 delete stateInit_;
284 stateInit_ = nullptr;
285 }
286 if (statePrepare_ != nullptr) {
287 delete statePrepare_;
288 statePrepare_ = nullptr;
289 }
290 if (statePlay_ != nullptr) {
291 delete statePlay_;
292 statePlay_ = nullptr;
293 }
294 if (stateTPlay_ != nullptr) {
295 delete stateTPlay_;
296 stateTPlay_ = nullptr;
297 }
298 if (statePause_ != nullptr) {
299 delete statePause_;
300 statePause_ = nullptr;
301 }
302 if (stateError_ != nullptr) {
303 delete stateError_;
304 stateError_ = nullptr;
305 }
306 }
307
Init(uint32_t maxQueueSize,uint32_t maxMsgPayloadSize)308 int32_t PlayerControlStateMachine::Init(uint32_t maxQueueSize, uint32_t maxMsgPayloadSize)
309 {
310 const std::string playerControlSmName = "playerCtrl_sm";
311 int32_t ret = HiStateMachine::Init(maxQueueSize, maxMsgPayloadSize, playerControlSmName);
312 if (ret != HI_SUCCESS) {
313 printf("HiStateMachine::Init failed");
314 return ret;
315 }
316 ret = CreateStates();
317 if (ret != HI_SUCCESS) {
318 MEDIA_ERR_LOG( "createStates failed");
319 return ret;
320 }
321 stateIdle_->AddTransition(PLAYERCONTROL_MSG_SET_DATASOURCE_FD, *stateInit_);
322 stateIdle_->AddTransition(PLAYERCONTROL_MSG_SET_DATASOURCE_URI, *stateInit_);
323 stateIdle_->AddTransition(PLAYERCONTROL_MSG_SET_DATASOURCE_STREAM, *stateInit_);
324 stateIdle_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
325 stateInit_->AddTransition(PLAYERCONTROL_MSG_PREPARE, *statePrepare_);
326 stateInit_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
327 stateInit_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
328 statePrepare_->AddTransition(PLAYERCONTROL_MSG_PLAY, *statePlay_);
329 statePrepare_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
330 statePrepare_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
331 statePlay_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
332 statePlay_->AddTransition(PLAYERCONTROL_MSG_TPLAY, *stateTPlay_);
333 statePlay_->AddTransition(PLAYERCONTROL_MSG_PAUSE, *statePause_);
334 statePlay_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
335 stateTPlay_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
336 stateTPlay_->AddTransition(PLAYERCONTROL_MSG_PLAY, *statePlay_);
337 stateTPlay_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
338 statePause_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
339 statePause_->AddTransition(PLAYERCONTROL_MSG_PLAY, *statePlay_);
340 statePause_->AddTransition(PLAYERCONTROL_MSG_ERROR, *stateError_);
341 stateError_->AddTransition(PLAYERCONTROL_MSG_STOP, *stateIdle_);
342 (void)AddState(*stateIdle_);
343 (void)AddState(*stateInit_);
344 (void)AddState(*statePrepare_);
345 (void)AddState(*statePlay_);
346 (void)AddState(*stateTPlay_);
347 (void)AddState(*statePause_);
348 (void)AddState(*stateError_);
349 (void)SetInitialState(*stateIdle_);
350 return HI_SUCCESS;
351 }
352
Deinit()353 int32_t PlayerControlStateMachine::Deinit()
354 {
355 DestroyStates();
356 int32_t ret = HiStateMachine::Deinit();
357 if (ret != HI_SUCCESS) {
358 MEDIA_ERR_LOG( "HiStateMachine::Deinit failed");
359 return ret;
360 }
361 return HI_SUCCESS;
362 }
363
GetCurState()364 PlayerStatus PlayerControlStateMachine::GetCurState()
365 {
366 const HiState* curState = CurrentState();
367 return StateConvert2Enum(curState->Name());
368 }
369
EventValidAtCurState(PlayerControlMsgType type)370 bool PlayerControlStateMachine::EventValidAtCurState(PlayerControlMsgType type)
371 {
372 if (type < PLAYERCONTROL_MSG_SETATTR || type >= PLAYERCONTROL_MSG_BUTT) {
373 MEDIA_ERR_LOG( "EventValidAtCurState MSG type not support %d", type);
374 return false;
375 }
376 return LITEPLAY_STATE[type][GetCurState()];
377 }
378 }
379 }
380