audio.js 3.1 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
import {
  getRealPath
} from '../util'

import {
  publish
} from '../../bridge'

let audios = {}

const evts = ['play', 'canplay', 'ended', 'stop', 'waiting', 'seeking', 'seeked', 'pause']

const publishAudioStateChange = (state, res = {}) => publish('onAudioStateChange', Object.assign({
  state
}, res))

const initStateChage = audioId => {
  const audio = audios[audioId]
  if (!audio) {
    return
  }
  if (!audio.initStateChage) {
    audio.initStateChage = true

    audio.addEventListener('error', error => {
      publishAudioStateChange('error', {
        audioId,
        errMsg: 'MediaError',
        errCode: error.code
      })
    })

    evts.forEach(event => {
      audio.addEventListener(event, () => {
        // 添加 isStopped 属性是为了解决 安卓设备停止播放后获取播放进度不正确的问题
        if (event === 'play') {
          audio.isStopped = false
        } else if (event === 'stop') {
          audio.isStopped = true
        }
        publishAudioStateChange(event, {
          audioId
        })
      })
    })
  }
}

export function createAudioInstance () {
  const audioId = `${Date.now()}${Math.random()}`
  const audio = audios[audioId] = plus.audio.createPlayer('')
  audio.volume = 1
  audio.startTime = 0
  return {
    errMsg: 'createAudioInstance:ok',
    audioId
  }
}

export function destroyAudioInstance ({
  audioId
}) {
  if (audios[audioId]) {
    audios[audioId].close()
    delete audios[audioId]
  }
  return {
    errMsg: 'destroyAudioInstance:ok',
    audioId
  }
}

export function setAudioState ({
  audioId,
  src,
  startTime,
  autoplay = false,
  loop = false,
  obeyMuteSwitch,
  volume
}) {
  const audio = audios[audioId]
  if (audio) {
    let style = {
      loop,
      autoplay
    }
    if (src) {
      audio.src = style.src = getRealPath(src)
    }
    if (startTime) {
      audio.startTime = style.startTime = startTime
    }
    if (typeof volume === 'number') {
      audio.volume = style.volume = volume
    }
    audio.setStyles(style)
    initStateChage(audioId)
  }
  return {
    errMsg: 'setAudioState:ok'
  }
}

export function getAudioState ({
  audioId
}) {
  const audio = audios[audioId]
  if (!audio) {
    return {
      errMsg: 'getAudioState:fail'
    }
  }
  let {
    src,
    startTime,
    volume
  } = audio

  return {
    errMsg: 'getAudioState:ok',
    duration: 1e3 * (audio.getDuration() || 0),
    currentTime: audio.isStopped ? 0 : 1e3 * audio.getPosition(),
    paused: audio.isPaused,
    src,
    volume,
    startTime: 1e3 * startTime,
    buffered: 1e3 * audio.getBuffered()
  }
}

export function operateAudio ({
  operationType,
  audioId,
  currentTime
}) {
  const audio = audios[audioId]
  const operationTypes = ['play', 'pause', 'stop']
  if (operationTypes.indexOf(operationType) >= 0) {
    audio[operationType === operationTypes[0] && audio.isPaused ? 'resume' : operationType]()
  } else if (operationType === 'seek') {
    audio.seekTo(currentTime / 1e3)
  }
  return {
    errMsg: 'operateAudio:ok'
  }
}