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 prompt from '@ohos.prompt' 17import router from '@ohos.router' 18import Logger from '../model/Logger' 19import MediaUtils from '../model/MediaUtils' 20import NextVideo from '../common/NextVideo' 21import PlayButton from '../common/PlayButton' 22import PlayTitle from '../common/PlayTitle' 23import PreVideo from '../common/PreVideo' 24import VideoPlayerUtils from '../model/VideoPlayerUtils' 25import { getTimeString } from '../model/TimeUtils' 26 27const TAG: string = 'Player' 28 29@Entry 30@Component 31struct Player { 32 private currentIndex: number = -1 33 private fileAsset: mediaLibrary.FileAsset = undefined 34 private fileId: number = router.getParams()['fileId'] 35 private fd: number = undefined 36 private intervalId: number = undefined 37 private mediaList: Array<mediaLibrary.FileAsset> = [] 38 private videoPlayer: VideoPlayerUtils = new VideoPlayerUtils() 39 private mXComponentController: XComponentController = new XComponentController() 40 private surfaceId: number = 0 41 private mediaUtil: MediaUtils = new MediaUtils(getContext(this) as any) 42 @State currentTime: number = 0 43 @State displayName: string = router.getParams()['displayName'] 44 @State isShowMenu: boolean = false 45 @State @Watch('playStateChange') isPlaying: boolean = false 46 @State ratio: number = 1.0 47 48 build() { 49 Stack({ alignContent: Alignment.Center }) { 50 if (this.isShowMenu) { 51 Column() { 52 PlayTitle({ title: this.displayName, handleBack: this.handleBack }) 53 Row() { 54 PreVideo({ handleClick: this.handlePrevClick }) 55 PlayButton({ isPlaying: $isPlaying }) 56 NextVideo({ handleClick: this.handleNextClick }) 57 } 58 .margin({ top: '40%' }) 59 60 Blank() 61 Row() { 62 Text(getTimeString(this.currentTime)) 63 .fontSize(25) 64 .fontColor(Color.White) 65 Blank() 66 Text(this.fileAsset ? getTimeString(this.fileAsset.duration) : '00:00') 67 .fontSize(25) 68 .fontColor(Color.White) 69 } 70 .width('95%') 71 72 Slider({ value: this.fileAsset ? this.currentTime / this.fileAsset.duration * 100 : 0 }) 73 .width('92%') 74 .selectedColor(Color.White) 75 .onChange((value: number) => { 76 Logger.info(TAG, 'seek time change') 77 this.currentTime = this.fileAsset.duration * value / 100 78 this.videoPlayer.seek(this.currentTime) 79 }) 80 } 81 .height('100%') 82 .zIndex(2) 83 } 84 Row() { 85 XComponent({ 86 id: 'componentId', 87 type: 'surface', 88 controller: this.mXComponentController 89 }) 90 .onLoad(() => { 91 Logger.info(TAG, 'onLoad is called') 92 this.playVideo() 93 }) 94 .width('100%') 95 .aspectRatio(this.ratio) 96 } 97 .height('100%') 98 .width('100%') 99 .justifyContent(FlexAlign.Center) 100 } 101 .width('100%') 102 .height('100%') 103 .backgroundColor(Color.Black) 104 .onClick(() => { 105 this.isShowMenu = !this.isShowMenu 106 }) 107 } 108 109 aboutToAppear() { 110 this.surfaceId = this.mXComponentController.getXComponentSurfaceId() 111 Logger.info(TAG, `aboutToAppear,surfaceId=${this.surfaceId}`) 112 Logger.info(TAG, `fileId=${this.fileId},displayName=${this.displayName}`) 113 this.videoPlayer.setFinishCallBack(() => { 114 this.isPlaying = false 115 this.currentTime = 0 116 }) 117 this.intervalId = setInterval(() => { 118 if (this.isPlaying) { 119 this.currentTime = this.videoPlayer.getCurrentTime() 120 } 121 }, 1000) 122 } 123 124 async getMediaList() { 125 Logger.info(TAG, `getMediaList,id=${this.fileId}`) 126 this.mediaList = await this.mediaUtil.getFileAssetsFromType(mediaLibrary.MediaType.VIDEO) 127 this.mediaList.forEach((file, index) => { 128 Logger.info(TAG, `file.id=${file.id}`) 129 if (file.id === this.fileId) { 130 this.fileAsset = file 131 this.currentIndex = index 132 } 133 }) 134 } 135 136 playStateChange() { 137 if (this.isPlaying) { 138 this.videoPlayer.play() 139 } else { 140 this.videoPlayer.pause() 141 } 142 } 143 144 handleBack = () => { 145 router.back() 146 this.clearVideoPlayer() 147 } 148 handlePrevClick = () => { 149 if (this.currentIndex > 0) { 150 this.currentIndex -= 1 151 this.resetVideo() 152 } else { 153 prompt.showToast({ message: '当前视频是第一个', duration: 1000 }) 154 } 155 } 156 handleNextClick = () => { 157 if (this.currentIndex < this.mediaList.length - 1) { 158 this.currentIndex += 1 159 this.resetVideo() 160 } else { 161 prompt.showToast({ message: '当前视频是最后一个', duration: 1000 }) 162 } 163 } 164 165 async resetVideo() { 166 await this.fileAsset.close(this.fd) 167 this.fileAsset = this.mediaList[this.currentIndex] 168 this.displayName = this.fileAsset.displayName 169 let fdPath = await this.prepareVideo() 170 await this.videoPlayer.reset(fdPath) 171 this.isPlaying = true 172 } 173 174 async prepareVideo() { 175 this.ratio = this.fileAsset.width / this.fileAsset.height 176 this.mXComponentController.setXComponentSurfaceSize({ 177 surfaceWidth: this.fileAsset.width, 178 surfaceHeight: this.fileAsset.height 179 }) 180 this.surfaceId = this.mXComponentController.getXComponentSurfaceId() 181 this.fd = await this.fileAsset.open('Rw') 182 Logger.info(TAG, `fd://' ${this.fd} `) 183 return 'fd://' + this.fd 184 } 185 186 async playVideo() { 187 Logger.info(TAG, 'playVideo') 188 try{ 189 await this.getMediaList() 190 let fdPath = await this.prepareVideo() 191 await this.videoPlayer.initVideoPlayer(fdPath, this.surfaceId) 192 this.isPlaying = true 193 }catch(error) { 194 Logger.info(TAG, `playVideo error ${JSON.stringify(error)}`) 195 } 196 } 197 198 onPageHide() { 199 this.clearVideoPlayer() 200 router.replace({ 201 url: 'pages/Index' 202 }) 203 } 204 205 clearVideoPlayer() { 206 clearInterval(this.intervalId) 207 if (this.videoPlayer) { 208 this.videoPlayer.stop() 209 this.videoPlayer.release() 210 } 211 if (this.fileAsset) { 212 this.fileAsset.close(this.fd) 213 } 214 } 215}