2024-01-24 21:53:26 +00:00
|
|
|
#include utility.js
|
2023-07-17 14:37:39 +00:00
|
|
|
#include watcher.js
|
|
|
|
|
2023-01-29 20:29:20 +00:00
|
|
|
const MszAudioEmbedPlayerEvents = function() {
|
|
|
|
return [
|
|
|
|
'play', 'pause', 'stop',
|
|
|
|
'mute', 'volume',
|
|
|
|
'rate', 'duration', 'time',
|
|
|
|
];
|
|
|
|
};
|
|
|
|
|
|
|
|
const MszAudioEmbed = function(player) {
|
|
|
|
const elem = $e({
|
|
|
|
attrs: {
|
|
|
|
classList: ['aembed', 'aembed-' + player.getType()],
|
|
|
|
},
|
|
|
|
child: player,
|
|
|
|
});
|
|
|
|
|
|
|
|
return {
|
|
|
|
getElement: function() {
|
|
|
|
return elem;
|
|
|
|
},
|
|
|
|
appendTo: function(target) {
|
|
|
|
target.appendChild(elem);
|
|
|
|
},
|
|
|
|
insertBefore: function(ref) {
|
|
|
|
$ib(ref, elem);
|
|
|
|
},
|
|
|
|
nuke: function() {
|
|
|
|
$r(elem);
|
|
|
|
},
|
|
|
|
replaceElement(target) {
|
|
|
|
$ib(target, elem);
|
|
|
|
$r(target);
|
|
|
|
},
|
|
|
|
getPlayer: function() {
|
|
|
|
return player;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const MszAudioEmbedPlayer = function(metadata, options) {
|
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
const shouldAutoplay = options.autoplay === undefined || options.autoplay,
|
|
|
|
haveNativeControls = options.nativeControls !== undefined && options.nativeControls;
|
|
|
|
|
|
|
|
const playerAttrs = {
|
|
|
|
src: metadata.url,
|
|
|
|
style: {},
|
|
|
|
};
|
|
|
|
|
|
|
|
if(shouldAutoplay)
|
|
|
|
playerAttrs.autoplay = 'autoplay';
|
|
|
|
if(haveNativeControls)
|
|
|
|
playerAttrs.controls = 'controls';
|
|
|
|
|
2024-01-30 23:47:02 +00:00
|
|
|
const watchers = new MszWatchers;
|
2023-01-29 20:29:20 +00:00
|
|
|
watchers.define(MszAudioEmbedPlayerEvents());
|
|
|
|
|
|
|
|
const player = $e({
|
|
|
|
tag: 'audio',
|
|
|
|
attrs: playerAttrs,
|
|
|
|
});
|
|
|
|
|
|
|
|
const pub = {
|
|
|
|
getElement: function() {
|
|
|
|
return player;
|
|
|
|
},
|
|
|
|
appendTo: function(target) {
|
|
|
|
target.appendChild(player);
|
|
|
|
},
|
|
|
|
insertBefore: function(ref) {
|
|
|
|
$ib(ref, player);
|
|
|
|
},
|
|
|
|
nuke: function() {
|
|
|
|
$r(player);
|
|
|
|
},
|
|
|
|
replaceElement(target) {
|
|
|
|
$ib(target, player);
|
|
|
|
$r(target);
|
|
|
|
},
|
|
|
|
getType: function() { return 'external'; },
|
|
|
|
};
|
|
|
|
|
2024-01-24 21:53:26 +00:00
|
|
|
pub.watch = (name, handler) => watchers.watch(name, handler);
|
|
|
|
pub.unwatch = (name, handler) => watchers.unwatch(name, handler);
|
2023-01-29 20:29:20 +00:00
|
|
|
|
|
|
|
player.addEventListener('play', function() { watchers.call('play', pub); });
|
|
|
|
|
|
|
|
const pPlay = function() { player.play(); };
|
|
|
|
pub.play = pPlay;
|
|
|
|
|
|
|
|
const pPause = function() { player.pause(); };
|
|
|
|
pub.pause = pPause;
|
|
|
|
|
|
|
|
let stopCalled = false;
|
|
|
|
player.addEventListener('pause', function() {
|
|
|
|
watchers.call(stopCalled ? 'stop' : 'pause', pub);
|
|
|
|
stopCalled = false;
|
|
|
|
});
|
|
|
|
|
|
|
|
const pStop = function() {
|
|
|
|
stopCalled = true;
|
|
|
|
player.pause();
|
|
|
|
player.currentTime = 0;
|
|
|
|
};
|
|
|
|
pub.stop = pStop;
|
|
|
|
|
|
|
|
const pIsPlaying = function() { return !player.paused; };
|
|
|
|
pub.isPlaying = pIsPlaying;
|
|
|
|
|
|
|
|
const pIsMuted = function() { return player.muted; };
|
|
|
|
pub.isMuted = pIsMuted;
|
|
|
|
|
|
|
|
let lastMuteState = player.muted;
|
|
|
|
player.addEventListener('volumechange', function() {
|
|
|
|
if(lastMuteState !== player.muted) {
|
|
|
|
lastMuteState = player.muted;
|
|
|
|
watchers.call('mute', pub, [lastMuteState]);
|
|
|
|
} else
|
|
|
|
watchers.call('volume', pub, [player.volume]);
|
|
|
|
});
|
|
|
|
|
|
|
|
const pSetMuted = function(state) { player.muted = state; };
|
|
|
|
pub.setMuted = pSetMuted;
|
|
|
|
|
|
|
|
const pGetVolume = function() { return player.volume; };
|
|
|
|
pub.getVolume = pGetVolume;
|
|
|
|
|
|
|
|
const pSetVolume = function(volume) { player.volume = volume; };
|
|
|
|
pub.setVolume = pSetVolume;
|
|
|
|
|
|
|
|
const pGetPlaybackRate = function() { return player.playbackRate; };
|
|
|
|
pub.getPlaybackRate = pGetPlaybackRate;
|
|
|
|
|
|
|
|
player.addEventListener('ratechange', function() {
|
|
|
|
watchers.call('rate', pub, [player.playbackRate]);
|
|
|
|
});
|
|
|
|
|
|
|
|
const pSetPlaybackRate = function(rate) { player.playbackRate = rate; };
|
|
|
|
pub.setPlaybackRate = pSetPlaybackRate;
|
|
|
|
|
|
|
|
window.addEventListener('durationchange', function() {
|
|
|
|
watchers.call('duration', pub, [player.duration]);
|
|
|
|
});
|
|
|
|
|
|
|
|
const pGetDuration = function() { return player.duration; };
|
|
|
|
pub.getDuration = pGetDuration;
|
|
|
|
|
|
|
|
window.addEventListener('timeupdate', function() {
|
|
|
|
watchers.call('time', pub, [player.currentTime]);
|
|
|
|
});
|
|
|
|
|
|
|
|
const pGetTime = function() { return player.currentTime; };
|
|
|
|
pub.getTime = pGetTime;
|
|
|
|
|
|
|
|
const pSeek = function(time) { player.currentTime = time; };
|
|
|
|
pub.seek = pSeek;
|
|
|
|
|
|
|
|
return pub;
|
|
|
|
};
|
|
|
|
|
|
|
|
const MszAudioEmbedPlaceholder = function(metadata, options) {
|
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
if(typeof options.player !== 'function' && typeof options.onclick !== 'function')
|
|
|
|
throw 'Neither a player nor an onclick handler were provided.';
|
|
|
|
|
|
|
|
let title = [],
|
|
|
|
album = undefined;
|
|
|
|
if(metadata.media !== undefined && metadata.media.tags !== undefined) {
|
|
|
|
const tags = metadata.media.tags;
|
|
|
|
|
|
|
|
if(tags.title !== undefined) {
|
|
|
|
if(tags.artist !== undefined) {
|
|
|
|
title.push({
|
|
|
|
tag: 'span',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-title-artist',
|
|
|
|
},
|
|
|
|
child: tags.artist,
|
|
|
|
});
|
|
|
|
title.push(' - ');
|
|
|
|
}
|
|
|
|
|
|
|
|
title.push({
|
|
|
|
tag: 'span',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-title-title',
|
|
|
|
},
|
|
|
|
child: tags.title,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
title.push({
|
|
|
|
tag: 'span',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-title-title',
|
|
|
|
},
|
|
|
|
child: metadata.title,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if(tags.album !== undefined && tags.album !== tags.title)
|
|
|
|
album = tags.album;
|
|
|
|
}
|
|
|
|
|
|
|
|
const infoChildren = [];
|
|
|
|
|
|
|
|
infoChildren.push({
|
|
|
|
tag: 'h1',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-title',
|
|
|
|
},
|
|
|
|
child: title,
|
|
|
|
});
|
|
|
|
|
|
|
|
infoChildren.push({
|
|
|
|
tags: 'p',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-album',
|
|
|
|
},
|
|
|
|
child: album,
|
|
|
|
});
|
|
|
|
|
|
|
|
infoChildren.push({
|
|
|
|
tag: 'div',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-site',
|
|
|
|
},
|
|
|
|
child: metadata.site_name,
|
|
|
|
});
|
|
|
|
|
|
|
|
const style = [];
|
|
|
|
if(typeof metadata.color !== 'undefined')
|
|
|
|
style.push('--aembedph-colour: ' + metadata.color);
|
|
|
|
|
|
|
|
const coverBackground = $e({
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-bg',
|
|
|
|
},
|
|
|
|
child: {
|
|
|
|
tag: 'img',
|
|
|
|
attrs: {
|
|
|
|
alt: '',
|
|
|
|
src: metadata.image,
|
|
|
|
onerror: function(ev) {
|
|
|
|
coverBackground.classList.add('aembedph-bg-none');
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const coverPreview = $e({
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-cover',
|
|
|
|
},
|
|
|
|
child: {
|
|
|
|
tag: 'img',
|
|
|
|
attrs: {
|
|
|
|
alt: '',
|
|
|
|
src: metadata.image,
|
|
|
|
onerror: function(ev) {
|
|
|
|
coverPreview.classList.add('aembedph-info-cover-none');
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
|
|
|
const pub = {};
|
|
|
|
|
|
|
|
const elem = $e({
|
|
|
|
attrs: {
|
|
|
|
className: ('aembedph aembedph-' + (options.type || 'external')),
|
|
|
|
style: style.join(';'),
|
|
|
|
title: metadata.title,
|
|
|
|
},
|
|
|
|
child: [
|
|
|
|
coverBackground,
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-fg',
|
|
|
|
},
|
|
|
|
child: [
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info',
|
|
|
|
},
|
|
|
|
child: [
|
|
|
|
coverPreview,
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-info-body',
|
|
|
|
},
|
|
|
|
child: infoChildren,
|
|
|
|
}
|
|
|
|
],
|
|
|
|
},
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-play',
|
|
|
|
onclick: function(ev) {
|
|
|
|
if(ev.target.tagName.toLowerCase() === 'a')
|
|
|
|
return;
|
|
|
|
|
|
|
|
if(typeof options.onclick === 'function') {
|
|
|
|
options.onclick(ev);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const player = new options.player(metadata, options);
|
|
|
|
|
|
|
|
const embed = new MszAudioEmbed(player);
|
|
|
|
if(options.autoembed === undefined || options.autoembed)
|
|
|
|
embed.replaceElement(elem);
|
|
|
|
|
|
|
|
if(typeof options.onembed === 'function')
|
|
|
|
options.onembed(embed);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
child: [
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-play-internal',
|
|
|
|
},
|
|
|
|
child: {
|
|
|
|
tag: 'i',
|
|
|
|
attrs: {
|
|
|
|
className: 'fas fa-play fa-3x fa-fw',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-play-external',
|
|
|
|
},
|
|
|
|
child: {
|
|
|
|
tag: 'a',
|
|
|
|
attrs: {
|
|
|
|
className: 'aembedph-play-external-link',
|
|
|
|
href: metadata.url,
|
|
|
|
target: '_blank',
|
|
|
|
rel: 'noopener',
|
|
|
|
},
|
|
|
|
child: ('or listen on ' + metadata.site_name + '?')
|
|
|
|
},
|
|
|
|
}
|
|
|
|
],
|
|
|
|
}
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
pub.getElement = function() { return elem; };
|
|
|
|
pub.appendTo = function(target) { target.appendChild(elem); };
|
|
|
|
pub.insertBefore = function(ref) { $ib(ref, elem); };
|
|
|
|
pub.nuke = function() {
|
|
|
|
$r(elem);
|
|
|
|
};
|
|
|
|
pub.replaceElement = function(target) {
|
|
|
|
$ib(target, elem);
|
|
|
|
$r(target);
|
|
|
|
};
|
|
|
|
|
|
|
|
return pub;
|
|
|
|
}
|