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
2775d747
Commit
2775d747
authored
Dec 12, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
output/Thread: move MusicPipe code to class SharedPipeConsumer
parent
99659e4c
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
177 additions
and
82 deletions
+177
-82
Makefile.am
Makefile.am
+1
-0
Internal.cxx
src/output/Internal.cxx
+1
-16
Internal.hxx
src/output/Internal.hxx
+4
-20
MultipleOutputs.cxx
src/output/MultipleOutputs.cxx
+2
-4
OutputControl.cxx
src/output/OutputControl.cxx
+3
-5
OutputThread.cxx
src/output/OutputThread.cxx
+11
-37
SharedPipeConsumer.cxx
src/output/SharedPipeConsumer.cxx
+58
-0
SharedPipeConsumer.hxx
src/output/SharedPipeConsumer.hxx
+97
-0
No files found.
Makefile.am
View file @
2775d747
...
...
@@ -1333,6 +1333,7 @@ OUTPUT_API_SRC = \
src/output/Wrapper.hxx
\
src/output/Registry.cxx src/output/Registry.hxx
\
src/output/MultipleOutputs.cxx src/output/MultipleOutputs.hxx
\
src/output/SharedPipeConsumer.cxx src/output/SharedPipeConsumer.hxx
\
src/output/OutputThread.cxx
\
src/output/Domain.cxx src/output/Domain.hxx
\
src/output/OutputControl.cxx
\
...
...
src/output/Internal.cxx
View file @
2775d747
...
...
@@ -19,10 +19,6 @@
#include "config.h"
#include "Internal.hxx"
#include "MusicPipe.hxx"
#include "MusicChunk.hxx"
#include <assert.h>
bool
AudioOutput
::
IsChunkConsumed
(
const
MusicChunk
&
chunk
)
const
...
...
@@ -30,16 +26,5 @@ AudioOutput::IsChunkConsumed(const MusicChunk &chunk) const
if
(
!
open
)
return
true
;
if
(
current_chunk
==
nullptr
)
return
false
;
assert
(
&
chunk
==
current_chunk
||
pipe
->
Contains
(
current_chunk
));
if
(
&
chunk
!=
current_chunk
)
{
assert
(
chunk
.
next
!=
nullptr
);
return
true
;
}
return
current_chunk_finished
&&
chunk
.
next
==
nullptr
;
return
pipe
.
IsConsumed
(
chunk
);
}
src/output/Internal.hxx
View file @
2775d747
...
...
@@ -20,6 +20,7 @@
#ifndef MPD_OUTPUT_INTERNAL_HXX
#define MPD_OUTPUT_INTERNAL_HXX
#include "SharedPipeConsumer.hxx"
#include "AudioFormat.hxx"
#include "pcm/PcmBuffer.hxx"
#include "pcm/PcmDither.hxx"
...
...
@@ -247,13 +248,7 @@ struct AudioOutput {
Command
command
=
Command
::
NONE
;
/**
* The music pipe which provides music chunks to be played.
*/
const
MusicPipe
*
pipe
;
/**
* This mutex protects #open, #fail_timer, #current_chunk and
* #current_chunk_finished.
* This mutex protects #open, #fail_timer, #pipe.
*/
Mutex
mutex
;
...
...
@@ -270,17 +265,9 @@ struct AudioOutput {
PlayerControl
*
player_control
;
/**
* The #MusicChunk which is currently being played. All
* chunks before this one may be returned to the
* #music_buffer, because they are not going to be used by
* this output anymore.
*/
const
MusicChunk
*
current_chunk
;
/**
* Has the output finished playing #current_chunk?
* A reference to the #MusicPipe and the current position.
*/
bool
current_chunk_finished
;
SharedPipeConsumer
pipe
;
/**
* Throws #std::runtime_error on error.
...
...
@@ -445,9 +432,6 @@ private:
*/
bool
WaitForDelay
();
gcc_pure
const
MusicChunk
*
GetNextChunk
()
const
;
bool
PlayChunk
(
const
MusicChunk
*
chunk
);
/**
...
...
src/output/MultipleOutputs.cxx
View file @
2775d747
...
...
@@ -262,7 +262,7 @@ MultipleOutputs::IsChunkConsumed(const MusicChunk *chunk) const
}
inline
void
MultipleOutputs
::
ClearTailChunk
(
gcc_unused
const
MusicChunk
*
chunk
,
MultipleOutputs
::
ClearTailChunk
(
const
MusicChunk
*
chunk
,
bool
*
locked
)
{
assert
(
chunk
->
next
==
nullptr
);
...
...
@@ -281,9 +281,7 @@ MultipleOutputs::ClearTailChunk(gcc_unused const MusicChunk *chunk,
continue
;
}
assert
(
ao
->
current_chunk
==
chunk
);
assert
(
ao
->
current_chunk_finished
);
ao
->
current_chunk
=
nullptr
;
ao
->
pipe
.
ClearTail
(
*
chunk
);
}
}
...
...
src/output/OutputControl.cxx
View file @
2775d747
...
...
@@ -113,11 +113,10 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
fail_timer
.
Reset
();
if
(
open
&&
audio_format
==
in_audio_format
)
{
assert
(
pipe
==
&
mp
||
(
always_on
&&
pause
));
assert
(
&
pipe
.
GetPipe
()
==
&
mp
||
(
always_on
&&
pause
));
if
(
pause
)
{
current_chunk
=
nullptr
;
pipe
=
&
mp
;
pipe
.
Init
(
mp
);
/* unpause with the CANCEL command; this is a
hack, but suits well for forcing the thread
...
...
@@ -133,9 +132,8 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp)
}
in_audio_format
=
audio_format
;
current_chunk
=
nullptr
;
pipe
=
&
mp
;
pipe
.
Init
(
mp
)
;
if
(
!
thread
.
IsDefined
())
StartThread
();
...
...
src/output/OutputThread.cxx
View file @
2775d747
...
...
@@ -134,8 +134,6 @@ AudioOutput::Open()
struct
audio_format_string
af_string
;
assert
(
!
open
);
assert
(
pipe
!=
nullptr
);
assert
(
current_chunk
==
nullptr
);
assert
(
in_audio_format
.
IsValid
());
fail_timer
.
Reset
();
...
...
@@ -239,9 +237,8 @@ AudioOutput::Close(bool drain)
{
assert
(
open
);
pipe
=
nullptr
;
pipe
.
Deinit
()
;
current_chunk
=
nullptr
;
open
=
false
;
const
ScopeUnlock
unlock
(
mutex
);
...
...
@@ -292,9 +289,9 @@ AudioOutput::Reopen()
{
if
(
!
config_audio_format
.
IsFullyDefined
())
{
if
(
open
)
{
const
MusicPipe
*
mp
=
pipe
;
const
MusicPipe
&
old_pipe
=
pipe
.
GetPipe
()
;
Close
(
true
);
pipe
=
mp
;
pipe
.
Init
(
old_pipe
)
;
}
/* no audio format is configured: copy in->out, let
...
...
@@ -499,50 +496,28 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
return
true
;
}
inline
const
MusicChunk
*
AudioOutput
::
GetNextChunk
()
const
{
return
current_chunk
!=
nullptr
/* continue the previous play() call */
?
current_chunk
->
next
/* get the first chunk from the pipe */
:
pipe
->
Peek
();
}
inline
bool
AudioOutput
::
Play
()
{
assert
(
pipe
!=
nullptr
);
const
MusicChunk
*
chunk
=
GetNextChunk
();
const
MusicChunk
*
chunk
=
pipe
.
Get
();
if
(
chunk
==
nullptr
)
/* no chunk available */
return
false
;
current_chunk_finished
=
false
;
assert
(
!
in_playback_loop
);
in_playback_loop
=
true
;
while
(
chunk
!=
nullptr
&&
command
==
Command
::
NONE
)
{
assert
(
!
current_chunk_finished
);
current_chunk
=
chunk
;
if
(
!
PlayChunk
(
chunk
))
{
assert
(
current_chunk
==
nullptr
);
if
(
!
PlayChunk
(
chunk
))
break
;
}
assert
(
current_chunk
==
chunk
);
chunk
=
chunk
->
next
;
pipe
.
Consume
(
*
chunk
);
chunk
=
pipe
.
Get
()
;
}
assert
(
in_playback_loop
);
in_playback_loop
=
false
;
current_chunk_finished
=
true
;
const
ScopeUnlock
unlock
(
mutex
);
player_control
->
LockSignal
();
...
...
@@ -626,7 +601,6 @@ AudioOutput::Task()
case
Command
:
:
CLOSE
:
assert
(
open
);
assert
(
pipe
!=
nullptr
);
Close
(
false
);
CommandFinished
();
...
...
@@ -651,8 +625,8 @@ AudioOutput::Task()
case
Command
:
:
DRAIN
:
if
(
open
)
{
assert
(
current_chunk
==
nullptr
);
assert
(
pipe
->
Peek
()
==
nullptr
);
assert
(
pipe
.
IsInitial
()
);
assert
(
pipe
.
GetPipe
().
Peek
()
==
nullptr
);
const
ScopeUnlock
unlock
(
mutex
);
ao_plugin_drain
(
this
);
...
...
@@ -662,7 +636,7 @@ AudioOutput::Task()
continue
;
case
Command
:
:
CANCEL
:
current_chunk
=
nullptr
;
pipe
.
Cancel
()
;
if
(
open
)
{
const
ScopeUnlock
unlock
(
mutex
);
...
...
@@ -673,7 +647,7 @@ AudioOutput::Task()
continue
;
case
Command
:
:
KILL
:
current_chunk
=
nullptr
;
pipe
.
Cancel
()
;
CommandFinished
();
return
;
}
...
...
src/output/SharedPipeConsumer.cxx
0 → 100644
View file @
2775d747
/*
* Copyright 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include "SharedPipeConsumer.hxx"
#include "MusicChunk.hxx"
#include "MusicPipe.hxx"
const
MusicChunk
*
SharedPipeConsumer
::
Get
()
{
if
(
chunk
!=
nullptr
)
{
if
(
!
consumed
)
return
chunk
;
if
(
chunk
->
next
==
nullptr
)
return
nullptr
;
consumed
=
false
;
return
chunk
=
chunk
->
next
;
}
else
{
/* get the first chunk from the pipe */
consumed
=
false
;
return
chunk
=
pipe
->
Peek
();
}
}
bool
SharedPipeConsumer
::
IsConsumed
(
const
MusicChunk
&
_chunk
)
const
{
if
(
chunk
==
nullptr
)
return
false
;
assert
(
&
_chunk
==
chunk
||
pipe
->
Contains
(
chunk
));
if
(
&
_chunk
!=
chunk
)
{
assert
(
_chunk
.
next
!=
nullptr
);
return
true
;
}
return
consumed
&&
_chunk
.
next
==
nullptr
;
}
src/output/SharedPipeConsumer.hxx
0 → 100644
View file @
2775d747
/*
* Copyright 2003-2016 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef SHARED_PIPE_CONSUMER_HXX
#define SHARED_PIPE_CONSUMER_HXX
#include "check.h"
#include "Compiler.h"
#include <assert.h>
struct
MusicChunk
;
class
MusicPipe
;
/**
* A utility class which helps with consuming data from a #MusicPipe.
*/
class
SharedPipeConsumer
{
/**
* The music pipe which provides music chunks to be played.
*/
const
MusicPipe
*
pipe
=
nullptr
;
/**
* The #MusicChunk which is currently being played. All
* chunks before this one may be returned to the #MusicBuffer,
* because they are not going to be used by this output
* anymore.
*/
const
MusicChunk
*
chunk
;
/**
* Has the output finished playing #current_chunk?
*/
bool
consumed
;
public
:
void
Init
(
const
MusicPipe
&
_pipe
)
{
pipe
=
&
_pipe
;
chunk
=
nullptr
;
}
void
Deinit
()
{
pipe
=
nullptr
;
chunk
=
nullptr
;
}
const
MusicPipe
&
GetPipe
()
{
assert
(
pipe
!=
nullptr
);
return
*
pipe
;
}
bool
IsInitial
()
{
return
chunk
==
nullptr
;
}
void
Cancel
()
{
chunk
=
nullptr
;
}
const
MusicChunk
*
Get
();
void
Consume
(
gcc_unused
const
MusicChunk
&
_chunk
)
{
assert
(
chunk
!=
nullptr
);
assert
(
chunk
==
&
_chunk
);
consumed
=
true
;
}
gcc_pure
bool
IsConsumed
(
const
MusicChunk
&
_chunk
)
const
;
void
ClearTail
(
gcc_unused
const
MusicChunk
&
_chunk
)
{
assert
(
chunk
==
&
_chunk
);
assert
(
consumed
);
chunk
=
nullptr
;
}
};
#endif
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