mami/src/mami.js/sound/sndpacks.js

198 lines
5.6 KiB
JavaScript

#include settings.js
#include sound/sndlibrary.js
const MamiSoundPack = function(name, isReadOnly, title, events) {
name = (name || '').toString();
isReadOnly = !!isReadOnly;
title = (title || '').toString();
events = events || new Map;
return {
getName: function() {
return name;
},
isReadOnly: function() {
return isReadOnly;
},
getTitle: function() {
return title;
},
setTitle: function(newTitle) {
if(isReadOnly)
throw 'Cannot edit read only sound pack.';
title = (newTitle || '').toString();
},
getEventNames: function() {
return Array.from(events.keys());
},
hasEventSound: function(eventName) {
return events.has(eventName);
},
getEventSound: function(eventName) {
if(!events.has(eventName))
throw 'event not registered';
return events.get(eventName);
},
setEventSound: function(eventName, soundName) {
events.set(
(eventName || '').toString(),
(soundName || '').toString()
);
},
removeEventSound: function(eventName) {
events.delete(eventName);
},
clearEventSounds: function() {
events.clear();
},
clone: function(newName, readOnly) {
return new MamiSoundPack(newName, readOnly, 'Clone of ' + title, new Map(events));
},
};
};
const MamiSoundPackPlayer = function(soundMgr, sndLibrary) {
const pub = {};
let pack = null;
pub.loadPack = function(packInfo) {
if(typeof pack !== 'object' && typeof pack.getEventSound !== 'function')
throw 'pack is not a valid soundpack';
pack = packInfo;
};
pub.unloadPack = function() {
pack = null;
buffers.clear();
};
pub.hasPack = function() {
return pack !== null;
};
const playSource = function(source, hasCallback, callback) {
if(hasCallback)
source.whenEnded(function() {
callback(true);
});
source.play();
};
const handlePlayError = function(ex, hasCallback, callback) {
console.error(ex);
if(hasCallback)
callback(false, ex);
};
pub.hasEvent = function(eventName) {
return pack !== null && pack.hasEventSound(eventName);
};
pub.playEvent = function(eventName, callback) {
if(pack === null)
return;
if(Array.isArray(eventName)) {
const names = eventName;
eventName = null;
for(const name of names) {
if(pack.hasEventSound(name)) {
eventName = name;
break;
}
}
if(eventName === null)
return;
} else if(!pack.hasEventSound(eventName))
return;
const hasCallback = typeof callback === 'function';
try {
const soundInfo = sndLibrary.getSound(pack.getEventSound(eventName)),
soundName = soundInfo.getName();
if(soundMgr.isLoaded(soundName)) {
playSource(soundMgr.get(soundName), hasCallback, callback);
} else {
soundMgr.load(soundName, soundInfo.getSources(), function(success, buffer) {
if(success)
playSource(buffer.createSource(), hasCallback, callback);
else
handlePlayError(buffer, hasCallback, callback);
});
}
} catch(ex) {
handlePlayError(ex, hasCallback, callback);
}
};
return pub;
};
const MamiSoundPacks = function() {
const packs = new Map;
const addPack = function(packInfo) {
if(packs.has(packInfo.getName()))
throw 'a pack with that name has already been registered';
packs.set(packInfo.getName(), packInfo);
};
const loadPack = function(packInfo, readOnly) {
if(typeof packInfo !== 'object')
throw 'packInfo must be an object';
if(typeof packInfo.name !== 'string')
throw 'packInfo must contain a name field';
if(typeof packInfo.events !== 'object')
throw 'packInfo must contain a events field';
const events = new Map;
for(const eventName in packInfo.events) {
if(typeof packInfo.events[eventName] !== 'string')
continue;
events.set(eventName, packInfo.events[eventName]);
}
if(events.size < 1)
throw 'packInfo does not contain any valid events';
addPack(new MamiSoundPack(
packInfo.name,
readOnly,
packInfo.title,
events
));
};
return {
addPack: addPack,
loadPack: loadPack,
loadPacks: function(packInfos, readOnly) {
for(const packInfo of packInfos)
loadPack(packInfo, readOnly);
},
removePack: function(name) {
packs.delete(name);
},
clearPacks: function() {
packs.clear();
},
forEachPack: function(body) {
if(typeof body !== 'function')
return;
packs.forEach(body);
},
hasPack: function(name) {
return packs.has(name);
},
getPack: function(name) {
if(!packs.has(name))
throw 'No pack with this name has been registered.';
return packs.get(name);
},
};
};