misuzu/assets/misuzu.js/embed/audio.js

320 lines
9.2 KiB
JavaScript
Raw Normal View History

#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 element = $element('div', { classList: ['aembed', 'aembed-' + player.getType()] }, player);
2023-01-29 20:29:20 +00:00
return {
get element() { return element; },
get player() { return player; },
2023-01-29 20:29:20 +00:00
appendTo: function(target) {
target.appendChild(element);
2023-01-29 20:29:20 +00:00
},
insertBefore: function(ref) {
$insertBefore(ref, element);
2023-01-29 20:29:20 +00:00
},
nuke: function() {
element.remove();
2023-01-29 20:29:20 +00:00
},
replaceElement(target) {
$insertBefore(target, element);
target.remove();
2023-01-29 20:29:20 +00:00
},
};
};
const MszAudioEmbedPlayer = function(metadata, options) {
options = options || {};
const shouldAutoplay = options.autoplay === undefined || options.autoplay;
const haveNativeControls = options.nativeControls !== undefined && options.nativeControls;
2023-01-29 20:29:20 +00:00
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 element = $element('audio', playerAttrs);
2023-01-29 20:29:20 +00:00
const pub = {
get element() { return element; },
2023-01-29 20:29:20 +00:00
appendTo: function(target) {
target.appendChild(element);
2023-01-29 20:29:20 +00:00
},
insertBefore: function(ref) {
$insertBefore(ref, element);
2023-01-29 20:29:20 +00:00
},
nuke: function() {
element.remove();
2023-01-29 20:29:20 +00:00
},
replaceElement(target) {
$insertBefore(target, element);
target.remove();
2023-01-29 20:29:20 +00:00
},
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
element.addEventListener('play', function() { watchers.call('play', pub); });
2023-01-29 20:29:20 +00:00
const pPlay = function() { element.play(); };
2023-01-29 20:29:20 +00:00
pub.play = pPlay;
const pPause = function() { element.pause(); };
2023-01-29 20:29:20 +00:00
pub.pause = pPause;
let stopCalled = false;
element.addEventListener('pause', function() {
2023-01-29 20:29:20 +00:00
watchers.call(stopCalled ? 'stop' : 'pause', pub);
stopCalled = false;
});
const pStop = function() {
stopCalled = true;
element.pause();
element.currentTime = 0;
2023-01-29 20:29:20 +00:00
};
pub.stop = pStop;
const pIsPlaying = function() { return !element.paused; };
2023-01-29 20:29:20 +00:00
pub.isPlaying = pIsPlaying;
const pIsMuted = function() { return element.muted; };
2023-01-29 20:29:20 +00:00
pub.isMuted = pIsMuted;
let lastMuteState = element.muted;
element.addEventListener('volumechange', function() {
if(lastMuteState !== element.muted) {
lastMuteState = element.muted;
2023-01-29 20:29:20 +00:00
watchers.call('mute', pub, [lastMuteState]);
} else
watchers.call('volume', pub, [element.volume]);
2023-01-29 20:29:20 +00:00
});
const pSetMuted = function(state) { element.muted = state; };
2023-01-29 20:29:20 +00:00
pub.setMuted = pSetMuted;
const pGetVolume = function() { return element.volume; };
2023-01-29 20:29:20 +00:00
pub.getVolume = pGetVolume;
const pSetVolume = function(volume) { element.volume = volume; };
2023-01-29 20:29:20 +00:00
pub.setVolume = pSetVolume;
const pGetPlaybackRate = function() { return element.playbackRate; };
2023-01-29 20:29:20 +00:00
pub.getPlaybackRate = pGetPlaybackRate;
element.addEventListener('ratechange', function() {
watchers.call('rate', pub, [element.playbackRate]);
2023-01-29 20:29:20 +00:00
});
const pSetPlaybackRate = function(rate) { element.playbackRate = rate; };
2023-01-29 20:29:20 +00:00
pub.setPlaybackRate = pSetPlaybackRate;
window.addEventListener('durationchange', function() {
watchers.call('duration', pub, [element.duration]);
2023-01-29 20:29:20 +00:00
});
const pGetDuration = function() { return element.duration; };
2023-01-29 20:29:20 +00:00
pub.getDuration = pGetDuration;
window.addEventListener('timeupdate', function() {
watchers.call('time', pub, [element.currentTime]);
2023-01-29 20:29:20 +00:00
});
const pGetTime = function() { return element.currentTime; };
2023-01-29 20:29:20 +00:00
pub.getTime = pGetTime;
const pSeek = function(time) { element.currentTime = time; };
2023-01-29 20:29:20 +00:00
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 = [];
let album;
2023-01-29 20:29:20 +00:00
if(metadata.media !== undefined && metadata.media.tags !== undefined) {
const tags = metadata.media.tags;
if(tags.title !== undefined) {
if(tags.artist !== undefined) {
title.push($element(
'span',
{ className: 'aembedph-info-title-artist' },
tags.artist,
));
2023-01-29 20:29:20 +00:00
title.push(' - ');
}
title.push($element(
'span',
{ className: 'aembedph-info-title-title' },
tags.title,
));
2023-01-29 20:29:20 +00:00
} else {
title.push($element(
'span',
{ className: 'aembedph-info-title-title' },
metadata.title,
));
2023-01-29 20:29:20 +00:00
}
if(tags.album !== undefined && tags.album !== tags.title)
album = tags.album;
}
const infoChildren = [];
infoChildren.push($element(
'h1',
{ className: 'aembedph-info-title' },
...title,
));
2023-01-29 20:29:20 +00:00
infoChildren.push($element(
'p',
{ className: 'aembedph-info-album' },
album,
));
2023-01-29 20:29:20 +00:00
infoChildren.push($element(
'div',
{ className: 'aembedph-info-site' },
metadata.site_name,
));
2023-01-29 20:29:20 +00:00
const style = [];
if(typeof metadata.color !== 'undefined')
style.push('--aembedph-colour: ' + metadata.color);
const coverBackground = $element(
'div',
{ className: 'aembedph-bg' },
$element('img', {
alt: '',
src: metadata.image,
onerror: function(ev) {
coverBackground.classList.add('aembedph-bg-none');
2023-01-29 20:29:20 +00:00
},
}),
);
const coverPreview = $element(
'div',
{ className: 'aembedph-info-cover' },
$element('img', {
alt: '',
src: metadata.image,
onerror: function(ev) {
coverPreview.classList.add('aembedph-info-cover-none');
2023-01-29 20:29:20 +00:00
},
}),
);
2023-01-29 20:29:20 +00:00
let element;
const pub = {
get element() { return element; },
};
2023-01-29 20:29:20 +00:00
element = $element(
'div',
{
2023-01-29 20:29:20 +00:00
className: ('aembedph aembedph-' + (options.type || 'external')),
style: style.join(';'),
title: metadata.title,
},
coverBackground,
$element(
'div',
{ className: 'aembedph-fg' },
$element(
'div',
{ className: 'aembedph-info' },
coverPreview,
$element(
'div',
{ className: 'aembedph-info-body' },
...infoChildren
),
),
$element(
'div',
{
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(element);
if(typeof options.onembed === 'function')
options.onembed(embed);
2023-01-29 20:29:20 +00:00
},
},
$element(
'div',
{ className: 'aembedph-play-internal', },
$element('i', { className: 'fas fa-play fa-3x fa-fw' }),
),
$element(
'div',
{ className: 'aembedph-play-external' },
$element(
'a',
{
className: 'aembedph-play-external-link',
href: metadata.url,
target: '_blank',
rel: 'noopener',
2023-01-29 20:29:20 +00:00
},
`or listen on ${metadata.site_name}?`
),
),
),
),
);
pub.appendTo = function(target) { target.appendChild(element); };
pub.insertBefore = function(ref) { $insertBefore(ref, element); };
2023-01-29 20:29:20 +00:00
pub.nuke = function() {
element.remove();
2023-01-29 20:29:20 +00:00
};
pub.replaceElement = function(target) {
$insertBefore(target, element);
target.remove();
2023-01-29 20:29:20 +00:00
};
return pub;
}