1/* 2 * Copyright (c) 2022 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 */ 15import mediaLibrary from '@ohos.multimedia.mediaLibrary' 16import router from '@ohos.router' 17import MediaUtils from '../model/MediaUtils' 18import Logger from '../model/Logger' 19import PlayButton from '../common/PlayButton' 20import PlayTitle from '../common/PlayTitle' 21import PlayAbility from '../PlayAbility/PlayAbility' 22import VideoPlayerUtils from '../model/VideoPlayerUtils' 23import { getTimeString } from '../model/TimeUtils' 24 25const TAG: string = 'Play' 26 27@Entry 28@Component 29struct Play { 30 @StorageLink('fileId') fileId: number = 0 31 private fileAsset: mediaLibrary.FileAsset = undefined 32 private fd: number = undefined 33 private intervalId: number = undefined 34 private mXComponentController: XComponentController = new XComponentController() 35 private videoPlayer: VideoPlayerUtils = new VideoPlayerUtils() 36 private surfaceId: number = 0 37 private mediaUtil: MediaUtils = new MediaUtils(getContext(this) as any) 38 @State currentTime: number = 0 39 @State displayName: string = '' 40 @State isShowMenu: boolean = false 41 @State @Watch('playStateChange') isPlaying: boolean = false 42 @State ratio: number = 1.0 43 44 aboutToAppear() { 45 Logger.info(TAG, `aboutToAppear, fileId =${this.fileId }`) 46 this.surfaceId = this.mXComponentController.getXComponentSurfaceId() 47 this.videoPlayer.setFinishCallBack(() => { 48 this.isPlaying = false 49 this.currentTime = 0 50 }) 51 this.intervalId = setInterval(() => { 52 if (this.isPlaying) { 53 this.currentTime = this.videoPlayer.getCurrentTime() 54 } 55 }, 1000) 56 } 57 58 async playVideo() { 59 Logger.info(TAG, 'playVideo') 60 let context = getContext(this) as any 61 await context.requestPermissionsFromUser(['ohos.permission.READ_MEDIA']) 62 this.fileAsset = await this.mediaUtil.queryFile(this.fileId) 63 this.displayName = this.fileAsset.displayName 64 this.ratio = this.fileAsset.width / this.fileAsset.height 65 this.mXComponentController.setXComponentSurfaceSize({ 66 surfaceWidth: this.fileAsset.width, 67 surfaceHeight: this.fileAsset.height 68 }) 69 this.surfaceId = this.mXComponentController.getXComponentSurfaceId() 70 Logger.info(TAG, `onLoad,surfaceId =${this.surfaceId}`) 71 this.fd = await this.fileAsset.open('Rw') 72 let fdPath = 'fd://' + this.fd 73 await this.videoPlayer.initVideoPlayer(fdPath, this.surfaceId) 74 this.isPlaying = true 75 } 76 77 playStateChange() { 78 if (this.isPlaying) { 79 this.videoPlayer.play() 80 Logger.info(TAG, 'play') 81 } else { 82 this.videoPlayer.pause() 83 Logger.info(TAG, 'pause') 84 } 85 } 86 87 handleBack = () => { 88 router.back() 89 this.clearVideoPlayer() 90 } 91 92 build() { 93 Row() { 94 Stack({ alignContent: Alignment.Center }) { 95 if (this.isShowMenu) { 96 Column() { 97 PlayTitle({ title: this.displayName, handleBack: this.handleBack }) 98 Row() { 99 PlayButton({ isPlaying: $isPlaying }) 100 } 101 .margin({ top: '40%' }) 102 103 Blank() 104 Row() { 105 Text(getTimeString(this.currentTime)) 106 .fontSize(25) 107 .fontColor(Color.White) 108 Blank() 109 Text(this.fileAsset ? getTimeString(this.fileAsset.duration) : '00:00') 110 .fontSize(25) 111 .fontColor(Color.White) 112 } 113 .width('95%') 114 115 Slider({ value: this.fileAsset ? this.currentTime / this.fileAsset.duration * 100 : 0 }) 116 .width('92%') 117 .selectedColor(Color.White) 118 .onChange((value: number) => { 119 Logger.info(TAG, 'seek time change') 120 this.currentTime = this.fileAsset.duration * value / 100 121 this.videoPlayer.seek(this.currentTime) 122 }) 123 } 124 .height('100%') 125 .zIndex(2) 126 } 127 Row() { 128 XComponent({ 129 id: 'componentId', 130 type: 'surface', 131 controller: this.mXComponentController 132 }) 133 .onLoad(() => { 134 Logger.info(TAG, 'onLoad is called') 135 this.playVideo() 136 }) 137 .width('100%') 138 .aspectRatio(this.ratio) 139 } 140 .height('100%') 141 .width('100%') 142 .justifyContent(FlexAlign.Center) 143 } 144 .width('100%') 145 .height('100%') 146 .backgroundColor(Color.Black) 147 .onClick(() => { 148 this.isShowMenu = !this.isShowMenu 149 }) 150 } 151 .height('100%') 152 } 153 154 onPageHide() { 155 this.isPlaying = false 156 this.clearVideoPlayer() 157 } 158 159 clearVideoPlayer() { 160 clearInterval(this.intervalId) 161 this.videoPlayer.stop() 162 this.videoPlayer.release() 163 this.fileAsset.close(this.fd) 164 } 165}