audio: Wait for state change instead of async done in scanner.

This increases the robustness by quite a bit, we no longer:
- Fail on elements such as mmssrc that can't go to playing ASYNC.
- Try going to playing if we've already tried before.
This commit is contained in:
Thomas Adamcik 2016-10-25 22:41:57 +02:00
parent c0836d9d97
commit 74cf673171
2 changed files with 23 additions and 22 deletions

View File

@ -35,7 +35,7 @@ Feature release.
- Audio: Fix handling of MMS (and any other streams) that can't switch to - Audio: Fix handling of MMS (and any other streams) that can't switch to
playing ``ASYNC``. Previously we would time out trying to get a duration from playing ``ASYNC``. Previously we would time out trying to get a duration from
these. (Fixes: :issue:`1553`, PR :issue:`1575`) these. (Fixes: :issue:`1553`, PR :issue:`1575`, :issue:`1576`)
v2.0.1 (2016-08-16) v2.0.1 (2016-08-16)

View File

@ -194,13 +194,14 @@ def _process(pipeline, timeout_ms):
missing_message = None missing_message = None
duration = None duration = None
# TODO: Turn this into a callback table to cleanup code.
types = ( types = (
Gst.MessageType.ELEMENT |
Gst.MessageType.APPLICATION | Gst.MessageType.APPLICATION |
Gst.MessageType.ERROR |
Gst.MessageType.EOS |
Gst.MessageType.ASYNC_DONE |
Gst.MessageType.DURATION_CHANGED | Gst.MessageType.DURATION_CHANGED |
Gst.MessageType.ELEMENT |
Gst.MessageType.EOS |
Gst.MessageType.ERROR |
Gst.MessageType.STATE_CHANGED |
Gst.MessageType.TAG Gst.MessageType.TAG
) )
@ -235,25 +236,25 @@ def _process(pipeline, timeout_ms):
raise exceptions.ScannerError(error) raise exceptions.ScannerError(error)
elif msg.type == Gst.MessageType.EOS: elif msg.type == Gst.MessageType.EOS:
return tags, mime, have_audio, duration return tags, mime, have_audio, duration
elif msg.type == Gst.MessageType.ASYNC_DONE: elif msg.type == Gst.MessageType.STATE_CHANGED and msg.src == pipeline:
success, duration = _query_duration(pipeline) old_state, new_state, pending = msg.parse_state_changed()
if tags and success:
return tags, mime, have_audio, duration
# Workaround for upstream bug which causes tags/duration to arrive if pending == Gst.State.VOID_PENDING:
# after pre-roll. We get around this by starting to play the track success, duration = _query_duration(pipeline)
# and then waiting for a duration change. if tags and success:
# https://bugzilla.gnome.org/show_bug.cgi?id=763553 return tags, mime, have_audio, duration
logger.debug('Using workaround for duration missing before play.')
result = pipeline.set_state(Gst.State.PLAYING)
if result == Gst.StateChangeReturn.FAILURE:
return tags, mime, have_audio, duration
# Try again to get duration since we changed without async, then if new_state == Gst.State.PAUSED:
# just give up as there is nothing more that can happen. # Workaround for upstream bug which causes tags/duration to
if result == Gst.StateChangeReturn.SUCCESS: # arrive after pre-roll. We get around this by starting to
_, duration = _query_duration(pipeline) # play the track and then waiting for a duration change.
return tags, mime, have_audio, duration # https://bugzilla.gnome.org/show_bug.cgi?id=763553
logger.debug('Using workaround for duration missing.')
result = pipeline.set_state(Gst.State.PLAYING)
if result == Gst.StateChangeReturn.FAILURE:
return tags, mime, have_audio, duration
else:
return tags, mime, have_audio, duration
elif msg.type == Gst.MessageType.DURATION_CHANGED: elif msg.type == Gst.MessageType.DURATION_CHANGED:
# duration will be read after ASYNC_DONE received; for now # duration will be read after ASYNC_DONE received; for now