diff --git a/js/api.js b/js/api.js index e73269b..b196d28 100644 --- a/js/api.js +++ b/js/api.js @@ -278,3 +278,343 @@ function getRandomSongList(action, appendto) { } }); } + +function search(type, query) { + $.ajax({ + url: baseURL + '/search2.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&query=' + query, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + if (data["subsonic-response"].searchResult2 !== "") { + $("#AlbumRows").empty(); + var header = generateSongHeaderHTML(); + $("#AlbumHeader").html(header); + // There is a bug in the API that doesn't return a JSON array for one artist + var children = []; + if (data["subsonic-response"].searchResult2.song.length > 0) { + children = data["subsonic-response"].searchResult2.song; + } else { + children[0] = data["subsonic-response"].searchResult2.song; + } + + var rowcolor; + var albumhtml; + $.each(children, function (i, child) { + if (i % 2 === 0) { + rowcolor = 'even'; + } else { + rowcolor = 'odd'; + } + + var track; + if (child.track === undefined) { track = " "; } else { track = child.track; } + var time = secondsToTime(child.duration); + albumhtml = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']); + $(albumhtml).appendTo("#AlbumRows"); + }); + } + } + }); +} + +function loadPlaylists(refresh) { + if (refresh) { + $('#PlaylistContainer').empty(); + } + var content = $('#PlaylistContainer').html(); + if (content === "") { + // Load Playlists + $.ajax({ + url: baseURL + '/getPlaylists.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp', + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + var playlists = []; + if (data["subsonic-response"].playlists.playlist.length > 0) { + playlists = data["subsonic-response"].playlists.playlist; + } else { + playlists[0] = data["subsonic-response"].playlists.playlist; + } + $.each(playlists, function (i, playlist) { + var html = ""; + html += '
  • '; + html += '' + playlist.name + ''; + html += '
    '; + html += '
    '; + html += '
  • '; + $(html).appendTo("#PlaylistContainer"); + }); + } + }); + } +} +function loadPlaylistsForMenu(menu) { + $('#' + menu).empty(); + $.ajax({ + url: baseURL + '/getPlaylists.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp', + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + var playlists = []; + if (data["subsonic-response"].playlists.playlist.length > 0) { + playlists = data["subsonic-response"].playlists.playlist; + } else { + playlists[0] = data["subsonic-response"].playlists.playlist; + } + $.each(playlists, function (i, playlist) { + if (menu === 'submenu_AddCurrentToPlaylist') { + $("" + playlist.name + "
    ").appendTo("#" + menu); + } else { + $("" + playlist.name + "
    ").appendTo("#" + menu); + } + }); + //$("+ New Playlist
    ").appendTo("#submenu"); + } + }); +} +function newPlaylist() { + var reply = prompt("Choose a name for your new playlist.", ""); + if (reply) { + $.ajax({ + url: baseURL + '/createPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&name=' + reply, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + loadPlaylists(true); + } + }); + } +} +function deletePlaylist(id) { + $.ajax({ + url: baseURL + '/deletePlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + loadPlaylists(true); + $('#TrackContainer tbody').empty(); + } + }); +} +function addToPlaylist(playlistid, from) { + var selected = []; + var el; + if (from === 'current') { + el = $('#CurrentPlaylist table.songlist tr.selected'); + } else { + el = $('#Albums table.songlist tr.selected'); + } + el.each(function (index) { + selected.push($(this).attr('childid')); + }); + if (selected.length > 0) { + if (playlistid !== 'new') { // Create new playlist from here, will implement in UI later + // Get songs from playlist + var currentsongs = []; + $.ajax({ + url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + playlistid, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + // There is a bug in the API that doesn't return a JSON array for one artist + var children = []; + if (data["subsonic-response"].playlist.entry !== undefined) { + if (data["subsonic-response"].playlist.entry.length > 1) { + children = data["subsonic-response"].playlist.entry; + } else { + children[0] = data["subsonic-response"].playlist.entry; + } + $.each(children, function (i, child) { + currentsongs.push(child.id); + }); + } + var newsongs = []; + var count = 0; + $.each(selected, function (i, songid) { + if (jQuery.inArray(songid, currentsongs) === -1) { + currentsongs.push(songid); + count++; + } + }); + if (count > 0) { + $.ajax({ + type: 'GET', + url: baseURL + '/createPlaylist.view', + dataType: 'jsonp', + timeout: 10000, + data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", playlistId: playlistid, songId: currentsongs }, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + $('table.songlist tr.song').each(function () { + $(this).removeClass('selected'); + }); + updateMessage('Playlist Updated!'); + }, + traditional: true // Fixes POST with an array in JQuery 1.4 + }); + } + } + }); + } else { + $.ajax({ + type: 'GET', + url: baseURL + '/createPlaylist.view', + dataType: 'jsonp', + timeout: 10000, + data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", name: 'New Playlist', songId: selected }, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + $('table.songlist tr.song').each(function () { + $(this).removeClass('selected'); + }); + updateMessage('Playlist Created!'); + }, + traditional: true // Fixes POST with an array in JQuery 1.4 + }); + } + setTimeout(function () { $('div.submenu').fadeOut(); }, 100); + } +} +function addToCurrent(addAll) { + var count; + if (addAll) { + count = $('#AlbumContainer tr.song').length; + } else { + count = $('#AlbumContainer tr.selected').length; + } + if (count > 0) { + if (addAll) { + $('#AlbumContainer tr.song').each(function (index) { + $(this).clone().appendTo('#CurrentPlaylistContainer tbody'); + updateMessage(count + ' Song(s) Added'); + }); + } else { + $('#AlbumContainer tr.selected').each(function (index) { + $(this).clone().appendTo('#CurrentPlaylistContainer tbody'); + updateMessage(count + ' Song(s) Added'); + }); + } + } +} +function downloadItem(id) { + var url; + if (id) { + url = baseURL + '/download.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id; + window.location = url; + } + /* + $('table.songlist tr.selected').each(function (index) { + id = $(this).attr('childid'); + if (id) { + url = baseURL + '/download.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id; + window.location = url; + } + }); + */ +} +function savePlaylist(playlistid) { + var songs = []; + $('#TrackContainer tr.song').each(function (index) { + songs.push($(this).attr('childid')); + }); + if (songs.length > 0) { + $.ajax({ + type: 'GET', + url: baseURL + '/createPlaylist.view', + dataType: 'jsonp', + timeout: 10000, + data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", playlistId: playlistid, songId: songs }, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + getPlaylist(playlistid); + updateMessage('Playlist Updated!'); + }, + traditional: true // Fixes POST with an array in JQuery 1.4 + }); + } +} +function getPlaylist(id, action, appendto) { + $.ajax({ + url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + if (data["subsonic-response"].playlist.entry !== undefined) { + if (appendto === '#TrackContainer tbody') { + $(appendto).empty(); + var header = generateSongHeaderHTML(); + $("#TrackContainer thead").html(header); + } + if (action === 'autoplay') { + $(appendto).empty(); + } + // There is a bug in the API that doesn't return a JSON array for one artist + var children = []; + if (data["subsonic-response"].playlist.entry.length > 0) { + children = data["subsonic-response"].playlist.entry; + } else { + children[0] = data["subsonic-response"].playlist.entry; + } + + var rowcolor; + var html; + $.each(children, function (i, child) { + if (i % 2 === 0) { + rowcolor = 'even'; + } else { + rowcolor = 'odd'; + } + var track; + if (child.track === undefined) { track = " "; } else { track = child.track; } + var time = secondsToTime(child.duration); + html = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']); + $(html).appendTo(appendto); + }); + if (appendto === '#CurrentPlaylistContainer tbody') { + updateMessage(children.length + ' Song(s) Added'); + } + if (action === 'autoplay') { + autoPlay(); + } + } else { + if (appendto === '#TrackContainer tbody') { + $(appendto).empty(); + } + } + } + }); +} diff --git a/js/app.js b/js/app.js index a08fad7..25ddfd1 100644 --- a/js/app.js +++ b/js/app.js @@ -62,289 +62,6 @@ function loadTabContent(tab) { } } -var scrobbled = false; -function playSong(el, songid, albumid) { - $.ajax({ - url: baseURL + '/getMusicDirectory.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + albumid, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - var title, artist, album; - if (data["subsonic-response"].directory !== undefined) { - // There is a bug in the API that doesn't return a JSON array for one artist - var children = []; - if (data["subsonic-response"].directory.child.length > 0) { - children = data["subsonic-response"].directory.child; - } else { - children[0] = data["subsonic-response"].directory.child; - } - $.each(children, function (i, child) { - if (child.id === songid) { - title = child.title; - artist = child.artist; - album = child.album; - coverart = child.coverArt; - } - }); - } - $('#songdetails_song').html(title); - $('#songdetails_song').attr('parentid', albumid); - $('#songdetails_song').attr('childid', songid); - $('#songdetails_artist').html(artist + ' - ' + album); - $('#coverartimage').attr('href', baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + coverart); - $('#coverartimage img').attr('src', baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart); - $('#playermiddle').css('visibility', 'visible'); - $('#songdetails').css('visibility', 'visible'); - // SoundManager Initialize - var salt = Math.floor(Math.random() * 100000); - if (audio) { - soundManager.destroySound('audio'); - } - audio = soundManager.createSound({ - id: 'audio', - url: baseURL + '/stream.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&id=' + songid + '&salt=' + salt, - stream: true, - whileloading: function () { - if (debug) { - console.log('loaded:' + this.bytesLoaded + ' total:' + this.bytesTotal); - } - var percent = this.bytesLoaded / this.bytesTotal; - var scrubber = $('#audio_wrapper0').find(".scrubber"); - var loaded = $('#audio_wrapper0').find(".loaded"); - loaded.css('width', (scrubber.get(0).offsetWidth * percent) + 'px'); - }, - whileplaying: function () { - //console.log('position:' + this.position + ' duration:' + this.duration); - var percent = this.position / this.duration; - var scrubber = $('#audio_wrapper0').find(".scrubber"); - var progress = $('#audio_wrapper0').find(".progress"); - progress.css('width', (scrubber.get(0).offsetWidth * percent) + 'px'); - - var played = $('#audio_wrapper0').find(".played"); - var p = (this.duration / 1000) * percent, - m = Math.floor(p / 60), - s = Math.floor(p % 60); - played.html((m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s); - - // Scrobble song once percentage is reached - if (!scrobbled && p > 30 && (percent > 0.5 || p > 480)) { - scrobbleSong(true); - } - }, - onload: function () { - var duration = $('#audio_wrapper0').find(".duration"); - var dp = this.duration / 1000, - dm = Math.floor(dp / 60), - ds = Math.floor(dp % 60); - duration.html((dm < 10 ? '0' : '') + dm + ':' + (ds < 10 ? '0' : '') + ds); - }, - onfinish: function () { - var next = $('#CurrentPlaylistContainer tr.playing').next(); - changeTrack(next); - } - }); - audio.play('audio'); - - $('table.songlist tr.song').removeClass('playing'); - $(el).addClass('playing'); - $('#PlayTrack').find('img').attr('src', 'images/pause_24x32.png'); - $('#PlayTrack').addClass('playing'); - scrobbleSong(false); - scrobbled = false; - - if ($.cookie('EnableNotifications')) { - showNotification(baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart, toHTML.un(title), toHTML.un(artist + ' - ' + album)); - } - if ($.cookie('ScrollTitle')) { - scrollTitle(toHTML.un(artist) + ' - ' + toHTML.un(title)); - } else { - setTitle(toHTML.un(artist) + ' - ' + toHTML.un(title)); - } - } - }); -} -function scrobbleSong(submission) { - var songid = $('#songdetails_song').attr('childid'); - $.ajax({ - url: baseURL + '/scrobble.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + songid + "&submission=" + submission, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - if (submission) { - scrobbled = true; - } - } - }); -} -function rateSong(songid, rating) { - $.ajax({ - url: baseURL + '/setRating.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + songid + "&rating=" + rating, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - updateMessage('Rating Updated!'); - } - }); -} -function playPauseSong() { - var el = '#PlayTrack'; - if ($(el).hasClass('playing')) { - $(el).find('img').attr('src', 'images/play_24x32.png'); - $(el).removeClass('playing'); - $(el).addClass('paused'); - soundManager.pause('audio'); - } else if ($(el).hasClass('paused')) { - $(el).find('img').attr('src', 'images/pause_24x32.png'); - $(el).removeClass('paused'); - $(el).addClass('playing'); - soundManager.resume('audio'); - } else { - // Start playing song - var play = $('#CurrentPlaylistContainer tr.selected').first(); - if (changeTrack(play)) { - $(el).find('img').attr('src', 'images/pause_24x32.png'); - $(el).addClass('playing'); - } else { - var first = $('#CurrentPlaylistContainer tr').first(); - changeTrack(first); - } - } -} -function changeTrack(next) { - var songid = $(next).attr('childid'); - if (songid !== undefined) { - var albumid = $(next).attr('parentid'); - playSong(next, songid, albumid); - return true; - } else { - return false; - } -} -function autoPlay() { - var firstsong = $('#CurrentPlaylistContainer tr.song:first'); - var songid = $(firstsong).attr('childid'); - var albumid = $(firstsong).attr('parentid'); - playSong(firstsong, songid, albumid); -} -function search(type, query) { - $.ajax({ - url: baseURL + '/search2.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&query=' + query, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - if (data["subsonic-response"].searchResult2 !== "") { - $("#AlbumRows").empty(); - var header = generateSongHeaderHTML(); - $("#AlbumHeader").html(header); - // There is a bug in the API that doesn't return a JSON array for one artist - var children = []; - if (data["subsonic-response"].searchResult2.song.length > 0) { - children = data["subsonic-response"].searchResult2.song; - } else { - children[0] = data["subsonic-response"].searchResult2.song; - } - - var rowcolor; - var albumhtml; - $.each(children, function (i, child) { - if (i % 2 === 0) { - rowcolor = 'even'; - } else { - rowcolor = 'odd'; - } - - var track; - if (child.track === undefined) { track = " "; } else { track = child.track; } - var time = secondsToTime(child.duration); - albumhtml = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']); - $(albumhtml).appendTo("#AlbumRows"); - }); - } - } - }); -} -var starttime; -var updater; -function updateChatMessages() { - updater = $.periodic({ period: 1000, decay: 1.5, max_period: 1800000 }, function () { - $.ajax({ - periodic: this, - url: baseURL + '/getChatMessages.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&since=' + starttime, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - if (data["subsonic-response"].chatMessages.chatMessage === undefined) { - this.periodic.increment(); - } else { - var msgs = []; - if (data["subsonic-response"].chatMessages.chatMessage.length > 0) { - msgs = data["subsonic-response"].chatMessages.chatMessage; - } else { - msgs[0] = data["subsonic-response"].chatMessages.chatMessage; - } - this.periodic.reset(); - var sorted = msgs.sort(function (a, b) { - return a.time - b.time; - }); - var x = 1; - $.each(sorted, function (i, msg) { - var chathtml = '
    '; - chathtml += '' + $.format.date(new Date(parseInt(msg.time, 10)), 'hh:mm:ss a') + ' '; - chathtml += '' + msg.username + '
    '; - chathtml += '' + msg.message + ''; - chathtml += '
    '; - $(chathtml).appendTo("#ChatMsgs"); - if (x === sorted.length) { - starttime = msg.time; - } - x++; - }); - $("#ChatMsgs").linkify(); - $("#ChatMsgs").attr({ scrollTop: $("#ChatMsgs").attr("scrollHeight") }); - } - } - }); - }); -} -function stopUpdateChatMessages() { - updater.cancel(); -} -function addChatMessage(msg) { - $.ajax({ - type: 'GET', - url: baseURL + '/addChatMessage.view', - dataType: 'jsonp', - timeout: 10000, - data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", message: msg }, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - updater.reset(); - }, - traditional: true // Fixes POST with an array in JQuery 1.4 - }); -} var updaterNowPlaying; var updaterNowPlayingData; function updateNowPlaying() { @@ -398,301 +115,4 @@ function stopUpdateNowPlaying() { updaterNowPlaying.cancel(); } -function loadPlaylists(refresh) { - if (refresh) { - $('#PlaylistContainer').empty(); - } - var content = $('#PlaylistContainer').html(); - if (content === "") { - // Load Playlists - $.ajax({ - url: baseURL + '/getPlaylists.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp', - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - var playlists = []; - if (data["subsonic-response"].playlists.playlist.length > 0) { - playlists = data["subsonic-response"].playlists.playlist; - } else { - playlists[0] = data["subsonic-response"].playlists.playlist; - } - $.each(playlists, function (i, playlist) { - var html = ""; - html += '
  • '; - html += '' + playlist.name + ''; - html += '
    '; - html += '
    '; - html += '
  • '; - $(html).appendTo("#PlaylistContainer"); - }); - } - }); - } -} -function loadPlaylistsForMenu(menu) { - $('#' + menu).empty(); - $.ajax({ - url: baseURL + '/getPlaylists.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp', - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - var playlists = []; - if (data["subsonic-response"].playlists.playlist.length > 0) { - playlists = data["subsonic-response"].playlists.playlist; - } else { - playlists[0] = data["subsonic-response"].playlists.playlist; - } - $.each(playlists, function (i, playlist) { - if (menu === 'submenu_AddCurrentToPlaylist') { - $("" + playlist.name + "
    ").appendTo("#" + menu); - } else { - $("" + playlist.name + "
    ").appendTo("#" + menu); - } - }); - //$("+ New Playlist
    ").appendTo("#submenu"); - } - }); -} -function newPlaylist() { - var reply = prompt("Choose a name for your new playlist.", ""); - if (reply) { - $.ajax({ - url: baseURL + '/createPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&name=' + reply, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - loadPlaylists(true); - } - }); - } -} -function deletePlaylist(id) { - $.ajax({ - url: baseURL + '/deletePlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - loadPlaylists(true); - $('#TrackContainer tbody').empty(); - } - }); -} -function addToPlaylist(playlistid, from) { - var selected = []; - var el; - if (from === 'current') { - el = $('#CurrentPlaylist table.songlist tr.selected'); - } else { - el = $('#Albums table.songlist tr.selected'); - } - el.each(function (index) { - selected.push($(this).attr('childid')); - }); - if (selected.length > 0) { - if (playlistid !== 'new') { // Create new playlist from here, will implement in UI later - // Get songs from playlist - var currentsongs = []; - $.ajax({ - url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + playlistid, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - // There is a bug in the API that doesn't return a JSON array for one artist - var children = []; - if (data["subsonic-response"].playlist.entry !== undefined) { - if (data["subsonic-response"].playlist.entry.length > 1) { - children = data["subsonic-response"].playlist.entry; - } else { - children[0] = data["subsonic-response"].playlist.entry; - } - $.each(children, function (i, child) { - currentsongs.push(child.id); - }); - } - var newsongs = []; - var count = 0; - $.each(selected, function (i, songid) { - if (jQuery.inArray(songid, currentsongs) === -1) { - currentsongs.push(songid); - count++; - } - }); - if (count > 0) { - $.ajax({ - type: 'GET', - url: baseURL + '/createPlaylist.view', - dataType: 'jsonp', - timeout: 10000, - data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", playlistId: playlistid, songId: currentsongs }, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - $('table.songlist tr.song').each(function () { - $(this).removeClass('selected'); - }); - updateMessage('Playlist Updated!'); - }, - traditional: true // Fixes POST with an array in JQuery 1.4 - }); - } - } - }); - } else { - $.ajax({ - type: 'GET', - url: baseURL + '/createPlaylist.view', - dataType: 'jsonp', - timeout: 10000, - data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", name: 'New Playlist', songId: selected }, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - $('table.songlist tr.song').each(function () { - $(this).removeClass('selected'); - }); - updateMessage('Playlist Created!'); - }, - traditional: true // Fixes POST with an array in JQuery 1.4 - }); - } - setTimeout(function () { $('div.submenu').fadeOut(); }, 100); - } -} -function addToCurrent(addAll) { - var count; - if (addAll) { - count = $('#AlbumContainer tr.song').length; - } else { - count = $('#AlbumContainer tr.selected').length; - } - if (count > 0) { - if (addAll) { - $('#AlbumContainer tr.song').each(function (index) { - $(this).clone().appendTo('#CurrentPlaylistContainer tbody'); - updateMessage(count + ' Song(s) Added'); - }); - } else { - $('#AlbumContainer tr.selected').each(function (index) { - $(this).clone().appendTo('#CurrentPlaylistContainer tbody'); - updateMessage(count + ' Song(s) Added'); - }); - } - } -} -function downloadItem(id) { - var url; - if (id) { - url = baseURL + '/download.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id; - window.location = url; - } - /* - $('table.songlist tr.selected').each(function (index) { - id = $(this).attr('childid'); - if (id) { - url = baseURL + '/download.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id; - window.location = url; - } - }); - */ -} -function savePlaylist(playlistid) { - var songs = []; - $('#TrackContainer tr.song').each(function (index) { - songs.push($(this).attr('childid')); - }); - if (songs.length > 0) { - $.ajax({ - type: 'GET', - url: baseURL + '/createPlaylist.view', - dataType: 'jsonp', - timeout: 10000, - data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", playlistId: playlistid, songId: songs }, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function () { - getPlaylist(playlistid); - updateMessage('Playlist Updated!'); - }, - traditional: true // Fixes POST with an array in JQuery 1.4 - }); - } -} -function getPlaylist(id, action, appendto) { - $.ajax({ - url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + id, - method: 'GET', - dataType: 'jsonp', - timeout: 10000, - beforeSend: function (req) { - req.setRequestHeader('Authorization', auth); - }, - success: function (data) { - if (data["subsonic-response"].playlist.entry !== undefined) { - if (appendto === '#TrackContainer tbody') { - $(appendto).empty(); - var header = generateSongHeaderHTML(); - $("#TrackContainer thead").html(header); - } - if (action === 'autoplay') { - $(appendto).empty(); - } - // There is a bug in the API that doesn't return a JSON array for one artist - var children = []; - if (data["subsonic-response"].playlist.entry.length > 0) { - children = data["subsonic-response"].playlist.entry; - } else { - children[0] = data["subsonic-response"].playlist.entry; - } - - var rowcolor; - var html; - $.each(children, function (i, child) { - if (i % 2 === 0) { - rowcolor = 'even'; - } else { - rowcolor = 'odd'; - } - var track; - if (child.track === undefined) { track = " "; } else { track = child.track; } - var time = secondsToTime(child.duration); - html = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, child.artist, child.album, child.coverArt, child.userRating, time['m'], time['s']); - $(html).appendTo(appendto); - }); - if (appendto === '#CurrentPlaylistContainer tbody') { - updateMessage(children.length + ' Song(s) Added'); - } - if (action === 'autoplay') { - autoPlay(); - } - } else { - if (appendto === '#TrackContainer tbody') { - $(appendto).empty(); - } - } - } - }); -} diff --git a/js/chat.js b/js/chat.js new file mode 100644 index 0000000..2b07f96 --- /dev/null +++ b/js/chat.js @@ -0,0 +1,66 @@ +var starttime; +var updater; +function updateChatMessages() { + updater = $.periodic({ period: 1000, decay: 1.5, max_period: 1800000 }, function () { + $.ajax({ + periodic: this, + url: baseURL + '/getChatMessages.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&since=' + starttime, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + if (data["subsonic-response"].chatMessages.chatMessage === undefined) { + this.periodic.increment(); + } else { + var msgs = []; + if (data["subsonic-response"].chatMessages.chatMessage.length > 0) { + msgs = data["subsonic-response"].chatMessages.chatMessage; + } else { + msgs[0] = data["subsonic-response"].chatMessages.chatMessage; + } + this.periodic.reset(); + var sorted = msgs.sort(function (a, b) { + return a.time - b.time; + }); + var x = 1; + $.each(sorted, function (i, msg) { + var chathtml = '
    '; + chathtml += '' + $.format.date(new Date(parseInt(msg.time, 10)), 'hh:mm:ss a') + ' '; + chathtml += '' + msg.username + '
    '; + chathtml += '' + msg.message + ''; + chathtml += '
    '; + $(chathtml).appendTo("#ChatMsgs"); + if (x === sorted.length) { + starttime = msg.time; + } + x++; + }); + $("#ChatMsgs").linkify(); + $("#ChatMsgs").attr({ scrollTop: $("#ChatMsgs").attr("scrollHeight") }); + } + } + }); + }); +} +function stopUpdateChatMessages() { + updater.cancel(); +} +function addChatMessage(msg) { + $.ajax({ + type: 'GET', + url: baseURL + '/addChatMessage.view', + dataType: 'jsonp', + timeout: 10000, + data: { u: username, p: passwordenc, v: version, c: applicationName, f: "jsonp", message: msg }, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + updater.reset(); + }, + traditional: true // Fixes POST with an array in JQuery 1.4 + }); +} diff --git a/js/main.js b/js/main.js index 9f70827..a98b8c1 100644 --- a/js/main.js +++ b/js/main.js @@ -1,7 +1,7 @@ require(["jquery", "sm/soundmanager2-jsmin", "jquery.scrollTo-1.4.2-min", "jquery.disable.text.select.pack", "jquery.cookie", "jquery.base64", "jquery.dateFormat-1.0", "jquery.periodic", "jquery.shuffle", "fancybox/jquery.fancybox-1.3.4.pack", - "jquery.linkify-1.0-min", "utils", "api", "generators", "app", "ui-load", "ui-ready" + "jquery.linkify-1.0-min", "utils", "api", "generators", "chat", "player", "app", "ui-load", "ui-ready" ], function($) { $(function() { diff --git a/js/player.js b/js/player.js new file mode 100644 index 0000000..0b15410 --- /dev/null +++ b/js/player.js @@ -0,0 +1,176 @@ +var scrobbled = false; +function playSong(el, songid, albumid) { + $.ajax({ + url: baseURL + '/getMusicDirectory.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + albumid, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function (data) { + var title, artist, album; + if (data["subsonic-response"].directory !== undefined) { + // There is a bug in the API that doesn't return a JSON array for one artist + var children = []; + if (data["subsonic-response"].directory.child.length > 0) { + children = data["subsonic-response"].directory.child; + } else { + children[0] = data["subsonic-response"].directory.child; + } + $.each(children, function (i, child) { + if (child.id === songid) { + title = child.title; + artist = child.artist; + album = child.album; + coverart = child.coverArt; + } + }); + } + $('#songdetails_song').html(title); + $('#songdetails_song').attr('parentid', albumid); + $('#songdetails_song').attr('childid', songid); + $('#songdetails_artist').html(artist + ' - ' + album); + $('#coverartimage').attr('href', baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + coverart); + $('#coverartimage img').attr('src', baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart); + $('#playermiddle').css('visibility', 'visible'); + $('#songdetails').css('visibility', 'visible'); + // SoundManager Initialize + var salt = Math.floor(Math.random() * 100000); + if (audio) { + soundManager.destroySound('audio'); + } + audio = soundManager.createSound({ + id: 'audio', + url: baseURL + '/stream.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&id=' + songid + '&salt=' + salt, + stream: true, + whileloading: function () { + if (debug) { + console.log('loaded:' + this.bytesLoaded + ' total:' + this.bytesTotal); + } + var percent = this.bytesLoaded / this.bytesTotal; + var scrubber = $('#audio_wrapper0').find(".scrubber"); + var loaded = $('#audio_wrapper0').find(".loaded"); + loaded.css('width', (scrubber.get(0).offsetWidth * percent) + 'px'); + }, + whileplaying: function () { + //console.log('position:' + this.position + ' duration:' + this.duration); + var percent = this.position / this.duration; + var scrubber = $('#audio_wrapper0').find(".scrubber"); + var progress = $('#audio_wrapper0').find(".progress"); + progress.css('width', (scrubber.get(0).offsetWidth * percent) + 'px'); + + var played = $('#audio_wrapper0').find(".played"); + var p = (this.duration / 1000) * percent, + m = Math.floor(p / 60), + s = Math.floor(p % 60); + played.html((m < 10 ? '0' : '') + m + ':' + (s < 10 ? '0' : '') + s); + + // Scrobble song once percentage is reached + if (!scrobbled && p > 30 && (percent > 0.5 || p > 480)) { + scrobbleSong(true); + } + }, + onload: function () { + var duration = $('#audio_wrapper0').find(".duration"); + var dp = this.duration / 1000, + dm = Math.floor(dp / 60), + ds = Math.floor(dp % 60); + duration.html((dm < 10 ? '0' : '') + dm + ':' + (ds < 10 ? '0' : '') + ds); + }, + onfinish: function () { + var next = $('#CurrentPlaylistContainer tr.playing').next(); + changeTrack(next); + } + }); + audio.play('audio'); + + $('table.songlist tr.song').removeClass('playing'); + $(el).addClass('playing'); + $('#PlayTrack').find('img').attr('src', 'images/pause_24x32.png'); + $('#PlayTrack').addClass('playing'); + scrobbleSong(false); + scrobbled = false; + + if ($.cookie('EnableNotifications')) { + showNotification(baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=jsonp&size=50&id=' + coverart, toHTML.un(title), toHTML.un(artist + ' - ' + album)); + } + if ($.cookie('ScrollTitle')) { + scrollTitle(toHTML.un(artist) + ' - ' + toHTML.un(title)); + } else { + setTitle(toHTML.un(artist) + ' - ' + toHTML.un(title)); + } + } + }); +} +function scrobbleSong(submission) { + var songid = $('#songdetails_song').attr('childid'); + $.ajax({ + url: baseURL + '/scrobble.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + songid + "&submission=" + submission, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + if (submission) { + scrobbled = true; + } + } + }); +} +function rateSong(songid, rating) { + $.ajax({ + url: baseURL + '/setRating.view?u=' + username + '&p=' + passwordenc + '&v=' + version + '&c=' + applicationName + '&f=jsonp&id=' + songid + "&rating=" + rating, + method: 'GET', + dataType: 'jsonp', + timeout: 10000, + beforeSend: function (req) { + req.setRequestHeader('Authorization', auth); + }, + success: function () { + updateMessage('Rating Updated!'); + } + }); +} +function playPauseSong() { + var el = '#PlayTrack'; + if ($(el).hasClass('playing')) { + $(el).find('img').attr('src', 'images/play_24x32.png'); + $(el).removeClass('playing'); + $(el).addClass('paused'); + soundManager.pause('audio'); + } else if ($(el).hasClass('paused')) { + $(el).find('img').attr('src', 'images/pause_24x32.png'); + $(el).removeClass('paused'); + $(el).addClass('playing'); + soundManager.resume('audio'); + } else { + // Start playing song + var play = $('#CurrentPlaylistContainer tr.selected').first(); + if (changeTrack(play)) { + $(el).find('img').attr('src', 'images/pause_24x32.png'); + $(el).addClass('playing'); + } else { + var first = $('#CurrentPlaylistContainer tr').first(); + changeTrack(first); + } + } +} +function changeTrack(next) { + var songid = $(next).attr('childid'); + if (songid !== undefined) { + var albumid = $(next).attr('parentid'); + playSong(next, songid, albumid); + return true; + } else { + return false; + } +} +function autoPlay() { + var firstsong = $('#CurrentPlaylistContainer tr.song:first'); + var songid = $(firstsong).attr('childid'); + var albumid = $(firstsong).attr('parentid'); + playSong(firstsong, songid, albumid); +}