383 lines
12 KiB
JavaScript
383 lines
12 KiB
JavaScript
|
/* eslint-disable no-param-reassign */
|
|||
|
import moduleHelper from '../module-helper';
|
|||
|
import { isSupportPlayBackRate } from '../../check-version';
|
|||
|
import { audios, localAudioMap, downloadingAudioMap, innerAudioVolume, WEBAudio } from './store';
|
|||
|
import { createInnerAudio, destroyInnerAudio, printErrMsg } from './utils';
|
|||
|
import { IGNORE_ERROR_MSG, INNER_AUDIO_UNDEFINED_MSG } from './const';
|
|||
|
const funs = {
|
|||
|
|
|||
|
getFullUrl(v) {
|
|||
|
if (!/^https?:\/\//.test(v) && !/^wxfile:\/\//.test(v)) {
|
|||
|
const cdnPath = GameGlobal.manager.assetPath;
|
|||
|
v = `${cdnPath.replace(/\/$/, '')}/${v.replace(/^\//, '').replace(/^Assets\//, '')}`;
|
|||
|
}
|
|||
|
return v;
|
|||
|
},
|
|||
|
|
|||
|
downloadAudios(paths) {
|
|||
|
const list = paths.split(',');
|
|||
|
return Promise.all(list.map((v) => {
|
|||
|
const src = funs.getFullUrl(v);
|
|||
|
return new Promise((resolve, reject) => {
|
|||
|
|
|||
|
if (!downloadingAudioMap[src]) {
|
|||
|
downloadingAudioMap[src] = [
|
|||
|
{
|
|||
|
resolve,
|
|||
|
reject,
|
|||
|
},
|
|||
|
];
|
|||
|
if (funs.checkLocalFile(src)) {
|
|||
|
funs.handleDownloadEnd(src, true);
|
|||
|
}
|
|||
|
else if (!GameGlobal.unityNamespace.isCacheableFile(src)) {
|
|||
|
|
|||
|
wx.downloadFile({
|
|||
|
url: src,
|
|||
|
success(res) {
|
|||
|
if (res.statusCode === 200 && res.tempFilePath) {
|
|||
|
localAudioMap[src] = res.tempFilePath;
|
|||
|
funs.handleDownloadEnd(src, true);
|
|||
|
}
|
|||
|
else {
|
|||
|
funs.handleDownloadEnd(src, false);
|
|||
|
}
|
|||
|
},
|
|||
|
fail(e) {
|
|||
|
funs.handleDownloadEnd(src, false);
|
|||
|
printErrMsg(e);
|
|||
|
},
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
const xmlhttp = new GameGlobal.unityNamespace.UnityLoader.UnityCache.XMLHttpRequest();
|
|||
|
xmlhttp.open('GET', src, true);
|
|||
|
xmlhttp.responseType = 'arraybuffer';
|
|||
|
xmlhttp.onsave = () => {
|
|||
|
localAudioMap[src] = GameGlobal.manager.getCachePath(src);
|
|||
|
funs.handleDownloadEnd(src, true);
|
|||
|
};
|
|||
|
xmlhttp.onsavefail = () => {
|
|||
|
funs.handleDownloadEnd(src, false);
|
|||
|
};
|
|||
|
xmlhttp.onerror = () => {
|
|||
|
funs.handleDownloadEnd(src, false);
|
|||
|
};
|
|||
|
xmlhttp.send();
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
downloadingAudioMap[src].push({
|
|||
|
resolve,
|
|||
|
reject,
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
}));
|
|||
|
},
|
|||
|
|
|||
|
handleDownloadEnd(src, succeeded) {
|
|||
|
if (!downloadingAudioMap[src]) {
|
|||
|
return;
|
|||
|
}
|
|||
|
while (downloadingAudioMap[src] && downloadingAudioMap[src].length > 0) {
|
|||
|
const item = downloadingAudioMap[src].shift();
|
|||
|
if (!succeeded) {
|
|||
|
item?.reject();
|
|||
|
}
|
|||
|
else {
|
|||
|
item?.resolve('');
|
|||
|
}
|
|||
|
}
|
|||
|
delete downloadingAudioMap[src];
|
|||
|
},
|
|||
|
// 是否存在本地文件
|
|||
|
checkLocalFile(src) {
|
|||
|
if (localAudioMap[src]) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
const path = GameGlobal.manager.getCachePath(src);
|
|||
|
if (path) {
|
|||
|
localAudioMap[src] = path;
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
},
|
|||
|
// 设置路径
|
|||
|
setAudioSrc(audio, getSrc) {
|
|||
|
return new Promise((resolve, reject) => {
|
|||
|
const src = funs.getFullUrl(getSrc);
|
|||
|
// 设置原始路径,后面用此路径作为key值
|
|||
|
audio.isLoading = src;
|
|||
|
if (funs.checkLocalFile(src)) {
|
|||
|
audio.src = localAudioMap[src];
|
|||
|
delete audio.isLoading;
|
|||
|
funs.handleDownloadEnd(src, true);
|
|||
|
resolve(localAudioMap[src]);
|
|||
|
}
|
|||
|
else if (audio.needDownload) {
|
|||
|
funs
|
|||
|
.downloadAudios(src)
|
|||
|
.then(() => {
|
|||
|
if (audio) {
|
|||
|
audio.src = localAudioMap[src];
|
|||
|
delete audio.isLoading;
|
|||
|
resolve(localAudioMap[src]);
|
|||
|
}
|
|||
|
else {
|
|||
|
console.warn('资源已被删除:', src);
|
|||
|
reject({
|
|||
|
errCode: -1,
|
|||
|
errMsg: '资源已被删除',
|
|||
|
});
|
|||
|
}
|
|||
|
})
|
|||
|
.catch(() => {
|
|||
|
console.warn('资源下载失败:', src);
|
|||
|
if (audio) {
|
|||
|
audio.src = src;
|
|||
|
delete audio.isLoading;
|
|||
|
}
|
|||
|
reject({
|
|||
|
errCode: -1,
|
|||
|
errMsg: '资源下载失败',
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
// 不推荐这样处理,建议优先下载再使用,除非是需要立即播放的长音频文件或一次性播放音频
|
|||
|
// console.warn('建议优先下载再使用:', src);
|
|||
|
audio.src = src;
|
|||
|
delete audio.isLoading;
|
|||
|
resolve(src);
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
};
|
|||
|
function checkHasAudio(id) {
|
|||
|
if (audios[id]) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
console.error(INNER_AUDIO_UNDEFINED_MSG, id);
|
|||
|
return false;
|
|||
|
}
|
|||
|
export default {
|
|||
|
// 创建audio对象
|
|||
|
WXCreateInnerAudioContext(src, loop, startTime, autoplay, volume, playbackRate, needDownload) {
|
|||
|
const { audio: getAudio, id } = createInnerAudio();
|
|||
|
getAudio.needDownload = needDownload;
|
|||
|
if (src) {
|
|||
|
// 设置原始src
|
|||
|
funs.setAudioSrc(getAudio, src).catch((e) => {
|
|||
|
moduleHelper.send('OnAudioCallback', JSON.stringify({
|
|||
|
callbackId: id,
|
|||
|
errMsg: 'onError',
|
|||
|
result: JSON.stringify(e),
|
|||
|
}));
|
|||
|
});
|
|||
|
}
|
|||
|
if (loop) {
|
|||
|
getAudio.loop = true;
|
|||
|
}
|
|||
|
if (autoplay) {
|
|||
|
getAudio.autoplay = true;
|
|||
|
}
|
|||
|
if (typeof startTime === 'undefined') {
|
|||
|
startTime = 0;
|
|||
|
}
|
|||
|
if (startTime > 0) {
|
|||
|
getAudio.startTime = +startTime.toFixed(2);
|
|||
|
}
|
|||
|
|
|||
|
let volumeValue;
|
|||
|
if (typeof volume === 'undefined') {
|
|||
|
volumeValue = 1;
|
|||
|
}
|
|||
|
else {
|
|||
|
volumeValue = +volume.toFixed(2);
|
|||
|
}
|
|||
|
innerAudioVolume.set(getAudio, volumeValue);
|
|||
|
if (WEBAudio.isMute) {
|
|||
|
volumeValue = 0;
|
|||
|
}
|
|||
|
if (volumeValue !== 1) {
|
|||
|
getAudio.volume = volumeValue;
|
|||
|
}
|
|||
|
|
|||
|
if (!isSupportPlayBackRate) {
|
|||
|
playbackRate = 1;
|
|||
|
}
|
|||
|
if (typeof playbackRate !== 'undefined' && playbackRate !== 1) {
|
|||
|
getAudio.playbackRate = +playbackRate.toFixed(2);
|
|||
|
}
|
|||
|
return id;
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextSetBool(id, k, v) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
audios[id][k] = Boolean(+v);
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextSetString(id, k, v) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (k === 'src') {
|
|||
|
funs.setAudioSrc(audios[id], v);
|
|||
|
}
|
|||
|
else if (k === 'needDownload') {
|
|||
|
audios[id].needDownload = !!v;
|
|||
|
}
|
|||
|
else {
|
|||
|
audios[id][k] = v;
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextSetFloat(id, k, v) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
let value = +v.toFixed(2);
|
|||
|
if (k === 'volume') {
|
|||
|
innerAudioVolume.set(audios[id], value);
|
|||
|
if (WEBAudio.isMute) {
|
|||
|
value = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
audios[id][k] = value;
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextGetFloat(id, k) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
return audios[id][k];
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextGetBool(id, k) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
return audios[id][k];
|
|||
|
},
|
|||
|
WXInnerAudioContextPlay(id) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
const url = audios[id].isLoading;
|
|||
|
if (url) {
|
|||
|
if (downloadingAudioMap[url]) {
|
|||
|
downloadingAudioMap[url].push({
|
|||
|
resolve: () => {
|
|||
|
if (typeof audios[id] !== 'undefined') {
|
|||
|
audios[id].play();
|
|||
|
}
|
|||
|
},
|
|||
|
reject: () => { },
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
audios[id].src = url;
|
|||
|
audios[id].play();
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
audios[id].play();
|
|||
|
}
|
|||
|
},
|
|||
|
WXInnerAudioContextPause(id) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
audios[id].pause();
|
|||
|
},
|
|||
|
WXInnerAudioContextStop(id) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
audios[id].stop();
|
|||
|
},
|
|||
|
WXInnerAudioContextDestroy(id) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
destroyInnerAudio(id, false);
|
|||
|
},
|
|||
|
WXInnerAudioContextSeek(id, position) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
audios[id].seek(+position.toFixed(3));
|
|||
|
},
|
|||
|
|
|||
|
WXInnerAudioContextAddListener(id, key) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (key === 'onCanplay') {
|
|||
|
audios[id][key](() => {
|
|||
|
|
|||
|
// @ts-ignore
|
|||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|||
|
const { duration, buffered, referrerPolicy, volume } = audios[id];
|
|||
|
setTimeout(() => {
|
|||
|
moduleHelper.send('OnAudioCallback', JSON.stringify({
|
|||
|
callbackId: id,
|
|||
|
errMsg: key,
|
|||
|
}));
|
|||
|
}, 0);
|
|||
|
});
|
|||
|
}
|
|||
|
else if (key === 'onError') {
|
|||
|
audios[id][key]((e) => {
|
|||
|
if (key === 'onError') {
|
|||
|
console.error(e);
|
|||
|
|
|||
|
if (e.errMsg && e.errMsg.indexOf(IGNORE_ERROR_MSG) > -1) {
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
moduleHelper.send('OnAudioCallback', JSON.stringify({
|
|||
|
callbackId: id,
|
|||
|
errMsg: key,
|
|||
|
result: JSON.stringify(e),
|
|||
|
}));
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
audios[id][key](() => {
|
|||
|
moduleHelper.send('OnAudioCallback', JSON.stringify({
|
|||
|
callbackId: id,
|
|||
|
errMsg: key,
|
|||
|
}));
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
WXInnerAudioContextRemoveListener(id, key) {
|
|||
|
if (!checkHasAudio(id)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
audios[id][key]();
|
|||
|
},
|
|||
|
WXPreDownloadAudios(paths, id) {
|
|||
|
funs
|
|||
|
.downloadAudios(paths)
|
|||
|
.then(() => {
|
|||
|
moduleHelper.send('WXPreDownloadAudiosCallback', JSON.stringify({
|
|||
|
callbackId: id.toString(),
|
|||
|
errMsg: '0',
|
|||
|
}));
|
|||
|
})
|
|||
|
.catch(() => {
|
|||
|
moduleHelper.send('WXPreDownloadAudiosCallback', JSON.stringify({
|
|||
|
callbackId: id.toString(),
|
|||
|
errMsg: '1',
|
|||
|
}));
|
|||
|
});
|
|||
|
},
|
|||
|
};
|