Skip to content

Commit

Permalink
Prepare v0.6.2
Browse files Browse the repository at this point in the history
  • Loading branch information
tkem committed Feb 11, 2015
1 parent 22a084b commit 8c0d06f
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 95 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
@@ -1,3 +1,9 @@
0.6.2 2015-02-11
----------------

- Playback time/seek improvements.


0.6.1 2015-02-11
----------------

Expand Down
2 changes: 1 addition & 1 deletion mopidy_mobile/__init__.py
Expand Up @@ -4,7 +4,7 @@

from mopidy import config, ext

__version__ = '0.6.1'
__version__ = '0.6.2'


def factory(config, core):
Expand Down
2 changes: 1 addition & 1 deletion www/js/connection.js
Expand Up @@ -184,7 +184,7 @@ angular.module('mopidy-mobile.connection', [])

return angular.extend(connection, {
on: function on(obj, listener) {
$log.info('on', obj, listener);
//$log.info('on', obj, listener);
if (listener === undefined) {
angular.forEach(obj, function(value, key) { on(key, value); });
} else if (obj in listeners) {
Expand Down
185 changes: 99 additions & 86 deletions www/js/playback.js
Expand Up @@ -12,30 +12,56 @@ angular.module('mopidy-mobile.playback', ['ionic', 'mopidy-mobile.settings'])
return connection(function(mopidy) {
return mopidy.tracklist.getOptions();
});
},
state: function(connection) {
return connection(function(mopidy) {
return mopidy.playback.getState();
});
},
tlTracks: function(connection) {
return connection(function(mopidy) {
var currentTlTrack;
return mopidy.playback.getCurrentTlTrack().then(function(tlTrack) {
currentTlTrack = tlTrack;
return mopidy.tracklist.getPlaybackTlTracks({tl_track: tlTrack});
}).then(function(tlTracks) {
return angular.extend(tlTracks, {current: currentTlTrack});
});
});
}
}
}
}
});
})

