WDPlayerController.ets 8.67 KB
import media from '@ohos.multimedia.media';
import prompt from '@ohos.promptAction';
import { Logger } from '../utils/Logger';
import { PlayerConstants, AVPlayerStatus, Events } from '../constants/PlayerConstants';

@Observed
export class WDPlayerController {
  private initPromise: Promise<void>;
  private avPlayer?: media.AVPlayer;
  private duration: number = 0;
  private status: number = PlayerConstants.STATUS_IDLE;
  private loop: boolean = false;
  private url: string = '';
  private surfaceId: string = ''; // 若播放音频,无需设置surfaceId
  private playSpeed: number = 1;
  private seekTime: number = 0;
  private positionY: number = 0;
  private startTime: number = 0;
  public onVideoSizeChange?: (width: number, height: number) => void;
  public onTimeUpdate?: (position: number, duration: number) => void;
  public onVolumeUpdate?: (volume: number) => void;
  public continue?: () => void;

  constructor() {
    Logger.error("初始化")
    this.initPromise = this.createAVPlayer();
  }

  /**
   * 创建 videoPlayer对象
   */
  private createAVPlayer(): Promise<void> {
    return new Promise((resolve, reject) => {
      Logger.error("开始创建")
      media.createAVPlayer().then((avPlayer) => {
        if (avPlayer) {
          Logger.error("创建完成1")
          this.avPlayer = avPlayer;
          this.bindState();
          resolve();
        } else {
          Logger.error("创建完成0")
          Logger.error('[PlayVideoModel] createAvPlayer fail!');
          reject();
        }
      });
    });
  }

  /**
   * AVPlayer 绑定事件.
   */
  private bindState() {
    this.avPlayer?.on(Events.STATE_CHANGE, async (state) => {
      if (this.avPlayer == null) {
        return
      }
      switch (state) {
        case AVPlayerStatus.IDLE:
          this.resetProgress();
          this.avPlayer.url = this.url;
          break;
        case AVPlayerStatus.INITIALIZED:
          if (this.surfaceId) {
            this.avPlayer.surfaceId = this.surfaceId;
          }

          this.avPlayer?.prepare();
          break;
        case AVPlayerStatus.PREPARED:
          this.avPlayer.videoScaleType = 0;
          if (this.startTime) {
            this.setSeekTime(this.startTime, SliderChangeMode.Begin);
          }
          this.avPlayer.play();
          this.duration = this.avPlayer.duration;
          break;
        case AVPlayerStatus.PLAYING:
          this.setBright();
          this.status = PlayerConstants.STATUS_START;
          this.watchStatus();
          break;
        case AVPlayerStatus.PAUSED:
          this.status = PlayerConstants.STATUS_PAUSE;
          this.watchStatus();
          break;
        case AVPlayerStatus.COMPLETED:
        // this.titleThis.playSpeed = 1;
          if (this.continue) {
            this.continue();
          } else {
            this.duration = 0;
            this.url = this.avPlayer.url || '';
            this.avPlayer.reset();
          }
          break;
        case AVPlayerStatus.RELEASED:
          this.avPlayer.release();
          this.status = PlayerConstants.STATUS_STOP;
          this.watchStatus();
          Logger.info('[PlayVideoModel] state released called')
          break;
        default:
          Logger.info('[PlayVideoModel] unKnown state: ' + state);
          break;
      }
    });
    this.avPlayer?.on(Events.TIME_UPDATE, (time: number) => {
      this.initProgress(time);
    });
    this.avPlayer?.on(Events.ERROR, (error) => {
      this.playError(error.message);
    })
    this.avPlayer?.on(Events.VIDEO_SIZE_CHANGE, (width: number, height: number) => {
      if (this.onVideoSizeChange) {
        this.onVideoSizeChange(width, height);
      }
    })
  }

  public setXComponentController(controller: XComponentController) {
    this.surfaceId = controller.getXComponentSurfaceId()
  }

  async firstPlay(url: string) {
    this.url = url;
    if (this.avPlayer == null) {
      Logger.error("等待")
      await this.initPromise;
    } else {
      if (this.avPlayer.state != AVPlayerStatus.IDLE) {
        await this.avPlayer.stop()
        await this.avPlayer.release()
        this.initPromise = this.createAVPlayer();
        await this.initPromise;
      }
    }
    if (this.avPlayer == null) {
      return
    }
    Logger.error("开始播放")
    this.avPlayer.url = this.url;
  }

