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