| Commit message (Collapse) | Author | Files | Lines |
|
player_wait_for_decoder() emits the PLAYLIST event on success, remove
the duplicate PLAYLIST event in its caller.
|
|
The "TAG" event is emitted by the player thread when the current
song's tag has changed. Split this event from "PLAYLIST" and make it
a separate callback, which is more efficient.
|
|
Moved the software volume code to a separate library.
|
|
GLib mandates that you initialize all GError objects with NULL prior
to passing it.
|
|
|
|
When the decoder of the new song is not fast enough, the player thread
has to wait for it for a moment. However the variable "nextChunk" was
reset to -1 during that, making the next loop iteration assume that
cross-fading has not begun yet. This patch overwrites it with "0"
while waiting.
|
|
Commit b3e2635a introduced a regression: when a stream tag was
changed, the playlist version had to be updated. This was done in
syncCurrentPlayerDecodeMetadata(), called by syncPlayerAndPlaylist().
After b3e2635a, this was not called anymore. Fix this by emitting
PIPE_EVENT_PLAYLIST.
|
|
There is only one location using PIPE_EVENT_SIGNAL: to synchronize
player_command() with player_command_finished(). Use the "notify"
library instead of the event_pipe here.
|
|
Make the event_pipe (formerly main_notify) send/receive a set of
events, with a callback for each one.
The default event PIPE_EVENT_SIGNAL does not have a callback. It
is still there for waking up the main thread, when it is waiting for
the player thread.
|
|
Continuing the previous patch.
|
|
We are going to migrate away from the concept of notifying the main
thread. There should be events sent to it instead. This patch starts
a series to implement that.
|
|
|
|
|
|
When MPD exits, it should manually free all resources in use, to allow
easy memory leak debugging. Make the decoder thread terminate during
that.
|
|
I have found something that looks like a bug in MPD:
- When a song is finished, the next one is played and the 'player'
event is emitted.
- When the client sends the status command just after this event, the
songid is the new one but the 'elapsed' time is not reseted to 0.
This is problem because I have implemented the solution using a timer
on client side to compute the elapsed time but with this bug the
elapsed time continues to be incremented on a new song.
|
|
|
|
The music pipe audio format bugs seem to be fixed (hopefully).
Disable music_pipe_check_format() for now, since it consumes a lot of
CPU cycles.
|
|
Don't send a "next song" request to the main thread when the current
song hasn't started playing yet, i.e. there are already two different
songs in the music pipe. This would erase information about the song
boundary within the music pipe, and thus triggered an assertion
failure. The bug could occur when playing very short songs which fit
into the pipe as a whole.
|
|
Fix a deadlock: when the decoder waited for buffer space, the player
could enter a deadlock situation because it waits for more chunks for
crossfading chunks. Signal the decoder before entering notify_wait().
|
|
When a CANCEL command is received, the player should drop all chunks
of the next song. Added new funciton music_pipe_chop() which is used
for that.
|
|
Provide a debug function which asserts on the sample format of all
chunks. Call this function in each iteration of the player main loop.
|
|
When assigning the next_song_chunk variable, it must have been empty.
If not, there may be 3 songs overlapping in the music pipe.
|
|
When a tag is updated, the old tag was freed before the new one was
created. Reverse the order to be sure that other threads always see a
valid pointer.
This still leaves a possible race condition, but it will be addressed
later.
|
|
The player did not care about the exact error value, it only checked
whether an error has occured. This could fit well into
decoder_control.state - introduce a new state "DECODE_STATE_ERROR".
|
|
Renamed variables and internal functions. Most of the
player_control.h API remains in CamelCase for now.
|
|
Renamed variables and functions.
|
|
An empty chunk may happen when it only contains a tag, but no PCM
data. Don't call playAudio() then.
|
|
Non-local songs used to have no tags. If the decoder sends us a tag,
we should incorporate it into the song struct. This way, clients can
always show the correct song name (if provided by the server).
|
|
Always remember which song is currently being sent to the audio
device.
|
|
If a chunk contains a tag, send it to the audio output device. Few
output plugins support this, e.g. shout has support for sending tags.
|
|
Rename all variables and struct members.
|
|
Replace all direct music_pipe struct accesses with wrapper functions.
The compiled machine code is the same, but this way, we can change
struct internals more easily.
|
|
.. and rename dc.audioFormat to dc.in_audio_format. The music pipe
does not need to know the audio format, and its former "audioFormat"
property indicated the format of the most recently added chunk, which
might be confusing when you are reading the oldest chunks.
|
|
Rename all functions to the new prefix.
|
|
.. and rename ob_chunk to struct music_chunk.
|
|
Don't return 0/-1 on success/error, but true/false. Instead of int,
use bool for storing flags.
|
|
Stopping an audio output device without cancelling its buffer doesn't
make sense. Combine the two operations, which saves several cancel
calls.
|
|
Don't return 0/-1 on success/error, but true/false. Instead of int,
use bool for storing flags.
|
|
When the decoder exited before the buffer has grown big enough
("buffer_before_play"), the player thread waited forever. Add an
additional check which disables buffering as soon as the decoder
exits.
|
|
The local variable "play_audio_format" is updated every time the
player starts playing a new song. This way, we always know exactly
which audio format is current. The old code broke when a new song had
a different format: ob.audio_format is the format of the next song,
not of the current one - using this caused breakage for the software
volume control.
|
|
Request the next song from the playlist (by clearing pc.next_song)
only if the player command is empty. If it is not, the player may be
clearing the song that has already been queued, leading to an
assertion failure.
|
|
When the decoder failed to start, the function do_play() returned,
still having pc.command==PLAY. This is because pc.command was reset
only when the decoder started up successfully. Add another
player_command_finished() call in the error handler.
|
|
This bug caused the audio output devices to stay open, although MPD
wasn't playing: quitDecode() resetted player_control.command, assuming
that the command was STOP. This way, player_task() didn't see the
CLOSE_AUDIO command, and the device was kept open.
Don't clear player_control.command in quitDecode().
|
|
Another partial frame fix: the silence buffer was 1020 bytes, which
had room for 127.5 24 bit stereo frames. Don't send the partial last
frame in this case.
|
|
Renamed all functions which were still in CamelCase.
|
|
buffered_before_play was copied to struct player because it was used
to disable buffering when seeking. Instead of mainaining a copy of
this number, move just the flag to the player struct.
|
|
QUEUE adds a new song to the player's queue. CANCEL clears the queue.
These two commands replace the old and complex queueState and
queueLockState code.
|
|
The player struct holds the local variables which used to be passed to
all those helper functions in player_thread.c.
|
|
This variable is superfluous, it is only used to copy its value to
player_control.totalTime. Since the original source of this value
(song->tag->time) will still be available at this point, we can safely
remove fileTime.
|
|
The decoder was woken up after each chunk which had been played. That
caused a lot of superfluous context switches. Wake up the decoder
only when a certain amount of the buffer has been consumed. This
formula is somewhat arbitrary, and has to be proven experimentally.
|