This covers over that audio will fail query position while a seek is in
progress. It also means that instead of returning zero we at least return
something which is much closer to the time that we will soon end up playing
from.
Gapless broke this, so this change makes sure that next/prev/play and gapless
track changes all correctly emit events.
Note that this only ensures we get PLAYING -> PLAYING events. Not the old
STOPPED -> PLAYING and then PLAYING -> STOPPED.
Trigger playback ended on:
- stream changed
- EOS
- stop via stream changed events
Old behavior was to manually trigger on:
- next
- prev
- play with other track and old state != STOPPED
- stop
When about to finish gets called we are running in some GStreamer thread. Our
audio code then calls the shim core callback which is responsible for
transferring our execution to the core actor thread and waiting for the
response. From this point we do normal actor calls to the backend(s) which in
turn call into the audio actor. Since the initial audio code that was called is
outside the actor this should never deadlock due to this loop.
This fixes#1240.
In internals/path.py. there is a snippet of code that multiples mtime
for a file with 1000, and then casting it to `int`, to return the number
of milliseconds since epoch (or whatever). This will, however, not
ensure that the result is an `int`.
>>> type(int(2**32))
<type 'long'>
Instead, fix the tests to look for (int, long), and clarify the
implementation.
This bug found on a 32-bit VM :)
All backends are expected to support the exact argument. A friendly log message
will be printed to prompt users to upgrade backends that fail due to this.
Backends that still implement find_exact will be called without exact as an
argument to search, and we will continue to use find_exact. Please remove
find_exact from such backends and switch to the new search API.
Functionality has been replaced with an `exact` param in the search method.
Backends that still implement find_exact will continue being called via
the old method for now.
This is needed as otherwise each and every backend needs to handle the fact
that some "bad" clients might send {'field': 'value'} instead of
{'field': ['value']} Though the real problem isn't the clients but our
organically grown query API.
This change has us checking the return value of change_track when deciding if
the play call was a success or if the track is unplayable. Which ensures that
the following can no longer happen: 1) play stream 2) play stream that fails
change_track 3) stream 1) continues playing. Correct behavior being the next
stream playing instead.
All uris given to lookup should be in the result even if there is no
backend to handle the uri, and the lookup result thus is an empty list.
As a side effect, future.get() is now called in the order of the URIs
in the `uris` list, making it easier to mock out
backend.library.lookup() in core layer tests.
While trying to remove traces of stop calls in core to get gapless working I
found we had no way to switch to switch tracks without triggering a play. This
change fixes this by changing the backends playback provider API.
- play() now _only_ starts playback and does not take any arguments.
- prepare_change() has been added, this could have been avoided with a kwarg to
change_track(track), but that would break more backends.
- core has been updated to call prepare_change+change_track+play as needed.
- tests have been updated to handle this change.
Longer term I hope to completely rework the playback API in backends, as 99% of
our backends only use change_track(track) to translate URIs. So we should make
simple case simple, and handle mopidy-spotify / appsrc in some other way.
Cherry picked from the WIP gapless branch.
Instead of changing the signature to add(uri, name) I opted for
renaming it to _add_track(track).
Since it's internal we may change it whenever we like to. Since you need
different logic for extracting an interesting name from a track and from
a ref or a stream title, it makes sense to add another method for adding
refs/stream titles to the history when that time comes.
Fixes#1056
For now this doesn't add any corresponding APIs to backends, or for that matter
tracklist.add(uris). This is just to get the API in for clients in 0.20.
- Pending track should only be triggered by stream_changed if there is one.
- Tracklist changed was incorrectly calling stop breaking tests and gapless
- Tests have been updated to capture and replay audio events. This should avoid
test deadlocks while still using the audio fakes.
This is done by checking for the presence of the organization tag typically set
by web streams. This might be a bit to strict and a bad heuristic, but it's
currently better than wrongly emitting stream titles for non streams IMO.
Seeks will now fail when the duration is None, this is an approximation to if
the track is seekable or not. This check is need as otherwise seeking a radio
stream will trigger the next track.
If the track truly isn't seekable despite having a duration we should still
fail as GStreamer will reject the seek.