  async release() {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    this.avPlayer.release();
  }

  async pause() {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    this.avPlayer.pause();
  }

  async stop() {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    this.avPlayer.stop();
  }

  async setLoop() {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    this.loop = !this.loop;
  }

  async setSpeed(playSpeed: number) {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    if (PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer.state) === -1) {
      return;
    }
    this.playSpeed = playSpeed;
    this.avPlayer.setSpeed(this.playSpeed);
  }

  async switchPlayOrPause() {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    if (this.status === PlayerConstants.STATUS_START) {
      this.avPlayer.pause();
    } else {
      this.avPlayer.play();
    }
  }

  async setSeekTime(value: number, mode: SliderChangeMode) {
    if (this.avPlayer == null) {
      await this.initPromise;
    }
    if (this.avPlayer == null) {
      return
    }
    if (mode == SliderChangeMode.Begin) {
      this.seekTime = value * 1000;
      this.avPlayer.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC);
    }
    if (mode === SliderChangeMode.Moving) {
      // this.progressThis.progressVal = value;
      // this.progressThis.currentTime = DateFormatUtil.secondToTime(Math.floor(value * this.duration /
      // 100 / 1000));
    }
    if (mode === SliderChangeMode.End) {
      this.seekTime = value * this.duration / 100;
      this.avPlayer.seek(this.seekTime, media.SeekMode.SEEK_PREV_SYNC);
    }
  }

  setBright() {
    // globalThis.windowClass.setWindowBrightness(this.playerThis.bright)
  }

  getStatus() {
    return this.status;
  }

  initProgress(time: number) {
    let nowSeconds = Math.floor(time / 1000);
    let totalSeconds = Math.floor(this.duration / 1000);
    if (this.onTimeUpdate) {
      this.onTimeUpdate(nowSeconds, totalSeconds);
    }
  }

  resetProgress() {
    this.seekTime = 0;
    // this.progressThis.currentTime = '00:00';
    // this.progressThis.progressVal = 0;
  }

  onVolumeActionStart(event: GestureEvent) {
    this.positionY = event.offsetY;
  }

  onBrightActionStart(event: GestureEvent) {
    this.positionY = event.offsetY;
  }

  volume: number = 1

  onVolumeActionUpdate(event: GestureEvent) {
    if (!this.avPlayer) {
      return
    }
    if (PlayerConstants.OPERATE_STATE.indexOf(this.avPlayer.state) === -1) {
      return;
    }
    let changeVolume = (event.offsetY - this.positionY) / 300;
    let currentVolume = this.volume - changeVolume;
    if (currentVolume > 1) {
      currentVolume = 1;
    }
    if (currentVolume <= 0) {
      currentVolume = 0;
    }
    this.volume = currentVolume;
    this.avPlayer?.setVolume(this.volume);
    this.positionY = event.offsetY;
    if (this.onVolumeUpdate) {
      this.onVolumeUpdate(this.volume);
    }
    console.log("volume : " + this.volume)
  }

  onBrightActionUpdate(event: GestureEvent) {
    // if (!this.playerThis.volumeShow) {
    //   this.playerThis.brightShow = true;
    //   let changeBright = (this.positionY - event.offsetY) / globalThis.screenHeight;
    //   let currentBright = this.playerThis.bright + changeBright;
    //   let brightMinFlag = currentBright <= 0;
    //   let brightMaxFlag = currentBright > 1;
    //   this.playerThis.bright = brightMinFlag ? 0 :
    //     (brightMaxFlag ? 1 : currentBright);
    //   this.setBright();
    //   this.positionY = event.offsetY;
    // }
  }

  onActionEnd() {
    setTimeout(() => {
      this.positionY = 0;
    }, 200);
  }

  watchStatus() {
    // if (this.status === PlayConstants.STATUS_START) {
    //   globalThis.windowClass.setWindowKeepScreenOn(true);
    // } else {
    //   globalThis.windowClass.setWindowKeepScreenOn(false);
    // }
  }

  playError(msg?: string) {
    prompt.showToast({
      duration: 3000,
      message: msg ? msg : "请检查地址输入正确且网络正常"
    });
  }

  setStartTime(time?: number) {
    this.startTime = time ?? 0;
  }
}