From 4eeea640f4641ec7c2b303567adf3e79855eb885 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 22 May 2014 11:10:41 +0200 Subject: DecoderAPI: add function decoder_open_uri() Move and refactor code from the Wavpack decoder plugin. --- src/decoder/DecoderAPI.cxx | 32 ++++++++++++++++++++++++++++ src/decoder/DecoderAPI.hxx | 10 +++++++++ src/decoder/plugins/WavpackDecoderPlugin.cxx | 19 +---------------- test/FakeDecoderAPI.cxx | 6 ++++++ test/FakeDecoderAPI.hxx | 5 +++++ test/run_decoder.cxx | 7 ++---- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/decoder/DecoderAPI.cxx b/src/decoder/DecoderAPI.cxx index 555e5c89b..5c4822804 100644 --- a/src/decoder/DecoderAPI.cxx +++ b/src/decoder/DecoderAPI.cxx @@ -240,6 +240,38 @@ void decoder_seek_error(Decoder & decoder) decoder_command_finished(decoder); } +InputStream * +decoder_open_uri(Decoder &decoder, const char *uri, Error &error) +{ + assert(decoder.dc.state == DecoderState::START || + decoder.dc.state == DecoderState::DECODE); + + DecoderControl &dc = decoder.dc; + Mutex &mutex = dc.mutex; + Cond &cond = dc.cond; + + InputStream *is = InputStream::Open(uri, mutex, cond, error); + if (is == nullptr) + return nullptr; + + mutex.lock(); + while (true) { + is->Update(); + if (is->IsReady()) { + mutex.unlock(); + return is; + } + + if (dc.command == DecoderCommand::STOP) { + mutex.unlock(); + delete is; + return nullptr; + } + + cond.wait(mutex); + } +} + /** * Should be read operation be cancelled? That is the case when the * player thread has sent a command such as "STOP". diff --git a/src/decoder/DecoderAPI.hxx b/src/decoder/DecoderAPI.hxx index 0a7b84371..c57a02e01 100644 --- a/src/decoder/DecoderAPI.hxx +++ b/src/decoder/DecoderAPI.hxx @@ -40,6 +40,8 @@ // IWYU pragma: end_exports +class Error; + /** * Notify the player thread that it has finished initialization and * that it has read the song's meta data. @@ -95,6 +97,14 @@ decoder_seek_where(Decoder &decoder); void decoder_seek_error(Decoder &decoder); +/** + * Open a new #InputStream and wait until it's ready. Can get + * cancelled by DecoderCommand::STOP (returns nullptr without setting + * #Error). + */ +InputStream * +decoder_open_uri(Decoder &decoder, const char *uri, Error &error); + /** * Blocking read from the input stream. * diff --git a/src/decoder/plugins/WavpackDecoderPlugin.cxx b/src/decoder/plugins/WavpackDecoderPlugin.cxx index e47bcbb30..e14d93369 100644 --- a/src/decoder/plugins/WavpackDecoderPlugin.cxx +++ b/src/decoder/plugins/WavpackDecoderPlugin.cxx @@ -440,7 +440,6 @@ wavpack_input_init(WavpackInput *isp, Decoder &decoder, static InputStream * wavpack_open_wvc(Decoder &decoder, const char *uri, - Mutex &mutex, Cond &cond, WavpackInput *wpi) { /* @@ -452,28 +451,13 @@ wavpack_open_wvc(Decoder &decoder, const char *uri, char *wvc_url = g_strconcat(uri, "c", nullptr); - InputStream *is_wvc = InputStream::Open(wvc_url, mutex, cond, - IgnoreError()); + InputStream *is_wvc = decoder_open_uri(decoder, uri, IgnoreError()); g_free(wvc_url); if (is_wvc == nullptr) return nullptr; - /* - * And we try to buffer in order to get know - * about a possible 404 error. - */ - char first_byte; - size_t nbytes = decoder_read(decoder, *is_wvc, - &first_byte, sizeof(first_byte)); - if (nbytes == 0) { - delete is_wvc; - return nullptr; - } - - /* push it back */ wavpack_input_init(wpi, decoder, *is_wvc); - wpi->last_byte = first_byte; return is_wvc; } @@ -488,7 +472,6 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is) WavpackInput isp_wvc; InputStream *is_wvc = wavpack_open_wvc(decoder, is.GetURI(), - is.mutex, is.cond, &isp_wvc); if (is_wvc != nullptr) { open_flags |= OPEN_WVC; diff --git a/test/FakeDecoderAPI.cxx b/test/FakeDecoderAPI.cxx index 155e7d5df..7aa24c4df 100644 --- a/test/FakeDecoderAPI.cxx +++ b/test/FakeDecoderAPI.cxx @@ -66,6 +66,12 @@ decoder_seek_error(gcc_unused Decoder &decoder) { } +InputStream * +decoder_open_uri(Decoder &decoder, const char *uri, Error &error) +{ + return InputStream::OpenReady(uri, decoder.mutex, decoder.cond, error); +} + size_t decoder_read(gcc_unused Decoder *decoder, InputStream &is, diff --git a/test/FakeDecoderAPI.hxx b/test/FakeDecoderAPI.hxx index 134e77117..6f1933977 100644 --- a/test/FakeDecoderAPI.hxx +++ b/test/FakeDecoderAPI.hxx @@ -21,8 +21,13 @@ #define FAKE_DECODER_API_HXX #include "check.h" +#include "thread/Mutex.hxx" +#include "thread/Cond.hxx" struct Decoder { + Mutex mutex; + Cond cond; + bool initialized; Decoder() diff --git a/test/run_decoder.cxx b/test/run_decoder.cxx index b1c739405..3980340cc 100644 --- a/test/run_decoder.cxx +++ b/test/run_decoder.cxx @@ -27,7 +27,6 @@ #include "fs/Path.hxx" #include "AudioFormat.hxx" #include "util/Error.hxx" -#include "thread/Cond.hxx" #include "Log.hxx" #include "stdbin.h" @@ -77,11 +76,9 @@ int main(int argc, char **argv) if (plugin->file_decode != nullptr) { plugin->FileDecode(decoder, Path::FromFS(uri)); } else if (plugin->stream_decode != nullptr) { - Mutex mutex; - Cond cond; - InputStream *is = - InputStream::OpenReady(uri, mutex, cond, error); + InputStream::OpenReady(uri, decoder.mutex, + decoder.cond, error); if (is == NULL) { if (error.IsDefined()) LogError(error); -- cgit v1.2.3