.controller('PlaybackCtrl', function($scope, $interval, $log, connection, options, state, tlTracks) {
.factory('timer', function($interval, $window) {
var timer = {
value: 0,
limit: null,
interval: null
};

return angular.extend(timer, {
update: function() {
//$log.log('update', timer.value, timer.limit);
var t = $window.parseInt(timer.value) + 1000;
if (timer.limit !== null) {
timer.value = Math.min(t, timer.limit);
} else {
timer.value = t;
}
},
start: function(value, limit) {
//$log.log('start', value, limit);
if (value !== undefined) {
timer.value = value;
}
if (limit !== undefined) {
timer.limit = limit;
}
if (!timer.interval) {
timer.interval = $interval(timer.update, 1000);
}
},
stop: function(value) {
//$log.log('stop', value);
if (value !== undefined) {
timer.value = value;
}
if (timer.interval) {
$interval.cancel(timer.interval);
timer.interval = null;
}
}
});
})

.controller('PlaybackCtrl', function($scope, $q, $window, $log, connection, options, timer) {
function setCurrentTlTrack(tlTrack) {
if (!tlTrack || !$scope.tlTracks.current || tlTrack.tlid !== $scope.tlTracks.current.tlid) {
connection(function(mopidy) {
Expand All @@ -62,21 +88,39 @@ angular.module('mopidy-mobile.playback', ['ionic', 'mopidy-mobile.settings'])
});
},
'event:playbackStateChanged': function(event) {
$scope.state = event.new_state;
if (($scope.state = event.new_state) === 'playing') {
$scope.time.start();
} else {
$scope.time.stop();
}
},
'event:trackPlaybackStarted': function(event) {
setCurrentTlTrack(event.tl_track);
'event:seeked': function(event) {
if (!$scope.time.pending) {
$scope.time.value = event.time_position;
}
},
'event:tracklistChanged': function() {
this.playback.getCurrentTlTrack().then(setCurrentTlTrack);
},
'event:trackPlaybackEnded':function() {
$scope.time.stop(0);
},
'event:trackPlaybackPaused': function(event) {
$scope.time.stop(event.time_position);
},
'event:trackPlaybackResumed': function(event) {
$scope.time.start(event.time_position);
},
'event:trackPlaybackStarted': function(event) {
setCurrentTlTrack(event.tl_track);
$scope.time.start(0, event.tl_track.track.length || null);
}
};

angular.extend($scope, {
options: options,
state: state,
tlTracks: tlTracks,
track: (tlTracks.current || tlTracks.eot || {track: null}).track,
time: timer,
tlTracks: {},
play: function() {
connection(function(mopidy) {
return mopidy.playback.play();
Expand Down Expand Up @@ -128,96 +172,65 @@ angular.module('mopidy-mobile.playback', ['ionic', 'mopidy-mobile.settings'])
}
});

connection.on(handlers);

$scope.$on('$destroy', function() {
connection.off(handlers);
$interval.cancel($scope.interval);
});
})

.controller('SeekCtrl', function($scope, $interval, $log, $q, $window, connection) {
var scope = angular.extend(this, {
value: 0,
pending: false,
interval: null
});
var handlers = {
'event:seeked': function(event) {
if (!scope.pending) {
scope.value = event.time_position;
}
},
'event:trackPlaybackEnded':function() {
$interval.cancel(scope.interval);
scope.value = 0;
},
'event:trackPlaybackPaused': function(event) {
$interval.cancel(scope.interval);
scope.value = event.time_position;
},
'event:trackPlaybackResumed': function(event) {
scope.value = event.time_position;
scope.interval = $interval(update, 1000);
},
'event:trackPlaybackStarted': function() {
scope.interval = $interval(update, 1000);
scope.value = 0;
}
};
connection.on(handlers);

function update() {
var t = $window.parseInt(scope.value);
$log.log('update: ' + t);
scope.value = t + 1000; // FIXME: store (computed) start time?
}

scope.change = function() {
if (scope.pending) {
$scope.seek = function() {
var time = $scope.time;
if (time.pending) {
return;
}
var defer = $q.defer();
function update(value) {
connection(function(mopidy) {
return mopidy.playback.seek({time_position: value});
}).then(function() {
if (value === $window.parseInt(scope.value)) {
if (value === $window.parseInt(time.value)) {
defer.resolve(value);
} else {
defer.notify(value);
}
});
}
scope.pending = true;
update($window.parseInt(scope.value));
time.pending = true;
update($window.parseInt(time.value));
defer.promise.then(
function(value) {
$log.debug('seek done: ' + value);
scope.pending = false;
time.pending = false;
}, function() {
$log.debug('seek error');
scope.pending = false;
time.pending = false;
}, function(value) {
$log.debug('seek pending: ' + value + ' (' + scope.value + ')');
update($window.parseInt(scope.value));
$log.debug('seek pending: ' + value + ' (' + time.value + ')');
update($window.parseInt(time.value));
}
);
};

$q.all({
state: connection(function(mopidy) { return mopidy.playback.getState(); }),
time: connection(function(mopidy) { return mopidy.playback.getTimePosition(); })
}).then(function(result) {
$log.debug('got state: ' + result.state + ', time position: ' + result.time);
scope.value = result.time;
if (result.state === 'playing') {
scope.interval = $interval(update, 1000);
}
connection.on(handlers);

$scope.$on('$ionicView.enter', function() {
connection(function(mopidy) {
return mopidy.constructor.when.join(
mopidy.playback.getCurrentTlTrack(),
mopidy.playback.getTimePosition(),
mopidy.playback.getState()
);
}).then(function(results) {
setCurrentTlTrack(results[0]);
if (($scope.state = results[2]) === 'playing') {
$scope.time.start(results[1], results[0].track.length || null);
} else {
$scope.time.stop(results[1]);
}
});
});

$scope.$on('$ionicView.leave', function() {
$log.log('leave view');
});

$scope.$on('$destroy', function() {
connection.off(handlers);
$scope.time.stop();
});
})

Expand Down
13 changes: 6 additions & 7 deletions www/templates/playback.html
@@ -1,14 +1,13 @@
<ion-view hide-nav-bar="true" view-title="{{'Playback' | translate}}">

<ion-header-bar ng-controller="SeekCtrl as seek">
<ion-header-bar>
<div class="range" style="width: 100%">
{{seek.value | duration}}
<input ng-change="seek.change()"
{{time.value | duration}}
<input min="0" max="{{track.length || 100}}"
ng-change="seek()"
ng-disabled="!track.length"
ng-model="seek.value"
type="range"
min="0"
max="{{track ? track.length - 1 : 0}}">
ng-model="time.value"
type="range">
{{track.length | duration}}
</div>
</ion-header-bar>
Expand Down

0 comments on commit 8c0d06f

Please sign in to comment.