Skip to content

Commit

Permalink
Dynamically update duration if it changes while playing (closes #15)
Browse files Browse the repository at this point in the history
Strange thing - GStreamer sometimes can't query the duration of a file. The only
workaround I found is to just play the file and it normally updates after some
time automatically.
  • Loading branch information
innir committed Aug 27, 2020
1 parent d8be2b6 commit 14f64d1
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 14 deletions.
30 changes: 20 additions & 10 deletions bin/gtranscribe
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class gTranscribeWindow:
self.player = gTranscribePlayer()
self.player.connect('ready', self.on_file_ready)
self.player.connect('ended', self.on_file_ended)
self.player.connect('duration_changed', self.on_duration_changed)

if audiofile:
# Open a file passed as command-line parameter.
Expand Down Expand Up @@ -220,6 +221,21 @@ class gTranscribeWindow:
logger.debug('received signal "ready"')
GLib.idle_add(self.update_file, audiofile)

# pylint: disable=unused-argument
def on_duration_changed(self, sig):
if sig is not None:
logger.debug('received signal "duration_changed"')
duration = ns_to_time(self.player.duration)
if duration.hour:
self.time_str = '%H:%M:%S.%f'
else:
self.time_str = '%M:%S.%f'
# set duration
dur_str = trim(duration.strftime(self.time_str))
self.dur_label.set_text(dur_str)
# set position
self.set_position_label(time_to_ns(duration))

def update_file(self, audiofile):
self.position = 0
fileinfo = MetaData(audiofile, self.md5)
Expand All @@ -231,16 +247,8 @@ class gTranscribeWindow:
if fileinfo.speed:
logger.debug('Resuming with speed %s', fileinfo.speed)
self.speedscale.set_value(fileinfo.speed)
duration = ns_to_time(self.player.duration)
if duration.hour:
self.time_str = '%H:%M:%S.%f'
else:
self.time_str = '%M:%S.%f'
# set duration
dur_str = trim(duration.strftime(self.time_str))
self.dur_label.set_text(dur_str)
# set position
self.set_position_label(time_to_ns(duration))
# Query duration once before we start playing
self.on_duration_changed(None)
# set window title
filename = os.path.basename(audiofile)
self.window.set_title(u'gTranscribe \u2013 %s' % filename)
Expand Down Expand Up @@ -331,6 +339,8 @@ class gTranscribeWindow:
self.slider.set_value(scalepos)
pos_str = trim(ns_to_time(self.position).strftime(self.time_str))
self.pos_label.set_text(pos_str)
else:
logger.warning("Can't update position, don't know the duration")

def dec_speed(self, action):
self.speedscale.set_value(self.speedscale.get_value() - 0.1)
Expand Down
16 changes: 12 additions & 4 deletions gtranscribe/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ class gTranscribePlayer(Gst.Bin):

__gsignals__ = {
'ready': (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_STRING,)),
'ended': (GObject.SignalFlags.RUN_LAST, None, ())
'ended': (GObject.SignalFlags.RUN_LAST, None, ()),
'duration_changed': (GObject.SignalFlags.RUN_LAST, None, ())
}

def __init__(self):
super(gTranscribePlayer, self).__init__()

self._rate = 1
self._duration = None
self._messageType = Gst.MessageType.UNKNOWN
self.init_pipeline()

def init_pipeline(self):
Expand Down Expand Up @@ -89,10 +91,13 @@ def filename(self):
def duration(self):
"""Return the duration of the current stream."""
success = False
if self._duration is None:
if self._duration is None or self._messageType == Gst.MessageType.DURATION_CHANGED:
success, self._duration = self.pipeline.query_duration(Gst.Format.TIME)
logger.debug('Query was successful: %s, Duration is: "%s"', success, self._duration)
return self._duration if success else 0
if not success:
self._duration = 0
logger.debug('Query was successful: %s, Duration is: "%s"',
success, self._duration)
return self._duration

def _get_position(self):
"""Return the position of the current stream."""
Expand Down Expand Up @@ -175,12 +180,15 @@ def on_new_decoded_pad(self, element, pad):
# pylint: disable=unused-argument
def on_message(self, bus, message):
"""Handle message and react accordingly."""
self._messageType = message.type
if message.type == Gst.MessageType.EOS:
self.state = Gst.State.NULL
self.emit('ended')
elif message.type == Gst.MessageType.ERROR:
logger.debug("%s", print(message.parse_error()))
self.state = Gst.State.NULL
elif message.type == Gst.MessageType.DURATION_CHANGED:
self.emit('duration_changed')

def open(self, filepath, duration=True):
"""Open audio file and optionally query duration."""
Expand Down

0 comments on commit 14f64d1

Please sign in to comment.