| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
This command manually drains the hardware buffer. This is useful when
the player thread want to make sure that everything has been played.
|
|
|
|
|
|
|
| |
When an output's enable() method has failed, and playback starts,
retry to enable it. Without this, the user may be confused, because
he sees the device is "enabled" but cannot use it, and currently there
is no error message in the log.
|
|
|
|
|
|
|
| |
After CANCEL, the output thread waits for another signal before it
continues playback, to synchronize with the caller. There were some
situations where this signal wasn't sent properly. This patch adds an
explicit g_cond_signal() at two code positions.
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tracking the "elapsed" time from the chunks which we have sent to the
output pipe is very imprecise: since we have implemented the music
pipe, we're sending large number of chunks at once, giving the
"elapsed" time stamp a resolution of usually more than a second.
This patch changes the source of this information to the outputs. If
a chunk has been played by all outputs, the "elapsed" time stamp is
updated.
The new command PLAYER_COMMAND_REFRESH makes the player thread update
its status information: it tells the outputs to update the chunk time
stamp. After that, player_control.elapsed_time is current.
|
|
|
|
|
|
|
|
| |
When MPD was paused, and the client sent the "stop" command (or
"clear"), a glitch caused MPD to continue playback for a split second.
This was because audio_output_all_cancel() calls
audio_output_all_update(), which reopens all output devices, and
re-ignites the playback loop.
|
|
|
|
|
|
| |
Instead of returning the local variable "ret" which is always true at
this point, hard-code the "true" return value, because that might be
more readable.
|
|
|
|
|
|
|
|
|
| |
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().
|
|
|
|
|
|
| |
Synchronization with the output thread will be implemented in
output_all.c, not in player_thread.c. Currently, that's just a simple
g_usleep(1ms).
|
|
|
|
|
|
| |
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.
|
|
|
|
|
| |
When printing the error message, MPD dereferences the NULL pointer to
print an error message if no audio_output section is present.
|
|
|
|
| |
In NDEBUG, clear_tail_chunk() does not use its "chunk" parameter.
|
|
|
|
|
| |
The source output_all.c accesses music_chunk struct members, but did
not include chunk.h directly.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
| |
When there are chunks which are not yet finished,
audio_output_all_check() returned the size of its music pipe minus
one. I can't remember exactly why I subtracted 1 from the return
value, it must have had something to do with a former meaning of this
function. Now it induces assertion failures.
|
|
|
|
|
|
| |
When the audio outputs are closed, also clear the audio format. If we
don't do this, every call to audio_output_all_update() will open the
device, even if it's meant to be paused.
|
|
|
|
|
|
| |
Don't allow reopening an audio device after pause with
audio_format==NULL, force the caller to provide the audio_format each
time.
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
Sometimes, audio_output_update() isn't called for the second device
when the first one has succeeded. The patch
"audio_output_all_update() returns bool" broke it, because the boolean
evaluation ended after the first "true".
|
|
|
|
|
| |
audio_output_all_update() returns true when there is at least open
output device which is open.
|
|
|
|
| |
Do error handling with GError instead of aborting with g_error().
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
| |
When all outputs are disabled, MPD printed only a meaningless message
"problems opening audio device", although it didn't attempt to open a
device.
|
|
|
|
|
| |
After initialization, audio_outputs is always non-NULL. Don't check
that.
|
| |
|
|
|
|
|
| |
Don't include output_api.h in output_internal.h. This change requires
adding missing includes in several sources.
|
|
|
|
|
|
|
| |
When MPD explicitly starts playing, ignore the "REOPEN_AFTER" timeout.
This timeout was useful when MPD attempted to reopen a failed device
over and over, but it confuses users when they explicitly tell MPD to
start playing, while MPD insists to wait for the 10 seconds to pass.
|
|
|
|
| |
audio_output_all_finished() returns bool, not int.
|
|
|
|
| |
Renamed functions and variables.
|
|
Moved code which deals with all audio outputs at once into a separate
library.
|