Jamstash/app/subsonic/subsonic.js

497 lines
20 KiB
JavaScript

/**
* jamstash.subsonic.controller Module
*
* Access and use the Subsonic Server. The Controller is in charge of relaying the Service's messages to the user through the
* notifications.
*/
angular.module('jamstash.subsonic.controller', ['jamstash.subsonic.service', 'jamstash.player.service'])
.controller('SubsonicController', ['$scope', '$rootScope', '$routeParams', 'utils', 'globals', 'map', 'subsonic', 'notifications', 'player',
function ($scope, $rootScope, $routeParams, utils, globals, map, subsonic, notifications, player) {
'use strict';
$scope.settings = globals.settings;
$scope.itemType = 'ss';
$scope.Server = globals.settings.Server;
$scope.playlistMenu = [];
$scope.AutoAlbums = [
{ id: "random", name: "Random" },
{ id: "newest", name: "Recently Added" },
{ id: "starred", name: "Starred" },
{ id: "highest", name: "Top Rated" },
{ id: "frequent", name: "Most Played" },
{ id: "recent", name: "Recently Played" }
];
$scope.SelectedAlbumSort = globals.settings.DefaultAlbumSort;
$scope.AlbumSort = globals.AlbumSorts;
$rootScope.showIndex = subsonic.showIndex;
$scope.$watch("showIndex", function (newValue, oldValue) {
if (newValue !== oldValue) {
subsonic.showIndex = $rootScope.showIndex;
}
});
$scope.toggleIndex = function () {
if ($rootScope.showIndex) {
$rootScope.showIndex = false;
} else {
$rootScope.showIndex = true;
$scope.showPlaylist = false;
$scope.showPodcast = false;
}
$scope.saveDefaultSection('index');
};
$scope.showPlaylist = subsonic.showPlaylist;
$scope.$watch("showPlaylist", function (newValue, oldValue) {
if (newValue !== oldValue) {
subsonic.showPlaylist = $scope.showPlaylist;
}
});
$scope.togglePlaylist = function () {
if ($scope.showPlaylist) {
$scope.showPlaylist = false;
} else {
$scope.showPlaylist = true;
$rootScope.showIndex = false;
$scope.showPodcast = false;
}
$scope.saveDefaultSection('playlist');
};
$scope.showPodcast = subsonic.showPodcast;
$scope.$watch("showPodcast", function (newValue, oldValue) {
if (newValue !== oldValue) {
subsonic.showPodcast = $scope.showPodcast;
}
});
$scope.togglePodcast = function () {
if ($scope.showPodcast) {
$scope.showPodcast = false;
} else {
$scope.showPodcast = true;
$scope.showPlaylist = false;
$rootScope.showIndex = false;
}
$scope.saveDefaultSection('podcast');
};
$scope.saveDefaultSection = function (val) {
utils.setValue('DefaultSection', val, false);
};
$scope.openDefaultSection = function () {
var section = utils.getValue('DefaultSection');
switch (section) {
case 'index':
$rootScope.showIndex = true;
break;
case 'playlist':
$scope.showPlaylist = true;
break;
case 'podcast':
$scope.showPodcast = true;
break;
default:
break;
}
};
$scope.$watch("SelectedAlbumSort.id", function (newValue, oldValue) {
if (newValue !== oldValue) {
if (subsonic.song.length > 0) {
subsonic.sortSubsonicSongs(newValue);
} else if (subsonic.content.album.length > 0) {
subsonic.sortSubsonicAlbums(newValue);
var indexes = $.map(globals.AlbumSorts, function (obj, index) {
if (obj.id === newValue) {
return index;
}
});
globals.settings.DefaultAlbumSort = globals.AlbumSorts[indexes];
}
}
});
$rootScope.$watch("SelectedMusicFolder", function (newValue, oldValue) {
if (newValue !== oldValue) {
utils.setValue('MusicFolders', angular.toJson(newValue), true);
$scope.getArtists(newValue.id, true);
}
});
$scope.SearchType = globals.settings.DefaultSearchType;
$scope.SearchTypes = globals.SearchTypes;
$scope.playlistsGenre = globals.SavedGenres;
$scope.$watch("selectedGenre", function (newValue, oldValue) {
if (newValue !== oldValue) {
globals.SavedGenres.push(newValue);
utils.setValue('SavedGenres', globals.SavedGenres.join(), false);
}
});
$scope.rescanLibrary = function (data, event) {
$.ajax({
url: globals.BaseURL() + '/getUser.view?' + globals.BaseParams() + '&username=' + globals.settings.Username,
method: 'GET',
dataType: globals.settings.Protocol,
timeout: globals.settings.Timeout,
success: function (data) {
if (data["subsonic-response"].user.adminRole === true) {
//$.get(globals.settings.Server + '/musicFolderSettings.view?scanNow');
$.get(globals.settings.Server + '/musicFolderSettings.view?scanNow&' + globals.BaseParams());
} else {
alert('You are not logged in as an admin user!');
}
}
});
};
$scope.selectAll = function () {
$rootScope.selectAll($scope.song);
};
$scope.selectNone = function () {
$rootScope.selectNone($scope.song);
};
// TODO: Hyz: Replace
$scope.playAll = function () {
$rootScope.playAll($scope.song);
};
// TODO: Hyz: Replace
$scope.playFrom = function (index) {
$rootScope.playFrom(index, $scope.song);
};
// TODO: Hyz: Replace
$scope.removeSong = function (item) {
$rootScope.removeSong(item, $scope.song);
};
// TODO: Hyz: Replace
$scope.songsRemoveSelected = function () {
subsonic.songsRemoveSelected($scope.selectedSongs).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
});
};
$scope.getArtists = function (id, refresh) {
subsonic.getArtists(id, refresh).then(function (data) {
$scope.index = data.artists;
$scope.shortcut = data.shortcuts;
});
};
$scope.refreshArtists = function () {
utils.setValue('MusicFolders', null, true);
$scope.getArtists(0, true);
$scope.getPlaylists(true);
};
$scope.getAlbums = function (id, name) {
subsonic.getAlbums(id, name).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.BreadCrumbs = data.breadcrumb;
$scope.selectedAutoAlbum = data.selectedAutoAlbum;
$scope.selectedArtist = data.selectedArtist;
$scope.selectedAlbum = data.selectedAlbum;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
$scope.getAlbumListBy = function (id, off) {
subsonic.getAlbumListBy(id, off).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.BreadCrumbs = data.breadcrumb;
$scope.selectedAutoAlbum = data.selectedAutoAlbum;
$scope.selectedArtist = data.selectedArtist;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
/**
* Handles common actions with songs such as displaying them on the scope, adding them to the playing queue
* and playing the first song after adding them to the queue. Displays notifications for songs added to the playing queue
* Also handles error notifications in case of: a service error, a subsonic error or an HTTP error
* @param {Promise} promise a Promise that must be resolved with an array of songs or must be rejected with an object : {'reason': a message that can be displayed to a user, 'httpError': the HTTP error code, 'subsonicError': the error Object sent by Subsonic}
* @param {String} action the action to be taken with the songs. Must be 'add', 'play' or 'display'
* @return {Promise} the original promise passed in first param. That way we can chain it further !
*/
$scope.requestSongs = function (promise, action) {
promise.then(function (songs) {
if(action === 'play') {
player.emptyQueue().addSongs(songs).playFirstSong();
notifications.updateMessage(songs.length + ' Song(s) Added to Queue', true);
} else if (action === 'add') {
player.addSongs(songs);
notifications.updateMessage(songs.length + ' Song(s) Added to Queue', true);
} else if (action === 'display') {
$scope.album = [];
$scope.song = songs;
}
}, function (error) {
var errorNotif;
if (error.subsonicError !== undefined) {
errorNotif = error.reason + ' ' + error.subsonicError.message;
} else if (error.httpError !== undefined) {
errorNotif = error.reason + ' HTTP error ' + error.httpError;
} else {
errorNotif = error.reason;
}
notifications.updateMessage(errorNotif, true);
});
return promise;
};
$scope.getSongs = function (id, action) {
subsonic.getSongs(id, action).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
});
};
$scope.getRandomStarredSongs = function (action) {
var promise = subsonic.getRandomStarredSongs();
$scope.requestSongs(promise, action);
$scope.selectedPlaylist = null;
$scope.selectedAutoPlaylist = 'starred';
};
$scope.getRandomSongs = function (action, genre, folder) {
var promise = subsonic.getRandomSongs(genre, folder);
$scope.requestSongs(promise, action);
$scope.selectedPlaylist = null;
if (!isNaN(folder)) {
$scope.selectedAutoPlaylist = folder;
} else if (genre !== undefined && genre !== '' && genre !== 'Random') {
$scope.selectedAutoPlaylist = genre;
} else {
$scope.selectedAutoPlaylist = 'random';
}
};
$scope.getArtistByTag = function (id) { // Gets Artist by ID3 tag
$scope.selectedAutoAlbum = null;
$scope.selectedArtist = id;
var url = globals.BaseURL() + '/getArtist.view?' + globals.BaseParams() + '&id=' + id;
$.ajax({
url: url,
method: 'GET',
dataType: globals.settings.Protocol,
timeout: globals.settings.Timeout,
success: function (data) {
var items = [];
if (typeof data["subsonic-response"].artist !== 'undefined') {
if (data["subsonic-response"].artist.album.length > 0) {
items = data["subsonic-response"].artist.album;
} else {
items[0] = data["subsonic-response"].artist.album;
}
subsonic.content.album = [];
subsonic.song = [];
angular.forEach(items, function (item) {
subsonic.content.album.push(map.mapAlbum(item));
});
$scope.$apply();
} else {
notifications.updateMessage('No Albums Returned :(', true);
}
}
});
};
$scope.getAlbumByTag = function (id) { // Gets Album by ID3 tag
subsonic.getAlbumByTag(id).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.BreadCrumbs = data.breadcrumb;
$scope.selectedAutoAlbum = data.selectedAutoAlbum;
$scope.selectedArtist = data.selectedArtist;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
$scope.search = function () {
var query = $('#Search').val();
var type = $('#SearchType').val();
subsonic.search(query, type).then(function (data) {
//$scope.shortcut = data.shortcuts;
$scope.album = data.album;
$scope.song = data.song;
});
};
$scope.toggleAZ = function () {
$scope.toggleSubmenu('#submenu_AZIndex', '#AZIndex', 'right', 44);
};
$scope.getPlaylists = function (refresh) {
subsonic.getPlaylists(refresh).then(function (data) {
$scope.playlists = data.playlists;
$scope.playlistsPublic = data.playlistsPublic;
$scope.selectedAutoPlaylist = data.selectedAutoPlaylist;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
$scope.getPlaylist = function (id, action) {
subsonic.getPlaylist(id, action).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.selectedAutoPlaylist = data.selectedAutoPlaylist;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
$scope.getStarred = function (action, type) {
subsonic.getStarred(action, type).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.selectedAutoPlaylist = data.selectedAutoPlaylist;
$scope.selectedPlaylist = data.selectedPlaylist;
});
};
$scope.newPlaylist = function (data, event) {
subsonic.newPlaylist(data, event).then(function (data) {
$scope.getPlaylists(true);
});
};
$scope.deletePlaylist = function () {
subsonic.deletePlaylist().then(function (data) {
$scope.getPlaylists(true);
});
};
$scope.savePlaylist = function () {
var id = $scope.selectedPlaylist;
subsonic.savePlaylist().then(function (data) {
$scope.getPlaylist(id, '');
notifications.updateMessage('Playlist Updated!', true);
});
};
$scope.loadPlaylistsForMenu = function (data, event) {
$.ajax({
url: globals.BaseURL() + '/getPlaylists.view?' + globals.BaseParams(),
method: 'GET',
dataType: globals.settings.Protocol,
timeout: globals.settings.Timeout,
success: function (data) {
var playlists = [];
$scope.playlistMenu = [];
if (typeof data["subsonic-response"].playlists.playlist != 'undefined') {
if (data["subsonic-response"].playlists.playlist.length > 0) {
playlists = data["subsonic-response"].playlists.playlist;
} else {
playlists[0] = data["subsonic-response"].playlists.playlist;
}
angular.forEach(playlists, function (item, key) {
if (item.owner == globals.settings.Username) {
$scope.playlistMenu.push(map.mapPlaylist(item));
}
});
if ($scope.playlistMenu.length > 0) {
$scope.$apply();
$scope.toggleSubmenu('#submenu_AddToPlaylist', '#action_AddToPlaylist', 'left', 124);
} else {
notifications.updateMessage('No Playlists :(', true);
}
}
}
});
};
$scope.addToPlaylist = function (id) {
var songs = [];
if ($scope.selectedSongs.length !== 0) {
angular.forEach($scope.selectedSongs, function (item) {
songs.push(item.id);
});
var runningVersion = utils.parseVersionString(globals.settings.ApiVersion);
var minimumVersion = utils.parseVersionString('1.8.0');
if (utils.checkVersion(runningVersion, minimumVersion)) { // is 1.8.0 or newer
$.ajax({
type: 'GET',
url: globals.BaseURL() + '/updatePlaylist.view?' + globals.BaseParams(),
dataType: globals.settings.Protocol,
timeout: globals.settings.Timeout,
data: { playlistId: id, songIdToAdd: songs },
success: function (data) {
$scope.selectedSongs.length = 0;
notifications.updateMessage('Playlist Updated!', true);
},
traditional: true // Fixes POST with an array in JQuery 1.4
});
}
}
};
$scope.getGenres = function () {
subsonic.getGenres().then(function (data) {
$scope.Genres = data;
});
};
$scope.getPodcasts = function (refresh) {
subsonic.getPodcasts(refresh).then(function (data) {
$scope.podcasts = data;
});
};
$scope.getPodcast = function (id, action) {
subsonic.getPodcast(id, action).then(function (data) {
$scope.album = data.album;
$scope.song = data.song;
$scope.selectedPodcast = data.selectedPodcast;
});
};
$scope.getMusicFolders = function () {
$.ajax({
url: globals.BaseURL() + '/getMusicFolders.view?' + globals.BaseParams(),
method: 'GET',
dataType: globals.settings.Protocol,
timeout: globals.settings.Timeout,
success: function (data) {
if (data["subsonic-response"].musicFolders.musicFolder !== undefined) {
var folders = [];
if (data["subsonic-response"].musicFolders.musicFolder.length > 0) {
folders = data["subsonic-response"].musicFolders.musicFolder;
} else {
folders[0] = data["subsonic-response"].musicFolders.musicFolder;
}
folders.unshift({
"id": -1,
"name": "All Folders"
});
$rootScope.MusicFolders = folders;
if (utils.getValue('MusicFolders')) {
var folder = angular.fromJson(utils.getValue('MusicFolders'));
var i = 0, index = "";
angular.forEach($rootScope.MusicFolders, function (item, key) {
if (item.id == folder.id) {
index = i;
}
i++;
});
$rootScope.SelectedMusicFolder = $rootScope.MusicFolders[index];
} else {
$rootScope.SelectedMusicFolder = $rootScope.MusicFolders[0];
}
$scope.$apply();
}
}
});
};
/**
* Change the order of playlists through jQuery UI's sortable
*/
$scope.dragStart = function (event, ui) {
ui.item.data('start', ui.item.index());
};
$scope.dragEnd = function (event, ui) {
var start = ui.item.data('start'),
end = ui.item.index();
$scope.song.splice(end, 0, $scope.song.splice(start, 1)[0]);
};
$scope.playSong = function (song) {
player.play(song);
};
$scope.addSongToQueue = function(song) {
player.addSong(song);
};
/* Launch on Startup */
$scope.getArtists();
$scope.getAlbums();
$scope.getPlaylists();
$scope.getGenres();
$scope.getPodcasts();
$scope.openDefaultSection();
$scope.getMusicFolders();
if ($routeParams.artistId && $routeParams.albumId) {
$scope.getAlbumByTag($routeParams.albumId);
} else if ($routeParams.artistId) {
$scope.getAlbums($routeParams.artistId);
}
/* End Startup */
}]);