JamStash.service('model', function () { // Figure out how to move this, circular dependency with utils secondsToTime = function (secs) { // secs = 4729 var times = new Array(3600, 60, 1); var time = ''; var tmp; for (var i = 0; i < times.length; i++) { tmp = Math.floor(secs / times[i]); // 0: 4729/3600 = 1 // 1: 1129/60 = 18 // 2: 49/1 = 49 if (tmp < 1) { tmp = '00'; } else if (tmp < 10) { tmp = '0' + tmp; } if (i === 0 && tmp == '00') { } else { time += tmp; if (i < 2) { time += ':'; } } secs = secs % times[i]; } return time; }; this.Index = function (name, artist) { this.name = name; this.artist = artist; }; this.Artist = function (id, name) { this.id = id; this.name = name; }; this.Album = function (id, parentid, name, artist, artistId, coverartthumb, coverartfull, date, starred, description, url, type) { this.id = id; this.parentid = parentid; this.name = name; this.artist = artist; this.artistId = artistId; this.coverartthumb = coverartthumb; this.coverartfull = coverartfull; this.date = date; this.starred = starred; this.description = description; this.url = url; this.type = type; }; this.Song = function (id, parentid, track, name, artist, artistId, album, albumId, coverartthumb, coverartfull, duration, rating, starred, suffix, specs, url, position, description) { this.id = id; this.parentid = parentid; this.track = track; this.name = name; this.artist = artist; this.artistId = artistId; this.album = album; this.albumId = albumId; this.coverartthumb = coverartthumb; this.coverartfull = coverartfull; this.duration = duration; this.time = duration === '' ? '00:00' : secondsToTime(duration); this.rating = rating; this.starred = starred; this.suffix = suffix; this.specs = specs; this.url = url; this.position = position; this.selected = false; this.playing = false; this.description = description; this.displayName = this.name + " - " + this.album + " - " + this.artist; }; }); JamStash.service('notifications', function ($rootScope, globals) { var msgIndex = 1; this.updateMessage = function (msg, autohide) { if (msg != '') { var id = msgIndex; $('#messages').append('' + msg + ''); $('#messages').fadeIn(); $("#messages").scrollTo('100%'); var el = '#msg_' + id; if (autohide) { setTimeout(function () { $(el).fadeOut(function () { $(this).remove(); }); }, globals.settings.Timeout); } else { $(el).click(function () { $(el).fadeOut(function () { $(this).remove(); }); return false; }); } msgIndex++; } } this.requestPermissionIfRequired = function () { if (window.Notify.isSupported() && window.Notify.needsPermission()) { window.Notify.requestPermission(); } } this.hasNotificationPermission = function () { return (window.Notify.needsPermission() === false); } this.hasNotificationSupport = function () { return window.Notify.isSupported(); } var notifications = new Array(); this.showNotification = function (pic, title, text, type, bind) { if (this.hasNotificationPermission()) { //closeAllNotifications() var settings = {} if (bind = '#NextTrack') { settings.notifyClick = function () { $rootScope.nextTrack(); this.close(); }; } if (type == 'text') { settings.body = text; settings.icon = pic; } else if (type == 'html') { settings.body = text; } var notification = new Notify(title, settings); notifications.push(notification); setTimeout(function (notWin) { notWin.close(); }, globals.settings.Timeout, notification); notification.show(); } else { console.log("showNotification: No Permission"); } } this.closeAllNotifications = function () { for (notification in notifications) { notifications[notification].close(); } } }); // Directives JamStash.directive('sortable', function () { return { link: function (scope, elm, attrs) { elm.sortable({ start: scope.dragStart, update: scope.dragEnd }); elm.disableSelection(); } }; }); /* JamStash.directive('split', function () { return { link: function (scope, elm, attrs) { elm.splitPane(); } }; }); */ JamStash.directive('fancybox', function ($compile) { return { restrict: 'A', replace: false, link: function($scope, element, attrs) { $scope.fancyboxOpen = function() { var el = angular.element(element.html()), compiled = $compile(el); $.fancybox.open(el); compiled($scope); }; $scope.fancyboxOpenUrl = function () { var el = angular.element(element.html()), compiled = $compile(el); $.fancybox.open(el); compiled($scope); }; } }; }); JamStash.directive('songpreview', function ($compile, subsonic) { return { restrict: 'E', templateUrl: 'js/partials/songs.html', replace: false, // pass these two names from attrs into the template scope scope: { song: '@' }, link: function (scope, element, attrs) { subsonic.getSongTemplate(function (data) { scope.song = data; //var el = angular.element(element.html()), //var el = element.html(), //compiled = $compile(el); $.fancybox.open(element); //compiled($scope); }); } }; }); JamStash.directive('stopEvent', function () { return { restrict: 'A', link: function (scope, element, attr) { element.bind(attr.stopEvent, function (e) { e.stopPropagation(); }); } }; }); JamStash.directive('ngEnter', function () { return { scope: { onEnter: '&' }, link: function (scope, element) { console.log(scope); element.bind("keydown keypress", function (event) { if (event.which === 13) { scope.onEnter(); scope.$apply(); } }); } } }); JamStash.directive('ngDownload', function ($compile) { return { restrict: 'E', scope: { data: '=' }, link: function (scope, elm, attrs) { function getUrl() { return URL.createObjectURL(new Blob([JSON.stringify(scope.data)], { type: "application/json" })); } elm.append($compile( '' + 'Download' + '' )(scope)); scope.$watch(scope.data, function () { elm.children()[0].href = getUrl(); }); } }; }); JamStash.directive('stopEvent', function () { return { restrict: 'A', link: function (scope, element, attr) { element.bind(attr.stopEvent, function (e) { e.stopPropagation(); }); } }; }); JamStash.directive('ngEnter', function () { return function (scope, element, attrs) { element.bind("keydown keypress", function (event) { if (event.which === 13) { scope.$apply(function () { scope.$eval(attrs.ngEnter); }); event.preventDefault(); } }); }; }); /* Factory */ JamStash.factory('json', function ($http) { // Deferred loading return { getCollections: function (callback) { $http.get('js/json_collections.js').success(callback); }, getChangeLog: function (callback) { $http.get('js/json_changelog.js').success(callback); } }; }); /* JamStash.factory('template', function ($http, $compile, $http, $templateCache) { // Deferred loading return { getCollections: function (callback) { $http.get('js/json_collections.js', { cache: $templateCache }).success(callback); }, getChangeLog: function (callback) { $http.get('js/json_changelog.js', { cache: $templateCache }).success(callback); }, getSongs: function (callback) { templateUrl = 'js/partials/songs.html'; $http.get(templateUrl, { cache: $templateCache }).success(callback); } }; }); */ JamStash.service('map', function ($http, globals, utils, model) { this.mapArtist = function (data) { var name = ''; var artist = data.artist; var artists = []; if (artist.length > 0) { artists = artist; } else { artists[0] = artist; } angular.forEach(artists, function (item, key) { if (typeof item.name !== 'undefined') { item.name = item.name.toString(); } }); if (typeof data.name !== 'undefined') { name = data.name.toString(); } return new model.Index(name, artists); }; this.mapIndex = function (data) { var name, id = ''; if (typeof data.id !== 'undefined') { id = data.id; } if (typeof data.name !== 'undefined') { name = data.name.toString(); } return new model.Artist(id, name); }; this.mapAlbum = function (data) { var album = data; var title, coverartthumb, coverartfull, starred; if (typeof album.coverArt != 'undefined') { coverartthumb = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&size=160&id=' + album.coverArt; coverartfull = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&id=' + album.coverArt; } if (typeof album.starred !== 'undefined') { starred = true; } else { starred = false; } if (typeof album.title !== 'undefined') { title = album.title; } else { title = album.name; } var type; if (album.isDir) { type = 'byfolder'; } else { type = 'bytag'; } return new model.Album(album.id, album.parent, title, album.artist.toString(), album.artistId, coverartthumb, coverartfull, $.format.date(new Date(album.created), "yyyy-MM-dd h:mm a"), starred, '', '', type); }; this.mapSong = function (data) { var song = data; var url, title, artist, track, rating, starred, contenttype, suffix, description; var specs = '', coverartthumb = '', coverartfull = ''; if (typeof song.coverArt != 'undefined') { coverartthumb = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&size=30&id=' + song.coverArt; coverartfull = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&id=' + song.coverArt; } else { coverartthumb = 'images/albumdefault_60.jpg'; coverartfull = 'images/albumdefault_160.jpg'; } if (typeof song.description == 'undefined') { description = ''; } else { description = song.description; } if (typeof song.artist == 'undefined') { artist = ' '; } else { artist = song.artist.toString(); } if (typeof song.title == 'undefined') { title = ' '; } else { title = song.title.toString(); } if (typeof song.track == 'undefined') { track = ' '; } else { track = song.track.toString(); } if (typeof song.starred !== 'undefined') { starred = true; } else { starred = false; } if (song.bitRate !== undefined) { specs += song.bitRate + ' Kbps'; } if (song.transcodedSuffix !== undefined) { specs += ', transcoding:' + song.suffix + ' > ' + song.transcodedSuffix; } else { specs += ', ' + song.suffix; } if (song.transcodedSuffix !== undefined) { suffix = song.transcodedSuffix; } else { suffix = song.suffix; } if (suffix == 'ogg') { suffix = 'oga'; } var salt = Math.floor(Math.random() * 100000); url = globals.BaseURL() + '/stream.view?' + globals.BaseParams() + '&id=' + song.id + '&salt=' + salt; return new model.Song(song.id, song.parent, track, title, artist, song.artistId, song.album, song.albumId, coverartthumb, coverartfull, song.duration, song.userRating, starred, suffix, specs, url, 0, description); }; this.mapPlaylist = function (data) { return new model.Artist(data.id, data.name); }; this.mapPodcast = function (data) { var song = data; var url, track, rating, starred, contenttype, suffix, description, artist, album, title; var specs = '', coverartthumb = '', coverartfull = ''; if (typeof song.coverArt != 'undefined') { coverartthumb = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&size=60&id=' + song.coverArt; coverartfull = globals.BaseURL() + '/getCoverArt.view?' + globals.BaseParams() + '&id=' + song.coverArt; } if (typeof song.album == 'undefined') { album = ' '; } else { album = song.album.toString(); } if (typeof song.artist == 'undefined') { artist = ' '; } else { artist = song.artist.toString(); } if (typeof song.title == 'undefined') { title = ' '; } else { title = song.title.toString(); } if (typeof song.description == 'undefined') { description = ''; } else { description = song.description; } if (typeof song.track == 'undefined') { track = ' '; } else { track = song.track.toString(); } if (typeof song.starred !== 'undefined') { starred = true; } else { starred = false; } if (song.bitRate !== undefined) { specs += song.bitRate + ' Kbps'; } if (song.transcodedSuffix !== undefined) { specs += ', transcoding:' + song.suffix + ' > ' + song.transcodedSuffix; } else { specs += ', ' + song.suffix; } if (song.transcodedSuffix !== undefined) { suffix = song.transcodedSuffix; } else { suffix = song.suffix; } if (suffix == 'ogg') { suffix = 'oga'; } var salt = Math.floor(Math.random() * 100000); url = globals.BaseURL() + '/stream.view?' + globals.BaseParams() + '&id=' + song.streamId + '&salt=' + salt; return new model.Song(song.streamId, song.parent, track, title, artist, song.artistId, album, song.albumId, coverartthumb, coverartfull, song.duration, song.userRating, starred, suffix, specs, url, 0, description); }; }); JamStash.factory('archive', function ($rootScope, $http, $q, $sce, globals, model, utils, map, notifications) { var index = { shortcuts: [], artists: [] }; var content = { artist: [], album: [], song: [], breadcrumb: [], selectedArtist: null, selectedAlbum: null, selectedGenre: null, selectedArchiveAlbumSort: "date desc" }; var offset = 0; var mapAlbum = function (data) { var song = data; var coverartthumb, coverartfull, starred, title, album, publisher, avg_rating, downloads, identifier; var url = globals.archiveUrl + 'details/' + song.identifier; coverartthumb = 'images/albumdefault_50.jpg'; coverartfull = 'images/albumdefault_160.jpg'; if (parseInt(song.avg_rating) == 5) { starred = true; } else { starred = false; } if (typeof song.title == 'undefined') { title = ' '; } else { title = song.title.toString(); } if (typeof song.identifier == 'undefined') { identifier = ' '; } else { identifier = song.identifier.toString(); } if (typeof song.collection[0] == 'undefined') { album = ' '; } else { album = song.collection[0].toString(); } if (typeof song.source == 'undefined') { source = ' '; } else { source = song.source.toString(); } if (typeof song.date == 'undefined') { date = ' '; } else { date = song.date.toString(); } if (typeof song.publisher == 'undefined') { publisher = ' '; } else { publisher = song.publisher.toString(); } if (typeof song.avg_rating == 'undefined') { avg_rating = ' '; } else { avg_rating = song.avg_rating.toString(); } if (typeof song.downloads == 'undefined') { downloads = ' '; } else { downloads = song.downloads.toString(); } //var description = 'Details
'; var description = 'Source: ' + source + '
'; description += 'Date: ' + date + '
'; description += 'Transferer: ' + publisher + '
'; description += 'Rating: ' + avg_rating + '
'; description += 'Downloads: ' + downloads + '
'; return new model.Album(identifier, null, title, album, '', coverartthumb, coverartfull, $.format.date(new Date(song.publicdate), "yyyy-MM-dd h:mm a"), starred, $sce.trustAsHtml(description), url); }; var mapSong = function (key, song, server, dir, identifier, coverart) { var url, time, track, title, rating, starred, contenttype, suffix; var specs = ''; if (song.format == 'VBR MP3') { url = 'http://' + server + dir + key; if (typeof song.bitrate == 'undefined' || typeof song.format == 'undefined') { specs = ' '; } else { specs = song.bitrate + 'kbps, ' + song.format.toLowerCase(); } if (typeof song.track == 'undefined') { track = ' '; } else { track = song.track; } if (typeof song.title == 'undefined') { title = ' '; } else { title = song.title; } if (typeof song.length == 'undefined') { time = ' '; } else { time = utils.timeToSeconds(song.length); } return new model.Song(song.md5, identifier, song.track, title, song.creator, '', song.album, '', coverart, coverart, time, '', '', 'mp3', specs, url, 0, ''); } }; return { getArtists: function (query) { var deferred = $q.defer(); if (globals.settings.Debug) { console.log("LOAD ARCHIVE.ORG COLLECTIONS"); } var url = globals.archiveUrl + 'advancedsearch.php?q='; if (query !== '') { //url += 'collection:(' + collection + ') AND mediatype:(collection) AND identifier:(' + query + ')'; url += 'mediatype:(collection) AND identifier:(' + query + ')'; } else { url += 'collection:(collection)'; } url += '&fl[]=identifier&sort[]=&sort[]=&sort[]=&rows=50&page=1&output=json'; $.ajax({ url: url, method: 'GET', dataType: globals.settings.Protocol, timeout: globals.settings.Timeout, success: function (data) { if (data.response.docs.length > 0) { items = data.response.docs; //alert(JSON.stringify(data["response"])); content.artist = []; angular.forEach(items, function (item, key) { content.artist.push(item.identifier); }); } else { notifications.updateMessage("Sorry :(", true); } deferred.resolve(content); } }); return deferred.promise; }, getAlbums: function (name, filter) { var deferred = $q.defer(); if (name) { var url = globals.archiveUrl + 'advancedsearch.php?q='; if (name !== '') { content.selectedArtist = name; url += 'collection:(' + name + ') AND format:(MP3)'; } else if (content.selectedArtist) { name = content.selectedArtist; url += 'collection:(' + content.selectedArtist + ') AND format:(MP3)'; } else { url += 'collection:(' + name + ')'; } content.breadcrumb = []; content.breadcrumb.push({ 'type': 'artist', 'id': name, 'name': name }); if (filter.Source) { url += ' AND source:(' + filter.Source + ')'; } if (filter.Year) { if (parseInt(filter.Year)) { url += ' AND year:(' + filter.Year + ')'; } } if (filter.Description) { url += ' AND description:(' + filter.Description + ')'; } if (content.selectedArtist) { url += '&sort[]=' + globals.settings.DefaultArchiveAlbumSort; } url += '&fl[]=avg_rating,collection,date,description,downloads,headerImage,identifier,publisher,publicdate,source,subject,title,year'; url += '&rows=50&page=1&output=json'; $.ajax({ url: url, method: 'GET', dataType: globals.settings.Protocol, timeout: globals.settings.Timeout, success: function (data) { var items = []; if (data.response.docs.length > 0) { items = data.response.docs; //alert(JSON.stringify(data["response"])); content.album = []; content.song = []; angular.forEach(items, function (item, key) { content.album.push(mapAlbum(item)); }); notifications.updateMessage(content.album.length, true); } else { notifications.updateMessage("Sorry :(", true); } deferred.resolve(content); }, error: function () { notifications.updateMessage('Archive.org service down :('); } }); } else { deferred.resolve(content); } return deferred.promise; }, getSongs: function (id, action) { var deferred = $q.defer(); if (id) { content.selectedAlbum = id; if (content.breadcrumb.length > 0) { content.breadcrumb.splice(1, (content.breadcrumb.length - 1)); } content.breadcrumb.push({ 'type': 'album', 'id': id, 'name': id }); var url = globals.archiveUrl + 'details/' + id + '?output=json'; $.ajax({ url: url, method: 'GET', dataType: globals.settings.Protocol, timeout: globals.settings.Timeout, success: function (data) { var coverart = ''; var server = data.server; var dir = data.dir; var identifier = data.metadata.identifier[0]; if (typeof data.misc.image != 'undefined') { coverart = data.misc.image; } var items = data.files; if (action == 'add') { angular.forEach(items, function (item, key) { var song = mapSong(key, item, server, dir, identifier, coverart); if (song) { $rootScope.queue.push(song); } }); notifications.updateMessage(Object.keys(items).length + ' Song(s) Added to Queue', true); } else if (action == 'play') { $rootScope.queue = []; angular.forEach(items, function (item, key) { var song = mapSong(key, item, server, dir, identifier, coverart); if (song) { $rootScope.queue.push(song); } }); var next = $rootScope.queue[0]; $rootScope.playSong(false, next); notifications.updateMessage(Object.keys(items).length + ' Song(s) Added to Queue', true); } else { content.album = []; content.song = []; angular.forEach(items, function (item, key) { var song = mapSong(key, item, server, dir, identifier, coverart); if (song) { content.song.push(song); } }); } deferred.resolve(content); } }); } else { deferred.resolve(content); } return deferred.promise; } }; }); JamStash.factory('json', function ($http, $q) { // Deferred loading return { getCollections: function (callback) { //$http.get('js/json_collections.js').success(callback); var deferred = $q.defer(); var collections = ['etree', 'dnalounge']; deferred.resolve(collections); return deferred.promise; }, getChangeLog: function (callback) { $http.get('js/json_changelog.js').success(callback); } } }); /* Filters */ JamStash.filter('capitalize', function () { return function (input, scope) { return input.substring(0, 1).toUpperCase() + input.substring(1); }; }); JamStash.filter('musicfolder', function () { return function (items, scope) { return items.slice(1, items.length); }; }); JamStash.filter('capitalize', function () { return function (input, scope) { return input.substring(0, 1).toUpperCase() + input.substring(1); } });