From 84232f3c120ed8e00271ded38f718ce9f1bded6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 19:22:27 +0100 Subject: [PATCH 1/6] Prepare resume playback dialog --- src/dialogs.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/dialogs.js b/src/dialogs.js index 4c153d70..10ce82da 100644 --- a/src/dialogs.js +++ b/src/dialogs.js @@ -162,6 +162,45 @@ class ClapperUriDialog extends Gtk.Dialog } }); +var ResumeDialog = GObject.registerClass( +class ClapperResumeDialog extends Gtk.MessageDialog +{ + _init(window, resumeInfo) + { + const percentage = Math.round((resumeInfo.time / resumeInfo.duration) * 100); + + const msg = [ + `Title: ${resumeInfo.title}`, + `Completed: ${percentage}%` + ].join('\n'); + + super._init({ + transient_for: window, + modal: true, + message_type: Gtk.MessageType.QUESTION, + buttons: Gtk.ButtonsType.YES_NO, + text: 'Resume playback?', + secondary_use_markup: true, + secondary_text: msg, + }); + + this.resumeInfo = resumeInfo; + this.connect('response', this._onResponse.bind(this)); + + this.show(); + } + + _onResponse(dialog, respId) + { + const { player } = this.transient_for.child; + + if(respId === Gtk.ResponseType.YES) + player.seek_seconds(this.resumeInfo.time); + + this.destroy(); + } +}); + var PrefsDialog = GObject.registerClass( class ClapperPrefsDialog extends Gtk.Dialog { From 15eeea2872c8a11877b4cb67946ab6cdd0945219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 20:02:19 +0100 Subject: [PATCH 2/6] Save resume info of last unfinished video --- data/com.github.rafostar.Clapper.gschema.xml | 8 ++++++++ src/player.js | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/data/com.github.rafostar.Clapper.gschema.xml b/data/com.github.rafostar.Clapper.gschema.xml index f0789201..93c3e91a 100644 --- a/data/com.github.rafostar.Clapper.gschema.xml +++ b/data/com.github.rafostar.Clapper.gschema.xml @@ -32,6 +32,14 @@ "second" Unit to use with seeking value + + true + Ask to resume unfinished video + + + '[]' + Data storing unfinished videos resume info + diff --git a/src/player.js b/src/player.js index f6092ea0..36da0d8c 100644 --- a/src/player.js +++ b/src/player.js @@ -372,6 +372,18 @@ class ClapperPlayer extends PlayerBase if(size[0] > 0 && size[1] > 0) clapperWidget._saveWindowSize(size); } + if(this.state !== GstClapper.ClapperState.STOPPED) { + let resumeInfo = {}; + if(settings.get_boolean('resume-enabled')) { + resumeInfo.title = this.playlistWidget.getActiveFilename(); + resumeInfo.time = Math.floor(this.position / 1000000000); + resumeInfo.duration = this.duration / 1000000000; + + debug(`saving resume info for: ${resumeInfo.title}`); + debug(`resume time: ${resumeInfo.time}, duration: ${resumeInfo.duration}`); + } + settings.set_string('resume-database', JSON.stringify([resumeInfo])); + } settings.set_double('volume-last', this.volume); clapperWidget.controls._onCloseRequest(); From dfbb8b8d70245a52b846641edf6c4b518a551a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 20:59:23 +0100 Subject: [PATCH 3/6] Ask to resume last unfinished video --- src/widget.js | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/src/widget.js b/src/widget.js index 2298b9ec..8224066a 100644 --- a/src/widget.js +++ b/src/widget.js @@ -1,6 +1,7 @@ const { Gdk, GLib, GObject, GstClapper, Gtk } = imports.gi; const { Controls } = imports.src.controls; const Debug = imports.src.debug; +const Dialogs = imports.src.dialogs; const Misc = imports.src.misc; const { Player } = imports.src.player; const Revealers = imports.src.revealers; @@ -487,21 +488,45 @@ class ClapperWidget extends Gtk.Grid this.revealerTop.endTime.set_visible(isNotStopped); } - _onPlayerDurationChanged(player) + _onPlayerDurationChanged(player, duration) { - const duration = Math.floor(player.get_duration() / 1000000000); + const durationSeconds = duration / 1000000000; + const durationFloor = Math.floor(durationSeconds); /* Sometimes GstPlayer might re-emit * duration changed during playback */ - if(this.controls.currentDuration === duration) + if(this.controls.currentDuration === durationFloor) return; - this.controls.currentDuration = duration; - this.controls.showHours = (duration >= 3600); + this.controls.currentDuration = durationFloor; + this.controls.showHours = (durationFloor >= 3600); - this.controls.positionAdjustment.set_upper(duration); - this.controls.durationFormatted = Misc.getFormattedTime(duration); + this.controls.positionAdjustment.set_upper(durationFloor); + this.controls.durationFormatted = Misc.getFormattedTime(durationFloor); this.controls.updateElapsedLabel(); + + if(settings.get_boolean('resume-enabled')) { + const resumeDatabase = JSON.parse(settings.get_string('resume-database')); + const title = player.playlistWidget.getActiveFilename(); + + debug(`searching database for resume info: ${title}`); + + const resumeInfo = resumeDatabase.find(info => { + return (info.title === title && info.duration === durationSeconds); + }); + + if(resumeInfo) { + debug('found resume info: ' + JSON.stringify(resumeInfo)); + new Dialogs.ResumeDialog(this.root, resumeInfo); + + const shrunkDatabase = resumeDatabase.filter(info => { + return !(info.title === title && info.duration === durationSeconds); + }); + settings.set_string('resume-database', JSON.stringify(shrunkDatabase)); + } + else + debug('resume info not found'); + } } _onPlayerPositionUpdated(player, position) From d952f37b0e5d16675a8ef56a6c5eb2fb295c9aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 21:24:44 +0100 Subject: [PATCH 4/6] Prevent saving unfinished video info when autoclosing --- src/player.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/player.js b/src/player.js index 36da0d8c..4c9f3858 100644 --- a/src/player.js +++ b/src/player.js @@ -372,7 +372,8 @@ class ClapperPlayer extends PlayerBase if(size[0] > 0 && size[1] > 0) clapperWidget._saveWindowSize(size); } - if(this.state !== GstClapper.ClapperState.STOPPED) { + /* If "quitOnStop" is set here it means that we are in middle of autoclosing */ + if(this.state !== GstClapper.ClapperState.STOPPED && !this.quitOnStop) { let resumeInfo = {}; if(settings.get_boolean('resume-enabled')) { resumeInfo.title = this.playlistWidget.getActiveFilename(); @@ -439,8 +440,8 @@ class ClapperPlayer extends PlayerBase if(settings.get_boolean('close-auto')) { /* Stop will be automatically called soon afterwards */ - this._performCloseCleanup(this.widget.get_root()); this.quitOnStop = true; + this._performCloseCleanup(this.widget.get_root()); } } From 17f73bb2228e9be663bac7034f4df761aa3f6afe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 21:53:22 +0100 Subject: [PATCH 5/6] Add resume last unfinished video setting to prefs --- src/prefs.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/prefs.js b/src/prefs.js index 1e516d15..c780dba7 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -70,6 +70,9 @@ class ClapperBehaviourPage extends PrefsBase.Grid ['percentage', "Percentage"], ], 'seeking-unit'); this.addSpinButton('Value', 1, 99, 'seeking-value'); + + this.addTitle('Resume'); + this.addCheckButton('Ask to resume last unfinished video', 'resume-enabled'); } }); From d1f32955b848c9fb7ae049f37000558cd1e358f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Mon, 8 Feb 2021 22:16:49 +0100 Subject: [PATCH 6/6] Do not save resume info under certain conditions Do not save when video is short, just started or almost finished --- src/player.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/player.js b/src/player.js index 4c9f3858..c57597ac 100644 --- a/src/player.js +++ b/src/player.js @@ -376,12 +376,20 @@ class ClapperPlayer extends PlayerBase if(this.state !== GstClapper.ClapperState.STOPPED && !this.quitOnStop) { let resumeInfo = {}; if(settings.get_boolean('resume-enabled')) { - resumeInfo.title = this.playlistWidget.getActiveFilename(); - resumeInfo.time = Math.floor(this.position / 1000000000); - resumeInfo.duration = this.duration / 1000000000; + const resumeTime = Math.floor(this.position / 1000000000); + const resumeDuration = this.duration / 1000000000; - debug(`saving resume info for: ${resumeInfo.title}`); - debug(`resume time: ${resumeInfo.time}, duration: ${resumeInfo.duration}`); + /* Do not save resume info when video is short, just started or almost finished */ + if(resumeDuration > 60 && resumeTime > 15 && resumeDuration - resumeTime > 20) { + resumeInfo.title = this.playlistWidget.getActiveFilename(); + resumeInfo.time = resumeTime; + resumeInfo.duration = resumeDuration; + + debug(`saving resume info for: ${resumeInfo.title}`); + debug(`resume time: ${resumeInfo.time}, duration: ${resumeInfo.duration}`); + } + else + debug('resume info is not worth saving'); } settings.set_string('resume-database', JSON.stringify([resumeInfo])); }