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
47a0f46c
Commit
47a0f46c
authored
Nov 18, 2016
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
decoder/Client: add DecoderCommand/seek virtual methods
parent
66fb352c
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
156 additions
and
172 deletions
+156
-172
Client.hxx
src/decoder/Client.hxx
+42
-0
DecoderAPI.cxx
src/decoder/DecoderAPI.cxx
+27
-41
DecoderAPI.hxx
src/decoder/DecoderAPI.hxx
+0
-50
DecoderInternal.hxx
src/decoder/DecoderInternal.hxx
+7
-3
AudiofileDecoderPlugin.cxx
src/decoder/plugins/AudiofileDecoderPlugin.cxx
+2
-2
DsdiffDecoderPlugin.cxx
src/decoder/plugins/DsdiffDecoderPlugin.cxx
+5
-5
DsfDecoderPlugin.cxx
src/decoder/plugins/DsfDecoderPlugin.cxx
+5
-5
FfmpegDecoderPlugin.cxx
src/decoder/plugins/FfmpegDecoderPlugin.cxx
+6
-6
FlacDecoderPlugin.cxx
src/decoder/plugins/FlacDecoderPlugin.cxx
+5
-6
FlacInput.cxx
src/decoder/plugins/FlacInput.cxx
+4
-4
GmeDecoderPlugin.cxx
src/decoder/plugins/GmeDecoderPlugin.cxx
+3
-3
MadDecoderPlugin.cxx
src/decoder/plugins/MadDecoderPlugin.cxx
+7
-7
ModplugDecoderPlugin.cxx
src/decoder/plugins/ModplugDecoderPlugin.cxx
+2
-2
MpcdecDecoderPlugin.cxx
src/decoder/plugins/MpcdecDecoderPlugin.cxx
+4
-5
Mpg123DecoderPlugin.cxx
src/decoder/plugins/Mpg123DecoderPlugin.cxx
+3
-3
OpusDecoderPlugin.cxx
src/decoder/plugins/OpusDecoderPlugin.cxx
+4
-4
PcmDecoderPlugin.cxx
src/decoder/plugins/PcmDecoderPlugin.cxx
+4
-4
SidplayDecoderPlugin.cxx
src/decoder/plugins/SidplayDecoderPlugin.cxx
+2
-2
SndfileDecoderPlugin.cxx
src/decoder/plugins/SndfileDecoderPlugin.cxx
+3
-3
VorbisDecoderPlugin.cxx
src/decoder/plugins/VorbisDecoderPlugin.cxx
+4
-4
WavpackDecoderPlugin.cxx
src/decoder/plugins/WavpackDecoderPlugin.cxx
+5
-5
WildmidiDecoderPlugin.cxx
src/decoder/plugins/WildmidiDecoderPlugin.cxx
+2
-3
FakeDecoderAPI.cxx
test/FakeDecoderAPI.cxx
+5
-5
FakeDecoderAPI.hxx
test/FakeDecoderAPI.hxx
+5
-0
No files found.
src/decoder/Client.hxx
View file @
47a0f46c
...
...
@@ -21,7 +21,11 @@
#define MPD_DECODER_CLIENT_HXX
#include "check.h"
#include "DecoderCommand.hxx"
#include "Chrono.hxx"
#include "Compiler.h"
#include <stdint.h>
struct
AudioFormat
;
...
...
@@ -42,6 +46,44 @@ public:
*/
virtual
void
Ready
(
AudioFormat
audio_format
,
bool
seekable
,
SignedSongTime
duration
)
=
0
;
/**
* Determines the pending decoder command.
*
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
gcc_pure
virtual
DecoderCommand
GetCommand
()
=
0
;
/**
* Called by the decoder when it has performed the requested command
* (dc->command). This function resets dc->command and wakes up the
* player thread.
*/
virtual
void
CommandFinished
()
=
0
;
/**
* Call this when you have received the DecoderCommand::SEEK command.
*
* @return the destination position for the seek in milliseconds
*/
gcc_pure
virtual
SongTime
GetSeekTime
()
=
0
;
/**
* Call this when you have received the DecoderCommand::SEEK command.
*
* @return the destination position for the seek in frames
*/
gcc_pure
virtual
uint64_t
GetSeekFrame
()
=
0
;
/**
* Call this instead of CommandFinished() when seeking has
* failed.
*/
virtual
void
SeekError
()
=
0
;
};
#endif
src/decoder/DecoderAPI.cxx
View file @
47a0f46c
...
...
@@ -164,50 +164,45 @@ decoder_lock_get_virtual_command(DecoderClient &client)
}
DecoderCommand
decoder_get_command
(
DecoderClient
&
client
)
Decoder
::
GetCommand
(
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
return
decoder_lock_get_virtual_command
(
decoder
);
return
decoder_lock_get_virtual_command
(
*
this
);
}
void
decoder_command_finished
(
DecoderClient
&
client
)
Decoder
::
CommandFinished
(
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
DecoderControl
&
dc
=
decoder
.
dc
;
const
ScopeLock
protect
(
dc
.
mutex
);
assert
(
dc
.
command
!=
DecoderCommand
::
NONE
||
decoder
.
initial_seek_running
);
assert
(
dc
.
command
!=
DecoderCommand
::
NONE
||
initial_seek_running
);
assert
(
dc
.
command
!=
DecoderCommand
::
SEEK
||
decoder
.
initial_seek_running
||
dc
.
seek_error
||
decoder
.
seeking
);
initial_seek_running
||
dc
.
seek_error
||
seeking
);
assert
(
dc
.
pipe
!=
nullptr
);
if
(
decoder
.
initial_seek_running
)
{
assert
(
!
decoder
.
seeking
);
assert
(
decoder
.
current_chunk
==
nullptr
);
if
(
initial_seek_running
)
{
assert
(
!
seeking
);
assert
(
current_chunk
==
nullptr
);
assert
(
dc
.
pipe
->
IsEmpty
());
decoder
.
initial_seek_running
=
false
;
decoder
.
timestamp
=
dc
.
start_time
.
ToDoubleS
();
initial_seek_running
=
false
;
timestamp
=
dc
.
start_time
.
ToDoubleS
();
return
;
}
if
(
decoder
.
seeking
)
{
decoder
.
seeking
=
false
;
if
(
seeking
)
{
seeking
=
false
;
/* delete frames from the old song position */
if
(
decoder
.
current_chunk
!=
nullptr
)
{
dc
.
buffer
->
Return
(
decoder
.
current_chunk
);
decoder
.
current_chunk
=
nullptr
;
if
(
current_chunk
!=
nullptr
)
{
dc
.
buffer
->
Return
(
current_chunk
);
current_chunk
=
nullptr
;
}
dc
.
pipe
->
Clear
(
*
dc
.
buffer
);
decoder
.
timestamp
=
dc
.
seek_time
.
ToDoubleS
();
timestamp
=
dc
.
seek_time
.
ToDoubleS
();
}
dc
.
command
=
DecoderCommand
::
NONE
;
...
...
@@ -215,53 +210,44 @@ decoder_command_finished(DecoderClient &client)
}
SongTime
decoder_seek_time
(
DecoderClient
&
client
)
Decoder
::
GetSeekTime
(
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
const
DecoderControl
&
dc
=
decoder
.
dc
;
assert
(
dc
.
pipe
!=
nullptr
);
if
(
decoder
.
initial_seek_running
)
if
(
initial_seek_running
)
return
dc
.
start_time
;
assert
(
dc
.
command
==
DecoderCommand
::
SEEK
);
decoder
.
seeking
=
true
;
seeking
=
true
;
return
dc
.
seek_time
;
}
uint64_t
decoder_seek_where_frame
(
DecoderClient
&
client
)
Decoder
::
GetSeekFrame
(
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
const
DecoderControl
&
dc
=
decoder
.
dc
;
return
decoder_seek_time
(
decoder
).
ToScale
<
uint64_t
>
(
dc
.
in_audio_format
.
sample_rate
);
return
GetSeekTime
().
ToScale
<
uint64_t
>
(
dc
.
in_audio_format
.
sample_rate
);
}
void
decoder_seek_error
(
DecoderClient
&
client
)
Decoder
::
SeekError
(
)
{
auto
&
decoder
=
(
Decoder
&
)
client
;
DecoderControl
&
dc
=
decoder
.
dc
;
assert
(
dc
.
pipe
!=
nullptr
);
if
(
decoder
.
initial_seek_running
)
{
if
(
initial_seek_running
)
{
/* d'oh, we can't seek to the sub-song start position,
what now? - no idea, ignoring the problem for now. */
decoder
.
initial_seek_running
=
false
;
initial_seek_running
=
false
;
return
;
}
assert
(
dc
.
command
==
DecoderCommand
::
SEEK
);
dc
.
seek_error
=
true
;
decoder
.
seeking
=
false
;
seeking
=
false
;
decoder_command_finished
(
decoder
);
CommandFinished
(
);
}
InputStreamPtr
...
...
src/decoder/DecoderAPI.hxx
View file @
47a0f46c
...
...
@@ -55,56 +55,6 @@ class DecoderClient;
class
StopDecoder
{};
/**
* Determines the pending decoder command.
*
* @param decoder the decoder object
* @return the current command, or DecoderCommand::NONE if there is no
* command pending
*/
gcc_pure
DecoderCommand
decoder_get_command
(
DecoderClient
&
decoder
);
/**
* Called by the decoder when it has performed the requested command
* (dc->command). This function resets dc->command and wakes up the
* player thread.
*
* @param decoder the decoder object
*/
void
decoder_command_finished
(
DecoderClient
&
decoder
);
/**
* Call this when you have received the DecoderCommand::SEEK command.
*
* @param decoder the decoder object
* @return the destination position for the seek in milliseconds
*/
gcc_pure
SongTime
decoder_seek_time
(
DecoderClient
&
decoder
);
/**
* Call this when you have received the DecoderCommand::SEEK command.
*
* @param decoder the decoder object
* @return the destination position for the seek in frames
*/
gcc_pure
uint64_t
decoder_seek_where_frame
(
DecoderClient
&
decoder
);
/**
* Call this instead of decoder_command_finished() when seeking has
* failed.
*
* @param decoder the decoder object
*/
void
decoder_seek_error
(
DecoderClient
&
decoder
);
/**
* Open a new #InputStream and wait until it's ready.
*
* Throws #StopDecoder if DecoderCommand::STOP was received.
...
...
src/decoder/DecoderInternal.hxx
View file @
47a0f46c
...
...
@@ -59,9 +59,8 @@ struct Decoder final : DecoderClient {
bool
initial_seek_running
=
false
;
/**
* This flag is set by decoder_seek_time(), and checked by
* decoder_command_finished(). It is used to clean up after
* seeking.
* This flag is set by GetSeekTime(), and checked by
* CommandFinished(). It is used to clean up after seeking.
*/
bool
seeking
=
false
;
...
...
@@ -120,6 +119,11 @@ struct Decoder final : DecoderClient {
/* virtual methods from DecoderClient */
void
Ready
(
AudioFormat
audio_format
,
bool
seekable
,
SignedSongTime
duration
)
override
;
DecoderCommand
GetCommand
()
override
;
void
CommandFinished
()
override
;
SongTime
GetSeekTime
()
override
;
uint64_t
GetSeekFrame
()
override
;
void
SeekError
()
override
;
};
#endif
src/decoder/plugins/AudiofileDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -228,10 +228,10 @@ audiofile_stream_decode(DecoderClient &client, InputStream &is)
kbit_rate
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
AFframecount
frame
=
decoder_seek_where_frame
(
client
);
AFframecount
frame
=
client
.
GetSeekFrame
(
);
afSeekFrame
(
fh
,
AF_DEFAULT_TRACK
,
frame
);
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
cmd
=
DecoderCommand
::
NONE
;
}
}
while
(
cmd
==
DecoderCommand
::
NONE
);
...
...
src/decoder/plugins/DsdiffDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -372,23 +372,23 @@ dsdiff_decode_chunk(DecoderClient &client, InputStream &is,
const
unsigned
buffer_frames
=
sizeof
(
buffer
)
/
frame_size
;
const
size_t
buffer_size
=
buffer_frames
*
frame_size
;
auto
cmd
=
decoder_get_command
(
client
);
auto
cmd
=
client
.
GetCommand
(
);
for
(
offset_type
remaining_bytes
=
total_bytes
;
remaining_bytes
>=
frame_size
&&
cmd
!=
DecoderCommand
::
STOP
;)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
uint64_t
frame
=
decoder_seek_where_frame
(
client
);
uint64_t
frame
=
client
.
GetSeekFrame
(
);
offset_type
offset
=
FrameToOffset
(
frame
,
channels
);
if
(
offset
>=
total_bytes
)
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
break
;
}
if
(
dsdlib_skip_to
(
&
client
,
is
,
start_offset
+
offset
))
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
remaining_bytes
=
total_bytes
-
offset
;
}
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
/* see how much aligned data from the remaining chunk
...
...
src/decoder/plugins/DsfDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -259,23 +259,23 @@ dsf_decode_chunk(DecoderClient &client, InputStream &is,
const
size_t
block_size
=
channels
*
DSF_BLOCK_SIZE
;
const
offset_type
start_offset
=
is
.
GetOffset
();
auto
cmd
=
decoder_get_command
(
client
);
auto
cmd
=
client
.
GetCommand
(
);
for
(
offset_type
i
=
0
;
i
<
n_blocks
&&
cmd
!=
DecoderCommand
::
STOP
;)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
uint64_t
frame
=
decoder_seek_where_frame
(
client
);
uint64_t
frame
=
client
.
GetSeekFrame
(
);
offset_type
block
=
FrameToBlock
(
frame
);
if
(
block
>=
n_blocks
)
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
break
;
}
offset_type
offset
=
start_offset
+
block
*
block_size
;
if
(
dsdlib_skip_to
(
&
client
,
is
,
offset
))
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
i
=
block
;
}
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
/* worst-case buffer size */
...
...
src/decoder/plugins/FfmpegDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -717,11 +717,11 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
uint64_t
min_frame
=
0
;
DecoderCommand
cmd
=
decoder_get_command
(
client
);
DecoderCommand
cmd
=
client
.
GetCommand
(
);
while
(
cmd
!=
DecoderCommand
::
STOP
)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
int64_t
where
=
ToFfmpegTime
(
decoder_seek_time
(
client
),
ToFfmpegTime
(
client
.
GetSeekTime
(
),
av_stream
.
time_base
)
+
start_time_fallback
(
av_stream
);
...
...
@@ -730,11 +730,11 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
stamp, not after */
if
(
av_seek_frame
(
&
format_context
,
audio_stream
,
where
,
AVSEEK_FLAG_ANY
|
AVSEEK_FLAG_BACKWARD
)
<
0
)
decoder_seek_error
(
client
);
client
.
SeekError
(
);
else
{
avcodec_flush_buffers
(
codec_context
);
min_frame
=
decoder_seek_where_frame
(
client
);
decoder_command_finished
(
client
);
min_frame
=
client
.
GetSeekFrame
(
);
client
.
CommandFinished
(
);
}
}
...
...
@@ -757,7 +757,7 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
interleaved_buffer
);
min_frame
=
0
;
}
else
cmd
=
decoder_get_command
(
client
);
cmd
=
client
.
GetCommand
(
);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 25, 100)
av_packet_unref
(
&
packet
);
...
...
src/decoder/plugins/FlacDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -151,16 +151,15 @@ flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec)
std
::
move
(
data
->
tag
));
data
->
tag
.
Clear
();
}
else
cmd
=
decoder_get_command
(
client
);
cmd
=
client
.
GetCommand
(
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
FLAC__uint64
seek_sample
=
decoder_seek_where_frame
(
client
);
FLAC__uint64
seek_sample
=
client
.
GetSeekFrame
();
if
(
FLAC__stream_decoder_seek_absolute
(
flac_dec
,
seek_sample
))
{
data
->
position
=
0
;
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
}
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
else
if
(
cmd
==
DecoderCommand
::
STOP
)
break
;
...
...
@@ -198,7 +197,7 @@ flac_decoder_loop(FlacDecoder *data, FLAC__StreamDecoder *flac_dec)
}
if
(
!
FLAC__stream_decoder_process_single
(
flac_dec
)
&&
decoder_get_command
(
client
)
==
DecoderCommand
::
NONE
)
{
client
.
GetCommand
(
)
==
DecoderCommand
::
NONE
)
{
/* a failure that was not triggered by a
decoder command */
flacPrintErroredState
(
FLAC__stream_decoder_get_state
(
flac_dec
));
...
...
src/decoder/plugins/FlacInput.cxx
View file @
47a0f46c
...
...
@@ -36,7 +36,7 @@ FlacInput::Read(FLAC__byte buffer[], size_t *bytes)
if
(
r
==
0
)
{
if
(
input_stream
.
LockIsEOF
()
||
(
client
!=
nullptr
&&
decoder_get_command
(
*
client
)
!=
DecoderCommand
::
NONE
))
client
->
GetCommand
(
)
!=
DecoderCommand
::
NONE
))
return
FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM
;
else
return
FLAC__STREAM_DECODER_READ_STATUS_ABORT
;
...
...
@@ -84,8 +84,8 @@ FLAC__bool
FlacInput
::
Eof
()
{
return
(
client
!=
nullptr
&&
decoder_get_command
(
*
client
)
!=
DecoderCommand
::
NONE
&&
decoder_get_command
(
*
client
)
!=
DecoderCommand
::
SEEK
)
||
client
->
GetCommand
(
)
!=
DecoderCommand
::
NONE
&&
client
->
GetCommand
(
)
!=
DecoderCommand
::
SEEK
)
||
input_stream
.
LockIsEOF
();
}
...
...
@@ -93,7 +93,7 @@ void
FlacInput
::
Error
(
FLAC__StreamDecoderErrorStatus
status
)
{
if
(
client
==
nullptr
||
decoder_get_command
(
*
client
)
!=
DecoderCommand
::
STOP
)
client
->
GetCommand
(
)
!=
DecoderCommand
::
STOP
)
LogWarning
(
flac_domain
,
FLAC__StreamDecoderErrorStatusString
[
status
]);
}
...
...
src/decoder/plugins/GmeDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -192,13 +192,13 @@ gme_file_decode(DecoderClient &client, Path path_fs)
cmd
=
decoder_data
(
client
,
nullptr
,
buf
,
sizeof
(
buf
),
0
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
unsigned
where
=
decoder_seek_time
(
client
).
ToMS
();
unsigned
where
=
client
.
GetSeekTime
(
).
ToMS
();
gme_err
=
gme_seek
(
emu
,
where
);
if
(
gme_err
!=
nullptr
)
{
LogWarning
(
gme_domain
,
gme_err
);
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
else
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
}
if
(
gme_track_ended
(
emu
))
...
...
src/decoder/plugins/MadDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -985,18 +985,18 @@ MadDecoder::Read()
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
assert
(
input_stream
.
IsSeekable
());
unsigned
long
j
=
TimeToFrame
(
decoder_seek_time
(
*
client
)
);
const
auto
t
=
client
->
GetSeekTime
();
unsigned
long
j
=
TimeToFrame
(
t
);
if
(
j
<
highest_frame
)
{
if
(
Seek
(
frame_offsets
[
j
]))
{
current_frame
=
j
;
decoder_command_finished
(
*
client
);
client
->
CommandFinished
(
);
}
else
decoder_seek_error
(
*
client
);
client
->
SeekError
(
);
}
else
{
seek_time
=
decoder_seek_time
(
*
client
)
;
seek_time
=
t
;
mute_frame
=
MUTEFRAME_SEEK
;
decoder_command_finished
(
*
client
);
client
->
CommandFinished
(
);
}
}
else
if
(
cmd
!=
DecoderCommand
::
NONE
)
return
false
;
...
...
@@ -1042,7 +1042,7 @@ mp3_decode(DecoderClient &client, InputStream &input_stream)
if
(
!
data
.
DecodeFirstFrame
(
&
tag
))
{
delete
tag
;
if
(
decoder_get_command
(
client
)
==
DecoderCommand
::
NONE
)
if
(
client
.
GetCommand
(
)
==
DecoderCommand
::
NONE
)
LogError
(
mad_domain
,
"input/Input does not appear to be a mp3 bit stream"
);
return
;
...
...
src/decoder/plugins/ModplugDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -165,8 +165,8 @@ mod_decode(DecoderClient &client, InputStream &is)
0
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
ModPlug_Seek
(
f
,
decoder_seek_time
(
client
).
ToMS
());
decoder_command_finished
(
client
);
ModPlug_Seek
(
f
,
client
.
GetSeekTime
(
).
ToMS
());
client
.
CommandFinished
(
);
}
}
while
(
cmd
!=
DecoderCommand
::
STOP
);
...
...
src/decoder/plugins/MpcdecDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -152,7 +152,7 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
mpc_demux
*
demux
=
mpc_demux_init
(
&
reader
);
if
(
demux
==
nullptr
)
{
if
(
decoder_get_command
(
client
)
!=
DecoderCommand
::
STOP
)
if
(
client
.
GetCommand
(
)
!=
DecoderCommand
::
STOP
)
LogWarning
(
mpcdec_domain
,
"Not a valid musepack stream"
);
return
;
...
...
@@ -180,16 +180,15 @@ mpcdec_decode(DecoderClient &client, InputStream &is)
DecoderCommand
cmd
=
DecoderCommand
::
NONE
;
do
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
mpc_int64_t
where
=
decoder_seek_where_frame
(
client
);
mpc_int64_t
where
=
client
.
GetSeekFrame
();
bool
success
;
success
=
mpc_demux_seek_sample
(
demux
,
where
)
==
MPC_STATUS_OK
;
if
(
success
)
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
MPC_SAMPLE_FORMAT
sample_buffer
[
MPC_DECODER_BUFFER_LENGTH
];
...
...
src/decoder/plugins/Mpg123DecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -260,12 +260,12 @@ mpd_mpg123_file_decode(DecoderClient &client, Path path_fs)
cmd
=
decoder_data
(
client
,
nullptr
,
buffer
,
nbytes
,
info
.
bitrate
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
off_t
c
=
decoder_seek_where_frame
(
client
);
off_t
c
=
client
.
GetSeekFrame
(
);
c
=
mpg123_seek
(
handle
,
c
,
SEEK_SET
);
if
(
c
<
0
)
decoder_seek_error
(
client
);
client
.
SeekError
(
);
else
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
decoder_timestamp
(
client
,
c
/
(
double
)
audio_format
.
sample_rate
);
}
...
...
src/decoder/plugins/OpusDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -181,7 +181,7 @@ MPDOpusDecoder::OnOggBeginning(const ogg_packet &packet)
output_buffer
=
new
opus_int16
[
opus_output_buffer_frames
*
audio_format
.
channels
];
auto
cmd
=
decoder_get_command
(
client
);
auto
cmd
=
client
.
GetCommand
(
);
if
(
cmd
!=
DecoderCommand
::
NONE
)
throw
cmd
;
}
...
...
@@ -291,10 +291,10 @@ mpd_opus_stream_decode(DecoderClient &client,
break
;
}
catch
(
DecoderCommand
cmd
)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
if
(
d
.
Seek
(
decoder_seek_where_frame
(
client
)))
decoder_command_finished
(
client
);
if
(
d
.
Seek
(
client
.
GetSeekFrame
(
)))
client
.
CommandFinished
(
);
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
else
if
(
cmd
!=
DecoderCommand
::
NONE
)
break
;
}
...
...
src/decoder/plugins/PcmDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -166,18 +166,18 @@ pcm_stream_decode(DecoderClient &client, InputStream &is)
cmd
=
!
r
.
IsEmpty
()
?
decoder_data
(
client
,
is
,
r
.
data
,
r
.
size
,
0
)
:
decoder_get_command
(
client
);
:
client
.
GetCommand
(
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
uint64_t
frame
=
decoder_seek_where_frame
(
client
);
uint64_t
frame
=
client
.
GetSeekFrame
(
);
offset_type
offset
=
frame
*
frame_size
;
try
{
is
.
LockSeek
(
offset
);
buffer
.
Clear
();
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
}
catch
(
const
std
::
runtime_error
&
e
)
{
LogError
(
e
);
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
cmd
=
DecoderCommand
::
NONE
;
...
...
src/decoder/plugins/SidplayDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -373,7 +373,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
unsigned
data_time
=
player
.
time
();
unsigned
target_time
=
decoder_seek_time
(
client
).
ToScale
(
timebase
);
client
.
GetSeekTime
(
).
ToScale
(
timebase
);
/* can't rewind so return to zero and seek forward */
if
(
target_time
<
data_time
)
{
...
...
@@ -386,7 +386,7 @@ sidplay_file_decode(DecoderClient &client, Path path_fs)
player
.
play
(
buffer
,
ARRAY_SIZE
(
buffer
))
>
0
)
data_time
=
player
.
time
();
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
}
if
(
end
>
0
&&
player
.
time
()
>=
end
)
...
...
src/decoder/plugins/SndfileDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -225,12 +225,12 @@ sndfile_stream_decode(DecoderClient &client, InputStream &is)
buffer
,
num_frames
*
frame_size
,
0
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
sf_count_t
c
=
decoder_seek_where_frame
(
client
);
sf_count_t
c
=
client
.
GetSeekFrame
(
);
c
=
sf_seek
(
sf
,
c
,
SEEK_SET
);
if
(
c
<
0
)
decoder_seek_error
(
client
);
client
.
SeekError
(
);
else
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
cmd
=
DecoderCommand
::
NONE
;
}
}
while
(
cmd
==
DecoderCommand
::
NONE
);
...
...
src/decoder/plugins/VorbisDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -264,7 +264,7 @@ VorbisDecoder::OnOggPacket(const ogg_packet &_packet)
if
(
vorbis_synthesis
(
&
block
,
&
packet
)
!=
0
)
{
/* ignore bad packets, but give the MPD core a
chance to stop us */
auto
cmd
=
decoder_get_command
(
client
);
auto
cmd
=
client
.
GetCommand
(
);
if
(
cmd
!=
DecoderCommand
::
NONE
)
throw
cmd
;
return
;
...
...
@@ -322,10 +322,10 @@ vorbis_stream_decode(DecoderClient &client,
break
;
}
catch
(
DecoderCommand
cmd
)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
if
(
d
.
Seek
(
decoder_seek_where_frame
(
client
)))
decoder_command_finished
(
client
);
if
(
d
.
Seek
(
client
.
GetSeekFrame
(
)))
client
.
CommandFinished
(
);
else
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
else
if
(
cmd
!=
DecoderCommand
::
NONE
)
break
;
}
...
...
src/decoder/plugins/WavpackDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -170,19 +170,19 @@ wavpack_decode(DecoderClient &client, WavpackContext *wpc, bool can_seek)
client
.
Ready
(
audio_format
,
can_seek
,
total_time
);
DecoderCommand
cmd
=
decoder_get_command
(
client
);
DecoderCommand
cmd
=
client
.
GetCommand
(
);
while
(
cmd
!=
DecoderCommand
::
STOP
)
{
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
if
(
can_seek
)
{
auto
where
=
decoder_seek_where_frame
(
client
);
auto
where
=
client
.
GetSeekFrame
(
);
if
(
WavpackSeekSample
(
wpc
,
where
))
{
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
}
else
{
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
}
else
{
decoder_seek_error
(
client
);
client
.
SeekError
(
);
}
}
...
...
src/decoder/plugins/WildmidiDecoderPlugin.cxx
View file @
47a0f46c
...
...
@@ -114,11 +114,10 @@ wildmidi_file_decode(DecoderClient &client, Path path_fs)
cmd
=
wildmidi_output
(
client
,
wm
);
if
(
cmd
==
DecoderCommand
::
SEEK
)
{
unsigned
long
seek_where
=
decoder_seek_where_frame
(
client
);
unsigned
long
seek_where
=
client
.
GetSeekFrame
();
WildMidi_FastSeek
(
wm
,
&
seek_where
);
decoder_command_finished
(
client
);
client
.
CommandFinished
(
);
cmd
=
DecoderCommand
::
NONE
;
}
...
...
test/FakeDecoderAPI.cxx
View file @
47a0f46c
...
...
@@ -46,30 +46,30 @@ FakeDecoder::Ready(const AudioFormat audio_format,
}
DecoderCommand
decoder_get_command
(
gcc_unused
DecoderClient
&
client
)
FakeDecoder
::
GetCommand
(
)
{
return
DecoderCommand
::
NONE
;
}
void
decoder_command_finished
(
gcc_unused
DecoderClient
&
client
)
FakeDecoder
::
CommandFinished
(
)
{
}
SongTime
decoder_seek_time
(
gcc_unused
DecoderClient
&
client
)
FakeDecoder
::
GetSeekTime
(
)
{
return
SongTime
();
}
uint64_t
decoder_seek_where_frame
(
gcc_unused
DecoderClient
&
client
)
FakeDecoder
::
GetSeekFrame
(
)
{
return
1
;
}
void
decoder_seek_error
(
gcc_unused
DecoderClient
&
client
)
FakeDecoder
::
SeekError
(
)
{
}
...
...
test/FakeDecoderAPI.hxx
View file @
47a0f46c
...
...
@@ -34,6 +34,11 @@ struct FakeDecoder final : DecoderClient {
/* virtual methods from DecoderClient */
void
Ready
(
AudioFormat
audio_format
,
bool
seekable
,
SignedSongTime
duration
)
override
;
DecoderCommand
GetCommand
()
override
;
void
CommandFinished
()
override
;
SongTime
GetSeekTime
()
override
;
uint64_t
GetSeekFrame
()
override
;
void
SeekError
()
override
;
};
#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