DecoderAPI: add function decoder_open_uri()
Move and refactor code from the Wavpack decoder plugin.
This commit is contained in:
		| @@ -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". | ||||
|   | ||||
| @@ -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. | ||||
|  * | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann