/* * Copyright (C) 2005-2011 Team XBMC * http://www.xbmc.org * * 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, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ var MediaLibrary = function() { this.init(); return true; }; MediaLibrary.prototype = { playlists: { }, init: function() { this.bindControls(); this.getPlaylists(); }, bindControls: function() { $('#musicLibrary').click(jQuery.proxy(this.musicLibraryOpen, this)); $('#movieLibrary').click(jQuery.proxy(this.movieLibraryOpen, this)); $('#tvshowLibrary').click(jQuery.proxy(this.tvshowLibraryOpen, this)); $('#pictureLibrary').click(jQuery.proxy(this.pictureLibraryOpen, this)); $('#remoteControl').click(jQuery.proxy(this.remoteControlOpen, this)); $('#overlay').click(jQuery.proxy(this.hideOverlay, this)); $(window).resize(jQuery.proxy(this.updatePlayButtonLocation, this)); }, resetPage: function() { $('#musicLibrary').removeClass('selected'); $('#movieLibrary').removeClass('selected'); $('#tvshowLibrary').removeClass('selected'); $('#remoteControl').removeClass('selected'); $('#pictureLibrary').removeClass('selected'); this.hideOverlay(); }, replaceAll: function(haystack, find, replace) { var parts = haystack.split(find); var result = ""; var first = true; for (index in parts) { if (!first) result += replace; else first = false; result += parts[index]; } return result; }, getPlaylists: function() { jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?GetPlaylists', data: '{"jsonrpc": "2.0", "method": "Playlist.GetPlaylists", "id": 1}', timeout: 3000, success: jQuery.proxy(function(data) { if (data && data.result && data.result.length > 0) { $.each($(data.result), jQuery.proxy(function(i, item) { this.playlists[item.type] = item.playlistid; }, this)); } }, this), error: jQuery.proxy(function(data, error) { displayCommunicationError(); setTimeout(jQuery.proxy(this.updateState, this), 2000); }, this), dataType: 'json'}); }, remoteControlOpen: function(event) { this.resetPage(); $('#remoteControl').addClass('selected'); $('.contentContainer').hide(); var libraryContainer = $('#remoteContainer'); if (!libraryContainer || libraryContainer.length == 0) { $('#spinner').show(); libraryContainer = $('
'); libraryContainer.attr('id', 'remoteContainer') .addClass('contentContainer'); $('#content').append(libraryContainer); var keys=[ {name:'up',width:'40px',height:'30px',top:'28px',left:'58px'} ,{name:'down',width:'40px',height:'30px',top:'122px',left:'58px'} ,{name:'left',width:'40px',height:'30px',top:'74px',left:'15px'} ,{name:'right',width:'40px',height:'30px',top:'74px',left:'104px'} ,{name:'ok',width:'40px',height:'30px',top:'74px',left:'58px'} ,{name:'back',width:'40px',height:'30px',top:'13px',left:'161px'} ,{name:'home',width:'40px',height:'30px',top:'154px',left:'8px'} ,{name:'mute',width:'40px',height:'30px',top:'107px',left:'391px'} ,{name:'power',width:'30px',height:'30px',top:'-3px',left:'13px'} ,{name:'volumeup',width:'30px',height:'30px',top:'49px',left:'422px'} ,{name:'volumedown',width:'30px',height:'30px',top:'49px',left:'367px'} ,{name:'playpause',width:'32px',height:'23px',top:'62px',left:'260px'} ,{name:'stop',width:'32px',height:'23px',top:'62px',left:'211px'} ,{name:'next',width:'38px',height:'25px',top:'102px',left:'304px'} ,{name:'previous',width:'38px',height:'25px',top:'101px',left:'160px'} ,{name:'forward',width:'32px',height:'23px',top:'102px',left:'259px'} ,{name:'rewind',width:'32px',height:'23px',top:'101px',left:'211px'} ,{name:'cleanlib_a',width:'46px',height:'26px',top:'47px',left:'553px'} ,{name:'updatelib_a',width:'46px',height:'26px',top:'47px',left:'492px'} ,{name:'cleanlib_v',width:'46px',height:'26px',top:'111px',left:'553px'} ,{name:'updatelib_v',width:'46px',height:'26px',top:'111px',left:'492px'} ]; for (var akey in keys) { var aremotekey=$('

').attr('id',keys[akey]['name']); aremotekey.addClass('remote_key') .css('height',keys[akey]['height']) .css('width',keys[akey]['width']) .css('top',keys[akey]['top']) .css('left',keys[akey]['left']) //.css('border','1px solid black') .bind('click',{key: keys[akey]['name']},jQuery.proxy(this.pressRemoteKey,this)); libraryContainer.append(aremotekey); } } else { libraryContainer.show(); libraryContainer.trigger('scroll'); } $('#spinner').hide(); }, pressRemoteKey: function(event) { var keyPressed=event.data.key; $('#spinner').show(); var player = -1; // TODO: Get active player if($('#videoDescription').is(':visible')) player = this.playlists["video"]; else if($('#audioDescription').is(':visible')) player = this.playlists["audio"]; //common part switch(keyPressed) { case 'cleanlib_a': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "AudioLibrary.Clean", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'updatelib_a': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "AudioLibrary.Scan", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'cleanlib_v': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "VideoLibrary.Clean", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'updatelib_v': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'back': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Back", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'home': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Home", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'mute': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Application.SetMute", "params": { "mute": "toggle" }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'power': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "System.Shutdown", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'volumeup': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": { "properties": [ "volume" ] }, "id": 1}', success: jQuery.proxy(function(data) { var volume = data.result.volume + 1; jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Application.SetVolume", "params": { "volume": '+volume+' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); }, this), dataType: 'json'}); return; case 'volumedown': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": { "properties": [ "volume" ] }, "id": 1}', success: jQuery.proxy(function(data) { var volume = data.result.volume - 1; jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Application.SetVolume", "params": { "volume": '+volume+' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); }, this), dataType: 'json'}); return; } switch(keyPressed) { case 'up': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Up", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'down': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Down", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'left': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Left", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'right': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Right", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'ok': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Input.Select", "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; } if (player >= 0) { switch(keyPressed) { case 'playpause': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.PlayPause", "params": { "playerid": ' + player + ' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'stop': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.Stop", "params": { "playerid": ' + player + ' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'next': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.GoNext", "params": { "playerid": ' + player + ' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'previous': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.GoPrevious", "params": { "playerid": ' + player + ' }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'forward': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.SetSpeed", "params": { "playerid": ' + player + ', "speed": "increment" }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; case 'rewind': jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?SendRemoteKey', data: '{"jsonrpc": "2.0", "method": "Player.SetSpeed", "params": { "playerid": ' + player + ', "speed": "decrement" }, "id": 1}', success: jQuery.proxy(function(data) { $('#spinner').hide(); }, this), dataType: 'json'}); return; } } }, musicLibraryOpen: function(event) { this.resetPage(); $('#musicLibrary').addClass('selected'); $('.contentContainer').hide(); var libraryContainer = $('#libraryContainer'); if (!libraryContainer || libraryContainer.length == 0) { $('#spinner').show(); libraryContainer = $('

'); libraryContainer.attr('id', 'libraryContainer') .addClass('contentContainer'); $('#content').append(libraryContainer); jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?GetAlbums', data: '{"jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": { "limits": { "start": 0 }, "properties": ["description", "theme", "mood", "style", "type", "albumlabel", "artist", "genre", "rating", "title", "year", "thumbnail"], "sort": { "method": "artist" } }, "id": 1}', success: jQuery.proxy(function(data) { if (data && data.result && data.result.albums) { this.albumList = data.result.albums; $.each($(this.albumList), jQuery.proxy(function(i, item) { var floatableAlbum = this.generateThumb('album', item.thumbnail, item.title, item.artist); floatableAlbum.bind('click', { album: item }, jQuery.proxy(this.displayAlbumDetails, this)); libraryContainer.append(floatableAlbum); }, this)); libraryContainer.append($('
').addClass('footerPadding')); $('#spinner').hide(); libraryContainer.bind('scroll', { activeLibrary: libraryContainer }, jQuery.proxy(this.updateScrollEffects, this)); libraryContainer.trigger('scroll'); myScroll = new iScroll('libraryContainer'); } else { libraryContainer.html(''); } }, this), dataType: 'json'}); } else { libraryContainer.show(); libraryContainer.trigger('scroll'); } }, getThumbnailPath: function(thumbnail) { return thumbnail ? ('image/' + encodeURI(thumbnail)) : DEFAULT_ALBUM_COVER; }, generateThumb: function(type, thumbnail, title, artist) { var floatableAlbum = $('
'); var path = this.getThumbnailPath(thumbnail); title = title || ''; artist = artist ||''; if (title.length > 18 && !(title.length <= 21)) { title = title.substring(0, 18) + '...'; } if (artist.length > 20 && !(artist.length <= 22)) { artist = artist.substring(0, 20) + '...'; } var className = ''; var code = ''; switch(type) { case 'album': className = 'floatableAlbum'; code = '

' + title + '

' + artist + '

'; break; case 'movie': className = 'floatableMovieCover'; code = '

' + title + '

'; break; case 'tvshow': className = 'floatableTVShowCover'; break; case 'tvshowseason': className = 'floatableTVShowCoverSeason'; break; case 'image': case 'directory': className = 'floatableAlbum'; code = '

' + title + '

'; break; } return floatableAlbum.addClass(className).html('
' + title + '
' + code); }, showAlbumSelectorBlock: function(album) { if (album) { //Find album in stored array var prevAlbum = null, nextAlbum = null; $.each($(this.albumList), jQuery.proxy(function(i, item) { if (item.albumid == album.albumid) { if (this.albumList.length > 1) { prevAlbum = this.albumList[i <= 0 ? this.albumList.length-1 : i-1]; nextAlbum = this.albumList[i >= this.albumList.length ? 0 : i+1]; } return false; /* .each break */ } }, this)); var albumSelectorBlock = $('#albumSelector'); if (!albumSelectorBlock || albumSelectorBlock.length == 0) { albumSelectorBlock = $('
'); albumSelectorBlock.attr('id', 'albumSelector') .html('
All Albums  
'); $('#content').prepend(albumSelectorBlock); $('#albumSelector .allAlbums').bind('click', jQuery.proxy(this.hideAlbumDetails, this)); } $('#albumSelector .prevAlbum').unbind(); $('#albumSelector .nextAlbum').unbind(); if (prevAlbum) { $('#albumSelector .prevAlbum').bind('click', {album: prevAlbum}, jQuery.proxy(this.displayAlbumDetails, this)); } if (nextAlbum) { $('#albumSelector .nextAlbum').bind('click', {album: nextAlbum}, jQuery.proxy(this.displayAlbumDetails, this)); } $('#albumSelector .activeAlbumTitle').html(album.title||'Unknown Album'); albumSelectorBlock.show(); } }, hideAlbumDetails: function() { $('.contentContainer').hide(); this.musicLibraryOpen(); }, displayAlbumDetails: function(event) { this.showAlbumSelectorBlock(event.data.album); var albumDetailsContainer = $('#albumDetails' + event.data.album.albumid); $('#topScrollFade').hide(); if (!albumDetailsContainer || albumDetailsContainer.length == 0) { $('#spinner').show(); jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?GetSongs', data: '{"jsonrpc": "2.0", "method": "AudioLibrary.GetSongs", "params": { "properties": ["title", "artist", "genre", "track", "duration", "year", "rating", "playcount"], "albumid" : ' + event.data.album.albumid + ' }, "id": 1}', success: jQuery.proxy(function(data) { albumDetailsContainer = $('
'); albumDetailsContainer.attr('id', 'albumDetails' + event.data.album.albumid) .addClass('contentContainer') .addClass('albumContainer') .html('
Artwork NameTimeArtistGenre
'); $('.contentContainer').hide(); $('#content').append(albumDetailsContainer); var albumThumbnail = event.data.album.thumbnail; var albumTitle = event.data.album.title||'Unknown Album'; var albumArtist = event.data.album.artist||'Unknown Artist'; var trackCount = data.result.limits.total; $.each($(data.result.songs), jQuery.proxy(function(i, item) { if (i == 0) { var trackRow = $('').addClass('trackRow').addClass('tr' + i % 2); trackRow.append($('').attr('rowspan', ++trackCount + 1).addClass('albumThumb')); for (var a = 0; a < 5; a++) { trackRow.append($('').html(' ').attr('style', 'display: none')); } $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow); } var trackRow = $('').addClass('trackRow').addClass('tr' + i % 2).bind('click', { album: event.data.album, itmnbr: i }, jQuery.proxy(this.playTrack,this)); var trackNumberTD = $('') .html(item.track) trackRow.append(trackNumberTD); var trackTitleTD = $('') .html(item.title); trackRow.append(trackTitleTD); var trackDurationTD = $('') .addClass('time') .html(durationToString(item.duration)); trackRow.append(trackDurationTD); var trackArtistTD = $('') .html(item.artist); trackRow.append(trackArtistTD); var trackGenreTD = $('') .html(item.genre); trackRow.append(trackGenreTD); $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow); }, this)); if (trackCount > 0) { var trackRow = $('').addClass('fillerTrackRow'); for (var i = 0; i < 5; i++) { trackRow.append($('').html(' ')); } $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow); var trackRow2 = $('').addClass('fillerTrackRow2'); trackRow2.append($('').addClass('albumBG').html(' ')); for (var i = 0; i < 5; i++) { trackRow2.append($('').html(' ')); } $('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow2); } $('#albumDetails' + event.data.album.albumid + ' .albumThumb') .append(this.generateThumb('album', albumThumbnail, albumTitle, albumArtist)) .append($('
').addClass('footerPadding')); $('#spinner').hide(); myScroll = new iScroll('albumDetails' + event.data.album.albumid); }, this), dataType: 'json'}); } else { $('.contentContainer').hide(); $('#albumDetails' + event.data.album.albumid).show(); } }, togglePosterView: function(event){ var view=event.data.mode; var wthumblist,hthumblist,hthumbdetails; $("#toggleBanner").removeClass('activeMode'); $("#togglePoster").removeClass('activeMode'); $("#toggleLandscape").removeClass('activeMode'); switch(view) { case 'poster': setCookie('TVView','poster'); wthumblist='135px'; hthumblist='199px'; hthumbdetails='559px'; $("#togglePoster").addClass('activeMode'); break; case 'landscape': setCookie('TVView','landscape'); wthumblist='210px'; hthumblist='118px'; hthumbdetails='213px'; $("#toggleLandscape").addClass('activeMode'); break; default: //set banner view as default setCookie('TVView','banner'); wthumblist='379px'; hthumblist='70px'; hthumbdetails='70px'; $("#toggleBanner").addClass('activeMode'); break; } $(".floatableTVShowCover, .floatableTVShowCover div.imgWrapper, .floatableTVShowCover img, .floatableTVShowCover div.imgWrapper div.inner").css('width',wthumblist).css('height',hthumblist); $(".floatableTVShowCoverSeason div.imgWrapper, .floatableTVShowCoverSeason div.imgWrapper div.inner,.floatableTVShowCoverSeason img, .floatableTVShowCoverSeason").css('height',hthumbdetails); }, displayTVShowDetails: function(event) { var tvshowDetailsContainer = $('#tvShowDetails' + event.data.tvshow.tvshowid); $('#topScrollFade').hide(); toggle=this.toggle.detach(); if (!tvshowDetailsContainer || tvshowDetailsContainer.length == 0) { $('#spinner').show(); jQuery.ajax({ type: 'POST', contentType: 'application/json', url: JSON_RPC + '?GetTVShowSeasons', data: '{"jsonrpc": "2.0", "method": "VideoLibrary.GetSeasons", "params": { "properties": [ "season", "showtitle", "playcount", "episode", "thumbnail","fanart" ], "tvshowid" : ' + event.data.tvshow.tvshowid + ' }, "id": 1}', success: jQuery.proxy(function(data) { tvshowDetailsContainer = $('
'); tvshowDetailsContainer.attr('id', 'tvShowDetails' + event.data.tvshow.tvshowid) .css('display', 'none') .addClass('contentContainer') .addClass('tvshowContainer'); var showThumb = this.generateThumb('tvshowseason', event.data.tvshow.thumbnail, event.data.tvshow.title); if (data && data.result && data.result.seasons && data.result.seasons.length > 0) { var showDetails = $('
').addClass('showDetails'); showDetails.append(toggle); showDetails.append($('

').html(data.result.seasons[0].showtitle).addClass('showTitle')); var seasonSelectionSelect = $('