From 83bec8e834ca27092d54c2f0badd5d333a2df8e9 Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Tue, 12 Jan 2021 18:26:28 +0100 Subject: [PATCH] Mark video chapters on progress bar --- clapper_src/player.js | 6 +++++ clapper_src/widget.js | 54 +++++++++++++++++++++++++++++++++++++++++++ css/styles.css | 50 +++++++++++++++++++++++++++++++++++---- 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/clapper_src/player.js b/clapper_src/player.js index f189a734..c58136a0 100644 --- a/clapper_src/player.js +++ b/clapper_src/player.js @@ -23,6 +23,7 @@ class ClapperPlayer extends PlayerBase this.playOnFullscreen = false; this.quitOnStop = false; + this.needsTocUpdate = true; this.posX = 0; this.posY = 0; @@ -191,6 +192,10 @@ class ClapperPlayer extends PlayerBase seek(position) { + /* avoid seek emits when position bar is altered */ + if(this.needsTocUpdate) + return; + this.seek_done = false; if(this.state === GstPlayer.PlayerState.STOPPED) @@ -417,6 +422,7 @@ class ClapperPlayer extends PlayerBase _onUriLoaded(player, uri) { debug(`URI loaded: ${uri}`); + this.needsTocUpdate = true; if(!this.doneStartup) { this.doneStartup = true; diff --git a/clapper_src/widget.js b/clapper_src/widget.js index 6fbfc8ff..50e6938a 100644 --- a/clapper_src/widget.js +++ b/clapper_src/widget.js @@ -205,6 +205,14 @@ class ClapperWidget extends Gtk.Grid this.isSeekable = mediaInfo.is_seekable(); this.controls.setLiveMode(isLive, this.isSeekable); + if(this.player.needsTocUpdate) { + /* FIXME: Remove `get_toc` check after required GstPlay(er) ver bump */ + if(!isLive && mediaInfo.get_toc) + this.updateChapters(mediaInfo.get_toc()); + + this.player.needsTocUpdate = false; + } + const streamList = mediaInfo.get_stream_list(); const parsedInfo = { videoTracks: [], @@ -342,6 +350,50 @@ class ClapperWidget extends Gtk.Grid return nextUpdate; } + updateChapters(toc) + { + if(!toc) return; + + const entries = toc.get_entries(); + if(!entries) return; + + for(let entry of entries) { + const subentries = entry.get_sub_entries(); + if(!subentries) continue; + + for(let subentry of subentries) + this._parseTocSubentry(subentry); + } + } + + _parseTocSubentry(subentry) + { + const [success, start, stop] = subentry.get_start_stop_times(); + if(!success) { + debug('could not obtain toc subentry start/stop times'); + return; + } + + /* FIXME: Use higher precision for position scale */ + const pos = Math.floor(start / 1000000) / 1000; + this.controls.positionScale.add_mark(pos, Gtk.PositionType.TOP, null); + this.controls.positionScale.add_mark(pos, Gtk.PositionType.BOTTOM, null); + + const tags = subentry.get_tags(); + if(!tags) { + debug('could not obtain toc subentry tags'); + return; + } + + const [isString, title] = tags.get_string('title'); + if(!isString) { + debug('toc subentry tag does not have a title'); + return; + } + + debug(`chapter at ${pos}: ${title}`); + } + showVisualizationsButton(isShow) { if(isShow && !this.controls.visualizationsButton.isVisList) { @@ -386,6 +438,8 @@ class ClapperWidget extends Gtk.Grid switch(state) { case GstPlayer.PlayerState.BUFFERING: debug('player state changed to: BUFFERING'); + if(player.needsTocUpdate) + this.controls.positionScale.clear_marks(); if(!player.is_local_file) { this.needsTracksUpdate = true; } diff --git a/css/styles.css b/css/styles.css index a64191d5..96f42cc1 100644 --- a/css/styles.css +++ b/css/styles.css @@ -72,6 +72,13 @@ radio { } /* Position Scale */ +.positionscale { + margin-top: -2px; + margin-bottom: -2px; +} +.osd .positionscale { + margin-top: -1px; +} .positionscale trough highlight { min-height: 4px; } @@ -81,14 +88,39 @@ radio { border-color: transparent; box-shadow: none; } -.osd .positionscale { - margin-top: 1px; +.positionscale mark indicator { + min-height: 6px; +} +.positionscale.fine-tune mark indicator { + min-height: 6px; +} +.osd .positionscale mark indicator { + min-height: 7px; + min-width: 2px; +} +.osd .positionscale.fine-tune mark indicator { + min-height: 7px; + min-width: 2px; +} +.positionscale marks.top { + margin-top: -6px; + margin-bottom: 4px; +} +.positionscale marks.bottom { + margin-top: 4px; + margin-bottom: -6px; +} +.osd .positionscale marks.top { + margin-bottom: 2px; +} +.osd .positionscale marks.bottom { + margin-top: 2px; } .osd .positionscale trough highlight { border-radius: 3px; min-height: 20px; } -.osd .positionscale.dragging trough highlight { +.osd .positionscale.fine-tune trough highlight { border-radius: 3px; min-height: 20px; } @@ -134,16 +166,24 @@ radio { min-height: 24px; } .osd.floatingcontrols .positionscale { - margin-top: 0px; + margin-top: -2px; } .osd.floatingcontrols .positionscale trough highlight { border-radius: 3px; min-height: 12px; } -.osd.floatingcontrols .positionscale.dragging trough highlight { +.osd.floatingcontrols .positionscale.fine-tune trough highlight { border-radius: 3px; min-height: 12px; } +.osd.floatingcontrols .positionscale mark indicator { + min-height: 5px; + min-width: 1px; +} +.osd.floatingcontrols .positionscale.fine-tune mark indicator { + min-height: 5px; + min-width: 1px; +} .narrowbutton { min-width: 8px;