DecoderControl: move functions into the class
This commit is contained in:
parent
e1b03b4a71
commit
32799fef5c
@ -64,10 +64,10 @@ decoder_initialized(struct decoder *decoder,
|
||||
dc->seekable = seekable;
|
||||
dc->total_time = total_time;
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
dc->state = DECODE_STATE_DECODE;
|
||||
g_cond_signal(dc->client_cond);
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
g_debug("audio_format=%s, seekable=%s",
|
||||
audio_format_to_string(&dc->in_audio_format, &af_string),
|
||||
@ -155,7 +155,7 @@ decoder_command_finished(struct decoder *decoder)
|
||||
{
|
||||
struct decoder_control *dc = decoder->dc;
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
assert(dc->command != DECODE_COMMAND_NONE ||
|
||||
decoder->initial_seek_running);
|
||||
@ -171,7 +171,7 @@ decoder_command_finished(struct decoder *decoder)
|
||||
|
||||
decoder->initial_seek_running = false;
|
||||
decoder->timestamp = dc->start_ms / 1000.;
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ decoder_command_finished(struct decoder *decoder)
|
||||
|
||||
dc->command = DECODE_COMMAND_NONE;
|
||||
g_cond_signal(dc->client_cond);
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
}
|
||||
|
||||
double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
|
||||
@ -377,9 +377,9 @@ decoder_data(struct decoder *decoder,
|
||||
assert(dc->pipe != NULL);
|
||||
assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
cmd = decoder_get_virtual_command(decoder);
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
|
||||
length == 0)
|
||||
@ -564,6 +564,6 @@ decoder_mixramp(struct decoder *decoder,
|
||||
struct decoder_control *dc = decoder->dc;
|
||||
assert(dc != NULL);
|
||||
|
||||
dc_mixramp_start(dc, mixramp_start);
|
||||
dc_mixramp_end(dc, mixramp_end);
|
||||
dc->MixRampStart(mixramp_start);
|
||||
dc->MixRampEnd(mixramp_end);
|
||||
}
|
||||
|
@ -27,46 +27,30 @@
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "decoder_control"
|
||||
|
||||
struct decoder_control *
|
||||
dc_new()
|
||||
decoder_control::decoder_control()
|
||||
:thread(nullptr),
|
||||
mutex(g_mutex_new()), cond(g_cond_new()),
|
||||
client_cond(g_cond_new()),
|
||||
state(DECODE_STATE_STOP),
|
||||
command(DECODE_COMMAND_NONE),
|
||||
song(nullptr),
|
||||
replay_gain_db(0), replay_gain_prev_db(0),
|
||||
mixramp_start(nullptr), mixramp_end(nullptr),
|
||||
mixramp_prev_end(nullptr) {}
|
||||
|
||||
decoder_control::~decoder_control()
|
||||
{
|
||||
struct decoder_control *dc = g_new(struct decoder_control, 1);
|
||||
ClearError();
|
||||
|
||||
dc->thread = NULL;
|
||||
if (song != NULL)
|
||||
song_free(song);
|
||||
|
||||
dc->mutex = g_mutex_new();
|
||||
dc->cond = g_cond_new();
|
||||
dc->client_cond = g_cond_new();
|
||||
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
dc->command = DECODE_COMMAND_NONE;
|
||||
|
||||
dc->song = NULL;
|
||||
|
||||
dc->replay_gain_db = 0;
|
||||
dc->replay_gain_prev_db = 0;
|
||||
dc->mixramp_start = NULL;
|
||||
dc->mixramp_end = NULL;
|
||||
dc->mixramp_prev_end = NULL;
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
void
|
||||
dc_free(struct decoder_control *dc)
|
||||
{
|
||||
dc_clear_error(dc);
|
||||
|
||||
if (dc->song != NULL)
|
||||
song_free(dc->song);
|
||||
|
||||
g_cond_free(dc->client_cond);
|
||||
g_cond_free(dc->cond);
|
||||
g_mutex_free(dc->mutex);
|
||||
g_free(dc->mixramp_start);
|
||||
g_free(dc->mixramp_end);
|
||||
g_free(dc->mixramp_prev_end);
|
||||
g_free(dc);
|
||||
g_cond_free(client_cond);
|
||||
g_cond_free(cond);
|
||||
g_mutex_free(mutex);
|
||||
g_free(mixramp_start);
|
||||
g_free(mixramp_end);
|
||||
g_free(mixramp_prev_end);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -80,45 +64,43 @@ static void
|
||||
dc_command_locked(struct decoder_control *dc, enum decoder_command cmd)
|
||||
{
|
||||
dc->command = cmd;
|
||||
decoder_signal(dc);
|
||||
dc->Signal();
|
||||
dc_command_wait_locked(dc);
|
||||
}
|
||||
|
||||
static void
|
||||
dc_command(struct decoder_control *dc, enum decoder_command cmd)
|
||||
{
|
||||
decoder_lock(dc);
|
||||
dc_clear_error(dc);
|
||||
dc->Lock();
|
||||
dc->ClearError();
|
||||
dc_command_locked(dc, cmd);
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
}
|
||||
|
||||
static void
|
||||
dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
|
||||
{
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
dc->command = cmd;
|
||||
decoder_signal(dc);
|
||||
dc->Signal();
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
}
|
||||
|
||||
bool
|
||||
decoder_is_current_song(const struct decoder_control *dc,
|
||||
const struct song *song)
|
||||
decoder_control::IsCurrentSong(const struct song *_song) const
|
||||
{
|
||||
assert(dc != NULL);
|
||||
assert(song != NULL);
|
||||
assert(_song != NULL);
|
||||
|
||||
switch (dc->state) {
|
||||
switch (state) {
|
||||
case DECODE_STATE_STOP:
|
||||
case DECODE_STATE_ERROR:
|
||||
return false;
|
||||
|
||||
case DECODE_STATE_START:
|
||||
case DECODE_STATE_DECODE:
|
||||
return song_equals(dc->song, song);
|
||||
return song_equals(song, _song);
|
||||
}
|
||||
|
||||
assert(false);
|
||||
@ -126,99 +108,91 @@ decoder_is_current_song(const struct decoder_control *dc,
|
||||
}
|
||||
|
||||
void
|
||||
dc_start(struct decoder_control *dc, struct song *song,
|
||||
unsigned start_ms, unsigned end_ms,
|
||||
struct music_buffer *buffer, struct music_pipe *pipe)
|
||||
decoder_control::Start(struct song *_song,
|
||||
unsigned _start_ms, unsigned _end_ms,
|
||||
music_buffer *_buffer, music_pipe *_pipe)
|
||||
{
|
||||
assert(song != NULL);
|
||||
assert(_song != NULL);
|
||||
assert(buffer != NULL);
|
||||
assert(pipe != NULL);
|
||||
assert(music_pipe_empty(pipe));
|
||||
|
||||
if (dc->song != NULL)
|
||||
song_free(dc->song);
|
||||
if (song != nullptr)
|
||||
song_free(song);
|
||||
|
||||
dc->song = song;
|
||||
dc->start_ms = start_ms;
|
||||
dc->end_ms = end_ms;
|
||||
dc->buffer = buffer;
|
||||
dc->pipe = pipe;
|
||||
dc_command(dc, DECODE_COMMAND_START);
|
||||
song = _song;
|
||||
start_ms = _start_ms;
|
||||
end_ms = _end_ms;
|
||||
buffer = _buffer;
|
||||
pipe = _pipe;
|
||||
|
||||
dc_command(this, DECODE_COMMAND_START);
|
||||
}
|
||||
|
||||
void
|
||||
dc_stop(struct decoder_control *dc)
|
||||
decoder_control::Stop()
|
||||
{
|
||||
decoder_lock(dc);
|
||||
Lock();
|
||||
|
||||
if (dc->command != DECODE_COMMAND_NONE)
|
||||
if (command != DECODE_COMMAND_NONE)
|
||||
/* Attempt to cancel the current command. If it's too
|
||||
late and the decoder thread is already executing
|
||||
the old command, we'll call STOP again in this
|
||||
function (see below). */
|
||||
dc_command_locked(dc, DECODE_COMMAND_STOP);
|
||||
dc_command_locked(this, DECODE_COMMAND_STOP);
|
||||
|
||||
if (dc->state != DECODE_STATE_STOP && dc->state != DECODE_STATE_ERROR)
|
||||
dc_command_locked(dc, DECODE_COMMAND_STOP);
|
||||
if (state != DECODE_STATE_STOP && state != DECODE_STATE_ERROR)
|
||||
dc_command_locked(this, DECODE_COMMAND_STOP);
|
||||
|
||||
decoder_unlock(dc);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
bool
|
||||
dc_seek(struct decoder_control *dc, double where)
|
||||
decoder_control::Seek(double where)
|
||||
{
|
||||
assert(dc->state != DECODE_STATE_START);
|
||||
assert(state != DECODE_STATE_START);
|
||||
assert(where >= 0.0);
|
||||
|
||||
if (dc->state == DECODE_STATE_STOP ||
|
||||
dc->state == DECODE_STATE_ERROR || !dc->seekable)
|
||||
if (state == DECODE_STATE_STOP ||
|
||||
state == DECODE_STATE_ERROR || !seekable)
|
||||
return false;
|
||||
|
||||
dc->seek_where = where;
|
||||
dc->seek_error = false;
|
||||
dc_command(dc, DECODE_COMMAND_SEEK);
|
||||
seek_where = where;
|
||||
seek_error = false;
|
||||
dc_command(this, DECODE_COMMAND_SEEK);
|
||||
|
||||
if (dc->seek_error)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return !seek_error;
|
||||
}
|
||||
|
||||
void
|
||||
dc_quit(struct decoder_control *dc)
|
||||
decoder_control::Quit()
|
||||
{
|
||||
assert(dc->thread != NULL);
|
||||
assert(thread != nullptr);
|
||||
|
||||
dc->quit = true;
|
||||
dc_command_async(dc, DECODE_COMMAND_STOP);
|
||||
quit = true;
|
||||
dc_command_async(this, DECODE_COMMAND_STOP);
|
||||
|
||||
g_thread_join(dc->thread);
|
||||
dc->thread = NULL;
|
||||
g_thread_join(thread);
|
||||
thread = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start)
|
||||
decoder_control::MixRampStart(char *_mixramp_start)
|
||||
{
|
||||
assert(dc != NULL);
|
||||
|
||||
g_free(dc->mixramp_start);
|
||||
dc->mixramp_start = mixramp_start;
|
||||
g_free(mixramp_start);
|
||||
mixramp_start = _mixramp_start;
|
||||
}
|
||||
|
||||
void
|
||||
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end)
|
||||
decoder_control::MixRampEnd(char *_mixramp_end)
|
||||
{
|
||||
assert(dc != NULL);
|
||||
|
||||
g_free(dc->mixramp_end);
|
||||
dc->mixramp_end = mixramp_end;
|
||||
g_free(mixramp_end);
|
||||
mixramp_end = _mixramp_end;
|
||||
}
|
||||
|
||||
void
|
||||
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end)
|
||||
decoder_control::MixRampPrevEnd(char *_mixramp_prev_end)
|
||||
{
|
||||
assert(dc != NULL);
|
||||
|
||||
g_free(dc->mixramp_prev_end);
|
||||
dc->mixramp_prev_end = mixramp_prev_end;
|
||||
g_free(mixramp_prev_end);
|
||||
mixramp_prev_end = _mixramp_prev_end;
|
||||
}
|
||||
|
@ -130,6 +130,41 @@ struct decoder_control {
|
||||
char *mixramp_end;
|
||||
char *mixramp_prev_end;
|
||||
|
||||
decoder_control();
|
||||
~decoder_control();
|
||||
|
||||
/**
|
||||
* Locks the object.
|
||||
*/
|
||||
void Lock() const {
|
||||
g_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the object.
|
||||
*/
|
||||
void Unlock() const {
|
||||
g_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the object. This function is only valid in the
|
||||
* player thread. The object should be locked prior to
|
||||
* calling this function.
|
||||
*/
|
||||
void Signal() {
|
||||
g_cond_signal(cond);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a signal on the #decoder_control object. This function
|
||||
* is only valid in the decoder thread. The object must be locked
|
||||
* prior to calling this function.
|
||||
*/
|
||||
void Wait() {
|
||||
g_cond_wait(cond, mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a signal from the decoder thread. This object
|
||||
* must be locked prior to calling this function. This method
|
||||
@ -138,211 +173,123 @@ struct decoder_control {
|
||||
void WaitForDecoder() {
|
||||
g_cond_wait(client_cond, mutex);
|
||||
}
|
||||
|
||||
bool IsIdle() const {
|
||||
return state == DECODE_STATE_STOP ||
|
||||
state == DECODE_STATE_ERROR;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
bool LockIsIdle() const {
|
||||
Lock();
|
||||
bool result = IsIdle();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsStarting() const {
|
||||
return state == DECODE_STATE_START;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
bool LockIsStarting() const {
|
||||
Lock();
|
||||
bool result = IsStarting();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool HasFailed() const {
|
||||
assert(command == DECODE_COMMAND_NONE);
|
||||
|
||||
return state == DECODE_STATE_ERROR;
|
||||
}
|
||||
|
||||
gcc_pure
|
||||
bool LockHasFailed() const {
|
||||
Lock();
|
||||
bool result = HasFailed();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an error has occurred, and if so, returns a newly
|
||||
* allocated copy of the #GError object.
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
GError *GetError() const {
|
||||
assert(command == DECODE_COMMAND_NONE);
|
||||
assert(state != DECODE_STATE_ERROR || error != nullptr);
|
||||
|
||||
return state == DECODE_STATE_ERROR
|
||||
? g_error_copy(error)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like dc_get_error(), but locks and unlocks the object.
|
||||
*/
|
||||
GError *LockGetError() const {
|
||||
Lock();
|
||||
GError *result = GetError();
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the error condition and free the #GError object (if any).
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
void ClearError() {
|
||||
if (state == DECODE_STATE_ERROR) {
|
||||
g_error_free(error);
|
||||
state = DECODE_STATE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified song is currently being decoded. If the
|
||||
* decoder is not running currently (or being started), then this
|
||||
* function returns false in any case.
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
gcc_pure
|
||||
bool IsCurrentSong(const struct song *_song) const;
|
||||
|
||||
gcc_pure
|
||||
bool LockIsCurrentSong(const struct song *_song) const {
|
||||
Lock();
|
||||
const bool result = IsCurrentSong(_song);
|
||||
Unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the decoder.
|
||||
*
|
||||
* @param song the song to be decoded; the given instance will be
|
||||
* owned and freed by the decoder
|
||||
* @param start_ms see #decoder_control
|
||||
* @param end_ms see #decoder_control
|
||||
* @param pipe the pipe which receives the decoded chunks (owned by
|
||||
* the caller)
|
||||
*/
|
||||
void Start(struct song *song, unsigned start_ms, unsigned end_ms,
|
||||
music_buffer *buffer, music_pipe *pipe);
|
||||
|
||||
void Stop();
|
||||
|
||||
bool Seek(double where);
|
||||
|
||||
void Quit();
|
||||
|
||||
void MixRampStart(char *_mixramp_start);
|
||||
void MixRampEnd(char *_mixramp_end);
|
||||
void MixRampPrevEnd(char *_mixramp_prev_end);
|
||||
};
|
||||
|
||||
G_GNUC_MALLOC
|
||||
struct decoder_control *
|
||||
dc_new();
|
||||
|
||||
void
|
||||
dc_free(struct decoder_control *dc);
|
||||
|
||||
/**
|
||||
* Locks the #decoder_control object.
|
||||
*/
|
||||
static inline void
|
||||
decoder_lock(struct decoder_control *dc)
|
||||
{
|
||||
g_mutex_lock(dc->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the #decoder_control object.
|
||||
*/
|
||||
static inline void
|
||||
decoder_unlock(struct decoder_control *dc)
|
||||
{
|
||||
g_mutex_unlock(dc->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a signal on the #decoder_control object. This function
|
||||
* is only valid in the decoder thread. The object must be locked
|
||||
* prior to calling this function.
|
||||
*/
|
||||
static inline void
|
||||
decoder_wait(struct decoder_control *dc)
|
||||
{
|
||||
g_cond_wait(dc->cond, dc->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals the #decoder_control object. This function is only valid
|
||||
* in the player thread. The object should be locked prior to calling
|
||||
* this function.
|
||||
*/
|
||||
static inline void
|
||||
decoder_signal(struct decoder_control *dc)
|
||||
{
|
||||
g_cond_signal(dc->cond);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_is_idle(const struct decoder_control *dc)
|
||||
{
|
||||
return dc->state == DECODE_STATE_STOP ||
|
||||
dc->state == DECODE_STATE_ERROR;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_is_starting(const struct decoder_control *dc)
|
||||
{
|
||||
return dc->state == DECODE_STATE_START;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_has_failed(const struct decoder_control *dc)
|
||||
{
|
||||
assert(dc->command == DECODE_COMMAND_NONE);
|
||||
|
||||
return dc->state == DECODE_STATE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether an error has occurred, and if so, returns a newly
|
||||
* allocated copy of the #GError object.
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
static inline GError *
|
||||
dc_get_error(const struct decoder_control *dc)
|
||||
{
|
||||
assert(dc != NULL);
|
||||
assert(dc->command == DECODE_COMMAND_NONE);
|
||||
assert(dc->state != DECODE_STATE_ERROR || dc->error != NULL);
|
||||
|
||||
return dc->state == DECODE_STATE_ERROR
|
||||
? g_error_copy(dc->error)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like dc_get_error(), but locks and unlocks the object.
|
||||
*/
|
||||
static inline GError *
|
||||
dc_lock_get_error(struct decoder_control *dc)
|
||||
{
|
||||
decoder_lock(dc);
|
||||
GError *error = dc_get_error(dc);
|
||||
decoder_unlock(dc);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the error condition and free the #GError object (if any).
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
static inline void
|
||||
dc_clear_error(struct decoder_control *dc)
|
||||
{
|
||||
if (dc->state == DECODE_STATE_ERROR) {
|
||||
g_error_free(dc->error);
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_lock_is_idle(struct decoder_control *dc)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
decoder_lock(dc);
|
||||
ret = decoder_is_idle(dc);
|
||||
decoder_unlock(dc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_lock_is_starting(struct decoder_control *dc)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
decoder_lock(dc);
|
||||
ret = decoder_is_starting(dc);
|
||||
decoder_unlock(dc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
decoder_lock_has_failed(struct decoder_control *dc)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
decoder_lock(dc);
|
||||
ret = decoder_has_failed(dc);
|
||||
decoder_unlock(dc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the specified song is currently being decoded. If the
|
||||
* decoder is not running currently (or being started), then this
|
||||
* function returns false in any case.
|
||||
*
|
||||
* Caller must lock the object.
|
||||
*/
|
||||
gcc_pure
|
||||
bool
|
||||
decoder_is_current_song(const struct decoder_control *dc,
|
||||
const struct song *song);
|
||||
|
||||
gcc_pure
|
||||
static inline bool
|
||||
decoder_lock_is_current_song(struct decoder_control *dc,
|
||||
const struct song *song)
|
||||
{
|
||||
decoder_lock(dc);
|
||||
const bool result = decoder_is_current_song(dc, song);
|
||||
decoder_unlock(dc);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the decoder.
|
||||
*
|
||||
* @param the decoder
|
||||
* @param song the song to be decoded; the given instance will be
|
||||
* owned and freed by the decoder
|
||||
* @param start_ms see #decoder_control
|
||||
* @param end_ms see #decoder_control
|
||||
* @param pipe the pipe which receives the decoded chunks (owned by
|
||||
* the caller)
|
||||
*/
|
||||
void
|
||||
dc_start(struct decoder_control *dc, struct song *song,
|
||||
unsigned start_ms, unsigned end_ms,
|
||||
struct music_buffer *buffer, struct music_pipe *pipe);
|
||||
|
||||
void
|
||||
dc_stop(struct decoder_control *dc);
|
||||
|
||||
bool
|
||||
dc_seek(struct decoder_control *dc, double where);
|
||||
|
||||
void
|
||||
dc_quit(struct decoder_control *dc);
|
||||
|
||||
void
|
||||
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start);
|
||||
|
||||
void
|
||||
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end);
|
||||
|
||||
void
|
||||
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end);
|
||||
|
||||
#endif
|
||||
|
@ -57,7 +57,7 @@ need_chunks(struct decoder_control *dc, bool do_wait)
|
||||
return dc->command;
|
||||
|
||||
if (do_wait) {
|
||||
decoder_wait(dc);
|
||||
dc->Wait();
|
||||
g_cond_signal(dc->client_cond);
|
||||
|
||||
return dc->command;
|
||||
@ -89,9 +89,9 @@ decoder_get_chunk(struct decoder *decoder)
|
||||
return decoder->chunk;
|
||||
}
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
cmd = need_chunks(dc, true);
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
} while (cmd == DECODE_COMMAND_NONE);
|
||||
|
||||
return NULL;
|
||||
|
@ -91,18 +91,18 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
|
||||
/* wait for the input stream to become ready; its metadata
|
||||
will be available then */
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
input_stream_update(is);
|
||||
while (!is->ready &&
|
||||
dc->command != DECODE_COMMAND_STOP) {
|
||||
decoder_wait(dc);
|
||||
dc->Wait();
|
||||
|
||||
input_stream_update(is);
|
||||
}
|
||||
|
||||
if (!input_stream_check(is, &error)) {
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
g_warning("%s", error->message);
|
||||
g_error_free(error);
|
||||
@ -110,7 +110,7 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
return is;
|
||||
}
|
||||
@ -137,11 +137,11 @@ decoder_stream_decode(const struct decoder_plugin *plugin,
|
||||
/* rewind the stream, so each plugin gets a fresh start */
|
||||
input_stream_seek(input_stream, 0, SEEK_SET, NULL);
|
||||
|
||||
decoder_unlock(decoder->dc);
|
||||
decoder->dc->Unlock();
|
||||
|
||||
decoder_plugin_stream_decode(plugin, decoder, input_stream);
|
||||
|
||||
decoder_lock(decoder->dc);
|
||||
decoder->dc->Lock();
|
||||
|
||||
assert(decoder->dc->state == DECODE_STATE_START ||
|
||||
decoder->dc->state == DECODE_STATE_DECODE);
|
||||
@ -167,11 +167,11 @@ decoder_file_decode(const struct decoder_plugin *plugin,
|
||||
if (decoder->dc->command == DECODE_COMMAND_STOP)
|
||||
return true;
|
||||
|
||||
decoder_unlock(decoder->dc);
|
||||
decoder->dc->Unlock();
|
||||
|
||||
decoder_plugin_file_decode(plugin, decoder, path);
|
||||
|
||||
decoder_lock(decoder->dc);
|
||||
decoder->dc->Lock();
|
||||
|
||||
assert(decoder->dc->state == DECODE_STATE_START ||
|
||||
decoder->dc->state == DECODE_STATE_DECODE);
|
||||
@ -280,15 +280,15 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
|
||||
struct input_stream *input_stream;
|
||||
bool success;
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
input_stream = decoder_input_stream_open(dc, uri);
|
||||
if (input_stream == NULL) {
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
return false;
|
||||
}
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
GSList *tried = NULL;
|
||||
|
||||
@ -305,9 +305,9 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
|
||||
|
||||
g_slist_free(tried);
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
input_stream_close(input_stream);
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -337,18 +337,18 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
|
||||
if (suffix == NULL)
|
||||
return false;
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
decoder_load_replay_gain(decoder, path_fs);
|
||||
|
||||
while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) {
|
||||
if (plugin->file_decode != NULL) {
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
if (decoder_file_decode(plugin, decoder, path_fs))
|
||||
return true;
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
} else if (plugin->stream_decode != NULL) {
|
||||
struct input_stream *input_stream;
|
||||
bool success;
|
||||
@ -357,23 +357,23 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
|
||||
if (input_stream == NULL)
|
||||
continue;
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
success = decoder_stream_decode(plugin, decoder,
|
||||
input_stream);
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
input_stream_close(input_stream);
|
||||
|
||||
if (success) {
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -394,14 +394,14 @@ decoder_run_song(struct decoder_control *dc,
|
||||
? decoder_run_file(&decoder, uri)
|
||||
: decoder_run_stream(&decoder, uri);
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
/* flush the last chunk */
|
||||
|
||||
if (decoder.chunk != NULL)
|
||||
decoder_flush_chunk(&decoder);
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
if (ret)
|
||||
dc->state = DECODE_STATE_STOP;
|
||||
@ -424,7 +424,7 @@ decoder_run_song(struct decoder_control *dc,
|
||||
static void
|
||||
decoder_run(struct decoder_control *dc)
|
||||
{
|
||||
dc_clear_error(dc);
|
||||
dc->ClearError();
|
||||
|
||||
const struct song *song = dc->song;
|
||||
char *uri;
|
||||
@ -455,7 +455,7 @@ decoder_task(gpointer arg)
|
||||
{
|
||||
struct decoder_control *dc = (struct decoder_control *)arg;
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
do {
|
||||
assert(dc->state == DECODE_STATE_STOP ||
|
||||
@ -463,8 +463,8 @@ decoder_task(gpointer arg)
|
||||
|
||||
switch (dc->command) {
|
||||
case DECODE_COMMAND_START:
|
||||
dc_mixramp_start(dc, NULL);
|
||||
dc_mixramp_prev_end(dc, dc->mixramp_end);
|
||||
dc->MixRampStart(nullptr);
|
||||
dc->MixRampPrevEnd(dc->mixramp_end);
|
||||
dc->mixramp_end = NULL; /* Don't free, it's copied above. */
|
||||
dc->replay_gain_prev_db = dc->replay_gain_db;
|
||||
dc->replay_gain_db = 0;
|
||||
@ -480,12 +480,12 @@ decoder_task(gpointer arg)
|
||||
break;
|
||||
|
||||
case DECODE_COMMAND_NONE:
|
||||
decoder_wait(dc);
|
||||
dc->Wait();
|
||||
break;
|
||||
}
|
||||
} while (dc->command != DECODE_COMMAND_NONE || !dc->quit);
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -176,9 +176,9 @@ player_dc_start(struct player *player, struct music_pipe *pipe)
|
||||
if (pc->command == PLAYER_COMMAND_SEEK)
|
||||
start_ms += (unsigned)(pc->seek_where * 1000);
|
||||
|
||||
dc_start(dc, song_dup_detached(pc->next_song),
|
||||
start_ms, pc->next_song->end_ms,
|
||||
player_buffer, pipe);
|
||||
dc->Start(song_dup_detached(pc->next_song),
|
||||
start_ms, pc->next_song->end_ms,
|
||||
player_buffer, pipe);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,7 +217,7 @@ player_dc_stop(struct player *player)
|
||||
{
|
||||
struct decoder_control *dc = player->dc;
|
||||
|
||||
dc_stop(dc);
|
||||
dc->Stop();
|
||||
|
||||
if (dc->pipe != NULL) {
|
||||
/* clear and free the decoder pipe */
|
||||
@ -249,7 +249,7 @@ player_wait_for_decoder(struct player *player)
|
||||
|
||||
player->queued = false;
|
||||
|
||||
GError *error = dc_lock_get_error(dc);
|
||||
GError *error = dc->LockGetError();
|
||||
if (error != NULL) {
|
||||
pc->Lock();
|
||||
pc->SetError(PLAYER_ERROR_DECODER, error);
|
||||
@ -369,22 +369,22 @@ player_check_decoder_startup(struct player *player)
|
||||
|
||||
assert(player->decoder_starting);
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
GError *error = dc_get_error(dc);
|
||||
GError *error = dc->GetError();
|
||||
if (error != NULL) {
|
||||
/* the decoder failed */
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
pc->Lock();
|
||||
pc->SetError(PLAYER_ERROR_DECODER, error);
|
||||
pc->Unlock();
|
||||
|
||||
return false;
|
||||
} else if (!decoder_is_starting(dc)) {
|
||||
} else if (!dc->IsStarting()) {
|
||||
/* the decoder is ready and ok */
|
||||
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
if (player->output_open &&
|
||||
!audio_output_all_wait(pc, 1))
|
||||
@ -414,7 +414,7 @@ player_check_decoder_startup(struct player *player)
|
||||
/* the decoder is not yet ready; wait
|
||||
some more */
|
||||
dc->WaitForDecoder();
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -480,7 +480,7 @@ static bool player_seek_decoder(struct player *player)
|
||||
|
||||
const unsigned start_ms = song->start_ms;
|
||||
|
||||
if (!decoder_lock_is_current_song(dc, song)) {
|
||||
if (!dc->LockIsCurrentSong(song)) {
|
||||
/* the decoder is already decoding the "next" song -
|
||||
stop it and start the previous song again */
|
||||
|
||||
@ -529,7 +529,7 @@ static bool player_seek_decoder(struct player *player)
|
||||
if (where < 0.0)
|
||||
where = 0.0;
|
||||
|
||||
if (!dc_seek(dc, where + start_ms / 1000.0)) {
|
||||
if (!dc->Seek(where + start_ms / 1000.0)) {
|
||||
/* decoder failure */
|
||||
player_command_finished(pc);
|
||||
return false;
|
||||
@ -782,19 +782,19 @@ play_next_chunk(struct player *player)
|
||||
} else {
|
||||
/* there are not enough decoded chunks yet */
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
|
||||
if (decoder_is_idle(dc)) {
|
||||
if (dc->IsIdle()) {
|
||||
/* the decoder isn't running, abort
|
||||
cross fading */
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
player->xfade = XFADE_DISABLED;
|
||||
} else {
|
||||
/* wait for the decoder */
|
||||
decoder_signal(dc);
|
||||
dc->Signal();
|
||||
dc->WaitForDecoder();
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -840,12 +840,12 @@ play_next_chunk(struct player *player)
|
||||
/* this formula should prevent that the decoder gets woken up
|
||||
with each chunk; it is more efficient to make it decode a
|
||||
larger block at a time */
|
||||
decoder_lock(dc);
|
||||
if (!decoder_is_idle(dc) &&
|
||||
dc->Lock();
|
||||
if (!dc->IsIdle() &&
|
||||
music_pipe_size(dc->pipe) <= (pc->buffered_before_play +
|
||||
music_buffer_size(player_buffer) * 3) / 4)
|
||||
decoder_signal(dc);
|
||||
decoder_unlock(dc);
|
||||
dc->Signal();
|
||||
dc->Unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -940,7 +940,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
prevent stuttering on slow machines */
|
||||
|
||||
if (music_pipe_size(player.pipe) < pc->buffered_before_play &&
|
||||
!decoder_lock_is_idle(dc)) {
|
||||
!dc->LockIsIdle()) {
|
||||
/* not enough decoded buffer space yet */
|
||||
|
||||
if (!player.paused &&
|
||||
@ -949,10 +949,10 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
!player_send_silence(&player))
|
||||
break;
|
||||
|
||||
decoder_lock(dc);
|
||||
dc->Lock();
|
||||
/* XXX race condition: check decoder again */
|
||||
dc->WaitForDecoder();
|
||||
decoder_unlock(dc);
|
||||
dc->Unlock();
|
||||
pc->Lock();
|
||||
continue;
|
||||
} else {
|
||||
@ -979,7 +979,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (decoder_lock_is_idle(dc) && player.queued &&
|
||||
if (dc->LockIsIdle() && player.queued &&
|
||||
dc->pipe == player.pipe) {
|
||||
/* the decoder has finished the current song;
|
||||
make it decode the next song */
|
||||
@ -994,7 +994,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
!pc->border_pause &&
|
||||
player_dc_at_next_song(&player) &&
|
||||
player.xfade == XFADE_UNKNOWN &&
|
||||
!decoder_lock_is_starting(dc)) {
|
||||
!dc->LockIsStarting()) {
|
||||
/* enable cross fading in this song? if yes,
|
||||
calculate how many chunks will be required
|
||||
for it */
|
||||
@ -1042,7 +1042,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
|
||||
if (!player_song_border(&player))
|
||||
break;
|
||||
} else if (decoder_lock_is_idle(dc)) {
|
||||
} else if (dc->LockIsIdle()) {
|
||||
/* check the size of the pipe again, because
|
||||
the decoder thread may have added something
|
||||
since we last checked */
|
||||
@ -1096,7 +1096,7 @@ player_task(gpointer arg)
|
||||
{
|
||||
struct player_control *pc = (struct player_control *)arg;
|
||||
|
||||
struct decoder_control *dc = dc_new();
|
||||
struct decoder_control *dc = new decoder_control();
|
||||
decoder_thread_start(dc);
|
||||
|
||||
player_buffer = music_buffer_new(pc->buffer_chunks);
|
||||
@ -1156,8 +1156,8 @@ player_task(gpointer arg)
|
||||
case PLAYER_COMMAND_EXIT:
|
||||
pc->Unlock();
|
||||
|
||||
dc_quit(dc);
|
||||
dc_free(dc);
|
||||
dc->Quit();
|
||||
delete dc;
|
||||
audio_output_all_close();
|
||||
music_buffer_free(player_buffer);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user