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