Playback progress and position handling
This commit is contained in:
parent
e6869016f2
commit
9001436256
3 changed files with 89 additions and 2 deletions
|
@ -28,6 +28,7 @@ Python {
|
||||||
property bool ready: false
|
property bool ready: false
|
||||||
signal downloading(int episode_id)
|
signal downloading(int episode_id)
|
||||||
signal downloadProgress(int episode_id, real progress)
|
signal downloadProgress(int episode_id, real progress)
|
||||||
|
signal playbackProgress(int episode_id, real progress)
|
||||||
signal downloaded(int episode_id)
|
signal downloaded(int episode_id)
|
||||||
signal deleted(int episode_id)
|
signal deleted(int episode_id)
|
||||||
signal isNewChanged(int episode_id, bool is_new)
|
signal isNewChanged(int episode_id, bool is_new)
|
||||||
|
@ -41,6 +42,7 @@ Python {
|
||||||
|
|
||||||
setHandler('downloading', py.downloading);
|
setHandler('downloading', py.downloading);
|
||||||
setHandler('download-progress', py.downloadProgress);
|
setHandler('download-progress', py.downloadProgress);
|
||||||
|
setHandler('playback-progress', py.playbackProgress);
|
||||||
setHandler('downloaded', py.downloaded);
|
setHandler('downloaded', py.downloaded);
|
||||||
setHandler('deleted', py.deleted);
|
setHandler('deleted', py.deleted);
|
||||||
setHandler('is-new-changed', py.isNewChanged);
|
setHandler('is-new-changed', py.isNewChanged);
|
||||||
|
|
|
@ -24,15 +24,84 @@ import QtMultimedia 5.0
|
||||||
MediaPlayer {
|
MediaPlayer {
|
||||||
id: player
|
id: player
|
||||||
|
|
||||||
property int episode
|
property int episode: 0
|
||||||
property var queue: ([])
|
property var queue: ([])
|
||||||
property bool isPlaying: playbackState == MediaPlayer.PlayingState
|
property bool isPlaying: playbackState == MediaPlayer.PlayingState
|
||||||
|
|
||||||
|
property bool inhibitPositionEvents: false
|
||||||
|
property bool seekAfterPlay: false
|
||||||
|
property int seekTargetSeconds: 0
|
||||||
|
property int lastPosition: 0
|
||||||
|
property int lastDuration: 0
|
||||||
|
property int playedFrom: 0
|
||||||
|
|
||||||
function playbackEpisode(episode_id) {
|
function playbackEpisode(episode_id) {
|
||||||
player.episode = episode_id;
|
if (episode == episode_id) {
|
||||||
|
// If the episode is already loaded, just start playing
|
||||||
|
play();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, make sure we stop any seeking / position update events
|
||||||
|
sendPositionToCore(lastPosition);
|
||||||
|
player.inhibitPositionEvents = true;
|
||||||
|
player.stop();
|
||||||
|
|
||||||
py.call('main.play_episode', [episode_id], function (episode) {
|
py.call('main.play_episode', [episode_id], function (episode) {
|
||||||
|
// Load media / prepare and start playback
|
||||||
|
player.episode = episode_id;
|
||||||
player.source = episode.source;
|
player.source = episode.source;
|
||||||
|
player.seekTargetSeconds = episode.position;
|
||||||
|
seekAfterPlay = true;
|
||||||
|
|
||||||
player.play();
|
player.play();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function seekAndSync(target_position) {
|
||||||
|
sendPositionToCore(lastPosition);
|
||||||
|
seek(target_position);
|
||||||
|
playedFrom = target_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
onPlaybackStateChanged: {
|
||||||
|
if (playbackState == MediaPlayer.PlayingState) {
|
||||||
|
if (seekAfterPlay) {
|
||||||
|
// A seek was scheduled, execute now that we're playing
|
||||||
|
player.inhibitPositionEvents = false;
|
||||||
|
player.seek(seekTargetSeconds * 1000);
|
||||||
|
player.playedFrom = seekTargetSeconds * 1000;
|
||||||
|
seekAfterPlay = false;
|
||||||
|
} else {
|
||||||
|
player.playedFrom = position;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendPositionToCore(lastPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendPositionToCore(positionToSend) {
|
||||||
|
if (episode != 0 && !inhibitPositionEvents) {
|
||||||
|
var begin = playedFrom / 1000;
|
||||||
|
var end = positionToSend / 1000;
|
||||||
|
var duration = ((lastDuration > 0) ? lastDuration : 0) / 1000;
|
||||||
|
var diff = end - begin;
|
||||||
|
|
||||||
|
// Only send playback events if they are 2 seconds or longer
|
||||||
|
// (all other events might just be seeking events or wrong ones)
|
||||||
|
if (diff >= 2) {
|
||||||
|
py.call('main.report_playback_event', [episode, begin, end, duration]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPositionChanged: {
|
||||||
|
if (isPlaying && !inhibitPositionEvents) {
|
||||||
|
lastPosition = position;
|
||||||
|
lastDuration = duration;
|
||||||
|
|
||||||
|
// Directly update the playback progress in the episode list
|
||||||
|
py.playbackProgress(episode, position / duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
16
main.py
16
main.py
|
@ -93,6 +93,12 @@ class gPotherSide:
|
||||||
return ''
|
return ''
|
||||||
return 'file://' + filename
|
return 'file://' + filename
|
||||||
|
|
||||||
|
def _get_playback_progress(self, episode):
|
||||||
|
if episode.total_time > 0 and episode.current_position > 0:
|
||||||
|
return float(episode.current_position) / float(episode.total_time)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
def convert_podcast(self, podcast):
|
def convert_podcast(self, podcast):
|
||||||
total, deleted, new, downloaded, unplayed = podcast.get_statistics()
|
total, deleted, new, downloaded, unplayed = podcast.get_statistics()
|
||||||
|
|
||||||
|
@ -118,6 +124,7 @@ class gPotherSide:
|
||||||
'progress': episode.download_progress(),
|
'progress': episode.download_progress(),
|
||||||
'downloadState': episode.state,
|
'downloadState': episode.state,
|
||||||
'isNew': episode.is_new,
|
'isNew': episode.is_new,
|
||||||
|
'playbackProgress': self._get_playback_progress(episode),
|
||||||
}
|
}
|
||||||
|
|
||||||
def load_episodes(self, id):
|
def load_episodes(self, id):
|
||||||
|
@ -254,8 +261,16 @@ class gPotherSide:
|
||||||
'source': episode.local_filename(False)
|
'source': episode.local_filename(False)
|
||||||
if episode.state == gpodder.STATE_DOWNLOADED
|
if episode.state == gpodder.STATE_DOWNLOADED
|
||||||
else episode.url,
|
else episode.url,
|
||||||
|
'position': episode.current_position,
|
||||||
|
'total': episode.total_time,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def report_playback_event(self, episode_id, position_from, position_to, duration):
|
||||||
|
episode = self._get_episode_by_id(episode_id)
|
||||||
|
print('Played', episode.title, 'from', position_from, 'to', position_to, 'of', duration)
|
||||||
|
episode.report_playback_event(position_from, position_to, duration)
|
||||||
|
pyotherside.send('playback-progress', episode_id, self._get_playback_progress(episode))
|
||||||
|
|
||||||
def show_episode(self, episode_id):
|
def show_episode(self, episode_id):
|
||||||
episode = self._get_episode_by_id(episode_id)
|
episode = self._get_episode_by_id(episode_id)
|
||||||
if episode is None:
|
if episode is None:
|
||||||
|
@ -287,3 +302,4 @@ delete_episode = gpotherside.delete_episode
|
||||||
toggle_new = gpotherside.toggle_new
|
toggle_new = gpotherside.toggle_new
|
||||||
rename_podcast = gpotherside.rename_podcast
|
rename_podcast = gpotherside.rename_podcast
|
||||||
change_section = gpotherside.change_section
|
change_section = gpotherside.change_section
|
||||||
|
report_playback_event = gpotherside.report_playback_event
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue