
- subsonic-service no longer computes the offset, it gets it as an int param and uses it. - subsonic-controller is now in charge of computing the offset given a 'prev', 'next' or undefined param. It no longer allows the offset to go in the negatives, which made no sense. - subsonic-controller's scope's AutoAlbums array is now a map indexed by the type of auto-album. It also contains each item's offset so we no longer share the offset between auto-albums, which avoids weird behaviours. - Plus some minor code style fixes.
737 lines
27 KiB
JavaScript
737 lines
27 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', [
|
|
'ngLodash',
|
|
'jamstash.subsonic.service',
|
|
'jamstash.player.service',
|
|
'jamstash.persistence',
|
|
'jamstash.breadcrumbs.directive',
|
|
'jamstash.breadcrumbs.service'
|
|
])
|
|
|
|
.controller('SubsonicController', [
|
|
'$scope',
|
|
'$rootScope',
|
|
'$routeParams',
|
|
'$window',
|
|
'lodash',
|
|
'utils',
|
|
'globals',
|
|
'map',
|
|
'subsonic',
|
|
'notifications',
|
|
'player',
|
|
'persistence',
|
|
'breadcrumbs',
|
|
function (
|
|
$scope,
|
|
$rootScope,
|
|
$routeParams,
|
|
$window,
|
|
_,
|
|
utils,
|
|
globals,
|
|
map,
|
|
subsonic,
|
|
notifications,
|
|
player,
|
|
persistence,
|
|
breadcrumbs
|
|
) {
|
|
'use strict';
|
|
|
|
_.extend($scope, {
|
|
AlbumSort: globals.AlbumSorts,
|
|
autoAlbums: {
|
|
random: {
|
|
name: 'Random',
|
|
offset: 0
|
|
},
|
|
newest: {
|
|
name: 'Recently Added',
|
|
offset: 0
|
|
},
|
|
starred: {
|
|
name: 'Starred',
|
|
offset: 0
|
|
},
|
|
highest: {
|
|
name: 'Top Rated',
|
|
offset: 0
|
|
},
|
|
frequent: {
|
|
name: 'Most Played',
|
|
offset: 0
|
|
},
|
|
recent: {
|
|
name: 'Recently Played',
|
|
offset: 0
|
|
}
|
|
},
|
|
itemType: 'ss',
|
|
playlistMenu: [],
|
|
SelectedAlbumSort: globals.settings.DefaultAlbumSort,
|
|
Server: globals.settings.Server,
|
|
settings: globals.settings
|
|
});
|
|
|
|
$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;
|
|
}
|
|
};
|
|
var sortSubsonicAlbums = function (newValue) {
|
|
if (typeof newValue != 'undefined') {
|
|
//alert(newValue);
|
|
switch (newValue) {
|
|
case 'createdate desc':
|
|
$scope.album.sort(utils.sortDateFunction);
|
|
break;
|
|
case 'artist':
|
|
$scope.album.sort(utils.sortArtistFunction);
|
|
break;
|
|
case 'album':
|
|
$scope.album.sort(utils.sortAlbumFunction);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
var sortSubsonicSongs = function (newValue) {
|
|
if (typeof newValue != 'undefined') {
|
|
//alert(content.song.length);
|
|
switch (newValue) {
|
|
case 'createdate desc':
|
|
$scope.song.sort(utils.sortDateFunction);
|
|
break;
|
|
case 'artist':
|
|
$scope.song.sort(utils.sortArtistFunction);
|
|
break;
|
|
case 'album':
|
|
$scope.song.sort(utils.sortAlbumFunction);
|
|
break;
|
|
case 'track':
|
|
$scope.song.sort(utils.sortTrackFunction);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
$scope.$watch("SelectedAlbumSort.id", function (newValue, oldValue) {
|
|
if (newValue !== oldValue) {
|
|
if ($scope.song.length > 0) {
|
|
sortSubsonicSongs(newValue);
|
|
} else if ($scope.album.length > 0) {
|
|
sortSubsonicAlbums(newValue);
|
|
var indexes = $.map(globals.AlbumSorts, function (obj, index) {
|
|
if (obj.id === newValue) {
|
|
return index;
|
|
}
|
|
});
|
|
globals.settings.DefaultAlbumSort = globals.AlbumSorts[indexes];
|
|
}
|
|
}
|
|
});
|
|
|
|
$scope.$watch("SelectedMusicFolder", function (newValue, oldValue) {
|
|
if (newValue !== oldValue) {
|
|
var folderId;
|
|
if (newValue) {
|
|
folderId = newValue.id;
|
|
persistence.saveSelectedMusicFolder(newValue);
|
|
} else {
|
|
persistence.deleteSelectedMusicFolder();
|
|
}
|
|
$scope.getArtists(folderId);
|
|
}
|
|
});
|
|
|
|
$scope.searching = {
|
|
query: '',
|
|
typeId: globals.settings.DefaultSearchType,
|
|
types: 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 (folder) {
|
|
var savedFolder = $scope.SelectedMusicFolder;
|
|
if (isNaN(folder) && savedFolder) {
|
|
folder = savedFolder.id;
|
|
}
|
|
var promise = subsonic.getArtists(folder);
|
|
$scope.handleErrors(promise).then(function (data) {
|
|
$scope.index = data.index;
|
|
$scope.shortcut = data.shortcut;
|
|
}, function (error) {
|
|
$scope.index = [];
|
|
$scope.shortcut = [];
|
|
if (error.serviceError === true) {
|
|
notifications.updateMessage(error.reason, true);
|
|
}
|
|
});
|
|
};
|
|
|
|
$scope.refreshArtists = function () {
|
|
$scope.SelectedMusicFolder = undefined;
|
|
$scope.getArtists();
|
|
$scope.getPlaylists();
|
|
};
|
|
|
|
/**
|
|
* Handles error notifications in case of a subsonic error or an HTTP error. Sets a 'serviceError' flag when
|
|
* it is neither.
|
|
* @param {Promise} promise a Promise that must be resolved or 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}
|
|
* @return {Promise} the original promise passed as argument. That way we can chain it further !
|
|
*/
|
|
// TODO: Hyz: Move this to a response interceptor ?
|
|
$scope.handleErrors = function (promise) {
|
|
promise.then(null, 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 {
|
|
error.serviceError = true;
|
|
}
|
|
if (error.subsonicError !== undefined || error.httpError !== undefined) {
|
|
notifications.updateMessage(errorNotif, true);
|
|
}
|
|
});
|
|
return promise;
|
|
};
|
|
|
|
/**
|
|
* 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
|
|
* Handles error notifications in case of service 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}
|
|
* @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 !
|
|
*/
|
|
// TODO: Hyz: Maybe we should move this to a service
|
|
$scope.requestSongs = function (promise, action) {
|
|
$scope.handleErrors(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) {
|
|
if (error.serviceError === true) {
|
|
notifications.updateMessage(error.reason, true);
|
|
}
|
|
});
|
|
return promise;
|
|
};
|
|
|
|
/**
|
|
* Get songs from the subsonic server. Provide with the id of the directory and its name.
|
|
* If action is 'play' or 'add', the songs will be retrieved recursively until all sub-directories
|
|
* of the provided one have been called.
|
|
* level is the level in the breadcrumbs. Can be 'root' which resets the breadcrumbs to one level
|
|
* or can be 'forward' which adds a level to the breadcrumbs.
|
|
* @param {String} action 'play', 'add' or 'display'
|
|
* @param {int} id the id of the directory to get songs from
|
|
* @param {String} name the name of the directory to get songs from
|
|
* @param {String} level 'root' or 'forward'
|
|
*/
|
|
$scope.getSongs = function (action, id, name, level) {
|
|
var promise;
|
|
if (action === 'play' || action === 'add') {
|
|
promise = subsonic.recursiveGetSongs(id);
|
|
$scope.requestSongs(promise, action);
|
|
} else if (action === 'display') {
|
|
promise = subsonic.getSongs(id);
|
|
$scope.handleErrors(promise).then(function (data) {
|
|
$scope.album = data.directories;
|
|
$scope.song = data.songs;
|
|
if (level === 'root') {
|
|
breadcrumbs.reset().push({
|
|
id: id,
|
|
name: name
|
|
});
|
|
} else if (level === 'forward') {
|
|
breadcrumbs.push({
|
|
id: id,
|
|
name: name
|
|
});
|
|
}
|
|
$scope.selectedAutoAlbum = null;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = id;
|
|
$scope.selectedAutoPlaylist = null;
|
|
$scope.selectedPlaylist = null;
|
|
$scope.selectedPodcast = null;
|
|
if ($scope.SelectedAlbumSort.id !== 'default') {
|
|
sortSubsonicAlbums($scope.SelectedAlbumSort.id);
|
|
}
|
|
}, function (error) {
|
|
notifications.updateMessage(error.reason, true);
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.getAlbumListBy = function (type, off) {
|
|
var offset = (type) ? $scope.autoAlbums[type].offset : 0;
|
|
if (off === 'next') {
|
|
offset = offset + Number(globals.settings.AutoAlbumSize);
|
|
} else if (off === 'prev') {
|
|
offset = offset - Number(globals.settings.AutoAlbumSize);
|
|
if (offset < 0) { offset = 0; }
|
|
} else {
|
|
offset = 0;
|
|
}
|
|
$scope.autoAlbums[type].offset = offset;
|
|
var promise = subsonic.getAlbumListBy(type, offset);
|
|
$scope.handleErrors(promise).then(function (data) {
|
|
$scope.album = data;
|
|
if ($scope.SelectedAlbumSort.id !== 'default') {
|
|
sortSubsonicAlbums($scope.SelectedAlbumSort.id);
|
|
}
|
|
}, function (error) {
|
|
$scope.album = [];
|
|
notifications.updateMessage(error.reason, true);
|
|
});
|
|
$scope.song = [];
|
|
breadcrumbs.reset();
|
|
$scope.selectedAutoAlbum = type;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = null;
|
|
$scope.selectedAutoPlaylist = null;
|
|
$scope.selectedPlaylist = null;
|
|
$scope.selectedPodcast = null;
|
|
};
|
|
|
|
$scope.getRandomStarredSongs = function (action) {
|
|
var promise = subsonic.getRandomStarredSongs();
|
|
$scope.requestSongs(promise, action);
|
|
|
|
$scope.album = [];
|
|
breadcrumbs.reset();
|
|
$scope.selectedAutoAlbum = null;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = null;
|
|
$scope.selectedAutoPlaylist = 'starred';
|
|
$scope.selectedPlaylist = null;
|
|
$scope.selectedPodcast = null;
|
|
};
|
|
|
|
$scope.getRandomSongs = function (action, genre, folder) {
|
|
var promise = subsonic.getRandomSongs(genre, folder);
|
|
$scope.requestSongs(promise, action);
|
|
|
|
if (! isNaN(folder)) {
|
|
$scope.selectedAutoPlaylist = folder;
|
|
} else if (genre !== undefined && genre !== '' && genre !== 'Random') {
|
|
$scope.selectedAutoPlaylist = genre;
|
|
} else {
|
|
$scope.selectedAutoPlaylist = 'random';
|
|
}
|
|
$scope.album = [];
|
|
breadcrumbs.reset();
|
|
$scope.selectedAutoAlbum = null;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = null;
|
|
$scope.selectedPlaylist = null;
|
|
$scope.selectedPodcast = null;
|
|
};
|
|
|
|
$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.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 (query, type) {
|
|
if (query && query.length > 0) {
|
|
var promise = subsonic.search(query, type);
|
|
$scope.handleErrors(promise).then(function (data) {
|
|
if (type === 0) {
|
|
$scope.song = data;
|
|
$scope.album = [];
|
|
} else if (type === 1) {
|
|
$scope.song = [];
|
|
$scope.album = data;
|
|
} else if (type === 2) {
|
|
$scope.song = [];
|
|
$scope.album = [];
|
|
$scope.shortcut = data;
|
|
}
|
|
breadcrumbs.reset();
|
|
}, function (error) {
|
|
if (error.serviceError === true) {
|
|
notifications.updateMessage(error.reason, true);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
$scope.toggleAZ = function () {
|
|
$scope.toggleSubmenu('#submenu_AZIndex', '#AZIndex', 'right', 44);
|
|
};
|
|
|
|
$scope.getPlaylists = function () {
|
|
var promise = subsonic.getPlaylists();
|
|
$scope.handleErrors(promise).then(function (data) {
|
|
$scope.playlists = data.playlists;
|
|
$scope.playlistsPublic = data.playlistsPublic;
|
|
}, function () {
|
|
// Do not display a notification, there simply are no playlists.
|
|
// Otherwise, a notification will be displayed at every page reload.
|
|
$scope.playlists = [];
|
|
$scope.playlistsPublic = [];
|
|
});
|
|
};
|
|
|
|
$scope.getPlaylist = function (action, id) {
|
|
var promise = subsonic.getPlaylist(id);
|
|
$scope.requestSongs(promise, action).then(function (songs) {
|
|
if (action === 'display') {
|
|
notifications.updateMessage(songs.length + ' Song(s) in Playlist', true);
|
|
}
|
|
});
|
|
$scope.song = [];
|
|
$scope.album = [];
|
|
breadcrumbs.reset();
|
|
$scope.selectedAutoAlbum = null;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = null;
|
|
$scope.selectedAutoPlaylist = null;
|
|
$scope.selectedPlaylist = id;
|
|
$scope.selectedPodcast = null;
|
|
};
|
|
|
|
$scope.newPlaylist = function () {
|
|
var name = $window.prompt('Choose a name for your new playlist.', '');
|
|
if (name !== null && name !== '' && name !== 'null') {
|
|
var promise = subsonic.newPlaylist(name);
|
|
$scope.handleErrors(promise).then(function () {
|
|
$scope.getPlaylists();
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.deletePlaylist = function () {
|
|
if ($scope.selectedPlaylist !== null) {
|
|
var ok = $window.confirm('Are you sure you want to delete the selected playlist?');
|
|
if (ok) {
|
|
var promise = subsonic.deletePlaylist($scope.selectedPlaylist);
|
|
$scope.handleErrors(promise).then(function () {
|
|
$scope.getPlaylists();
|
|
});
|
|
}
|
|
} else {
|
|
notifications.updateMessage('Please select a playlist to delete.');
|
|
}
|
|
};
|
|
|
|
$scope.savePlaylist = function () {
|
|
if ($scope.selectedPlaylist !== null) {
|
|
var promise = subsonic.savePlaylist($scope.selectedPlaylist, $scope.song);
|
|
$scope.handleErrors(promise).then(function () {
|
|
$scope.getPlaylist('display', $scope.selectedPlaylist);
|
|
notifications.updateMessage('Playlist Updated!', true);
|
|
});
|
|
} else {
|
|
notifications.updateMessage('Please select a playlist to save.');
|
|
}
|
|
};
|
|
|
|
$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 () {
|
|
$scope.selectedSongs.length = 0;
|
|
notifications.updateMessage('Playlist Updated!', true);
|
|
},
|
|
traditional: true // Fixes POST with an array in JQuery 1.4
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
$scope.getGenres = function () {
|
|
var promise = subsonic.getGenres();
|
|
$scope.handleErrors(promise).then(function (genres) {
|
|
$scope.Genres = genres;
|
|
}, function () {
|
|
// Do not display a notification, there simply are no genres.
|
|
// Otherwise, a notification will be displayed at every page reload.
|
|
$scope.Genres = [];
|
|
});
|
|
};
|
|
|
|
$scope.getPodcasts = function () {
|
|
var promise = subsonic.getPodcasts();
|
|
$scope.handleErrors(promise).then(function (podcasts) {
|
|
$scope.podcasts = podcasts;
|
|
}, function () {
|
|
// Do not display a notification, there simply are no podcasts.
|
|
// Otherwise, a notification will be displayed at every page reload.
|
|
$scope.podcasts = [];
|
|
});
|
|
};
|
|
|
|
$scope.getPodcast = function (action, id) {
|
|
var promise = subsonic.getPodcast(id);
|
|
$scope.requestSongs(promise, action);
|
|
|
|
$scope.song = [];
|
|
$scope.album = [];
|
|
breadcrumbs.reset();
|
|
$scope.selectedAutoAlbum = null;
|
|
$scope.selectedArtist = null;
|
|
$scope.selectedAlbum = null;
|
|
$scope.selectedAutoPlaylist = null;
|
|
$scope.selectedPlaylist = null;
|
|
$scope.selectedPodcast = id;
|
|
};
|
|
|
|
$scope.getMusicFolders = function () {
|
|
var promise = subsonic.getMusicFolders();
|
|
$scope.handleErrors(promise).then(function (musicFolders) {
|
|
var folders = musicFolders;
|
|
$scope.MusicFolders = folders;
|
|
var savedFolder = persistence.getSelectedMusicFolder();
|
|
if (savedFolder) {
|
|
if (_.findIndex(folders, { id: savedFolder.id }) !== -1) {
|
|
$scope.SelectedMusicFolder = savedFolder;
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 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.emptyQueue().addSong(song).playFirstSong();
|
|
};
|
|
$scope.addSongToQueue = function (song) {
|
|
player.addSong(song);
|
|
};
|
|
|
|
/* Launch on Startup */
|
|
$scope.getMusicFolders();
|
|
$scope.getArtists();
|
|
$scope.getPlaylists();
|
|
$scope.getGenres();
|
|
$scope.getPodcasts();
|
|
$scope.openDefaultSection();
|
|
if ($routeParams.artistId && $routeParams.albumId) {
|
|
$scope.getAlbumByTag($routeParams.albumId);
|
|
} else if ($routeParams.artistId) {
|
|
$scope.getAlbums($routeParams.artistId);
|
|
}
|
|
/* End Startup */
|
|
}]);
|