<repo_name>MusicBoxOUYA/MusicBoxContent<file_sep>/server.js
var express = require("express"),
	app = express(),
	http = require("http");

app.get("/", function(req,res)
{
	res.send("I'm up!");
});

app.use("/resources", express.static("resources"));

app.listen(process.env.PORT||3000);<file_sep>/resources/js/table.js
function Table(col, header){
  this.columns = cloneArray(col);
  this.names = cloneArray(col);
  this.tableProperties = {"table":{}, "head-row":{}, "head-data":{},"body-row":{}, "body-data":{}};
  this.columnProcesses = [];
  this.headerProperties = [];
  this.columnProperties = [];
  this.headerProcesses = [];
  this.advancedColumnProcesses = [];
  if(header != undefined){
    for(var i = 0; header.length > i; i++){
      this.names[i] = header[i];
    }
  }

  this.setColumns = function(col){
    this.columns = cloneArray(col);
  }

  this.setHeaders = function(header){
    this.names = cloneArray(this.columns);
    for(var i = 0; header.length > i; i++){
      this.names[i] = header[i];
    }
  }
  
  this.setProperties = function(type, prop){
    setObject(this.tableProperties[type], prop);
  }

  this.addColumnProperty = function(col, proc){
    this.columnProperties[col] = proc;
  }

  this.addHeaderProcessor = function(col, proc){
    this.headerProcesses[col] = proc;
  }

  this.addColumnProcessor = function(col, proc){
    this.columnProcesses[col] = proc;
  }

  this.addAdvancedColumnProcessor = function(col, proc){
    this.advancedColumnProcesses[col] = proc;
  }

  this.buildTable = function(rows){
    var table = createElement("table", this.tableProperties["table"]);
    var head = createElement("thead");
    var headRow = createElement("tr", this.tableProperties["head-row"]);
    var body = createElement("tbody");

    for(row in this.names){
      var properties = cloneArray(this.tableProperties["head-data"]);
      var data = this.names[row];
      for (var attrname in this.columnProperties[this.columns[row]]) { properties[attrname] = this.columnProperties[this.columns[row]][attrname]; }
      console.log(properties);
      var header = createElement("th", properties);
      if(this.columns[row] in this.headerProcesses){
        data = this.headerProcesses[this.columns[row]](data);
      }
      if(typeof data == "object")
        insertElementAt(data, header);
      else
        header.innerHTML = data;
      insertElementAt(header, headRow);
    }
    for(row in rows){
      var properties = cloneArray(this.tableProperties["body-data"]);
      var bodyRow = createElement("tr", this.tableProperties["body-row"]);
      var workingRow = rows[row];

      for(col in this.columns){
        console.log(this.tableProperties["body-data"]);
        var properties = cloneArray(this.tableProperties["body-data"]);
        var data = workingRow[this.columns[col]];
        for (var attrname in this.columnProperties[this.columns[col]]) { properties[attrname] = this.columnProperties[this.columns[col]][attrname]; }
        console.log(properties);
        var cell = createElement("td", properties);

        if(this.columns[col] in this.columnProcesses){
          data = this.columnProcesses[this.columns[col]](data);
        }
        if(this.columns[col] in this.advancedColumnProcesses){
          data = this.advancedColumnProcesses[this.columns[col]](workingRow);
        }
        if(typeof data == "object")
          insertElementAt(data, cell)
        else
          cell.innerHTML = data;
        insertElementAt(cell, bodyRow);
      }
      insertElementAt(bodyRow, body);
    }
    insertElementAt(headRow, head);
    insertElementAt(head, table);
    insertElementAt(body, table);
    return table;
  }
   return this;
}
<file_sep>/resources/js/queue.js
function call(){
  request("api/queue", "", function(result){
    buildQueueTable($("#queue-list"), JSON.parse(result));
  }, function(){
    stopCall();
    $("#connection-error-alert").modal({
      keyboard: false,
      backdrop:"static"
    }).modal("show");
  });
}

function startCall(){
  window.console&&console.log("Starting Call");
  callID = setInterval(call, 1000);
}

function stopCall(){
  window.console&&console.log("Stopping Call");
  clearInterval(callID);
}


$( document ).ready(function(){
  call();
  startCall();
  $("#connection-error-alert").on("hidden.bs.modal", function () {
    startCall();
  })
});
<file_sep>/package.json
{
  "name": "MusicBox_ContentServer",
  "description": "Metadata lookup for MusicBox",
  "version": "1.0.0",
  "dependencies": {
    "express": "*",
    "xml2js": "*",
	"memjs": "*"
  }
}<file_sep>/resources/js/bridge.js
function request(url, sendData, callBack, errorCallBack){
  errorCallBack = typeof errorCallBack === "function" ? errorCallBack : function(){};
  $.ajax({
    url:url,
    type:"GET",
    data:sendData,
    success:function(result){
      callBack(result)
    },
    error:function(result){
      errorCallBack(result);
    }
  })
}

function likeSong(id, parentEle) {
  var cookie = $.cookie("songs");
  var songs = cookie != null ? JSON.parse(cookie) : Array();
  songs.push(id);
  $.cookie("songs", JSON.stringify(songs), 1);
  request("api/like", "song="+id, function(data){
    console.log("Liking song");
  });
  $(".like-dislike").attr("disabled", "disabled");
}

function dislikeSong(id, parentEle) {
  var cookie = $.cookie("songs");
  var songs = cookie != null ? JSON.parse(cookie) : Array();
  songs.push(id);
  $.cookie("songs", JSON.stringify(songs), 1);
  request("api/dislike", "song="+id, function(data){
    console.log("Disliking song");
  });
  $(".like-dislike").attr("disabled", "disabled");
}

function queueSong(id){
  request("api/queue", "song="+id, function(data){
    console.log(JSON.parse(data))
  });
}

function buildAlbumArt(imgEle, ccEle, data){
  var source = data.song.art;
  if(imgEle.data("src") != source) {
    imgEle.fadeOut("slow", function() {
      $(this).data("src", source).attr("src", source).load(function(){
        $(this).fadeIn();
      });
    });
  }
}

function buildSongInfo(parentEle, data){
  var name = createElement("h2", {"class":"song-title"}, data.song.title);
  var div = createElement("div", {"class":"row"});
  var p = createElement("p", {"class":"col-xs-10"});
  var artist = createElement("span", {"class":"song-artist"}, data.song.artist);
  var br = createElement("br");
  var album = createElement("span", {"class":"song-album"}, data.song.album);
  var likeHolder = createElement("div", {"class":"col-xs-2"});
  var likes = createElement("span", null, Math.abs(data.song.score));
  var space = createText(" ");
  var icon = createElement("span", {"class":"glyphicon glyphicon-thumbs-" + (data.song.score >= 0 ? "up":"down") });
  parentEle.html("");
  insertElementAt(name, parentEle[0]);
  insertElementAt(p, div);
  insertElementAt(likeHolder, div);
  insertElementAt(likes, likeHolder);
  insertElementAt(space, likeHolder);
  insertElementAt(icon, likeHolder);
  insertElementAt(div, parentEle[0]);
  insertElementAt(album, p);
  insertElementAt(br, p);
  insertElementAt(artist, p);
}

function buildSongTime(parentEle, data){
  var currentMinutes = Math.floor((data.position/1000)/60);
  var currentSeconds = Math.floor((data.position/1000)%60);
  if(currentSeconds < 10){
    currentSeconds = "0" + currentSeconds;
  }
  var durationMinutes = Math.floor((data.duration/1000)/60);
  var durationSeconds = Math.floor((data.duration/1000)%60);
  if(durationSeconds < 10){
    durationSeconds = "0" + durationSeconds;
  }
  var currentTimeParent = createElement("div", {"class":"small-1 columns"});
  var currentTime = createElement("span", {"class":""}, currentMinutes + ":" + currentSeconds);
  var durationTime = createElement("span", {"class":""}, durationMinutes + ":" + durationSeconds);
  var percent = ((data.position/data.duration)*100);
  var progressPercent = createElement("div", {"class":"progress-bar progress-bar-info", "role":"progressbar","style":"width: " + percent + "%"});
  parentEle.html("");
  insertElementAt(currentTime,parentEle[0]);
  insertElementAt(progressPercent,parentEle[1]);
  insertElementAt(durationTime,parentEle[2]);
}

function buildUpNext(parentEle, data){
  parentEle.html("");
  if ( data.length == 0 )
	return;
  var p = createElement("p");
  var title = createElement("b", null, "Up Next: ");
  var artist = createElement("span", null, data[0].title);
  var album = createElement("span", null, data[0].artist); 
  var dash = createText(" - ");
  
  insertElementAt(title, p);
  insertElementAt(artist, p);
  insertElementAt(dash, p);
  insertElementAt(album, p);
  if(data.length != 0)
    insertElementAt(p, parentEle[0]);
}

function setButtonSongId(parentEle, data){
  var cookie = $.cookie("songs");
  var songs = cookie != null ? JSON.parse(cookie) : Array();
  if($.inArray(data.song.id, songs) == -1) {
    parentEle.removeAttr("disabled");
    parentEle.data("song-id", data.song.id);
  }
  else {
    parentEle.attr("disabled", "disabled");
    parentEle.data("song-id", 0);
  }
  
}

function buildQueueTable(parentEle, data){
  var table = new Table(["order", "title", "album", "artist", "score"], ["#", "Song", "Album", "Artist", "+1"]);
  parentEle.html("");
  var counter = 1;
  table.addAdvancedColumnProcessor("order", function(data){
    return counter++;
  });
  table.setProperties("table", {"class":"table table-condensed table-striped"});
  var html = table.buildTable(data);
  insertElementAt(html, parentEle[0]);
}

function buildSongTable(parentEle, res){
  var table = new Table(["title", "score", "add"], ["Song", "+1", ""]);
  parentEle.html("");
  table.setProperties("table", {"class":"table table-condensed table-striped"});
  table.addAdvancedColumnProcessor("add", function(data){
    var button = createElement("button", {"class":"btn btn-info btn-sm pull-right"}, "Add To Queue");
    $(button).click(function(){
      $(this).attr("disabled", "disabled").delay(10000).queue(function(next){
        $(this).removeAttr("disabled");
        next();
      });
      console.log("queuing song " + data["id"]);
      queueSong(data["id"]);
    });
    return button;
  });
  var html = table.buildTable(res);
  insertElementAt(html, parentEle[0]);
}

function buildAlbumList(parentEle, data){
  var albumSongs = [];
  parentEle.html("");
  var rows = [];
  var currentRow = 0;
  for(album in data){
    var div = createElement("div", {"class":"col-sm-3"});
    var holder = createElement("div", {"class":"album-holder"});
    var holderInner = createElement("div", {"class":"place-holder album-holder-inner"})
    var a = createElement("a", {"href":"#", "data-toggle":"modal", "data-target":"#album-song-list", "data-album-id":album})
    var img = createElement("img", {"src":"http://placehold.it/250x250", "class":"img-responsive album-art loading"});
    var info = createElement("div", {"class":"text-center"});
    var title = createElement("p", {"class":"album-artist"}, data[album].title);
    var artist = createElement("p", {"class":"album-artist lead small"}, data[album].artist);

    var source = data[album].songs[0].art;
    $(img).attr("src", source).load(function(){
      $(this).hide().removeClass("loading").fadeIn();
    });
    
    if(album % 4 == 0) {
      currentRow++;
      rows[currentRow] = createElement("div", {"class":"row"});
      insertElementAt(rows[currentRow], parentEle[0]);
    }

    insertElementAt(img, holderInner);
    insertElementAt(holderInner, a);
    insertElementAt(a, holder);
    insertElementAt(title, info);
    insertElementAt(artist, info);
    insertElementAt(holder, div);
    insertElementAt(info, div);
    insertElementAt(div, rows[currentRow]);

    albumSongs.push(data[album].songs);
    $(a).data("songs", data[album].songs);
    $(a).data("title", data[album].title);
    $(a).click(function(){
      $this = $(this);
      $("#album-list-title").html($this.data("title"));
      buildSongTable($("#album-song-table"), $this.data("songs"));
    });
  }
  return albumSongs;
}
