Skip to content

Instantly share code, notes, and snippets.

@klaascuvelier
Last active December 16, 2015 03:29
Show Gist options
  • Save klaascuvelier/5370520 to your computer and use it in GitHub Desktop.
Save klaascuvelier/5370520 to your computer and use it in GitHub Desktop.
Extension for Earport.fm: Drag & Drop mp3 files and m3u playlists on the screen to add them to the Earport playlist.
(function () {
var $dropView = $('<div style="position: absolute; left: 0; top: 0; bottom: 0; right: 0; background: rgba(0, 0, 0, 0.5); z-index: 9999; color: #fff; padding: 100px; text-align: center; font-size: 32px">drop music or playlists</div>'),
$body = $('body'),
songsToAdd = [],
filesToParse = [];
$body.append('<script src="https://raw.github.com/vjeux/jDataView/master/src/jdataview.js"></script>');
Earport.Api.socket.on('search.query', songsFound);
Earport.Api.socket.on('playlist.queue', songQueued);
$dropView.on('dragleave', function (evt) {
$dropView.remove();
});
$body.on('dragenter dragover', function (evt) {
evt.preventDefault();
evt.stopPropagation();
var dataTransfer = evt.dataTransfer ? evt.dataTransfer : evt.originalEvent.dataTransfer;
if (!dataTransfer || $.inArray('Files', dataTransfer.types) < 0) {
console.log(dataTransfer);
return;
}
$body.append($dropView);
});
$body.on('drop', function (evt) {
evt.preventDefault();
evt.stopPropagation();
$dropView.remove();
var dataTransfer = evt.dataTransfer ? evt.dataTransfer : evt.originalEvent.dataTransfer,
files = dataTransfer.files,
i = 0,
l = files.length;
filesToParse = $.merge(filesToParse, files);
parseNextFile();
});
/**
* Parse the next file, if any
* @return {void}
*/
function parseNextFile()
{
if (filesToParse.length === 0) {
if (songsToAdd.length > 0) {
addNextSong();
}
return;
}
var file = filesToParse.pop(),
type = void 0;
if (file) {
type = file.type;
if (type === 'audio/mp3') {
readID3Tags(file);
} else if (type === 'audio/x-mpegurl') {
readPlaylist(file);
} else if (!!window.console) {
console.log('unsupported type ' + type);
parseNextFile();
}
}
}
/**
* Read a playlist
* @param {file} file
* @return {void}
*/
function readPlaylist(file)
{
var reader = new FileReader();
reader.onload = function(e) {
var lines = this.result.split("\n"),
l = lines.length,
line = void 0,
i = void 0;
for (i = 0; i < l; i++) {
line = lines[i],
useFilename = false;
if (line.length > 1) {
useFilename = line.substr(0, 1) !== '#';
if (!useFilename) {
// use extinf, ignore next line
try {
info = line.split(',')[1].split('-');
addSong(info[0], info[1]);
i++;
} catch (e) {
// parsing failed use filename instead
line = lines[++i];
}
}
if (useFilename) {
// this is kinda crappy :(, filter out some characters and add it as a song ...
filename = line.substr(0, line.lastIndexOf('.'))
song = filename
.replace(/[0-9\-_\.]/gi, ' ') // strip some chars
.replace(/ /g, ' '); // replace double spaces by single
addSong('', song);
}
}
}
parseNextFile();
};
reader.onerror = function (evt) {
parseNextFile();
}
reader.readAsText(file);
}
/**
* Read ID3 tags from file
* @param {file} file
* @return {void}
*/
function readID3Tags(file)
{
var reader = new FileReader();
reader.onload = function(e) {
var dv = new jDataView(this.result);
if (dv.getString(3, dv.byteLength - 128) == 'TAG') {
var title = dv.getString(30, dv.tell()),
artist = dv.getString(30, dv.tell()),
album = dv.getString(30, dv.tell()),
year = dv.getString(4, dv.tell());
addSong(artist, title, album);
} else {
console.log('could not parse');
// no ID3v1 data found.
}
parseNextFile();
};
reader.onerror = function (evt) {
parseNextFile();
}
reader.readAsArrayBuffer(file);
}
/**
* Add song to search queye
* @param {string} artist
* @param {string} song
* @param {string} album
*/
function addSong(artist, song, album)
{
var data = $.trim([artist, song, album].join(' ')),
parts = data.split("\u0000"),
l = parts.length,
i = void 0,
result = '';
for (i = 0; i < l; i++ ) {
if (parts[i].length > 0) {
result += parts[i];
}
}
songsToAdd.push(result);
}
/**
* Let Earport find some matching songs!
*/
function addNextSong()
{
if (songsToAdd.length === 0) {
return;
}
var song = songsToAdd.pop();
if (!!song) {
console.log('finding song ' + song);
Earport.Api.socket.emit('search.query', {"query": song});
}
// fetch next song
addNextSong();
}
/**
* On search query result
* @param {array} data
* @return {void}
*/
function songsFound(data)
{
if (data && data.results && data.results.length) {
var track = data.results[0];
Earport.Api.socket.emit('playlist.queue',{"track": track});
}
}
/**
* On song queued
* @param {array} data
* @return {void}
*/
function songQueued(data)
{
// do nothing
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment