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
697c3f8c
Commit
697c3f8c
authored
Nov 18, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decoder/Internal: rename struct Decoder to class DecoderBridge
parent
bb292f50
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
136 additions
and
134 deletions
+136
-134
Makefile.am
Makefile.am
+1
-1
Bridge.cxx
src/decoder/Bridge.cxx
+4
-4
Bridge.hxx
src/decoder/Bridge.hxx
+11
-5
DecoderAPI.cxx
src/decoder/DecoderAPI.cxx
+60
-66
DecoderThread.cxx
src/decoder/DecoderThread.cxx
+60
-58
No files found.
Makefile.am
View file @
697c3f8c
...
...
@@ -102,7 +102,7 @@ libmpd_a_SOURCES = \
src/decoder/DecoderAPI.cxx src/decoder/DecoderAPI.hxx
\
src/decoder/Client.hxx
\
src/decoder/DecoderPlugin.hxx
\
src/decoder/
DecoderInternal.cxx src/decoder/DecoderInternal
.hxx
\
src/decoder/
Bridge.cxx src/decoder/Bridge
.hxx
\
src/decoder/DecoderPrint.cxx src/decoder/DecoderPrint.hxx
\
src/filter/FilterConfig.cxx src/filter/FilterConfig.hxx
\
src/filter/FilterPlugin.cxx src/filter/FilterPlugin.hxx
\
...
...
src/decoder/
DecoderInternal
.cxx
→
src/decoder/
Bridge
.cxx
View file @
697c3f8c
...
...
@@ -18,7 +18,7 @@
*/
#include "config.h"
#include "
DecoderInternal
.hxx"
#include "
Bridge
.hxx"
#include "DecoderControl.hxx"
#include "pcm/PcmConvert.hxx"
#include "MusicPipe.hxx"
...
...
@@ -28,7 +28,7 @@
#include <assert.h>
Decoder
::~
Decoder
()
Decoder
Bridge
::~
DecoderBridge
()
{
/* caller must flush the chunk */
assert
(
current_chunk
==
nullptr
);
...
...
@@ -64,7 +64,7 @@ LockNeedChunks(DecoderControl &dc)
}
MusicChunk
*
Decoder
::
GetChunk
()
Decoder
Bridge
::
GetChunk
()
{
DecoderCommand
cmd
;
...
...
@@ -88,7 +88,7 @@ Decoder::GetChunk()
}
void
Decoder
::
FlushChunk
()
Decoder
Bridge
::
FlushChunk
()
{
assert
(
!
seeking
);
assert
(
!
initial_seek_running
);
...
...
src/decoder/
DecoderInternal
.hxx
→
src/decoder/
Bridge
.hxx
View file @
697c3f8c
...
...
@@ -17,8 +17,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef MPD_DECODER_
INTERNAL
_HXX
#define MPD_DECODER_
INTERNAL
_HXX
#ifndef MPD_DECODER_
BRIDGE
_HXX
#define MPD_DECODER_
BRIDGE
_HXX
#include "Client.hxx"
#include "ReplayGainInfo.hxx"
...
...
@@ -30,7 +30,12 @@ struct MusicChunk;
struct
DecoderControl
;
struct
Tag
;
struct
Decoder
final
:
DecoderClient
{
/**
* A bridge between the #DecoderClient interface and the MPD core
* (#DecoderControl, #MusicPipe etc.).
*/
class
DecoderBridge
final
:
public
DecoderClient
{
public
:
DecoderControl
&
dc
;
/**
...
...
@@ -94,12 +99,13 @@ struct Decoder final : DecoderClient {
*/
std
::
exception_ptr
error
;
Decoder
(
DecoderControl
&
_dc
,
bool
_initial_seek_pending
,
Tag
*
_tag
)
DecoderBridge
(
DecoderControl
&
_dc
,
bool
_initial_seek_pending
,
Tag
*
_tag
)
:
dc
(
_dc
),
initial_seek_pending
(
_initial_seek_pending
),
song_tag
(
_tag
)
{}
~
Decoder
();
~
Decoder
Bridge
();
/**
* Returns the current chunk the decoder writes to, or allocates a new
...
...
src/decoder/DecoderAPI.cxx
View file @
697c3f8c
...
...
@@ -27,7 +27,7 @@
#include "MusicBuffer.hxx"
#include "MusicPipe.hxx"
#include "DecoderControl.hxx"
#include "
DecoderInternal
.hxx"
#include "
Bridge
.hxx"
#include "DetachedSong.hxx"
#include "input/InputStream.hxx"
#include "util/ConstBuffer.hxx"
...
...
@@ -38,8 +38,8 @@
#include <math.h>
void
Decoder
::
Ready
(
const
AudioFormat
audio_format
,
bool
seekable
,
SignedSongTime
duration
)
Decoder
Bridge
::
Ready
(
const
AudioFormat
audio_format
,
bool
seekable
,
SignedSongTime
duration
)
{
struct
audio_format_string
af_string
;
...
...
@@ -89,10 +89,9 @@ Decoder::Ready(const AudioFormat audio_format,
*/
gcc_pure
static
bool
decoder_prepare_initial_seek
(
Decoder
Client
&
client
)
decoder_prepare_initial_seek
(
Decoder
Bridge
&
bridge
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
const
DecoderControl
&
dc
=
decoder
.
dc
;
const
DecoderControl
&
dc
=
bridge
.
dc
;
assert
(
dc
.
pipe
!=
nullptr
);
if
(
dc
.
state
!=
DecoderState
::
DECODE
)
...
...
@@ -101,30 +100,30 @@ decoder_prepare_initial_seek(DecoderClient &client)
virtual "SEEK" command */
return
false
;
if
(
decoder
.
initial_seek_running
)
if
(
bridge
.
initial_seek_running
)
/* initial seek has already begun - override any other
command */
return
true
;
if
(
decoder
.
initial_seek_pending
)
{
if
(
bridge
.
initial_seek_pending
)
{
if
(
!
dc
.
seekable
)
{
/* seeking is not possible */
decoder
.
initial_seek_pending
=
false
;
bridge
.
initial_seek_pending
=
false
;
return
false
;
}
if
(
dc
.
command
==
DecoderCommand
::
NONE
)
{
/* begin initial seek */
decoder
.
initial_seek_pending
=
false
;
decoder
.
initial_seek_running
=
true
;
bridge
.
initial_seek_pending
=
false
;
bridge
.
initial_seek_running
=
true
;
return
true
;
}
/* skip initial seek when there's another command
(e.g. STOP) */
decoder
.
initial_seek_pending
=
false
;
bridge
.
initial_seek_pending
=
false
;
}
return
false
;
...
...
@@ -137,18 +136,16 @@ decoder_prepare_initial_seek(DecoderClient &client)
*/
gcc_pure
static
DecoderCommand
decoder_get_virtual_command
(
Decoder
Client
&
client
)
decoder_get_virtual_command
(
Decoder
Bridge
&
bridge
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
if
(
decoder
.
error
)
if
(
bridge
.
error
)
/* an error has occurred: stop the decoder plugin */
return
DecoderCommand
::
STOP
;
const
DecoderControl
&
dc
=
decoder
.
dc
;
const
DecoderControl
&
dc
=
bridge
.
dc
;
assert
(
dc
.
pipe
!=
nullptr
);
if
(
decoder_prepare_initial_seek
(
decoder
))
if
(
decoder_prepare_initial_seek
(
bridge
))
return
DecoderCommand
::
SEEK
;
return
dc
.
command
;
...
...
@@ -156,21 +153,20 @@ decoder_get_virtual_command(DecoderClient &client)
gcc_pure
static
DecoderCommand
decoder_lock_get_virtual_command
(
Decoder
Client
&
client
)
decoder_lock_get_virtual_command
(
Decoder
Bridge
&
bridge
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
const
ScopeLock
protect
(
decoder
.
dc
.
mutex
);
return
decoder_get_virtual_command
(
decoder
);
const
ScopeLock
protect
(
bridge
.
dc
.
mutex
);
return
decoder_get_virtual_command
(
bridge
);
}
DecoderCommand
Decoder
::
GetCommand
()
Decoder
Bridge
::
GetCommand
()
{
return
decoder_lock_get_virtual_command
(
*
this
);
}
void
Decoder
::
CommandFinished
()
Decoder
Bridge
::
CommandFinished
()
{
const
ScopeLock
protect
(
dc
.
mutex
);
...
...
@@ -210,7 +206,7 @@ Decoder::CommandFinished()
}
SongTime
Decoder
::
GetSeekTime
()
Decoder
Bridge
::
GetSeekTime
()
{
assert
(
dc
.
pipe
!=
nullptr
);
...
...
@@ -225,13 +221,13 @@ Decoder::GetSeekTime()
}
uint64_t
Decoder
::
GetSeekFrame
()
Decoder
Bridge
::
GetSeekFrame
()
{
return
GetSeekTime
().
ToScale
<
uint64_t
>
(
dc
.
in_audio_format
.
sample_rate
);
}
void
Decoder
::
SeekError
()
Decoder
Bridge
::
SeekError
()
{
assert
(
dc
.
pipe
!=
nullptr
);
...
...
@@ -251,7 +247,7 @@ Decoder::SeekError()
}
InputStreamPtr
Decoder
::
OpenUri
(
const
char
*
uri
)
Decoder
Bridge
::
OpenUri
(
const
char
*
uri
)
{
assert
(
dc
.
state
==
DecoderState
::
START
||
dc
.
state
==
DecoderState
::
DECODE
);
...
...
@@ -280,24 +276,24 @@ Decoder::OpenUri(const char *uri)
*/
gcc_pure
static
inline
bool
decoder_check_cancel_read
(
const
Decoder
*
decoder
)
decoder_check_cancel_read
(
const
Decoder
Bridge
*
bridge
)
{
if
(
decoder
==
nullptr
)
if
(
bridge
==
nullptr
)
return
false
;
if
(
decoder
->
error
)
if
(
bridge
->
error
)
/* this translates to DecoderCommand::STOP */
return
true
;
const
DecoderControl
&
dc
=
decoder
->
dc
;
const
DecoderControl
&
dc
=
bridge
->
dc
;
if
(
dc
.
command
==
DecoderCommand
::
NONE
)
return
false
;
/* ignore the SEEK command during initialization, the plugin
should handle that after it has initialized successfully */
if
(
dc
.
command
==
DecoderCommand
::
SEEK
&&
(
dc
.
state
==
DecoderState
::
START
||
decoder
->
seeking
||
decoder
->
initial_seek_running
))
(
dc
.
state
==
DecoderState
::
START
||
bridge
->
seeking
||
bridge
->
initial_seek_running
))
return
false
;
return
true
;
...
...
@@ -309,11 +305,11 @@ decoder_read(DecoderClient *client,
void
*
buffer
,
size_t
length
)
try
{
/* XXX don't allow decoder==nullptr */
auto
*
decoder
=
(
Decoder
*
)
client
;
auto
*
bridge
=
(
DecoderBridge
*
)
client
;
assert
(
decoder
==
nullptr
||
decoder
->
dc
.
state
==
DecoderState
::
START
||
decoder
->
dc
.
state
==
DecoderState
::
DECODE
);
assert
(
bridge
==
nullptr
||
bridge
->
dc
.
state
==
DecoderState
::
START
||
bridge
->
dc
.
state
==
DecoderState
::
DECODE
);
assert
(
buffer
!=
nullptr
);
if
(
length
==
0
)
...
...
@@ -322,7 +318,7 @@ try {
ScopeLock
lock
(
is
.
mutex
);
while
(
true
)
{
if
(
decoder_check_cancel_read
(
decoder
))
if
(
decoder_check_cancel_read
(
bridge
))
return
0
;
if
(
is
.
IsAvailable
())
...
...
@@ -336,9 +332,9 @@ try {
return
nbytes
;
}
catch
(
const
std
::
runtime_error
&
e
)
{
auto
*
decoder
=
(
Decoder
*
)
client
;
if
(
decoder
!=
nullptr
)
decoder
->
error
=
std
::
current_exception
();
auto
*
bridge
=
(
DecoderBridge
*
)
client
;
if
(
bridge
!=
nullptr
)
bridge
->
error
=
std
::
current_exception
();
else
LogError
(
e
);
return
0
;
...
...
@@ -379,7 +375,7 @@ decoder_skip(DecoderClient *client, InputStream &is, size_t size)
}
void
Decoder
::
SubmitTimestamp
(
double
t
)
Decoder
Bridge
::
SubmitTimestamp
(
double
t
)
{
assert
(
t
>=
0
);
...
...
@@ -388,26 +384,25 @@ Decoder::SubmitTimestamp(double t)
/**
* Sends a #tag as-is to the music pipe. Flushes the current chunk
* (
decoder.
chunk) if there is one.
* (
DecoderBridge::
chunk) if there is one.
*/
static
DecoderCommand
do_send_tag
(
DecoderClient
&
client
,
const
Tag
&
tag
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
MusicChunk
*
chunk
;
auto
&
bridge
=
(
DecoderBridge
&
)
client
;
if
(
decoder
.
current_chunk
!=
nullptr
)
{
if
(
bridge
.
current_chunk
!=
nullptr
)
{
/* there is a partial chunk - flush it, we want the
tag in a new chunk */
decoder
.
FlushChunk
();
bridge
.
FlushChunk
();
}
assert
(
decoder
.
current_chunk
==
nullptr
);
assert
(
bridge
.
current_chunk
==
nullptr
);
chunk
=
decoder
.
GetChunk
();
auto
*
chunk
=
bridge
.
GetChunk
();
if
(
chunk
==
nullptr
)
{
assert
(
decoder
.
dc
.
command
!=
DecoderCommand
::
NONE
);
return
decoder
.
dc
.
command
;
assert
(
bridge
.
dc
.
command
!=
DecoderCommand
::
NONE
);
return
bridge
.
dc
.
command
;
}
chunk
->
tag
=
new
Tag
(
tag
);
...
...
@@ -417,14 +412,13 @@ do_send_tag(DecoderClient &client, const Tag &tag)
static
bool
update_stream_tag
(
DecoderClient
&
client
,
InputStream
*
is
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
Tag
*
tag
;
auto
&
bridge
=
(
DecoderBridge
&
)
client
;
tag
=
is
!=
nullptr
auto
*
tag
=
is
!=
nullptr
?
is
->
LockReadTag
()
:
nullptr
;
if
(
tag
==
nullptr
)
{
tag
=
decoder
.
song_tag
;
tag
=
bridge
.
song_tag
;
if
(
tag
==
nullptr
)
return
false
;
...
...
@@ -432,19 +426,19 @@ update_stream_tag(DecoderClient &client, InputStream *is)
instead */
}
else
/* discard the song tag; we don't need it */
delete
decoder
.
song_tag
;
delete
bridge
.
song_tag
;
decoder
.
song_tag
=
nullptr
;
bridge
.
song_tag
=
nullptr
;
delete
decoder
.
stream_tag
;
decoder
.
stream_tag
=
tag
;
delete
bridge
.
stream_tag
;
bridge
.
stream_tag
=
tag
;
return
true
;
}
DecoderCommand
Decoder
::
SubmitData
(
InputStream
*
is
,
const
void
*
data
,
size_t
length
,
uint16_t
kbit_rate
)
Decoder
Bridge
::
SubmitData
(
InputStream
*
is
,
const
void
*
data
,
size_t
length
,
uint16_t
kbit_rate
)
{
assert
(
dc
.
state
==
DecoderState
::
DECODE
);
assert
(
dc
.
pipe
!=
nullptr
);
...
...
@@ -545,7 +539,7 @@ Decoder::SubmitData(InputStream *is,
}
DecoderCommand
Decoder
::
SubmitTag
(
InputStream
*
is
,
Tag
&&
tag
)
Decoder
Bridge
::
SubmitTag
(
InputStream
*
is
,
Tag
&&
tag
)
{
DecoderCommand
cmd
;
...
...
@@ -586,7 +580,7 @@ Decoder::SubmitTag(InputStream *is, Tag &&tag)
}
void
Decoder
::
SubmitReplayGain
(
const
ReplayGainInfo
*
new_replay_gain_info
)
Decoder
Bridge
::
SubmitReplayGain
(
const
ReplayGainInfo
*
new_replay_gain_info
)
{
if
(
new_replay_gain_info
!=
nullptr
)
{
static
unsigned
serial
;
...
...
@@ -620,7 +614,7 @@ Decoder::SubmitReplayGain(const ReplayGainInfo *new_replay_gain_info)
}
void
Decoder
::
SubmitMixRamp
(
MixRampInfo
&&
mix_ramp
)
Decoder
Bridge
::
SubmitMixRamp
(
MixRampInfo
&&
mix_ramp
)
{
dc
.
SetMixRamp
(
std
::
move
(
mix_ramp
));
}
src/decoder/DecoderThread.cxx
View file @
697c3f8c
...
...
@@ -20,7 +20,7 @@
#include "config.h"
#include "DecoderThread.hxx"
#include "DecoderControl.hxx"
#include "
DecoderInternal
.hxx"
#include "
Bridge
.hxx"
#include "DecoderError.hxx"
#include "DecoderPlugin.hxx"
#include "DetachedSong.hxx"
...
...
@@ -94,18 +94,18 @@ decoder_input_stream_open(DecoderControl &dc, Path path)
*/
static
bool
decoder_stream_decode
(
const
DecoderPlugin
&
plugin
,
Decoder
&
decoder
,
Decoder
Bridge
&
bridge
,
InputStream
&
input_stream
)
{
assert
(
plugin
.
stream_decode
!=
nullptr
);
assert
(
decoder
.
stream_tag
==
nullptr
);
assert
(
decoder
.
decoder_tag
==
nullptr
);
assert
(
bridge
.
stream_tag
==
nullptr
);
assert
(
bridge
.
decoder_tag
==
nullptr
);
assert
(
input_stream
.
IsReady
());
assert
(
decoder
.
dc
.
state
==
DecoderState
::
START
);
assert
(
bridge
.
dc
.
state
==
DecoderState
::
START
);
FormatDebug
(
decoder_thread_domain
,
"probing plugin %s"
,
plugin
.
name
);
if
(
decoder
.
dc
.
command
==
DecoderCommand
::
STOP
)
if
(
bridge
.
dc
.
command
==
DecoderCommand
::
STOP
)
throw
StopDecoder
();
/* rewind the stream, so each plugin gets a fresh start */
...
...
@@ -115,19 +115,19 @@ decoder_stream_decode(const DecoderPlugin &plugin,
}
{
const
ScopeUnlock
unlock
(
decoder
.
dc
.
mutex
);
const
ScopeUnlock
unlock
(
bridge
.
dc
.
mutex
);
FormatThreadName
(
"decoder:%s"
,
plugin
.
name
);
plugin
.
StreamDecode
(
decoder
,
input_stream
);
plugin
.
StreamDecode
(
bridge
,
input_stream
);
SetThreadName
(
"decoder"
);
}
assert
(
decoder
.
dc
.
state
==
DecoderState
::
START
||
decoder
.
dc
.
state
==
DecoderState
::
DECODE
);
assert
(
bridge
.
dc
.
state
==
DecoderState
::
START
||
bridge
.
dc
.
state
==
DecoderState
::
DECODE
);
return
decoder
.
dc
.
state
!=
DecoderState
::
START
;
return
bridge
.
dc
.
state
!=
DecoderState
::
START
;
}
/**
...
...
@@ -137,34 +137,34 @@ decoder_stream_decode(const DecoderPlugin &plugin,
*/
static
bool
decoder_file_decode
(
const
DecoderPlugin
&
plugin
,
Decoder
&
decoder
,
Path
path
)
Decoder
Bridge
&
bridge
,
Path
path
)
{
assert
(
plugin
.
file_decode
!=
nullptr
);
assert
(
decoder
.
stream_tag
==
nullptr
);
assert
(
decoder
.
decoder_tag
==
nullptr
);
assert
(
bridge
.
stream_tag
==
nullptr
);
assert
(
bridge
.
decoder_tag
==
nullptr
);
assert
(
!
path
.
IsNull
());
assert
(
path
.
IsAbsolute
());
assert
(
decoder
.
dc
.
state
==
DecoderState
::
START
);
assert
(
bridge
.
dc
.
state
==
DecoderState
::
START
);
FormatDebug
(
decoder_thread_domain
,
"probing plugin %s"
,
plugin
.
name
);
if
(
decoder
.
dc
.
command
==
DecoderCommand
::
STOP
)
if
(
bridge
.
dc
.
command
==
DecoderCommand
::
STOP
)
throw
StopDecoder
();
{
const
ScopeUnlock
unlock
(
decoder
.
dc
.
mutex
);
const
ScopeUnlock
unlock
(
bridge
.
dc
.
mutex
);
FormatThreadName
(
"decoder:%s"
,
plugin
.
name
);
plugin
.
FileDecode
(
decoder
,
path
);
plugin
.
FileDecode
(
bridge
,
path
);
SetThreadName
(
"decoder"
);
}
assert
(
decoder
.
dc
.
state
==
DecoderState
::
START
||
decoder
.
dc
.
state
==
DecoderState
::
DECODE
);
assert
(
bridge
.
dc
.
state
==
DecoderState
::
START
||
bridge
.
dc
.
state
==
DecoderState
::
DECODE
);
return
decoder
.
dc
.
state
!=
DecoderState
::
START
;
return
bridge
.
dc
.
state
!=
DecoderState
::
START
;
}
gcc_pure
...
...
@@ -198,7 +198,7 @@ decoder_check_plugin(const DecoderPlugin &plugin, const InputStream &is,
}
static
bool
decoder_run_stream_plugin
(
Decoder
&
decoder
,
InputStream
&
is
,
decoder_run_stream_plugin
(
Decoder
Bridge
&
bridge
,
InputStream
&
is
,
const
char
*
suffix
,
const
DecoderPlugin
&
plugin
,
bool
&
tried_r
)
...
...
@@ -206,14 +206,14 @@ decoder_run_stream_plugin(Decoder &decoder, InputStream &is,
if
(
!
decoder_check_plugin
(
plugin
,
is
,
suffix
))
return
false
;
decoder
.
error
=
std
::
exception_ptr
();
bridge
.
error
=
std
::
exception_ptr
();
tried_r
=
true
;
return
decoder_stream_decode
(
plugin
,
decoder
,
is
);
return
decoder_stream_decode
(
plugin
,
bridge
,
is
);
}
static
bool
decoder_run_stream_locked
(
Decoder
&
decoder
,
InputStream
&
is
,
decoder_run_stream_locked
(
Decoder
Bridge
&
bridge
,
InputStream
&
is
,
const
char
*
uri
,
bool
&
tried_r
)
{
UriSuffixBuffer
suffix_buffer
;
...
...
@@ -221,7 +221,7 @@ decoder_run_stream_locked(Decoder &decoder, InputStream &is,
using
namespace
std
::
placeholders
;
const
auto
f
=
std
::
bind
(
decoder_run_stream_plugin
,
std
::
ref
(
decoder
),
std
::
ref
(
is
),
suffix
,
std
::
ref
(
bridge
),
std
::
ref
(
is
),
suffix
,
_1
,
std
::
ref
(
tried_r
));
return
decoder_plugins_try
(
f
);
}
...
...
@@ -230,7 +230,7 @@ decoder_run_stream_locked(Decoder &decoder, InputStream &is,
* Try decoding a stream, using the fallback plugin.
*/
static
bool
decoder_run_stream_fallback
(
Decoder
&
decoder
,
InputStream
&
is
)
decoder_run_stream_fallback
(
Decoder
Bridge
&
bridge
,
InputStream
&
is
)
{
const
struct
DecoderPlugin
*
plugin
;
...
...
@@ -240,7 +240,7 @@ decoder_run_stream_fallback(Decoder &decoder, InputStream &is)
plugin
=
decoder_plugin_from_name
(
"mad"
);
#endif
return
plugin
!=
nullptr
&&
plugin
->
stream_decode
!=
nullptr
&&
decoder_stream_decode
(
*
plugin
,
decoder
,
is
);
decoder_stream_decode
(
*
plugin
,
bridge
,
is
);
}
/**
...
...
@@ -261,25 +261,25 @@ LoadReplayGain(DecoderClient &client, InputStream &is)
* DecoderControl::mutex is not locked by caller.
*/
static
bool
decoder_run_stream
(
Decoder
&
decoder
,
const
char
*
uri
)
decoder_run_stream
(
Decoder
Bridge
&
bridge
,
const
char
*
uri
)
{
DecoderControl
&
dc
=
decoder
.
dc
;
DecoderControl
&
dc
=
bridge
.
dc
;
auto
input_stream
=
decoder_input_stream_open
(
dc
,
uri
);
assert
(
input_stream
);
LoadReplayGain
(
decoder
,
*
input_stream
);
LoadReplayGain
(
bridge
,
*
input_stream
);
const
ScopeLock
protect
(
dc
.
mutex
);
bool
tried
=
false
;
return
dc
.
command
==
DecoderCommand
::
STOP
||
decoder_run_stream_locked
(
decoder
,
*
input_stream
,
uri
,
decoder_run_stream_locked
(
bridge
,
*
input_stream
,
uri
,
tried
)
||
/* fallback to mp3: this is needed for bastard streams
that don't have a suffix or set the mimeType */
(
!
tried
&&
decoder_run_stream_fallback
(
decoder
,
*
input_stream
));
decoder_run_stream_fallback
(
bridge
,
*
input_stream
));
}
/**
...
...
@@ -288,23 +288,23 @@ decoder_run_stream(Decoder &decoder, const char *uri)
* DecoderControl::mutex is not locked by caller.
*/
static
bool
TryDecoderFile
(
Decoder
&
decoder
,
Path
path_fs
,
const
char
*
suffix
,
TryDecoderFile
(
Decoder
Bridge
&
bridge
,
Path
path_fs
,
const
char
*
suffix
,
InputStream
&
input_stream
,
const
DecoderPlugin
&
plugin
)
{
if
(
!
plugin
.
SupportsSuffix
(
suffix
))
return
false
;
decoder
.
error
=
std
::
exception_ptr
();
bridge
.
error
=
std
::
exception_ptr
();
DecoderControl
&
dc
=
decoder
.
dc
;
DecoderControl
&
dc
=
bridge
.
dc
;
if
(
plugin
.
file_decode
!=
nullptr
)
{
const
ScopeLock
protect
(
dc
.
mutex
);
return
decoder_file_decode
(
plugin
,
decoder
,
path_fs
);
return
decoder_file_decode
(
plugin
,
bridge
,
path_fs
);
}
else
if
(
plugin
.
stream_decode
!=
nullptr
)
{
const
ScopeLock
protect
(
dc
.
mutex
);
return
decoder_stream_decode
(
plugin
,
decoder
,
input_stream
);
return
decoder_stream_decode
(
plugin
,
bridge
,
input_stream
);
}
else
return
false
;
}
...
...
@@ -315,21 +315,21 @@ TryDecoderFile(Decoder &decoder, Path path_fs, const char *suffix,
* DecoderControl::mutex is not locked by caller.
*/
static
bool
decoder_run_file
(
Decoder
&
decoder
,
const
char
*
uri_utf8
,
Path
path_fs
)
decoder_run_file
(
Decoder
Bridge
&
bridge
,
const
char
*
uri_utf8
,
Path
path_fs
)
{
const
char
*
suffix
=
uri_get_suffix
(
uri_utf8
);
if
(
suffix
==
nullptr
)
return
false
;
auto
input_stream
=
decoder_input_stream_open
(
decoder
.
dc
,
path_fs
);
auto
input_stream
=
decoder_input_stream_open
(
bridge
.
dc
,
path_fs
);
assert
(
input_stream
);
LoadReplayGain
(
decoder
,
*
input_stream
);
LoadReplayGain
(
bridge
,
*
input_stream
);
auto
&
is
=
*
input_stream
;
return
decoder_plugins_try
([
&
decoder
,
path_fs
,
suffix
,
return
decoder_plugins_try
([
&
bridge
,
path_fs
,
suffix
,
&
is
](
const
DecoderPlugin
&
plugin
){
return
TryDecoderFile
(
decoder
,
return
TryDecoderFile
(
bridge
,
path_fs
,
suffix
,
is
,
...
...
@@ -343,11 +343,12 @@ decoder_run_file(Decoder &decoder, const char *uri_utf8, Path path_fs)
* DecoderControl::mutex is not locked.
*/
static
bool
DecoderUnlockedRunUri
(
Decoder
&
decoder
,
const
char
*
real_uri
,
Path
path_fs
)
DecoderUnlockedRunUri
(
DecoderBridge
&
bridge
,
const
char
*
real_uri
,
Path
path_fs
)
try
{
return
!
path_fs
.
IsNull
()
?
decoder_run_file
(
decoder
,
real_uri
,
path_fs
)
:
decoder_run_stream
(
decoder
,
real_uri
);
?
decoder_run_file
(
bridge
,
real_uri
,
path_fs
)
:
decoder_run_stream
(
bridge
,
real_uri
);
}
catch
(
StopDecoder
)
{
return
true
;
}
catch
(...)
{
...
...
@@ -369,12 +370,13 @@ static void
decoder_run_song
(
DecoderControl
&
dc
,
const
DetachedSong
&
song
,
const
char
*
uri
,
Path
path_fs
)
{
Decoder
decoder
(
dc
,
dc
.
start_time
.
IsPositive
(),
/* pass the song tag only if it's
authoritative, i.e. if it's a local file -
tags on "stream" songs are just remembered
from the last time we played it*/
song
.
IsFile
()
?
new
Tag
(
song
.
GetTag
())
:
nullptr
);
DecoderBridge
bridge
(
dc
,
dc
.
start_time
.
IsPositive
(),
/* pass the song tag only if it's
authoritative, i.e. if it's a local
file - tags on "stream" songs are just
remembered from the last time we
played it*/
song
.
IsFile
()
?
new
Tag
(
song
.
GetTag
())
:
nullptr
);
dc
.
state
=
DecoderState
::
START
;
dc
.
CommandFinishedLocked
();
...
...
@@ -383,20 +385,20 @@ decoder_run_song(DecoderControl &dc,
{
const
ScopeUnlock
unlock
(
dc
.
mutex
);
AtScopeExit
(
&
decoder
)
{
AtScopeExit
(
&
bridge
)
{
/* flush the last chunk */
if
(
decoder
.
current_chunk
!=
nullptr
)
decoder
.
FlushChunk
();
if
(
bridge
.
current_chunk
!=
nullptr
)
bridge
.
FlushChunk
();
};
success
=
DecoderUnlockedRunUri
(
decoder
,
uri
,
path_fs
);
success
=
DecoderUnlockedRunUri
(
bridge
,
uri
,
path_fs
);
}
if
(
decoder
.
error
)
{
if
(
bridge
.
error
)
{
/* copy the Error from struct Decoder to
DecoderControl */
std
::
rethrow_exception
(
decoder
.
error
);
std
::
rethrow_exception
(
bridge
.
error
);
}
else
if
(
success
)
dc
.
state
=
DecoderState
::
STOP
;
else
{
...
...
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