| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
| |
Don't wake up the target thread in every iteration of the wait() loop.
Waking it up once, right after the command has been set, must be
enough.
|
|
|
|
| |
Call a version of audio_output_close() which doesn't lock recursively.
|
|
|
|
|
| |
Always keep the audio_output object locked within the output thread,
unless a plugin method is called. This fixes several race conditions.
|
|
|
|
|
|
|
| |
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.
|
| |
|
|\
| |
| |
| |
| |
| |
| | |
Conflicts:
NEWS
configure.ac
|
| |
| |
| |
| |
| |
| | |
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.
|
|/
|
|
|
| |
REOPEN is called when the input audio format changes. The output
thread may be reconfigure the PCM converter.
|
|
|
|
|
| |
For non-global mixers (only "pulse" currently), close the mixer when
MPD playback is paused.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Remember if a mixer object is open or closed. Don't call open() again
if it is already open. This guarantees that the mixer plugin is
always called in a consistent state, and we will be able to remove
lots of checks from the implementations.
To support mixers which are automatically opened even if the audio
output is still closed (to set the volume before playback starts),
this patch also adds the "global" flag to the mixer_plugin struct.
Both ALSA and OSS set this flag, while PULSE does not.
|
|
|
|
|
|
| |
The mixer core library is now responsible for creating and managing
the mixer object. This removes duplicated code from the output
plugins.
|
|
|
|
|
| |
To prevent a race condition, close the output thread before assigning
the new audio format.
|
|
|
|
|
|
|
| |
The config_audio_format used to contain the configured audio format,
which is copied to out_audio_format. Let's convert the former to a
boolean, which indicates whether out_audio_format was already set.
This simplifies some code and saves a few bytes.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
This function was part of a workaround which we don't need anymore.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
audio_output_open() is only called by audio_output_update(). Don't
export it.
|
|
|
|
|
| |
audio_output_all_update() returns true when there is at least open
output device which is open.
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
The meaning of the chunk depends on the audio format; don't suggest a
specific format by declaring the pointer as "char*", pass "void*"
instead.
|
|
|
|
|
| |
Similar to the decoder plugin API: added wrapper functions to increase
code readability.
|
|
|
|
| |
Renamed variables.
|
|
|
|
| |
Renamed audio_output struct members.
|
|
|
|
|
|
| |
Removed yet another superfluous buffer layer: return the PCM buffer
from pcm_convert() instead of copying PCM data into the
caller-supplied buffer.
|
|
|
|
|
| |
Be sure that the output thread has quite before we start destructing
the output object.
|
|
|
|
|
| |
Free memory allocated by the notify object (GMutex, GCond) when it's
not used by the output object anymore.
|
|
|
|
|
| |
All what's left in pcm_utils.h is the pcm_range() utility function,
which is only used internally by pcm_volume and pcm_mix.
|
| |
|
| |
|
|
|
|
| |
Don't use NOTIFY_INITIALIZER to initialize audio_output_client_notify.
|
|
|
|
|
| |
Nobody should call playAudio() with an empty chunk. Add some
assertions on that.
|
|
|
|
|
| |
Since open() and play() close the device on error, we can simply check
audio_output.open instead of audio_output.result after a call.
|
|
|
|
|
|
|
| |
When one of several output devices failed, MPD tried to reopen it
quite often, wasting a lot of resources. This patch adds a delay:
wait 10 seconds before retrying. This might be changed to exponential
delays later, but for now, it makes the problem go away.
|
|
|
|
| |
Moved code from syncAudioDeviceStates() to audio_output_update().
|
|
|
|
|
| |
Don't return 0/-1 on success/error, but true/false. Instead of int,
use bool for storing flags.
|
|
|
|
|
| |
When there are standardized headers, use these instead of the bloated
os_compat.h.
|
|
|
|
|
|
|
|
|
|
|
|
| |
pause() puts the audio output into pause mode: if supported, it may
perform a special action, which keeps the device open, but does not
play anything. Output plugins like "shout" might want to play silence
during pause, so their clients won't be disconnected. Plugins which
do not support pausing will simply be closed, and have to be reopened
when unpaused.
This pach includes an implementation for the shout plugin, which
sends silence chunks.
|
|
|
|
|
|
|
|
| |
During debugging, I found a deadlock between flushAudioBuffer() and
the audio_output_task(): audio_output_task() didn't notice that there
is a command, and flushAudioBuffer() waited forever in notify_wait().
I am not sure yet what is the real cause; work around this for now by
waking up non-finished audio outputs in every iteration.
|
|
|
|
|
|
|
| |
Send an output buffer to all output plugins at the same time, instead
of waiting for each of them separately. Make several functions
non-blocking, and introduce the new function audio_output_wait_all()
to synchronize with all audio output threads.
|
|
|
|
|
|
|
|
|
|
|
| |
We have eliminated direct accesses to the audio_output struct from
the all output plugins. Make it opaque for them, and move its real
declaration to output_internal.h, similar to decoder_internal.h.
Pass the opaque structure to plugin.init() only, which will return the
plugin's data pointer on success, and NULL on failure. This data
pointer will be passed to all other methods instead of the
audio_output struct.
|
|
|
|
|
|
| |
To keep I/O nastiness and latencies away from the core, move the audio
output code to a separate thread, one per output. The thread is
created on demand, and currently runs until mpd exits.
|
|
|
|
|
|
| |
If the output device is already open, it may have modified
outAudioFormat; in this case, outAudioFormat is still valid, and does
not need an overwrite.
|
|
|
|
|
| |
Eliminate sameInAndOutFormats and check with audio_format_equals()
each time it this information is needed. Another 4 bytes saved.
|
|
|
|
|
| |
Instead of checking convertAudioFormat, we can simply check if
reqAudioFormat is defined. This saves 4 bytes in the struct.
|
|
|
|
|
| |
Rename it to audio_format_equals() and return "true" if they are
equal.
|
|
|
|
|
|
|
|
|
| |
The "!src" check in copyAudioFormat() used to hide bugs - one should
never pass NULL to it. There is one caller which might pass NULL, add
a check in this caller.
Instead of doing mempcy(), we can simply assign the structures, which
looks more natural.
|
|
|
|
| |
Getting rid of CamcelCase, again.
|
|
Similar to decoder_control.c, output_control.c will provide functions
for controlling the output thread (which will be implemented later).
|