1 /*
2 * Copyright (c) 2020 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 "player_ability_slice.h"
17 #include <algorithm>
18 #include <vector>
19
20 #include "ability_env.h"
21 #include "ability_manager.h"
22 #include "components/ui_image_view.h"
23 #include "gfx_utils/file.h"
24
25 using OHOS::Media::Player;
26 using OHOS::Media::Source;
27 using namespace OHOS::Media;
28
29 namespace OHOS {
30 REGISTER_AS(PlayerAbilitySlice)
31
32
~PlayerAbilitySlice()33 PlayerAbilitySlice::~PlayerAbilitySlice()
34 {
35 printf("################ ~PlayerAbilitySlice enter\n");
36
37 /** released in DestoryPlayer(). */
38
39 printf("################ ~PlayerAbilitySlice exit\n");
40 }
41
CreatePlayer()42 std::shared_ptr<Player> PlayerAbilitySlice::CreatePlayer()
43 {
44 static std::shared_ptr<Player> instance_ = nullptr;
45 if (instance_ == nullptr) {
46 instance_ = std::make_shared<Player>();
47 }
48 return instance_;
49 }
50
Clear()51 void PlayerAbilitySlice::Clear()
52 {
53 printf("PlayerAbilitySlice::Clear | enter\n");
54 if (backIconListener_ != nullptr) {
55 delete backIconListener_;
56 backIconListener_ = nullptr;
57 }
58 if (onClickListener_ != nullptr) {
59 delete onClickListener_;
60 onClickListener_ = nullptr;
61 }
62 if (surfaceView_ != nullptr) {
63 delete surfaceView_;
64 surfaceView_ = nullptr;
65 }
66 if (animatorGroup_ != nullptr) {
67 delete animatorGroup_;
68 animatorGroup_ = nullptr;
69 }
70 if (backIcon_ != nullptr) {
71 delete backIcon_;
72 backIcon_ = nullptr;
73 }
74 if (backArea_ != nullptr) {
75 delete backArea_;
76 backArea_ = nullptr;
77 }
78 if (errorTips_ != nullptr) {
79 delete errorTips_;
80 errorTips_ = nullptr;
81 }
82 if (totalTimeLabel_ != nullptr) {
83 delete totalTimeLabel_;
84 totalTimeLabel_ = nullptr;
85 }
86 if (currentTimeLabel_ != nullptr) {
87 delete currentTimeLabel_;
88 currentTimeLabel_ = nullptr;
89 }
90 if (slider_ != nullptr) {
91 delete slider_;
92 slider_ = nullptr;
93 }
94 if (toggleButton_ != nullptr) {
95 delete toggleButton_;
96 toggleButton_ = nullptr;
97 }
98 if (toggleButtonArea_ != nullptr) {
99 delete toggleButtonArea_;
100 toggleButtonArea_ = nullptr;
101 }
102 if (rootView_ != nullptr) {
103 RootView::DestroyWindowRootView(rootView_);
104 rootView_ = nullptr;
105 }
106 printf("PlayerAbilitySlice::Clear() | end\n");
107 }
108
ShowErrorTips()109 void PlayerAbilitySlice::ShowErrorTips()
110 {
111 errorTips_ = new UILabel();
112 errorTips_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y, ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);
113 errorTips_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER,
114 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
115 errorTips_->SetFont(FONT_NAME, GALLERY_FONT_SIZE);
116 errorTips_->SetText("视频播放错误");
117
118 rootView_->Add(backArea_);
119 rootView_->Add(errorTips_);
120 rootView_->Add(backIcon_);
121 SetUIContent(rootView_);
122 }
123
SetUpRootView()124 void PlayerAbilitySlice::SetUpRootView()
125 {
126 if (rootView_ != nullptr) {
127 return;
128 }
129 rootView_ = RootView::GetWindowRootView();
130 rootView_->SetPosition(ROOT_VIEW_POSITION_X, ROOT_VIEW_POSITION_Y);
131 rootView_->Resize(ROOT_VIEW_WIDTH, ROOT_VIEW_HEIGHT);
132 rootView_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
133 }
134
SetUpBackArea(const char* pathHeader)135 void PlayerAbilitySlice::SetUpBackArea(const char* pathHeader)
136 {
137 auto onClick = [this] (UIView &view, const Event &event) -> bool {
138 printf("############ PlayerAbilitySlice terminate AS enter #############\n");
139 Terminate();
140 printf("############ PlayerAbilitySlice terminate AS exit #############\n");
141 return true;
142 };
143 backIcon_ = new UIImageView();
144 backIcon_->SetPosition(BACK_ICON_POSITION_X, BACK_ICON_POSITION_Y);
145
146 if (sprintf_s(backIconAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, BACK_ICON_PATH) < 0) {
147 printf("PlayerAbilitySlice::OnStart | backIconAbsolutePath | %s\n", pathHeader);
148 return;
149 }
150 backIcon_->SetSrc(backIconAbsolutePath);
151 backIcon_->SetTouchable(true);
152 backIconListener_ = new EventListener(onClick, nullptr);
153 backIcon_->SetOnClickListener(backIconListener_);
154
155 backArea_ = new UIViewGroup();
156 backArea_->SetPosition(0, 0, LABEL_POSITION_X, LABEL_HEIGHT);
157 backArea_->SetStyle(STYLE_BACKGROUND_OPA, 0);
158 backArea_->SetTouchable(true);
159 backArea_->SetOnClickListener(backIconListener_);
160
161 rootView_->Add(backArea_);
162 rootView_->Add(backIcon_);
163 }
164
SetUpVideoPlayer(const Want &want)165 void PlayerAbilitySlice::SetUpVideoPlayer(const Want &want)
166 {
167 if (videoPlayer_ == nullptr) {
168 videoPlayer_ = new PlayerAdapter();
169 }
170 videoPlayer_->sourceType = 1;
171
172 uint16_t videoPathLen = strlen(VIDEO_SOURCE_DIRECTORY) + strlen(reinterpret_cast<char*>(want.data)) + 1;
173 int8_t ret = sprintf_s(videoPlayer_->filePath, videoPathLen + 1, "%s/%s", VIDEO_SOURCE_DIRECTORY,
174 reinterpret_cast<char*>(want.data));
175 if (ret < 0) {
176 printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath | %s\n", reinterpret_cast<char*>(want.data));
177 return;
178 }
179 ret = sprintf_s(&videoPlayer_->filePath[videoPathLen - strlen(AVAILABEL_SOURCE_TYPE)],
180 strlen(AVAILABEL_SOURCE_TYPE) + 1, "%s", AVAILABEL_SOURCE_TYPE);
181 if (ret < 0) {
182 printf("PlayerAbilitySlice::OnStart | videoPlayer_->filePath \n");
183 return;
184 }
185 printf("------########### mp4 file path | %s\n", videoPlayer_->filePath);
186
187 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer();
188 std::string uri(videoPlayer_->filePath);
189 std::map<std::string, std::string> header;
190 Source source(uri, header);
191 videoPlayer_->adapter->SetSource(source);
192 }
193
SetUpSurfaceView()194 bool PlayerAbilitySlice::SetUpSurfaceView()
195 {
196 if (surfaceView_ != nullptr) {
197 return true;
198 }
199 int32_t width = 0;
200 int32_t height = 0;
201 videoPlayer_->adapter->GetVideoWidth(width);
202 printf("[%s,%d] width:%d\n", __func__, __LINE__, width);
203 videoPlayer_->adapter->GetVideoHeight(height);
204 printf("[%s,%d] height:%d\n", __func__, __LINE__, height);
205
206 if (width <= 0 || height <= 0) {
207 videoPlayer_->adapter->Release();
208 delete videoPlayer_;
209 videoPlayer_ = nullptr;
210 printf("******** width <= 0 || height <= 0 | return \n");
211 ShowErrorTips();
212 return false;
213 }
214 float ratio_x = static_cast<float>(width) / ROOT_VIEW_WIDTH;
215 float ratio_y = static_cast<float>(height) / ROOT_VIEW_HEIGHT;
216 uint16_t surfaceViewWidth;
217 uint16_t surfaceViewHeight;
218 uint16_t surfaceViewPositionX = 0;
219 uint16_t surfaceViewPositionY = 0;
220 if (ratio_x > ratio_y) {
221 surfaceViewWidth = ROOT_VIEW_WIDTH;
222 surfaceViewHeight = height / ratio_x;
223 surfaceViewPositionY = (ROOT_VIEW_HEIGHT - surfaceViewHeight) / 2; // 2: half
224 } else {
225 surfaceViewWidth = width / ratio_y;
226 surfaceViewHeight = ROOT_VIEW_HEIGHT;
227 surfaceViewPositionX = (ROOT_VIEW_WIDTH - surfaceViewWidth) / 2; // 2: half
228 }
229
230 surfaceView_ = new UISurfaceView();
231 surfaceView_->SetPosition(surfaceViewPositionX, surfaceViewPositionY);
232 surfaceView_->SetWidth(surfaceViewWidth - 1);
233 surfaceView_->SetHeight(surfaceViewHeight);
234 videoPlayer_->adapter->SetVideoSurface(surfaceView_->GetSurface());
235
236 rootView_->Add(surfaceView_);
237
238 return true;
239 }
240
SetUpProgress(int64_t duration)241 void PlayerAbilitySlice::SetUpProgress(int64_t duration)
242 {
243 slider_ = new UISlider();
244 slider_->SetPosition(SLIDER_X, SLIDER_Y, SLIDER_WIDTH, STATUS_BAR_GROUP_HEIGHT);
245 slider_->SetValidHeight(SLIDER_HEIGHT);
246 slider_->SetValidWidth(SLIDER_WIDTH - KNOB_WIDTH);
247 slider_->SetRange(SLIDER_WIDTH, 0);
248 slider_->SetValue(0);
249 slider_->SetKnobWidth(KNOB_WIDTH);
250 slider_->SetSliderRadius(SLIDER_HEIGHT, SLIDER_HEIGHT);
251 slider_->SetKnobRadius(KNOB_WIDTH / 2); // 2: half
252 slider_->SetKnobStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
253 slider_->SetBackgroundStyle(STYLE_BACKGROUND_COLOR, 0x1A888888);
254 slider_->SetBackgroundStyle(STYLE_BACKGROUND_OPA, 90); // 90: opacity is 90
255 slider_->SetDirection(UISlider::Direction::DIR_LEFT_TO_RIGHT);
256 slider_->SetTouchable(false);
257 animatorGroup_->Add(slider_);
258
259 animator_ = new SliderAnimator(videoPlayer_, slider_, currentTimeLabel_, duration, surfaceView_);
260 }
261
SetUpAnimatorGroup(const char* pathHeader)262 void PlayerAbilitySlice::SetUpAnimatorGroup(const char* pathHeader)
263 {
264 int64_t duration = 0;
265 videoPlayer_->adapter->GetDuration(duration);
266 printf("[%s,%d] GetDuration:%lld\n", __func__, __LINE__, duration);
267
268 animatorGroup_ = new UIViewGroup();
269 animatorGroup_->SetPosition(0, ROOT_VIEW_HEIGHT - STATUS_BAR_GROUP_HEIGHT,
270 ROOT_VIEW_WIDTH, STATUS_BAR_GROUP_HEIGHT);
271 animatorGroup_->SetStyle(STYLE_BACKGROUND_OPA, 0);
272
273 totalTimeLabel_ = new UILabel();
274 totalTimeLabel_->SetPosition(TOTAL_TIME_LABEL_X, TOTAL_TIME_LABEL_Y,
275 TOTAL_TIME_LABEL_WIDTH, TOTAL_TIME_LABEL_HEIGHT);
276 totalTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,
277 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
278 totalTimeLabel_->SetFont(FONT_NAME, PLAYER_FONT_SIZE);
279 int64_t second = duration / 1000; // 1000: 1s = 1000ms
280 char timer[6]; // 6: length of time label
281 if (sprintf_s(timer, sizeof(timer), "%02lld:%02lld", second / 60, second % 60) < 0) { // 60: 1minute = 60s
282 return;
283 }
284
285 totalTimeLabel_->SetText(timer);
286 totalTimeLabel_->SetTextColor(Color::White());
287 animatorGroup_->Add(totalTimeLabel_);
288
289 currentTimeLabel_ = new UILabel();
290 currentTimeLabel_->SetPosition(CURRENT_TIME_LABEL_X, CURRENT_TIME_LABEL_Y,
291 CURRENT_TIME_LABEL_WIDTH, CURRENT_TIME_LABEL_HEIGHT);
292 currentTimeLabel_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full);
293 currentTimeLabel_->SetFont(FONT_NAME, PLAYER_FONT_SIZE);
294 currentTimeLabel_->SetText("00:00");
295 currentTimeLabel_->SetTextColor(Color::White());
296 currentTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,
297 UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
298 animatorGroup_->Add(currentTimeLabel_);
299
300 SetUpProgress(duration);
301
302 SetUpToggleButton(pathHeader);
303
304 rootView_->Add(animatorGroup_);
305 }
306
SetUpToggleButton(const char* pathHeader)307 void PlayerAbilitySlice::SetUpToggleButton(const char* pathHeader)
308 {
309 toggleButton_ = new UIToggleButton();
310 toggleButton_->SetTouchable(false);
311 toggleButton_->SetPosition(TOGGLE_BUTTON_OFFSET_X, TOGGLE_BUTTON_OFFSET_Y,
312 TOGGLE_BUTTON_WIDTH, TOGGLE_BUTTON_HEIGHT);
313 toggleButton_->SetState(true);
314
315 if (sprintf_s(videoPlayAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PALY_PATH) < 0) {
316 printf("PlayerAbilitySlice::OnStart | videoPlayAbsolutePath\n");
317 return;
318 }
319
320 if (sprintf_s(videoPauseAbsolutePath, MAX_PATH_LENGTH, "%s%s", pathHeader, VIDEO_PAUSE_PATH) < 0) {
321 printf("PlayerAbilitySlice::OnStart | videoPauseAbsolutePath\n");
322 return;
323 }
324 toggleButton_->SetImages(videoPauseAbsolutePath, videoPlayAbsolutePath);
325 onClickListener_ = new ToggleBtnListener(toggleButton_, videoPlayer_, animator_, surfaceView_);
326
327 toggleButtonArea_ = new UIViewGroup();
328 toggleButtonArea_->SetPosition(0, 0, TOGGLE_BUTTON_OFFSET_X + TOGGLE_BUTTON_WIDTH, STATUS_BAR_GROUP_HEIGHT);
329 toggleButtonArea_->SetTouchable(true);
330 toggleButtonArea_->SetOnClickListener(onClickListener_);
331 toggleButtonArea_->Add(toggleButton_);
332
333 animatorGroup_->Add(toggleButtonArea_);
334 }
335
OnStart(const Want &want)336 void PlayerAbilitySlice::OnStart(const Want &want)
337 {
338 printf("@@@@@ PlayerAbilitySlice::OnStart\n");
339 AbilitySlice::OnStart(want);
340
341 SetUpRootView();
342 const char* pathHeader = GetSrcPath();
343 SetUpVideoPlayer(want);
344
345 videoPlayer_->adapter->Prepare();
346
347 if (!SetUpSurfaceView()) {
348 return;
349 }
350 SetUpBackArea(pathHeader);
351 SetUpAnimatorGroup(pathHeader);
352
353 SetUIContent(rootView_);
354
355 videoPlayer_->adapter->Play();
356 animator_->SetToggleButton(toggleButton_);
357 animator_->SetToggleBtnListener(onClickListener_);
358 animator_->Start();
359
360 printf("## @@@@@ PlayerAbilitySlice::OnStart | end \n");
361 }
362
OnInactive()363 void PlayerAbilitySlice::OnInactive()
364 {
365 printf("PlayerAbilitySlice::OnInactive\n");
366 AbilitySlice::OnInactive();
367 }
368
OnActive(const Want &want)369 void PlayerAbilitySlice::OnActive(const Want &want)
370 {
371 printf("PlayerAbilitySlice::OnActive\n");
372 AbilitySlice::OnActive(want);
373 }
374
OnBackground()375 void PlayerAbilitySlice::OnBackground()
376 {
377 printf("PlayerAbilitySlice::OnBackground\n");
378 AbilitySlice::OnBackground();
379 }
380
OnStop()381 void PlayerAbilitySlice::OnStop()
382 {
383 if (animator_ != nullptr) {
384 animator_->Stop();
385 delete animator_;
386 animator_ = nullptr;
387 }
388
389 if (videoPlayer_ != nullptr && videoPlayer_->adapter.get() != nullptr) {
390 videoPlayer_->adapter->Stop();
391 videoPlayer_->adapter->Reset();
392 delete videoPlayer_;
393 videoPlayer_ = nullptr;
394 }
395 Clear();
396 printf("PlayerAbilitySlice::OnStop\n");
397 AbilitySlice::OnStop();
398 }
399
Callback(UIView* view)400 void SliderAnimator::Callback(UIView* view)
401 {
402 if (needRefreshPlayer_) {
403 videoPlayer_->adapter->Stop();
404 videoPlayer_->adapter->Reset();
405
406 videoPlayer_->adapter = PlayerAbilitySlice::CreatePlayer();
407 std::string uri(videoPlayer_->filePath);
408 std::map<std::string, std::string> header;
409 Source source(uri, header);
410 videoPlayer_->adapter->SetSource(source);
411 videoPlayer_->adapter->Prepare();
412 videoPlayer_->adapter->SetVideoSurface(surfaceView_->GetSurface());
413 videoPlayer_->adapter->Play();
414 needRefreshPlayer_ = false;
415 }
416
417 int64_t currentTime = 0;
418 videoPlayer_->adapter->GetCurrentTime(currentTime);
419 int64_t currentSecond = currentTime / 1000; // 1000: 1s = 1000ms
420
421 char time[6]; // 6: length of time label
422 sprintf_s(time, sizeof(time), "%02lld:%02lld", currentSecond / 60, currentSecond % 60); // 60: 1minute = 60s
423 timeLabel_->SetText(time);
424 timeLabel_->Invalidate();
425
426 int64_t curPosition = currentTime * slider_->GetRangeMax() / duration_;
427 slider_->SetValue(curPosition);
428 slider_->Invalidate();
429
430 if (currentTime >= duration_) {
431 listener_->SetCompleteFlag(true);
432 toggleButton_->SetState(false);
433 needRefreshPlayer_ = true;
434 Stop();
435 }
436 }
437
OnClick(UIView &view, const ClickEvent& event)438 bool ToggleBtnListener::OnClick(UIView &view, const ClickEvent& event)
439 {
440 button_->OnClickEvent(event);
441 if (completeFlag_) {
442 animator_->Start();
443 button_->Invalidate();
444 completeFlag_ = false;
445 return true;
446 }
447
448 if (button_->GetState()) {
449 videoPlayer_->adapter->Play();
450 animator_->Resume();
451 printf("ToggleBtnListener::OnClick | play\n");
452 } else {
453 videoPlayer_->adapter->Pause();
454 animator_->Pause();
455 printf("ToggleBtnListener::OnClick | pause\n");
456 }
457 button_->Invalidate();
458 return true;
459 }
460 }
461