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
ce1d8975
Commit
ce1d8975
authored
Sep 26, 2013
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MusicPipe: expose the C++ API
parent
17e108a1
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
167 additions
and
222 deletions
+167
-222
DecoderAPI.cxx
src/DecoderAPI.cxx
+2
-2
DecoderControl.cxx
src/DecoderControl.cxx
+3
-4
DecoderControl.hxx
src/DecoderControl.hxx
+3
-2
DecoderInternal.cxx
src/DecoderInternal.cxx
+1
-1
MusicChunk.hxx
src/MusicChunk.hxx
+1
-1
MusicPipe.cxx
src/MusicPipe.cxx
+33
-105
MusicPipe.hxx
src/MusicPipe.hxx
+67
-46
OutputAll.cxx
src/OutputAll.cxx
+18
-19
OutputAll.hxx
src/OutputAll.hxx
+3
-3
OutputControl.cxx
src/OutputControl.cxx
+5
-8
OutputControl.hxx
src/OutputControl.hxx
+2
-2
OutputInternal.hxx
src/OutputInternal.hxx
+2
-1
OutputThread.cxx
src/OutputThread.cxx
+3
-3
PlayerThread.cxx
src/PlayerThread.cxx
+23
-24
PlayerThread.hxx
src/PlayerThread.hxx
+1
-1
No files found.
src/DecoderAPI.cxx
View file @
ce1d8975
...
...
@@ -164,7 +164,7 @@ decoder_command_finished(struct decoder *decoder)
if
(
decoder
->
initial_seek_running
)
{
assert
(
!
decoder
->
seeking
);
assert
(
decoder
->
chunk
==
NULL
);
assert
(
music_pipe_empty
(
dc
->
pipe
));
assert
(
dc
->
pipe
->
IsEmpty
(
));
decoder
->
initial_seek_running
=
false
;
decoder
->
timestamp
=
dc
->
start_ms
/
1000.
;
...
...
@@ -182,7 +182,7 @@ decoder_command_finished(struct decoder *decoder)
decoder
->
chunk
=
NULL
;
}
music_pipe_clear
(
dc
->
pipe
,
dc
->
buffer
);
dc
->
pipe
->
Clear
(
dc
->
buffer
);
decoder
->
timestamp
=
dc
->
seek_where
;
}
...
...
src/DecoderControl.cxx
View file @
ce1d8975
...
...
@@ -105,12 +105,11 @@ decoder_control::IsCurrentSong(const Song *_song) const
void
decoder_control
::
Start
(
Song
*
_song
,
unsigned
_start_ms
,
unsigned
_end_ms
,
music_buffer
*
_buffer
,
music_pipe
*
_pipe
)
music_buffer
*
_buffer
,
MusicPipe
&
_pipe
)
{
assert
(
_song
!=
NULL
);
assert
(
_buffer
!=
NULL
);
assert
(
_pipe
!=
NULL
);
assert
(
music_pipe_empty
(
_pipe
));
assert
(
_pipe
.
IsEmpty
());
if
(
song
!=
nullptr
)
song
->
Free
();
...
...
@@ -119,7 +118,7 @@ decoder_control::Start(Song *_song,
start_ms
=
_start_ms
;
end_ms
=
_end_ms
;
buffer
=
_buffer
;
pipe
=
_pipe
;
pipe
=
&
_pipe
;
dc_command
(
this
,
DECODE_COMMAND_START
);
}
...
...
src/DecoderControl.hxx
View file @
ce1d8975
...
...
@@ -31,6 +31,7 @@
#include <assert.h>
struct
Song
;
class
MusicPipe
;
enum
decoder_state
{
DECODE_STATE_STOP
=
0
,
...
...
@@ -127,7 +128,7 @@ struct decoder_control {
* The destination pipe for decoded chunks. The caller thread
* owns this object, and is responsible for freeing it.
*/
struct
music_p
ipe
*
pipe
;
MusicP
ipe
*
pipe
;
float
replay_gain_db
;
float
replay_gain_prev_db
;
...
...
@@ -287,7 +288,7 @@ struct decoder_control {
* the caller)
*/
void
Start
(
Song
*
song
,
unsigned
start_ms
,
unsigned
end_ms
,
music_buffer
*
buffer
,
music_pipe
*
pipe
);
music_buffer
*
buffer
,
MusicPipe
&
pipe
);
void
Stop
();
...
...
src/DecoderInternal.cxx
View file @
ce1d8975
...
...
@@ -100,7 +100,7 @@ decoder_flush_chunk(struct decoder *decoder)
if
(
decoder
->
chunk
->
IsEmpty
())
music_buffer_return
(
dc
->
buffer
,
decoder
->
chunk
);
else
music_pipe_push
(
dc
->
pipe
,
decoder
->
chunk
);
dc
->
pipe
->
Push
(
decoder
->
chunk
);
decoder
->
chunk
=
NULL
;
}
src/MusicChunk.hxx
View file @
ce1d8975
...
...
@@ -36,7 +36,7 @@ struct Tag;
/**
* A chunk of music data. Its format is defined by the
*
music_pipe_append
() caller.
*
MusicPipe::Push
() caller.
*/
struct
music_chunk
{
/** the next chunk in a linked list */
...
...
src/MusicPipe.cxx
View file @
ce1d8975
...
...
@@ -21,74 +21,15 @@
#include "MusicPipe.hxx"
#include "MusicBuffer.hxx"
#include "MusicChunk.hxx"
#include "thread/Mutex.hxx"
#include <glib.h>
#include <assert.h>
struct
music_pipe
{
/** the first chunk */
struct
music_chunk
*
head
;
/** a pointer to the tail of the chunk */
struct
music_chunk
**
tail_r
;
/** the current number of chunks */
unsigned
size
;
/** a mutex which protects #head and #tail_r */
mutable
Mutex
mutex
;
#ifndef NDEBUG
AudioFormat
audio_format
;
#endif
music_pipe
()
:
head
(
nullptr
),
tail_r
(
&
head
),
size
(
0
)
{
#ifndef NDEBUG
audio_format
.
Clear
();
#endif
}
~
music_pipe
()
{
assert
(
head
==
nullptr
);
assert
(
tail_r
==
&
head
);
}
};
struct
music_pipe
*
music_pipe_new
(
void
)
{
return
new
music_pipe
();
}
void
music_pipe_free
(
struct
music_pipe
*
mp
)
{
delete
mp
;
}
#ifndef NDEBUG
bool
music_pipe_check_format
(
const
struct
music_pipe
*
pipe
,
const
AudioFormat
audio_format
)
MusicPipe
::
Contains
(
const
music_chunk
*
chunk
)
const
{
assert
(
pipe
!=
NULL
);
const
ScopeLock
protect
(
mutex
);
return
!
pipe
->
audio_format
.
IsDefined
()
||
pipe
->
audio_format
==
audio_format
;
}
bool
music_pipe_contains
(
const
struct
music_pipe
*
mp
,
const
struct
music_chunk
*
chunk
)
{
const
ScopeLock
protect
(
mp
->
mutex
);
for
(
const
struct
music_chunk
*
i
=
mp
->
head
;
i
!=
NULL
;
i
=
i
->
next
)
for
(
const
struct
music_chunk
*
i
=
head
;
i
!=
nullptr
;
i
=
i
->
next
)
if
(
i
==
chunk
)
return
true
;
...
...
@@ -97,40 +38,34 @@ music_pipe_contains(const struct music_pipe *mp,
#endif
const
struct
music_chunk
*
music_pipe_peek
(
const
struct
music_pipe
*
mp
)
{
return
mp
->
head
;
}
struct
music_chunk
*
music_pipe_shift
(
struct
music_pipe
*
mp
)
music_chunk
*
MusicPipe
::
Shift
()
{
const
ScopeLock
protect
(
m
p
->
m
utex
);
const
ScopeLock
protect
(
mutex
);
struct
music_chunk
*
chunk
=
mp
->
head
;
if
(
chunk
!=
NULL
)
{
music_chunk
*
chunk
=
head
;
if
(
chunk
!=
nullptr
)
{
assert
(
!
chunk
->
IsEmpty
());
mp
->
head
=
chunk
->
next
;
--
mp
->
size
;
head
=
chunk
->
next
;
--
size
;
if
(
mp
->
head
==
NULL
)
{
assert
(
mp
->
size
==
0
);
assert
(
mp
->
tail_r
==
&
chunk
->
next
);
if
(
head
==
nullptr
)
{
assert
(
size
==
0
);
assert
(
tail_r
==
&
chunk
->
next
);
mp
->
tail_r
=
&
mp
->
head
;
tail_r
=
&
head
;
}
else
{
assert
(
mp
->
size
>
0
);
assert
(
mp
->
tail_r
!=
&
chunk
->
next
);
assert
(
size
>
0
);
assert
(
tail_r
!=
&
chunk
->
next
);
}
#ifndef NDEBUG
/* poison the "next" reference */
chunk
->
next
=
(
struct
music_chunk
*
)(
void
*
)
0x01010101
;
chunk
->
next
=
(
music_chunk
*
)(
void
*
)
0x01010101
;
if
(
mp
->
size
==
0
)
mp
->
audio_format
.
Clear
();
if
(
size
==
0
)
audio_format
.
Clear
();
#endif
}
...
...
@@ -138,41 +73,34 @@ music_pipe_shift(struct music_pipe *mp)
}
void
music_pipe_clear
(
struct
music_pipe
*
mp
,
struct
music_buffer
*
buffer
)
MusicPipe
::
Clear
(
music_buffer
*
buffer
)
{
struct
music_chunk
*
chunk
;
music_chunk
*
chunk
;
while
((
chunk
=
music_pipe_shift
(
mp
))
!=
NULL
)
while
((
chunk
=
Shift
())
!=
nullptr
)
music_buffer_return
(
buffer
,
chunk
);
}
void
music_pipe_push
(
struct
music_pipe
*
mp
,
struct
music_chunk
*
chunk
)
MusicPipe
::
Push
(
music_chunk
*
chunk
)
{
assert
(
!
chunk
->
IsEmpty
());
assert
(
chunk
->
length
==
0
||
chunk
->
audio_format
.
IsValid
());
const
ScopeLock
protect
(
m
p
->
m
utex
);
const
ScopeLock
protect
(
mutex
);
assert
(
mp
->
size
>
0
||
!
mp
->
audio_format
.
IsDefined
());
assert
(
!
mp
->
audio_format
.
IsDefined
()
||
chunk
->
CheckFormat
(
mp
->
audio_format
));
assert
(
size
>
0
||
!
audio_format
.
IsDefined
());
assert
(
!
audio_format
.
IsDefined
()
||
chunk
->
CheckFormat
(
audio_format
));
#ifndef NDEBUG
if
(
!
mp
->
audio_format
.
IsDefined
()
&&
chunk
->
length
>
0
)
mp
->
audio_format
=
chunk
->
audio_format
;
if
(
!
audio_format
.
IsDefined
()
&&
chunk
->
length
>
0
)
audio_format
=
chunk
->
audio_format
;
#endif
chunk
->
next
=
NULL
;
*
mp
->
tail_r
=
chunk
;
mp
->
tail_r
=
&
chunk
->
next
;
++
mp
->
size
;
}
chunk
->
next
=
nullptr
;
*
tail_r
=
chunk
;
tail_r
=
&
chunk
->
next
;
unsigned
music_pipe_size
(
const
struct
music_pipe
*
mp
)
{
const
ScopeLock
protect
(
mp
->
mutex
);
return
mp
->
size
;
++
size
;
}
src/MusicPipe.hxx
View file @
ce1d8975
...
...
@@ -20,12 +20,15 @@
#ifndef MPD_PIPE_H
#define MPD_PIPE_H
#include "thread/Mutex.hxx"
#include "gcc.h"
#ifndef NDEBUG
struct
AudioFormat
;
#include "AudioFormat.hxx"
#endif
#include <assert.h>
struct
music_chunk
;
struct
music_buffer
;
...
...
@@ -33,80 +36,98 @@ struct music_buffer;
* A queue of #music_chunk objects. One party appends chunks at the
* tail, and the other consumes them from the head.
*/
struct
music_pipe
;
class
MusicPipe
{
/** the first chunk */
music_chunk
*
head
;
/**
* Creates a new #music_pipe object. It is empty.
/** a pointer to the tail of the chunk */
music_chunk
**
tail_r
;
/** the current number of chunks */
unsigned
size
;
/** a mutex which protects #head and #tail_r */
mutable
Mutex
mutex
;
#ifndef NDEBUG
AudioFormat
audio_format
;
#endif
public
:
/**
* Creates a new #MusicPipe object. It is empty.
*/
gcc_malloc
struct
music_pipe
*
music_pipe_new
(
void
);
MusicPipe
()
:
head
(
nullptr
),
tail_r
(
&
head
),
size
(
0
)
{
#ifndef NDEBUG
audio_format
.
Clear
();
#endif
}
/**
/**
* Frees the object. It must be empty now.
*/
void
music_pipe_free
(
struct
music_pipe
*
mp
);
~
MusicPipe
()
{
assert
(
head
==
nullptr
);
assert
(
tail_r
==
&
head
);
}
#ifndef NDEBUG
/**
/**
* Checks if the audio format if the chunk is equal to the specified
* audio_format.
*/
bool
music_pipe_check_format
(
const
struct
music_pipe
*
pipe
,
AudioFormat
audio_format
);
gcc_pure
bool
CheckFormat
(
AudioFormat
other
)
const
{
return
!
audio_format
.
IsDefined
()
||
audio_format
==
other
;
}
/**
/**
* Checks if the specified chunk is enqueued in the music pipe.
*/
bool
music_pipe_contains
(
const
struct
music_pipe
*
mp
,
const
struct
music_chunk
*
chunk
);
gcc_pure
bool
Contains
(
const
music_chunk
*
chunk
)
const
;
#endif
/**
* Returns the first #music_chunk from the pipe. Returns NULL if the
*
pipe is empty.
/**
* Returns the first #music_chunk from the pipe. Returns
* nullptr if the
pipe is empty.
*/
gcc_pure
const
struct
music_chunk
*
music_pipe_peek
(
const
struct
music_pipe
*
mp
);
gcc_pure
const
music_chunk
*
Peek
()
const
{
return
head
;
}
/**
/**
* Removes the first chunk from the head, and returns it.
*/
struct
music_chunk
*
music_pipe_shift
(
struct
music_pipe
*
mp
);
music_chunk
*
Shift
();
/**
/**
* Clears the whole pipe and returns the chunks to the buffer.
*
* @param buffer the buffer object to return the chunks to
*/
void
music_pipe_clear
(
struct
music_pipe
*
mp
,
struct
music_buffer
*
buffer
);
void
Clear
(
music_buffer
*
buffer
);
/**
/**
* Pushes a chunk to the tail of the pipe.
*/
void
music_pipe_push
(
struct
music_pipe
*
mp
,
struct
music_chunk
*
chunk
);
void
Push
(
music_chunk
*
chunk
);
/**
/**
* Returns the number of chunks currently in this pipe.
*/
gcc_pure
unsigned
music_pipe_size
(
const
struct
music_pipe
*
mp
)
;
gcc_pure
static
inline
bool
music_pipe_empty
(
const
struct
music_pipe
*
mp
)
{
return
music_pipe_size
(
mp
)
==
0
;
}
gcc_pure
unsigned
GetSize
()
const
{
return
size
;
}
gcc_pure
bool
IsEmpty
()
const
{
return
GetSize
()
==
0
;
}
}
;
#endif
src/OutputAll.cxx
View file @
ce1d8975
...
...
@@ -50,10 +50,10 @@ static unsigned int num_audio_outputs;
static
struct
music_buffer
*
g_music_buffer
;
/**
* The #
music_p
ipe object which feeds all audio outputs. It is filled
* The #
MusicP
ipe object which feeds all audio outputs. It is filled
* by audio_output_all_play().
*/
static
struct
music_p
ipe
*
g_mp
;
static
MusicP
ipe
*
g_mp
;
/**
* The "elapsed_time" stamp of the most recently finished chunk.
...
...
@@ -262,7 +262,7 @@ audio_output_all_update(void)
for
(
i
=
0
;
i
<
num_audio_outputs
;
++
i
)
ret
=
audio_output_update
(
audio_outputs
[
i
],
input_audio_format
,
g_mp
)
||
ret
;
input_audio_format
,
*
g_mp
)
||
ret
;
return
ret
;
}
...
...
@@ -292,7 +292,7 @@ audio_output_all_play(struct music_chunk *chunk, Error &error)
return
false
;
}
music_pipe_push
(
g_mp
,
chunk
);
g_mp
->
Push
(
chunk
);
for
(
i
=
0
;
i
<
num_audio_outputs
;
++
i
)
audio_output_play
(
audio_outputs
[
i
]);
...
...
@@ -316,15 +316,14 @@ audio_output_all_open(const AudioFormat audio_format,
/* the audio format must be the same as existing chunks in the
pipe */
assert
(
g_mp
==
NULL
||
music_pipe_check_format
(
g_mp
,
audio_format
));
assert
(
g_mp
==
NULL
||
g_mp
->
CheckFormat
(
audio_format
));
if
(
g_mp
==
NULL
)
g_mp
=
music_pipe_new
();
g_mp
=
new
MusicPipe
();
else
/* if the pipe hasn't been cleared, the the audio
format must not have changed */
assert
(
music_pipe_empty
(
g_mp
)
||
audio_format
==
input_audio_format
);
assert
(
g_mp
->
IsEmpty
()
||
audio_format
==
input_audio_format
);
input_audio_format
=
audio_format
;
...
...
@@ -366,7 +365,7 @@ chunk_is_consumed_in(const struct audio_output *ao,
if
(
ao
->
chunk
==
NULL
)
return
false
;
assert
(
chunk
==
ao
->
chunk
||
music_pipe_contains
(
g_mp
,
ao
->
chunk
));
assert
(
chunk
==
ao
->
chunk
||
g_mp
->
Contains
(
ao
->
chunk
));
if
(
chunk
!=
ao
->
chunk
)
{
assert
(
chunk
->
next
!=
NULL
);
...
...
@@ -401,7 +400,7 @@ static void
clear_tail_chunk
(
gcc_unused
const
struct
music_chunk
*
chunk
,
bool
*
locked
)
{
assert
(
chunk
->
next
==
NULL
);
assert
(
music_pipe_contains
(
g_mp
,
chunk
));
assert
(
g_mp
->
Contains
(
chunk
));
for
(
unsigned
i
=
0
;
i
<
num_audio_outputs
;
++
i
)
{
struct
audio_output
*
ao
=
audio_outputs
[
i
];
...
...
@@ -433,13 +432,13 @@ audio_output_all_check(void)
assert
(
g_music_buffer
!=
NULL
);
assert
(
g_mp
!=
NULL
);
while
((
chunk
=
music_pipe_peek
(
g_mp
))
!=
NULL
)
{
assert
(
!
music_pipe_empty
(
g_mp
));
while
((
chunk
=
g_mp
->
Peek
())
!=
nullptr
)
{
assert
(
!
g_mp
->
IsEmpty
(
));
if
(
!
chunk_is_consumed
(
chunk
))
/* at least one output is not finished playing
this chunk */
return
music_pipe_size
(
g_mp
);
return
g_mp
->
GetSize
(
);
if
(
chunk
->
length
>
0
&&
chunk
->
times
>=
0.0
)
/* only update elapsed_time if the chunk
...
...
@@ -453,7 +452,7 @@ audio_output_all_check(void)
clear_tail_chunk
(
chunk
,
locked
);
/* remove the chunk from the pipe */
shifted
=
music_pipe_shift
(
g_mp
);
shifted
=
g_mp
->
Shift
(
);
assert
(
shifted
==
chunk
);
if
(
is_tail
)
...
...
@@ -523,7 +522,7 @@ audio_output_all_cancel(void)
/* clear the music pipe and return all chunks to the buffer */
if
(
g_mp
!=
NULL
)
music_pipe_clear
(
g_mp
,
g_music_buffer
);
g_mp
->
Clear
(
g_music_buffer
);
/* the audio outputs are now waiting for a signal, to
synchronize the cleared music pipe */
...
...
@@ -546,8 +545,8 @@ audio_output_all_close(void)
if
(
g_mp
!=
NULL
)
{
assert
(
g_music_buffer
!=
NULL
);
music_pipe_clear
(
g_mp
,
g_music_buffer
);
music_pipe_free
(
g_mp
)
;
g_mp
->
Clear
(
g_music_buffer
);
delete
g_mp
;
g_mp
=
NULL
;
}
...
...
@@ -569,8 +568,8 @@ audio_output_all_release(void)
if
(
g_mp
!=
NULL
)
{
assert
(
g_music_buffer
!=
NULL
);
music_pipe_clear
(
g_mp
,
g_music_buffer
);
music_pipe_free
(
g_mp
)
;
g_mp
->
Clear
(
g_music_buffer
);
delete
g_mp
;
g_mp
=
NULL
;
}
...
...
src/OutputAll.hxx
View file @
ce1d8975
...
...
@@ -104,7 +104,7 @@ audio_output_all_set_replay_gain_mode(enum replay_gain_mode mode);
/**
* Enqueue a #music_chunk object for playing, i.e. pushes it to a
* #
music_p
ipe.
* #
MusicP
ipe.
*
* @param chunk the #music_chunk object to be played
* @return true on success, false if no audio output was able to play
...
...
@@ -117,13 +117,13 @@ audio_output_all_play(struct music_chunk *chunk, Error &error);
* Checks if the output devices have drained their music pipe, and
* returns the consumed music chunks to the #music_buffer.
*
* @return the number of chunks to play left in the #
music_p
ipe
* @return the number of chunks to play left in the #
MusicP
ipe
*/
unsigned
audio_output_all_check
(
void
);
/**
* Checks if the size of the #
music_p
ipe is below the #threshold. If
* Checks if the size of the #
MusicP
ipe is below the #threshold. If
* not, it attempts to synchronize with all output threads, and waits
* until another #music_chunk is finished.
*
...
...
src/OutputControl.cxx
View file @
ce1d8975
...
...
@@ -141,14 +141,13 @@ audio_output_disable(struct audio_output *ao)
static
bool
audio_output_open
(
struct
audio_output
*
ao
,
const
AudioFormat
audio_format
,
const
struct
music_pipe
*
mp
)
const
MusicPipe
&
mp
)
{
bool
open
;
assert
(
ao
!=
NULL
);
assert
(
ao
->
allow_play
);
assert
(
audio_format
.
IsValid
());
assert
(
mp
!=
NULL
);
if
(
ao
->
fail_timer
!=
NULL
)
{
g_timer_destroy
(
ao
->
fail_timer
);
...
...
@@ -156,12 +155,12 @@ audio_output_open(struct audio_output *ao,
}
if
(
ao
->
open
&&
audio_format
==
ao
->
in_audio_format
)
{
assert
(
ao
->
pipe
==
mp
||
assert
(
ao
->
pipe
==
&
mp
||
(
ao
->
always_on
&&
ao
->
pause
));
if
(
ao
->
pause
)
{
ao
->
chunk
=
NULL
;
ao
->
pipe
=
mp
;
ao
->
pipe
=
&
mp
;
/* unpause with the CANCEL command; this is a
hack, but suits well for forcing the thread
...
...
@@ -179,7 +178,7 @@ audio_output_open(struct audio_output *ao,
ao
->
in_audio_format
=
audio_format
;
ao
->
chunk
=
NULL
;
ao
->
pipe
=
mp
;
ao
->
pipe
=
&
mp
;
if
(
ao
->
thread
==
NULL
)
audio_output_thread_start
(
ao
);
...
...
@@ -223,10 +222,8 @@ audio_output_close_locked(struct audio_output *ao)
bool
audio_output_update
(
struct
audio_output
*
ao
,
const
AudioFormat
audio_format
,
const
struct
music_pipe
*
mp
)
const
MusicPipe
&
mp
)
{
assert
(
mp
!=
NULL
);
const
ScopeLock
protect
(
ao
->
mutex
);
if
(
ao
->
enabled
&&
ao
->
really_enabled
)
{
...
...
src/OutputControl.hxx
View file @
ce1d8975
...
...
@@ -27,7 +27,7 @@
struct
audio_output
;
struct
AudioFormat
;
struct
config_param
;
struct
music_p
ipe
;
class
MusicP
ipe
;
struct
player_control
;
void
...
...
@@ -54,7 +54,7 @@ audio_output_disable(struct audio_output *ao);
bool
audio_output_update
(
struct
audio_output
*
ao
,
AudioFormat
audio_format
,
const
struct
music_pipe
*
mp
);
const
MusicPipe
&
mp
);
void
audio_output_play
(
struct
audio_output
*
ao
);
...
...
src/OutputInternal.hxx
View file @
ce1d8975
...
...
@@ -31,6 +31,7 @@
class
Error
;
class
Filter
;
class
MusicPipe
;
struct
config_param
;
enum
audio_output_command
{
...
...
@@ -209,7 +210,7 @@ struct audio_output {
/**
* The music pipe which provides music chunks to be played.
*/
const
struct
music_p
ipe
*
pipe
;
const
MusicP
ipe
*
pipe
;
/**
* This mutex protects #open, #fail_timer, #chunk and
...
...
src/OutputThread.cxx
View file @
ce1d8975
...
...
@@ -263,7 +263,7 @@ ao_reopen(struct audio_output *ao)
{
if
(
!
ao
->
config_audio_format
.
IsFullyDefined
())
{
if
(
ao
->
open
)
{
const
struct
music_p
ipe
*
mp
=
ao
->
pipe
;
const
MusicP
ipe
*
mp
=
ao
->
pipe
;
ao_close
(
ao
,
true
);
ao
->
pipe
=
mp
;
}
...
...
@@ -484,7 +484,7 @@ ao_next_chunk(struct audio_output *ao)
/* continue the previous play() call */
?
ao
->
chunk
->
next
/* get the first chunk from the pipe */
:
music_pipe_peek
(
ao
->
pipe
);
:
ao
->
pipe
->
Peek
(
);
}
/**
...
...
@@ -621,7 +621,7 @@ static gpointer audio_output_task(gpointer arg)
case
AO_COMMAND_DRAIN
:
if
(
ao
->
open
)
{
assert
(
ao
->
chunk
==
NULL
);
assert
(
music_pipe_peek
(
ao
->
pipe
)
==
NULL
);
assert
(
ao
->
pipe
->
Peek
()
==
nullptr
);
ao
->
mutex
.
unlock
();
ao_plugin_drain
(
ao
);
...
...
src/PlayerThread.cxx
View file @
ce1d8975
...
...
@@ -54,7 +54,7 @@ struct player {
struct
decoder_control
*
dc
;
struct
music_p
ipe
*
pipe
;
MusicP
ipe
*
pipe
;
/**
* are we waiting for buffered_before_play?
...
...
@@ -166,7 +166,7 @@ player_command_finished(struct player_control *pc)
* Player lock is not held.
*/
static
void
player_dc_start
(
struct
player
*
player
,
struct
music_pipe
*
pipe
)
player_dc_start
(
struct
player
*
player
,
MusicPipe
&
pipe
)
{
struct
player_control
*
pc
=
player
->
pc
;
struct
decoder_control
*
dc
=
player
->
dc
;
...
...
@@ -224,10 +224,10 @@ player_dc_stop(struct player *player)
if
(
dc
->
pipe
!=
NULL
)
{
/* clear and free the decoder pipe */
music_pipe_clear
(
dc
->
pipe
,
player_buffer
);
dc
->
pipe
->
Clear
(
player_buffer
);
if
(
dc
->
pipe
!=
player
->
pipe
)
music_pipe_free
(
dc
->
pipe
)
;
delete
dc
->
pipe
;
dc
->
pipe
=
NULL
;
}
...
...
@@ -493,10 +493,10 @@ static bool player_seek_decoder(struct player *player)
/* clear music chunks which might still reside in the
pipe */
music_pipe_clear
(
player
->
pipe
,
player_buffer
);
player
->
pipe
->
Clear
(
player_buffer
);
/* re-start the decoder */
player_dc_start
(
player
,
player
->
pipe
);
player_dc_start
(
player
,
*
player
->
pipe
);
if
(
!
player_wait_for_decoder
(
player
))
{
/* decoder failure */
player_command_finished
(
pc
);
...
...
@@ -506,8 +506,8 @@ static bool player_seek_decoder(struct player *player)
if
(
!
player_dc_at_current_song
(
player
))
{
/* the decoder is already decoding the "next" song,
but it is the same song file; exchange the pipe */
music_pipe_clear
(
player
->
pipe
,
player_buffer
);
music_pipe_free
(
player
->
pipe
)
;
player
->
pipe
->
Clear
(
player_buffer
);
delete
player
->
pipe
;
player
->
pipe
=
dc
->
pipe
;
}
...
...
@@ -734,11 +734,10 @@ play_next_chunk(struct player *player)
struct
music_chunk
*
chunk
=
NULL
;
if
(
player
->
xfade
==
XFADE_ENABLED
&&
player_dc_at_next_song
(
player
)
&&
(
cross_fade_position
=
music_pipe_size
(
player
->
pipe
))
(
cross_fade_position
=
player
->
pipe
->
GetSize
(
))
<=
player
->
cross_fade_chunks
)
{
/* perform cross fade */
struct
music_chunk
*
other_chunk
=
music_pipe_shift
(
dc
->
pipe
);
music_chunk
*
other_chunk
=
dc
->
pipe
->
Shift
();
if
(
!
player
->
cross_fading
)
{
/* beginning of the cross fade - adjust
...
...
@@ -750,7 +749,7 @@ play_next_chunk(struct player *player)
}
if
(
other_chunk
!=
NULL
)
{
chunk
=
music_pipe_shift
(
player
->
pipe
);
chunk
=
player
->
pipe
->
Shift
(
);
assert
(
chunk
!=
NULL
);
assert
(
chunk
->
other
==
NULL
);
...
...
@@ -806,7 +805,7 @@ play_next_chunk(struct player *player)
}
if
(
chunk
==
NULL
)
chunk
=
music_pipe_shift
(
player
->
pipe
);
chunk
=
player
->
pipe
->
Shift
(
);
assert
(
chunk
!=
NULL
);
...
...
@@ -848,7 +847,7 @@ play_next_chunk(struct player *player)
larger block at a time */
dc
->
Lock
();
if
(
!
dc
->
IsIdle
()
&&
music_pipe_size
(
dc
->
pipe
)
<=
(
pc
->
buffered_before_play
+
dc
->
pipe
->
GetSize
(
)
<=
(
pc
->
buffered_before_play
+
music_buffer_size
(
player_buffer
)
*
3
)
/
4
)
dc
->
Signal
();
dc
->
Unlock
();
...
...
@@ -874,7 +873,7 @@ player_song_border(struct player *player)
g_message
(
"played
\"
%s
\"
"
,
uri
);
g_free
(
uri
);
music_pipe_free
(
player
->
pipe
)
;
delete
player
->
pipe
;
player
->
pipe
=
player
->
dc
->
pipe
;
audio_output_all_song_border
();
...
...
@@ -910,15 +909,15 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
pc
->
Unlock
();
player
.
pipe
=
music_pipe_new
();
player
.
pipe
=
new
MusicPipe
();
player_dc_start
(
&
player
,
player
.
pipe
);
player_dc_start
(
&
player
,
*
player
.
pipe
);
if
(
!
player_wait_for_decoder
(
&
player
))
{
assert
(
player
.
song
==
NULL
);
player_dc_stop
(
&
player
);
player_command_finished
(
pc
);
music_pipe_free
(
player
.
pipe
)
;
delete
player
.
pipe
;
GlobalEvents
::
Emit
(
GlobalEvents
::
PLAYLIST
);
pc
->
Lock
();
return
;
...
...
@@ -949,7 +948,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
until the buffer is large enough, to
prevent stuttering on slow machines */
if
(
music_pipe_size
(
player
.
pipe
)
<
pc
->
buffered_before_play
&&
if
(
player
.
pipe
->
GetSize
(
)
<
pc
->
buffered_before_play
&&
!
dc
->
LockIsIdle
())
{
/* not enough decoded buffer space yet */
...
...
@@ -996,7 +995,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
assert
(
dc
->
pipe
==
NULL
||
dc
->
pipe
==
player
.
pipe
);
player_dc_start
(
&
player
,
music_pipe_new
());
player_dc_start
(
&
player
,
*
new
MusicPipe
());
}
if
(
/* no cross-fading if MPD is going to pause at the
...
...
@@ -1035,7 +1034,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
if
(
pc
->
command
==
PLAYER_COMMAND_NONE
)
pc
->
Wait
();
continue
;
}
else
if
(
!
music_pipe_empty
(
player
.
pipe
))
{
}
else
if
(
!
player
.
pipe
->
IsEmpty
(
))
{
/* at least one music chunk is ready - send it
to the audio output */
...
...
@@ -1056,7 +1055,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
/* check the size of the pipe again, because
the decoder thread may have added something
since we last checked */
if
(
music_pipe_empty
(
player
.
pipe
))
{
if
(
player
.
pipe
->
IsEmpty
(
))
{
/* wait for the hardware to finish
playback */
audio_output_all_drain
();
...
...
@@ -1075,8 +1074,8 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
player_dc_stop
(
&
player
);
music_pipe_clear
(
player
.
pipe
,
player_buffer
);
music_pipe_free
(
player
.
pipe
)
;
player
.
pipe
->
Clear
(
player_buffer
);
delete
player
.
pipe
;
delete
player
.
cross_fade_tag
;
...
...
src/PlayerThread.hxx
View file @
ce1d8975
...
...
@@ -31,7 +31,7 @@
*
* The player thread itself does not do any I/O. It synchronizes with
* other threads via #GMutex and #GCond objects, and passes
* #music_chunk instances around in #
music_p
ipe objects.
* #music_chunk instances around in #
MusicP
ipe objects.
*/
#ifndef MPD_PLAYER_THREAD_HXX
...
...
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