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.
After CANCEL, call g_cond_wait() only if the new command is still
NONE. Problem is that ao_command_finished() has to unlock the
audio_output object, and in the meantime, the player thread might have
submitted a new command.
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.
Return false when there was no chunk in the pipe. If the function
returns true, then audio_output_task() will not wait for a notify from
the player thread. This fixes a race condition.
drain() is the opposite of cancel(): it waits until all data in the
buffer has finished playing. Instead of implicitly draining in the
close() method like the ALSA plugin has been doing it forever, let the
output thread decide whether to drain or to cancel.
With these methods, an output plugin can allocate some global
resources only if it is actually enabled. The method enable() is
called after daemonization, which allows for more sophisticated
resource allocation during that method.
When the player thread unpauses, it sends CANCEL to the output thread,
after having checked that the output is still open. Problem is when
the output thread closes the device before it can process the CANCEL
command - race condition. This patch adds another "open" check inside
the output thread.
Explicitly make the output thread leave the ao_pause() loop. This
patch is a workaround, and the "pause" flag is not managed in a
thread-safe way, but that's good enough for now.
This patch adds initial filter support for audio outputs. Each audio
output gets a "filter" attribute, which is used by ao_play_chunk().
The PCM conversion is now performed by convert_filter_plugin.
audio_output.convert_state has been removed.
This patch fixes a longer delay when moving around songs in the
playlist. The main thread wants to enqueue a new "next" song into the
player thread, but the player thread is waiting inside
audio_output_all_wait() for the output threads. Use
player_control.notify there, so audio_output_all_wait() gets woken up
by the main thread, too.
Use audio_output_client_notify instead of g_usleep(1ms) in
audio_output_all_wait() to synchronize with the output_thread. Signal
the audio_output_client_notify object in ao_play().
There was a deadlock between the output thread and the player thread:
when the output thread failed (and closed itself) while the player
thread worked with the audio_output object, MPD could crash.
This updates the copyright header to all be the same, which is
pretty much an update of where to mail request for a copy of the GPL
and the years of the MPD project. This also puts all committers under
'The Music Player Project' umbrella. These entries should go
individually in the AUTHORS file, for consistancy.
Check audio_output.command after each sub-chunk has been played. It
discards the rest of the chunk, but since all commands make the device
stop anyway, this is not a problem, but part of the improvement. This
improves the latency of audio output commands.
Instead of passing individual buffers to audio_output_all_play(), pass
music_chunk objects. Append all those chunks asynchronously to a
music_pipe instance. All output threads may then read chunks from
this pipe. This reduces MPD's internal latency by an order of
magnitude.
This is similar to the MPD 0.14 patch "wait 10 seconds before
reopening a failed device", which only covered open() failures. This
patch adds the same feature for play().
time() is not a monotonic timer, and MPD might get confused by clock
skews. clock_gettime() provides a monotonic clock, but is not
portable to non-POSIX systems (i.e. Windows). This patch uses GLib's
GTimer API, which aims to be portable.
Use GLib's GError library for reporting output device failures.
Note that some init() methods don't clean up properly after a failure,
but that's ok for now, because the MPD core will abort anyway.
ao_play() gets PCM data in the in_audio_format, and converts it to
out_audio_format. Comparing the input data with out_audio_format is
wrong.
prefixed with "STG:" will be automatically removed. STG: Trailing
empty lines will be automatically removed. STG: vi: set textwidth=75
filetype=diff nobackup:
The old API required an output plugin to not return until all data
passed to the play() method is consumed. Some output plugins have to
loop to fulfill that requirement, and may block during that. Simplify
these, by letting them consume only part of the buffer: make play()
return the length of the consumed data.
Fix a memory leak: it was not guaranteed that pcm_convert_deinit() was
called for each pcm_convert_init(). This patch always (de)initializes
the pcm_convert library when the audio_output.open flag is flipped.
Move the "while" loop which checks for commands to the caller
ao_pause(). This simplifies the pause() method, and lets us remove
audio_output_is_pending().