owntone-server/admin-root/playlist.js

469 lines
14 KiB
JavaScript

/*
* $Id$
* Javascript for playlist.html
*
* Copyright (C) 2005 Anders Betnér (andbe611@users.sourceforge.net)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Detta script finns att hämta på http://www.jojoxx.net och
får användas fritt så länge som dessa rader står kvar. */
function DataDumper(obj,n,prefix){
var str=""; prefix=(prefix)?prefix:""; n=(n)?n+1:1; var ind=""; for(var i=0;i<n;i++){ ind+=" "; }
if(typeof(obj)=="string"){
str+=ind+prefix+"String:\""+obj+"\"\n";
} else if(typeof(obj)=="number"){
str+=ind+prefix+"Number:"+obj+"\n";
} else if(typeof(obj)=="function"){
str+=ind+prefix+"Function:"+obj+"\n";
} else if(typeof(obj) == 'boolean') {
str+=ind+prefix+"Boolean:" + obj + "\n";
} else {
var type="Array";
for(var i in obj){ type=(type=="Array"&&i==parseInt(i))?"Array":"Object" }
str+=ind+prefix+type+"[\n";
if(type=="Array"){
for(var i in obj){ str+=DataDumper(obj[i],n,i+"=>"); }
} else {
for(var i in obj){ str+=DataDumper(obj[i],n,i+"=>"); }
}
str+=ind+"]\n";
}
return str;
}
//var g_req;
var g_requestor;
var g_selectedGenres = Array();
var g_selectedAlbums = Array();
var g_selectedArtists = Array();
var baseUrl = window.location.toString();
baseUrl = baseUrl.substr(0,baseUrl.length-13);
String.prototype.myEncodeURI = function () {
s = encodeURI(this);
s = s.replace(/\'/,'%27');
return s.replace(/&/,'%26');
};
Requestor = function(baseUrl) {
g_requestor = this;
this.req = ''; // holds the request
this.responseHandler;
this.baseUrl = baseUrl;
this.que = Array();
// All browsers but IE
if (window.XMLHttpRequest) {
this.req = new XMLHttpRequest();
// MS IE
} else if (window.ActiveXObject) {
this.req = new ActiveXObject("Microsoft.XMLHTTP");
}
this.busy = false;
};
Requestor.prototype.setResponseHandler = function(resp) {
this.responseHandler = resp;
};
Requestor.prototype.addRequest = function(url) {
if (this.busy) {
this.que.push(url);
} else {
this._openRequest(url);
}
};
Requestor.prototype._openRequest = function(url) {
this.busy = true;
if (url.search(/\?/)> -1) {
url += '&output=xml';
} else {
url += '?output=xml';
}
this.req.open('get',this.baseUrl+url,true);
this.req.onreadystatechange = Requestor_handleRequest;
this.req.send(null);
};
Requestor_handleRequest = function() {
// readystate 4 means the whole document is loaded
if (4 == g_requestor.req.readyState) {
// Only try to parse the response if we got
// ok from the server
if (200 == g_requestor.req.status) {
// send the recieved document off to the handler
g_requestor.responseHandler(g_requestor.req.responseXML);
}
// Check if there are requests qued up
if (g_requestor.que.length > 0) {
// Just to be able to pull ourseves up by our boot straps
window.setTimeout(Requestor_queChecker,5);
return;
} else {
g_requestor.busy = false;
}
}
};
function Requestor_queChecker() {
if (url = g_requestor.que.shift()) {
g_requestor._openRequest(url);
}
}
function response(xmldoc) {
if ('daap.databaseplaylists' == xmldoc.firstChild.nodeName) {
el = document.getElementById('source');
addPlaylists(el,xmldoc);
} else if ('daap.databasebrowse' == xmldoc.firstChild.nodeName) {
// Ok we have response from a browse query
switch (xmldoc.firstChild.childNodes[3].nodeName) {
case 'daap.browsegenrelisting':
el = document.getElementById('genre');
addOptions(el,'genre',xmldoc);
break;
case 'daap.browseartistlisting':
el = document.getElementById('artist');
addOptions(el,'artist',xmldoc);
break;
case 'daap.browsealbumlisting':
el = document.getElementById('album');
addOptions(el,'album',xmldoc);
// All other boxes are updated, now get the songs
getSongs();
break;
default:
// We got something else back...
}
} else if ('daap.databasesongs' == xmldoc.firstChild.nodeName) {
// Songlist
addSongs(xmldoc);
}
}
function init() {
req = new Requestor(baseUrl);
req.setResponseHandler(response);
req.addRequest('databases/1/containers');
req.addRequest('databases/1/browse/genres');
req.addRequest('databases/1/browse/artists');
req.addRequest('databases/1/browse/albums');
el = document.getElementById('source');
el.addEventListener('change',playlistSelect,true);
el = document.getElementById('genre');
el.addEventListener('change',genreSelect,true);
el = document.getElementById('artist');
el.addEventListener('change',artistSelect,true);
el = document.getElementById('album');
el.addEventListener('change',albumSelect,true);
}
function addOptions(el,label,xmldoc) {
while(el.hasChildNodes()) {
el.removeChild(el.firstChild);
}
itemCnt = xmldoc.getElementsByTagName('dmap.specifiedtotalcount').item(0).textContent;
if (parseInt(itemCnt) > 1) {
plural = 's';
} else {
plural = '';
}
option = document.createElement('option');
option.value = '1';
option.selected = false;
option.appendChild(document.createTextNode('All ('+itemCnt+' '+label +plural+')'));
el.appendChild(option);
items = xmldoc.getElementsByTagName('dmap.listingitem');
selectAll = true;
for (i=0; i<items.length; i++) {
option = document.createElement('option');
itemName = items[i].textContent;
option.value = itemName;
switch (label) {
case 'genre':
if (g_selectedGenres[itemName]) {
option.selected = true;
selectAll = false;
}
break;
case 'artist':
if (g_selectedArtists[itemName]) {
option.selected = true;
selectAll = false;
}
break;
case 'album':
if (g_selectedAlbums[itemName]) {
option.selected = true;
selectAll = false;
}
default: // if we get here something is wrong
// silently ignore it
}
//###FIXME do some kind of itelligent truncation of the string
option.appendChild(document.createTextNode(itemName.substr(0,30)));
el.appendChild(option);
}
if (selectAll) {
// clear the global selections arrays
el.options[0].selected = true;
switch (label) {
case 'genre':
g_selectedGenres = Array();
break;
case 'artist':
g_selectedArtists = Array();
break;
case 'album':
g_selectedAlbums = Array();
break;
default:
// Can't get here
}
} else {
el.options[0].selected = false;
}
}
function addPlaylists(el,xmldoc) {
//items = xmldoc.getElementsByTagName('dmap.listingitem');
list = xmldoc.childNodes[0].childNodes[4];
// Start on 1 since the first node is the name of the daap server
for (i=1; i < list.childNodes.length; i++) {
option = document.createElement('option');
listNumber = list.childNodes[i].childNodes[0].textContent;
listName = list.childNodes[i].childNodes[2].textContent;
option.appendChild(document.createTextNode(listName));
option.setAttribute('value',listNumber);
el.appendChild(option);
}
}
function playlistSelect(event) {
table = document.getElementById('songs');
tableBody = removeRows(table);
playlistNumber = document.getElementById('source').value;
browse = document.getElementById('browse');
if (1 == playlistNumber) {
browse.style.display = 'block';
} else {
browse.style.display = 'none';
}
g_req.open('get',baseUrl + 'databases/1/containers/' + playlistNumber +
'/items?meta=dmap.itemname,daap.songalbum,daap.songartist,daap.songgenre,daap.songtime&output=xml',false);
g_req.send(null);
items = g_req.responseXML.getElementsByTagName('dmap.listingitem');
className = 'odd';
for (i=0; i < items.length; i++) {
// Have to check if the tag really was returned from the server
if (song = items[i].getElementsByTagName('dmap.itemname').item(0)) {
song = song.textContent;
} else {
song = '';
}
time = ''; //items[i].getElementsByTagName('daap.songtime').item(0).textContent;
if (artist = items[i].getElementsByTagName('daap.songartist').item(0)) {
artist = artist.textContent;
} else {
artist = '';
}
if (album = items[i].getElementsByTagName('daap.songalbum').item(0)) {
album = album.textContent;
} else {
album = '';
}
if (genre = items[i].getElementsByTagName('daap.songgenre').item(0)) {
genre = genre.textContent;
} else {
genre = '';
}
if ('odd' == className) {
className = 'even';
} else {
className = 'odd';
}
addRow(tableBody,className,song,time,artist,album,genre);
}
}
function addRow(tbody,className,song,time,artist,album,genre) {
row = document.createElement("tr");
row.setAttribute('class',className);
cell = document.createElement("td");
cell.appendChild(document.createTextNode(song));
row.appendChild(cell);
cell = document.createElement("td");
cell.appendChild(document.createTextNode(time));
row.appendChild(cell);
cell = document.createElement("td");
//###FIXME do some kind of itelligent truncation of the string
cell.appendChild(document.createTextNode(artist.substring(0,30)));
row.appendChild(cell);
cell = document.createElement("td");
cell.appendChild(document.createTextNode(album));
row.appendChild(cell);
cell = document.createElement("td");
cell.appendChild(document.createTextNode(genre));
row.appendChild(cell);
tbody.appendChild(row);
}
function removeRows(table) {
tableBody = table.getElementsByTagName('tbody').item(0);
table.removeChild(tableBody);
tableBody = document.createElement('tbody');
tableBody.setAttribute('class','mytbody');
table.appendChild(tableBody);
return tableBody;
}
function genreSelect(event) {
selectObject = event.target;
if (selectObject.options[0].selected) {
filter = '';
g_selectedGenres = Array();
//###FIXME must dselect all others
} else {
filter = Array();
//###FIXME if there is just the all genre there will be an error here
for (i=1; i<selectObject.options.length; i++) {
genre = selectObject.options[i].value;
if (selectObject.options[i].selected) {
filter.push("'daap.songgenre:" + genre.myEncodeURI() + "'");
g_selectedGenres[genre] = true;
} else {
g_selectedGenres[genre] = false;
}
}
filter = '?filter=' + filter.join(',');
}
//dump(DataDumper(g_selectedGenres));
g_requestor.addRequest('databases/1/browse/artists' + filter);
g_requestor.addRequest('databases/1/browse/albums' + filter);
}
function artistSelect(event) {
selectObject = event.target;
filter = '';
if (selectObject.options[0].selected) {
// All selected, sort according to genre
filter = Array();
for (genre in g_selectedGenres) {
if (g_selectedGenres[genre]) {
filter.push("'daap.songgenre:" + genre.myEncodeURI() + "'");
}
}
if (0 == filter.length) {
// If filter array is empty then "All genres" is selected
// so set filter to empty
filter = '';
} else {
filter = '?filter=' + filter.join(',');
}
} else {
filter = Array();
for (i=1; i<selectObject.options.length; i++) {
artist = selectObject.options[i].value;
if (selectObject.options[i].selected) {
filter.push("'daap.songartist:" + artist.myEncodeURI() + "'");
g_selectedArtists[artist] = true;
} else {
g_selectedArtists[artist] = false;
}
}
// If all is selected then search on all artists but honor genre
filter = '?filter=' + filter.join(',');
}
g_requestor.addRequest('databases/1/browse/albums' + filter);
}
function albumSelect(event) {
// just get the songs, the only box changed is this one
getSongs();
}
function getSongs() {
genre = document.getElementById('genre').value;
artist = document.getElementById('artist').value;
album = document.getElementById('album').value;
//alert("genre: "+genre +"\nartist: "+ artist + "\nalbum:"+ album);
query = Array();
if (genre != '1') {
query.push('\'daap.songgenre:' + genre.myEncodeURI() +"'");
}
if (artist != '1') {
query.push('\'daap.songartist:' + artist.myEncodeURI() +"'");
}
if (album != '1') {
query.push('\'daap.songalbum:' + album.myEncodeURI() +"'");
}
if (0 == query.length) {
// If filter array is empty then "All genres" is selected
// so set filter to empty
query = '';
} else {
query = '&query=' + query.join(' ');
}
//alert(query);
g_requestor.addRequest('databases/1/items' +
'?meta=dmap.itemname,daap.songalbum,daap.songartist,daap.songgenre,daap.songtime'+query);
///items?meta=dmap.itemname,daap.songalbum,daap.songartist,daap.songgenre,daap.songtime&output=xml
}
function addSongs(xmldoc) {
items = xmldoc.getElementsByTagName('dmap.listingitem');
className = 'odd';
table = document.getElementById('songs');
tableBody = removeRows(table);
for (i=0; i < items.length; i++) {
// Have to check if the tag really was returned from the server
if (song = items[i].getElementsByTagName('dmap.itemname').item(0)) {
song = song.textContent;
} else {
song = '';
}
time = ''; //items[i].getElementsByTagName('daap.songtime').item(0).textContent;
if (artist = items[i].getElementsByTagName('daap.songartist').item(0)) {
artist = artist.textContent;
} else {
artist = '';
}
if (album = items[i].getElementsByTagName('daap.songalbum').item(0)) {
album = album.textContent;
} else {
album = '';
}
if (genre = items[i].getElementsByTagName('daap.songgenre').item(0)) {
genre = genre.textContent;
} else {
genre = '';
}
if ('odd' == className) {
className = 'even';
} else {
className = 'odd';
}
addRow(tableBody,className,song,time,artist,album,genre);
}
}