UNPKG

solid-panes

Version:

Solid-compatible Panes: applets and views for the mashlib and databrowser

200 lines (164 loc) • 6.5 kB
"use strict"; /* Single audio play Pane ** */ var UI = require('solid-ui'); var $rdf = require('rdflib'); var ns = UI.ns; module.exports = { icon: UI.icons.iconBase + 'noun_534313.svg', name: 'audio', // Does the subject deserve an audio play pane? label: function label(subject, context) { var kb = context.session.store; var typeURIs = kb.findTypeURIs(subject); var prefix = $rdf.Util.mediaTypeClass('audio/*').uri.split('*')[0]; for (var t in typeURIs) { if (t.startsWith(prefix)) return 'Play audio'; } return null; }, render: function render(subject, context) { var kb = context.session.store; var dom = context.dom; var options = { autoplay: false, chain: true, chainAlbums: true, loop: false }; var removeExtension = function removeExtension(str) { var dot = str.lastIndexOf('.'); if (dot < 0) return str; // if any var slash = str.lastIndexOf('/'); if (dot < slash) return str; return str.slice(0, dot); }; // True if there is another file like song.mp3 when this is "song 1.mp3" // or this is song.m4a // var looksRedundant = function looksRedundant(x) { var folder = kb.any(undefined, ns.ldp('contains'), x); if (!folder) return false; var contents = kb.each(folder, ns.ldp('contains')); if (contents.length < 2) return false; var thisName = x.uri; for (var k = 0; k < contents.length; k++) { var otherName = contents[k].uri; if (thisName.length > otherName.length && thisName.startsWith(removeExtension(otherName))) { return true; } if (thisName.endsWith('.m4a') && otherName.endsWith('.mp3') && removeExtension(thisName) === removeExtension(otherName)) { return true; } } return false; }; // Alternative methods could include: // Accesing metadata in the audio contol, or paring the audio file var guessNames = function guessNames(x) { var a = x.uri.split('/').slice(-3); // Hope artist, album, track var decode = function decode(str) { try { return decodeURIComponent(str); } catch (e) { return str; } }; artistRow.textContent = decode(a[0]); albumRow.textContent = decode(a[1]); trackRow.textContent = decode(removeExtension(a[2])); }; var moveOn = function moveOn(current, level) { return new Promise(function (resolve) { level = level || 0; if (!options.chain) return resolve(null); // Ideally navigate graph else cheat with URI munging: var folder = kb.any(undefined, ns.ldp('contains'), current) || current.dir(); if (!folder) return resolve(null); kb.fetcher.load(folder).then(function (_xhr) { var contents = kb.each(folder, ns.ldp('contains')); // @@ load if not loaded // if (contents.length < 2) return resolve(null) NO might move on from 1-track album var j; contents.sort(); // sort by URI which hopefully will get tracks in order for (var i = 0; i < contents.length; i++) { if (current.uri === contents[i].uri) { j = (i + 1) % contents.length; if (j === 0) { if (!options.chainAlbums) { if (options.loop) { return resolve(contents[j]); } return resolve(null); // No more music needed } else { // chain albums if (level === 1 || !options.chainAlbums) return resolve(null); // limit of navigating treee moveOn(folder, level + 1).then(function (folder2) { if (folder2) { kb.fetcher.load(folder2).then(function (_xhr) { var contents = kb.each(folder2, ns.ldp('contains')); if (contents.length === 0) return resolve(null); contents.sort(); console.log('New Album: ' + folder2); return resolve(contents[0]); // Start off new album }); } }); } } else { return resolve(contents[j]); } } } // for }); }); }; var endedListener = function endedListener(event) { var current = kb.sym(event.target.getAttribute('src')); if (!options.chain) return; var tryNext = function tryNext(cur) { var current = cur; moveOn(current).then(function (next) { if (!next) { console.log('No successor to ' + current); return; } if (!looksRedundant(next)) { console.log('Moving on to ' + next); guessNames(next); controlRow.appendChild(audioControl(next, true)); // Force autoplay controlRow.removeChild(event.target); } else { console.log('Ignoring redundant ' + next); tryNext(next); } }); }; tryNext(current); }; var audioControl = function audioControl(song, autoplay) { var audio = dom.createElement('audio'); audio.setAttribute('controls', 'yes'); audio.setAttribute('src', song.uri); if (autoplay) { audio.setAttribute('autoplay', 'autoplay'); // Make this a personal preference } audio.addEventListener('ended', endedListener, false); return audio; }; var div = dom.createElement('div'); var table = div.appendChild(dom.createElement('table')); var labelStyle = 'padding: 0.3em; color:white; background-color: black;'; var artistRow = table.appendChild(dom.createElement('tr')); artistRow.style.cssText = labelStyle; var albumRow = table.appendChild(dom.createElement('tr')); albumRow.style.cssText = labelStyle; var trackRow = table.appendChild(dom.createElement('tr')); trackRow.style.cssText = labelStyle; var controlRow = table.appendChild(dom.createElement('tr')); guessNames(subject); controlRow.appendChild(audioControl(subject, options.autoplay)); if (!kb.holds(undefined, ns.ldp('contains'), subject) && subject.dir()) { kb.fetcher.load(subject.dir()); // Prefetch enclosing @@ or playlist } return div; } }; // ends //# sourceMappingURL=audioPane.js.map