From 57518861ea55546d8f491448ff65453d2cf0d184 Mon Sep 17 00:00:00 2001 From: SeeSpotRun Date: Tue, 15 Mar 2016 18:37:23 +1000 Subject: [PATCH] scanner: move _query_duration() into _process() --- mopidy/audio/scan.py | 59 +++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/mopidy/audio/scan.py b/mopidy/audio/scan.py index 1a199e58..4642c3f2 100644 --- a/mopidy/audio/scan.py +++ b/mopidy/audio/scan.py @@ -61,8 +61,7 @@ class Scanner(object): try: _start_pipeline(pipeline) - tags, mime, have_audio = _process(pipeline, timeout) - duration = _query_duration(pipeline) + tags, mime, have_audio, duration = _process(pipeline, timeout) seekable = _query_seekable(pipeline) finally: signals.clear() @@ -136,30 +135,6 @@ def _start_pipeline(pipeline): pipeline.set_state(Gst.State.PLAYING) -def _query_duration(pipeline, timeout=100): - # 1. Try and get a duration, return if success. - # 2. Some formats need to play some buffers before duration is found. - # 3. Wait for a duration change event. - # 4. Try and get a duration again. - - success, duration = pipeline.query_duration(Gst.Format.TIME) - if success and duration >= 0: - return duration // Gst.MSECOND - - result = pipeline.set_state(Gst.State.PLAYING) - if result == Gst.StateChangeReturn.FAILURE: - return None - - gst_timeout = timeout * Gst.MSECOND - bus = pipeline.get_bus() - bus.timed_pop_filtered(gst_timeout, Gst.MessageType.DURATION_CHANGED) - - success, duration = pipeline.query_duration(Gst.Format.TIME) - if success and duration >= 0: - return duration // Gst.MSECOND - return None - - def _query_seekable(pipeline): query = Gst.Query.new_seeking(Gst.Format.TIME) pipeline.query(query) @@ -172,6 +147,7 @@ def _process(pipeline, timeout_ms): mime = None have_audio = False missing_message = None + duration = None types = ( Gst.MessageType.ELEMENT | @@ -179,6 +155,7 @@ def _process(pipeline, timeout_ms): Gst.MessageType.ERROR | Gst.MessageType.EOS | Gst.MessageType.ASYNC_DONE | + Gst.MessageType.DURATION_CHANGED | Gst.MessageType.TAG ) @@ -197,7 +174,7 @@ def _process(pipeline, timeout_ms): mime = message.get_structure().get_value('caps').get_name() if mime and ( mime.startswith('text/') or mime == 'application/xml'): - return tags, mime, have_audio + return tags, mime, have_audio, duration elif message.get_structure().get_name() == 'have-audio': have_audio = True elif message.type == Gst.MessageType.ERROR: @@ -205,16 +182,28 @@ def _process(pipeline, timeout_ms): if missing_message and not mime: caps = missing_message.get_structure().get_value('detail') mime = caps.get_structure(0).get_name() - return tags, mime, have_audio + return tags, mime, have_audio, duration raise exceptions.ScannerError(error) elif message.type == Gst.MessageType.EOS: - return tags, mime, have_audio + return tags, mime, have_audio, duration elif message.type == Gst.MessageType.ASYNC_DONE: - if tags: - return tags, mime, have_audio + success, duration = pipeline.query_duration(Gst.Format.TIME) + if success: + duration = duration // Gst.MSECOND else: - # workaround for https://bugzilla.gnome.org/show_bug.cgi?id=763553: - pipeline.set_state(Gst.State.PLAYING) + duration = None + if (tags and duration + # workaround for + # https://bugzilla.gnome.org/show_bug.cgi?id=763553: + # try to start pipeline playing; if it doesn't then + # give up: + ) or ( pipeline.set_state(Gst.State.PLAYING) + == Gst.StateChangeReturn.FAILURE): + return tags, mime, have_audio, duration + elif message.type == Gst.MessageType.DURATION_CHANGED: + # duration will be read after ASYNC_DONE received; for now + # just give it a non-None value to flag that we have a duration: + duration = 0 elif message.type == Gst.MessageType.TAG: taglist = message.parse_tag() # Note that this will only keep the last tag. @@ -223,8 +212,10 @@ def _process(pipeline, timeout_ms): now = int(time.time() * 1000) timeout -= now - previous previous = now + # workaround for https://bugzilla.gnome.org/show_bug.cgi?id=763553: - if tags: + # if we got what we want then stop playing (and wait for ASYNC_DONE) + if tags and duration: pipeline.set_state(Gst.State.PAUSED) raise exceptions.ScannerError('Timeout after %dms' % timeout_ms)