| Commit message (Collapse) | Author | Files | Lines |
|
This commit reimplements the core of the "single" mode. Instead of
doing the detection in the playlist code from the outside, it is moved
to the player thread, which gets a new option called "border_pause".
It will now pause playback exactly at the beginning of the new song,
making the feature more reliable.
Now that the player thread knows what will happen, it can suppress
cross-fading.
Fixes mantis tickets 0003055 and 0003166.
|
|
Just in case "song" becomes invalid at some point.
|
|
Previously, the condition "defined(play_audio_format)" was used to see
if an output device has been opened, but if the device had failed on
startup, an assertion failure could occur. This patch adds a separate
flag.
|
|
Common function that manages "player" attributes after
audio_output_all_open() has returned.
|
|
|
|
Don't read song.start_ms and song.end_ms, let the player thread manage
this logic instead.
|
|
When playing a CUE track, the player thread waited for the decoder to
become ready, and then sent a SEEK command to the beginning of the CUE
track. If that is near the start of the song file, and the track is
short enough, the decoder could have finished decoding already at that
point, and seeking fails.
This commit makes this initial seek more robust: instead of letting
the player thread deal with the difficult timings, let the decoder API
emulate a SEEK command, and return it to the decoder plugin, as soon
as the plugin finishes its initialization.
|
|
|
|
These fixes were mostly generated with `codespell' [0] and manually
reviewed.
[0] http://git.profusion.mobi/cgit.cgi/lucas/codespell/
|
|
|
|
Remove the decoder dependency on player_control. All player_control
was needed for is to signal the player thread, and we can do that with
a simple GCond as well.
|
|
dc_new() allocates the object and returns it. dc_free() frees it
(replaces dc_deinit()).
|
|
Allocate a player_control object where needed, and pass it around.
Each "client" object is associated with a "player_control" instance.
This prepares multi-player support.
|
|
When a music_chunk to be crossfaded consists only of a tag,
cross-fading is not possible, and led to an assertion failure. This
patch just discards those, as if cross-fading was not enabled.
|
|
Until the decoder plugin has called decoder_initialized(), the player
may not submit seek commands. This however could occur with a slow
decoder and a CUE file with a virtual song offset. This patch adds
another check.
|
|
|
|
When one song is played twice, and the decoder is working on the
second "instance", but the first should be seeked, the check in
player_seek_decoder() may assume that it can reuse the decoder without
exchanging pipes. The last thing was the mistake: the pipe pointer
was different, which led to an assertion failure. This patch adds
another check which exchanges the player pipe.
|
|
More abstraction for decoder_control.pipe.
|
|
Some abstraction for decoder_control.pipe access.
|
|
|
|
Replaced all occurrences of g_error() with MPD_ERROR() located in a new header
file 'mpd_error.h'. This macro uses g_critical() to print the error message
and then exits gracefully in contrast to g_error() which would internally call
abort() to produce a core dump.
The macro name is distinctive and allows to find all places with dubious error
handling. The long-term goal is to get rid of MPD_ERROR() altogether. To
facilitate the eventual removal of this macro it was added in a new header
file rather than to an existing header file.
This fixes #2995 and #3007.
|
|
|
|
Remove cross_fade_apply(), and call pcm_mix() in the output thread,
mixing the chunk and chunk->other together.
|
|
Adds mixrampdb and mixrampdelay commands. Reads MIXRAP_START and
MIXRAMP_END tags from FLAC files and overlaps instead of crossfading.
|
|
Previously, tags of the new song being cross-faded in were sent
immediately. That can cause wrong information being displayed,
because the "previous" song might send its tag at the end again,
overriding the "next" song's tag. This patch saves & merges the tag
of the next song, and sends it when cross-fading is finished, and the
next song really starts.
|
|
Did you ever accidently click "stop" while feeding a radio station?
This option sets the output device to "pause" to disable the "close"
method. It falls back to "pause" then, which is specific to the
plugin. Some plugins implement it by feeding silence.
|
|
Another quirk fixed: after the last chunk of a song has been played,
the "elapsed_time" variable is set to the chunk's time stamp. When
the client receives the PLAYER idle event and asks MPD for the current
time stamp, MPD will return the last time stamp of the previous song
when it hasn't played the first chunk of the current song yet.
|
|
|
|
Seek the decoder to the start of the range before beginning with
playback. Stop the decoder when the end of the range has been
reached. Add the start position to the seek position. Expose the
duration of the range, not the full song file.
|
|
|
|
|
|
At this point, the function may be called from the SEEK handler.
|
|
When waiting for the decoder to provide more data, the player thread
generates silence chunks if needed. However, it forgot to initialize
the chunk.times attribute, which had now an undefined value. This
patch sets it to -1.0, meaning "value is undefined". Add a ">= 0.0"
check to audio_output_all_check(). This fixes spurious relative
seeking errors, because sometimes, the "elapsed" value falls back to
0.0.
|
|
After we've been hit by Large File Support problems several times in
the past week (which only occur on 32 bit platforms, which I don't
have), this is yet another attempt to fix the issue.
|
|
When there's no queued song, and the current one has finished playing,
first make sure that the hardware outputs have really finished playing
the last chunk: call the drain() method in all audio outputs. Without
this patch, MPD stopped playback shortly before the ALSA sound card
had finished playing.
|
|
If no song was queued, then player_control.next_song might contain the
value for the next QUEUE command. We must not reset that.
|
|
When the decoder finishes the "queued" song very quickly (before the
"current" song finishes playing), an assertion in do_play() fails
because it thinks that it should start decoding the queued song,
although that has in fact just finished.
|
|
Simplify several expressions.
|
|
Don't access attributes without the lock.
|
|
Don't access decoder_control attributes directly.
|
|
Lock the player_control object when modifying its attributes.
|
|
|
|
These two variables are redundant, we need only one of them.
|
|
It's not used if pc.error==PLAYER_ERROR_AUDIO.
|
|
The START command returns without blocking; we don't need the
asynchronous decoder start anymore.
|
|
While paused, the player thread re-locks its mutex and waits for a
signal. This is racy: when the command is set while the thread is
waiting for the lock, it may wait forever. This patch adds another
command check before player_wait().
|
|
Allocate a decoder_control object where needed, and pass it around.
This will allow more than one decoder thread one day.
|
|
Simply use "return" instead of g_thread_exit().
|
|
Use GMutex/GCond instead of the notify library. Manually lock the
player_control object before accessing the protected attributes. Use
the GCond object to notify the player thread and the main thread.
|
|
Right after seeking and song change, the elapsed_time shows old
information, because the output thread didn't finish a full chunk
yet. This patch re-adds a second elapsed_time variable, and keeps
track of a fallback value, in case the output thread can't provide a
reliable value.
|