Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
32799fef
Commit
32799fef
authored
Jan 21, 2013
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
DecoderControl: move functions into the class
parent
e1b03b4a
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
281 additions
and
360 deletions
+281
-360
DecoderAPI.cxx
src/DecoderAPI.cxx
+9
-9
DecoderControl.cxx
src/DecoderControl.cxx
+75
-101
DecoderControl.hxx
src/DecoderControl.hxx
+135
-188
DecoderInternal.cxx
src/DecoderInternal.cxx
+3
-3
DecoderThread.cxx
src/DecoderThread.cxx
+28
-28
PlayerThread.cxx
src/PlayerThread.cxx
+31
-31
No files found.
src/DecoderAPI.cxx
View file @
32799fef
...
...
@@ -64,10 +64,10 @@ decoder_initialized(struct decoder *decoder,
dc
->
seekable
=
seekable
;
dc
->
total_time
=
total_time
;
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
dc
->
state
=
DECODE_STATE_DECODE
;
g_cond_signal
(
dc
->
client_cond
);
d
ecoder_unlock
(
dc
);
d
c
->
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
;
d
ecoder_lock
(
dc
);
d
c
->
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.
;
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
return
;
}
...
...
@@ -192,7 +192,7 @@ decoder_command_finished(struct decoder *decoder)
dc
->
command
=
DECODE_COMMAND_NONE
;
g_cond_signal
(
dc
->
client_cond
);
d
ecoder_unlock
(
dc
);
d
c
->
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
);
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
cmd
=
decoder_get_virtual_command
(
decoder
);
d
ecoder_unlock
(
dc
);
d
c
->
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
);
}
src/DecoderControl.cxx
View file @
32799fef
...
...
@@ -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
;
d
ecoder_signal
(
dc
);
d
c
->
Signal
(
);
dc_command_wait_locked
(
dc
);
}
static
void
dc_command
(
struct
decoder_control
*
dc
,
enum
decoder_command
cmd
)
{
d
ecoder_lock
(
dc
);
dc
_clear_error
(
dc
);
d
c
->
Lock
(
);
dc
->
ClearError
(
);
dc_command_locked
(
dc
,
cmd
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
}
static
void
dc_command_async
(
struct
decoder_control
*
dc
,
enum
decoder_command
cmd
)
{
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
dc
->
command
=
cmd
;
d
ecoder_signal
(
dc
);
d
c
->
Signal
(
);
d
ecoder_unlock
(
dc
);
d
c
->
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
d
c_start
(
struct
decoder_control
*
dc
,
struct
song
*
song
,
unsigned
start_ms
,
unsigned
end_ms
,
struct
music_buffer
*
buffer
,
struct
music_pipe
*
pipe
)
d
ecoder_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
);
song
=
_song
;
start_ms
=
_start_ms
;
end_ms
=
_end_ms
;
buffer
=
_buffer
;
pipe
=
_pipe
;
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
);
dc_command
(
this
,
DECODE_COMMAND_START
);
}
void
d
c_stop
(
struct
decoder_control
*
dc
)
d
ecoder_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
d
c_seek
(
struct
decoder_control
*
dc
,
double
where
)
d
ecoder_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
);
if
(
dc
->
seek_error
)
return
false
;
seek_where
=
where
;
seek_error
=
false
;
dc_command
(
this
,
DECODE_COMMAND_SEEK
);
return
true
;
return
!
seek_error
;
}
void
d
c_quit
(
struct
decoder_control
*
dc
)
d
ecoder_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
d
c_mixramp_start
(
struct
decoder_control
*
dc
,
char
*
mixramp_start
)
d
ecoder_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
d
c_mixramp_end
(
struct
decoder_control
*
dc
,
char
*
mixramp_end
)
d
ecoder_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
d
c_mixramp_prev_end
(
struct
decoder_control
*
dc
,
char
*
mixramp_prev_end
)
d
ecoder_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
;
}
src/DecoderControl.hxx
View file @
32799fef
...
...
@@ -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
);
}
};
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
;
bool
IsIdle
()
const
{
return
state
==
DECODE_STATE_STOP
||
state
==
DECODE_STATE_ERROR
;
}
}
static
inline
bool
decoder_lock_is_idle
(
struct
decoder_control
*
dc
)
{
bool
ret
;
gcc_pure
bool
LockIsIdle
()
const
{
Lock
();
bool
result
=
IsIdle
();
Unlock
();
return
result
;
}
decoder_lock
(
dc
);
ret
=
decoder_is_idle
(
dc
)
;
decoder_unlock
(
dc
);
bool
IsStarting
()
const
{
return
state
==
DECODE_STATE_START
;
}
return
ret
;
}
gcc_pure
bool
LockIsStarting
()
const
{
Lock
();
bool
result
=
IsStarting
();
Unlock
();
return
result
;
}
static
inline
bool
decoder_lock_is_starting
(
struct
decoder_control
*
dc
)
{
bool
ret
;
bool
HasFailed
()
const
{
assert
(
command
==
DECODE_COMMAND_NONE
);
decoder_lock
(
dc
);
ret
=
decoder_is_starting
(
dc
);
decoder_unlock
(
dc
);
return
state
==
DECODE_STATE_ERROR
;
}
return
ret
;
}
gcc_pure
bool
LockHasFailed
()
const
{
Lock
();
bool
result
=
HasFailed
();
Unlock
();
return
result
;
}
static
inline
bool
decoder_lock_has_failed
(
struct
decoder_control
*
dc
)
{
bool
ret
;
/**
* 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
);
decoder_lock
(
dc
);
ret
=
decoder_has_failed
(
dc
);
decoder_unlock
(
dc
);
return
state
==
DECODE_STATE_ERROR
?
g_error_copy
(
error
)
:
nullptr
;
}
return
ret
;
}
/**
* Like dc_get_error(), but locks and unlocks the object.
*/
GError
*
LockGetError
()
const
{
Lock
();
GError
*
result
=
GetError
();
Unlock
();
return
result
;
}
/**
* 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
);
/**
* 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
;
}
}
void
dc_stop
(
struct
decoder_control
*
dc
);
/**
* 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
;
}
bool
dc_seek
(
struct
decoder_control
*
dc
,
double
where
);
/**
* 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
dc_quit
(
struct
decoder_control
*
dc
);
void
Stop
();
void
dc_mixramp_start
(
struct
decoder_control
*
dc
,
char
*
mixramp_start
);
bool
Seek
(
double
where
);
void
dc_mixramp_end
(
struct
decoder_control
*
dc
,
char
*
mixramp_end
);
void
Quit
();
void
dc_mixramp_prev_end
(
struct
decoder_control
*
dc
,
char
*
mixramp_prev_end
);
void
MixRampStart
(
char
*
_mixramp_start
);
void
MixRampEnd
(
char
*
_mixramp_end
);
void
MixRampPrevEnd
(
char
*
_mixramp_prev_end
);
};
#endif
src/DecoderInternal.cxx
View file @
32799fef
...
...
@@ -57,7 +57,7 @@ need_chunks(struct decoder_control *dc, bool do_wait)
return
dc
->
command
;
if
(
do_wait
)
{
d
ecoder_wait
(
dc
);
d
c
->
Wait
(
);
g_cond_signal
(
dc
->
client_cond
);
return
dc
->
command
;
...
...
@@ -89,9 +89,9 @@ decoder_get_chunk(struct decoder *decoder)
return
decoder
->
chunk
;
}
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
cmd
=
need_chunks
(
dc
,
true
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
}
while
(
cmd
==
DECODE_COMMAND_NONE
);
return
NULL
;
...
...
src/DecoderThread.cxx
View file @
32799fef
...
...
@@ -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 */
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
input_stream_update
(
is
);
while
(
!
is
->
ready
&&
dc
->
command
!=
DECODE_COMMAND_STOP
)
{
d
ecoder_wait
(
dc
);
d
c
->
Wait
(
);
input_stream_update
(
is
);
}
if
(
!
input_stream_check
(
is
,
&
error
))
{
d
ecoder_unlock
(
dc
);
d
c
->
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
;
}
d
ecoder_unlock
(
dc
);
d
c
->
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
;
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
input_stream
=
decoder_input_stream_open
(
dc
,
uri
);
if
(
input_stream
==
NULL
)
{
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
return
false
;
}
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
GSList
*
tried
=
NULL
;
...
...
@@ -305,9 +305,9 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
g_slist_free
(
tried
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
input_stream_close
(
input_stream
);
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
return
success
;
}
...
...
@@ -337,18 +337,18 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
if
(
suffix
==
NULL
)
return
false
;
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
decoder_load_replay_gain
(
decoder
,
path_fs
);
while
((
plugin
=
decoder_plugin_from_suffix
(
suffix
,
plugin
))
!=
NULL
)
{
if
(
plugin
->
file_decode
!=
NULL
)
{
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
if
(
decoder_file_decode
(
plugin
,
decoder
,
path_fs
))
return
true
;
d
ecoder_unlock
(
dc
);
d
c
->
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
;
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
success
=
decoder_stream_decode
(
plugin
,
decoder
,
input_stream
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
input_stream_close
(
input_stream
);
if
(
success
)
{
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
return
true
;
}
}
}
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
return
false
;
}
...
...
@@ -394,14 +394,14 @@ decoder_run_song(struct decoder_control *dc,
?
decoder_run_file
(
&
decoder
,
uri
)
:
decoder_run_stream
(
&
decoder
,
uri
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
/* flush the last chunk */
if
(
decoder
.
chunk
!=
NULL
)
decoder_flush_chunk
(
&
decoder
);
d
ecoder_lock
(
dc
);
d
c
->
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
;
d
ecoder_lock
(
dc
);
d
c
->
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
:
d
ecoder_wait
(
dc
);
d
c
->
Wait
(
);
break
;
}
}
while
(
dc
->
command
!=
DECODE_COMMAND_NONE
||
!
dc
->
quit
);
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
return
NULL
;
}
...
...
src/PlayerThread.cxx
View file @
32799fef
...
...
@@ -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
);
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
GError
*
error
=
dc
_get_error
(
dc
);
GError
*
error
=
dc
->
GetError
(
);
if
(
error
!=
NULL
)
{
/* the decoder failed */
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
pc
->
Lock
();
pc
->
SetError
(
PLAYER_ERROR_DECODER
,
error
);
pc
->
Unlock
();
return
false
;
}
else
if
(
!
d
ecoder_is_starting
(
dc
))
{
}
else
if
(
!
d
c
->
IsStarting
(
))
{
/* the decoder is ready and ok */
d
ecoder_unlock
(
dc
);
d
c
->
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
();
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
return
true
;
}
...
...
@@ -480,7 +480,7 @@ static bool player_seek_decoder(struct player *player)
const
unsigned
start_ms
=
song
->
start_ms
;
if
(
!
d
ecoder_lock_is_current_song
(
dc
,
song
))
{
if
(
!
d
c
->
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 */
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
if
(
d
ecoder_is_idle
(
dc
))
{
if
(
d
c
->
IsIdle
(
))
{
/* the decoder isn't running, abort
cross fading */
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
player
->
xfade
=
XFADE_DISABLED
;
}
else
{
/* wait for the decoder */
d
ecoder_signal
(
dc
);
d
c
->
Signal
(
);
dc
->
WaitForDecoder
();
d
ecoder_unlock
(
dc
);
d
c
->
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 */
d
ecoder_lock
(
dc
);
if
(
!
d
ecoder_is_idle
(
dc
)
&&
d
c
->
Lock
(
);
if
(
!
d
c
->
IsIdle
(
)
&&
music_pipe_size
(
dc
->
pipe
)
<=
(
pc
->
buffered_before_play
+
music_buffer_size
(
player_buffer
)
*
3
)
/
4
)
d
ecoder_signal
(
dc
);
d
ecoder_unlock
(
dc
);
d
c
->
Signal
(
);
d
c
->
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
&&
!
d
ecoder_lock_is_idle
(
dc
))
{
!
d
c
->
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
;
d
ecoder_lock
(
dc
);
d
c
->
Lock
(
);
/* XXX race condition: check decoder again */
dc
->
WaitForDecoder
();
d
ecoder_unlock
(
dc
);
d
c
->
Unlock
(
);
pc
->
Lock
();
continue
;
}
else
{
...
...
@@ -979,7 +979,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
*/
#endif
if
(
d
ecoder_lock_is_idle
(
dc
)
&&
player
.
queued
&&
if
(
d
c
->
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
&&
!
d
ecoder_lock_is_starting
(
dc
))
{
!
d
c
->
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
(
d
ecoder_lock_is_idle
(
dc
))
{
}
else
if
(
d
c
->
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
);
d
c_free
(
dc
)
;
dc
->
Quit
(
);
d
elete
dc
;
audio_output_all_close
();
music_buffer_free
(
player_buffer
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment