@@ -56,6 +57,7 @@
+
diff --git a/js/controllers.js b/js/controllers.js
index a7ef1d2..b781824 100644
--- a/js/controllers.js
+++ b/js/controllers.js
@@ -96,7 +96,6 @@ function QueueListCtrl($scope, $rootScope, pageSwitcher, feedItems, feeds, downl
$scope.queue = queueList.getQueueList();
$scope.$on('queueListRefresh', function(event) {
- console.log('rebuilding');
$rootScope.$apply(queueList.rebuildList());
});
@@ -161,7 +160,7 @@ function TopBarCtrl($scope, player, pageSwitcher)
};
$scope.$on('playItem', function(event, feedItem) {
- player.play(feedItem, $scope);
+ player.play(feedItem);
});
$scope.currentInfo = function() {
@@ -188,7 +187,21 @@ function TopBarCtrl($scope, player, pageSwitcher)
return !!pageSwitcher.backPage;
};
- $scope.jumpAudio = function(distance) {
+ var lastForwardJump = 0,
+ forwardJumpCount = 1;
+
+ $scope.jumpAudioForward = function() {
+ var distance = 5;
+ if (lastForwardJump > new Date().getTime() - 2000) {
+ distance = forwardJumpCount * distance;
+ forwardJumpCount++;
+ } else {
+ forwardJumpCount = 0;
+ }
+
+ player.jumpAudio(distance);
+ };
+ $scope.jumpAudioBack = function(distance) {
player.jumpAudio(distance);
};
}
diff --git a/js/player.js b/js/player.js
new file mode 100644
index 0000000..cc4b34d
--- /dev/null
+++ b/js/player.js
@@ -0,0 +1,207 @@
+angular.module('podcasts.player', [])
+ .run(['player', function(player) {
+ var acm = navigator.mozAudioChannelManager;
+ if (acm) {
+ acm.addEventListener('headphoneschange', function onheadphoneschange() {
+ if (!acm.headphones && player.playing()) {
+ player.pause();
+ }
+ });
+ }
+ }])
+ .directive('progressBar', function($timeout) {
+ // return the directive link function. (compile function not needed)
+ return {
+ link: function(scope, element, attrs)
+ {
+ var timeoutId; // timeoutId, so that we can cancel the time updates
+
+ // used to update the UI
+ function updateWidth() {
+ var duration = scope.$eval(attrs.progressBarDuration),
+ current = scope.$eval(attrs.progressBarCurrent);
+
+ var percentage = Math.round(current / (duration / 100));
+
+ if (percentage > 100) {
+ percentage = 100;
+ }
+
+ element.css('width', percentage + '%');
+
+ scope.$digest();
+ }
+
+ // schedule update in one second
+ function updateLater() {
+ // save the timeoutId for canceling
+ timeoutId = $timeout(function() {
+ updateWidth(); // update DOM
+ updateLater(); // schedule another update
+ }, 1000, false);
+ }
+
+ function initDom() {
+ var currentProgressElement = angular.element('
');
+ element.append(currentProgressElement);
+ }
+
+ // listen on DOM destroy (removal) event, and cancel the next UI update
+ // to prevent updating time after the DOM element was removed.
+ element.on('$destroy', function() {
+ $timeout.cancel(timeoutId);
+ });
+
+ initDom();
+ updateLater(); // kick off the UI update process.
+ },
+ scope: true
+ };
+ })
+ .service('player', ['url', '$timeout', 'feedItems', '$rootScope', '$log', '$q', function(url, $timeout, feedItems, $rootScope, $log, $q) {
+ var audio,
+ currentFeedItem = null,
+ nowPlaying = {
+ position: 0,
+ duration: 0,
+ title: '',
+ description: '',
+ feed: '',
+ date: 0,
+ context: ''
+ };
+
+ audio = new Audio();
+ audio.setAttribute("mozaudiochannel", "content");
+ _addOfflineErrorHandler();
+ _addPauseEventListener();
+
+ function _addOfflineErrorHandler()
+ {
+ audio.addEventListener("error", function(event) {
+ $log.info('Error when loading audio file, continuing to next file');
+
+ var nextFeedItemPromise = feedItems.getNextInQueue(currentFeedItem);
+ $rootScope.$apply(nextFeedItemPromise.then(function(nextFeedItem) {
+ play(nextFeedItem);
+ }));
+ });
+ }
+
+ function _addPauseEventListener()
+ {
+ audio.addEventListener("pause", function(event) {
+ currentFeedItem.position = Math.floor(event.target.currentTime);
+ feedItems.save(currentFeedItem);
+ });
+ }
+
+ function play(feedItem, context)
+ {
+ var delayPlay = false;
+ if (feedItem) {
+ $log.info('playing: ' + feedItem.title);
+
+ currentFeedItem = feedItem;
+
+ var audioSrc;
+
+ if (feedItem.audio) {
+ $log.info('Playing audio from download');
+ audioSrc = url.createObjectUrl(feedItem.audio);
+ } else {
+ $log.info('Playing audio from web');
+ audioSrc = feedItem.audioUrl;
+ }
+
+ audio.src = audioSrc;
+ updateSong(feedItem);
+
+ if (feedItem.position) {
+ delayPlay = true;
+ angular.element(audio).bind("canplay", function(event) {
+ event.target.currentTime = feedItem.position;
+
+ angular.element(this).unbind("canplay");
+
+ audio.play();
+ });
+ }
+ }
+
+ if (!delayPlay) {
+ audio.play();
+ }
+
+ audio.addEventListener("ended", function(event) {
+ continueToNextItem(feedItem)
+ .then(function(nextFeedItem) {
+ play(nextFeedItem);
+
+ unQueueFeedItem(feedItem);
+ }, function(error) {
+ $log.warn('got Errror when fetching next feed item');
+
+ unQueueFeedItem(feedItem);
+ });
+
+ angular.element(this).unbind();
+ });
+ }
+
+ function continueToNextItem(feedItem)
+ {
+ var deferred = $q.defer();
+ feedItems.getNextInQueue(feedItem)
+ .then(function(nextFeedItem) {
+ deferred.resolve(nextFeedItem);
+ }, function(error) {
+ deferred.reject(error);
+ });
+
+ return deferred.promise;
+ }
+
+ function unQueueFeedItem(feedItem)
+ {
+ feedItem.queued = 0;
+ feedItem.position = 0;
+
+ feedItems.save(feedItem);
+ }
+
+ function pause()
+ {
+ audio.pause();
+ }
+
+ function playing()
+ {
+ return !audio.paused;
+ }
+
+ function updateSong(feedItem)
+ {
+ nowPlaying.title = feedItem.title;
+ nowPlaying.currentFeedItem = feedItem;
+ nowPlaying.description = feedItem.description;
+ nowPlaying.feed = feedItem.feed;
+ nowPlaying.date = feedItem.date;
+ }
+
+ function jumpAudio(distance)
+ {
+ audio.currentTime = audio.currentTime + distance;
+ }
+
+
+ return {
+ audio: audio,
+ feedItem: currentFeedItem,
+ nowPlaying: nowPlaying,
+ play: play,
+ pause: pause,
+ playing: playing,
+ jumpAudio: jumpAudio
+ };
+ }]);
\ No newline at end of file
diff --git a/js/services.js b/js/services.js
index 9f5a499..9103fa7 100644
--- a/js/services.js
+++ b/js/services.js
@@ -1,7 +1,7 @@
'use strict';
/* Services */
-angular.module('podcasts.services', ['podcasts.utilities', 'podcasts.queueList', 'podcasts.models'])
+angular.module('podcasts.services', ['podcasts.utilities', 'podcasts.queueList', 'podcasts.models', 'podcasts.player'])
.service('url', ['$window', function($window) {
return {
url: $window.URL || $window.webkitURL,
@@ -10,168 +10,6 @@ angular.module('podcasts.services', ['podcasts.utilities', 'podcasts.queueList',
}
};
}])
- .service('player', ['url', '$timeout', 'feedItems', '$rootScope', function(url, $timeout, feedItems, $rootScope) {
- var audio = new Audio();
- audio.setAttribute("mozaudiochannel", "content");
- var currentFeedItem = null;
- var nowPlaying = {position: 0, duration: 0, title: '', description: '', feed: '', date: 0};
- var hasOfflineErrorHandler = false;
- var hasPauseEventListener = false;
-
- var acm = navigator.mozAudioChannelManager;
-
- if (acm) {
- acm.addEventListener('headphoneschange', function onheadphoneschange() {
- if (!acm.headphones && playing()) {
- pause();
- }
- });
- }
-
- function addOfflineErrorHandler($scope)
- {
- if (!hasOfflineErrorHandler) {
- audio.addEventListener("error", function(event) {
- console.log('Error when loading audio file, continuing to next file');
-
- var nextFeedItemPromise = feedItems.getNextInQueue(currentFeedItem);
- $rootScope.$apply(nextFeedItemPromise.then(function(nextFeedItem) {
- play(nextFeedItem, $scope);
- }));
- });
-
- hasOfflineErrorHandler = true;
- }
- }
-
- function addPauseEventListener()
- {
- if (!hasPauseEventListener) {
- audio.addEventListener("pause", function(event) {
- console.log('paused audio');
- currentFeedItem.position = Math.floor(event.target.currentTime);
- feedItems.save(currentFeedItem);
- });
-
- hasPauseEventListener = true;
- }
- }
-
- function play(feedItem, $scope)
- {
- var delayPlay = false;
- if (feedItem) {
- console.log('playing: ' + feedItem.title);
-
- currentFeedItem = feedItem;
- var audioSrc;
-
- if (feedItem.audio) {
- console.log('Playing audio from download');
- audioSrc = url.createObjectUrl(feedItem.audio);
- } else {
- console.log('Playing audio from web');
- audioSrc = feedItem.audioUrl;
- }
-
- audio.src = audioSrc;
- updateSong(feedItem, $scope);
-
- addOfflineErrorHandler($scope);
- addPauseEventListener();
-
- if (feedItem.position) {
- delayPlay = true;
- angular.element(audio).bind('canplay', function(event) {
- this.currentTime = feedItem.position;
-
- angular.element(this).unbind('canplay');
-
- audio.play();
- });
- }
- }
-
- if (!delayPlay) {
- audio.play();
- }
-
- // TODO: add something here for when audio is done to remove from queue and go to next song
- audio.addEventListener("ended", function(event) {
- var nextFeedItemPromise = feedItems.getNextInQueue(feedItem);
- console.log('got promise for next feed item');
- $rootScope.$apply(nextFeedItemPromise.then(function(nextFeedItem) {
- console.log('Got next Feed Item:');
- console.log(nextFeedItem.title);
- play(nextFeedItem, $scope);
-
- feedItem.queued = 0;
- feedItem.position = 0;
-
- feedItems.save(feedItem);
- }, function(error) {
- console.log('got Errror when fetching next feed item');
-
- feedItem.queued = 0;
- feedItem.position = 0;
-
- feedItems.save(feedItem);
- }));
-
- angular.element(this).unbind();
- });
- }
-
- function pause()
- {
- audio.pause();
- }
-
- function playing()
- {
- return !audio.paused;
- }
-
- function updateSong(feedItem, $scope)
- {
- nowPlaying.title = feedItem.title;
- nowPlaying.currentFeedItem = feedItem;
- nowPlaying.description = feedItem.description;
- nowPlaying.feed = feedItem.feed;
- nowPlaying.date = feedItem.date;
- updatePosition($scope);
- }
-
- function updatePosition($scope)
- {
- $timeout(function() {
- nowPlaying.duration = audio.duration;
- }, 500);
-
- setInterval(function() {
- nowPlaying.position = audio.currentTime;
- $scope.$apply();
- }, 1000);
- }
-
- function jumpAudio(distance)
- {
- audio.currentTime = audio.currentTime + distance;
- }
-
-
- return {
- audio: audio,
- feedItem: currentFeedItem,
- nowPlaying: nowPlaying,
- play: play,
- pause: pause,
- playing: playing,
- updateSong: updateSong,
- updatePosition: updatePosition,
- jumpAudio: jumpAudio
- }
- }])
.service('pageSwitcher', ['$location', '$route', function($location, $route) {
return {
//TODO: change these getElementById's to something else
diff --git a/partials/info.html b/partials/info.html
index 91b9669..2366891 100644
--- a/partials/info.html
+++ b/partials/info.html
@@ -7,7 +7,7 @@
\ No newline at end of file