Commit 6b421cc3 authored by Max Kellermann's avatar Max Kellermann

DecoderPlugin: pass Path instance to file_decode() and scan_file()

parent 37ec29b2
......@@ -53,7 +53,7 @@ public:
}
bool ScanFile(const DecoderPlugin &plugin) {
return plugin.ScanFile(path_fs.c_str(), handler, handler_ctx);
return plugin.ScanFile(path_fs, handler, handler_ctx);
}
bool ScanStream(const DecoderPlugin &plugin) {
......
......@@ -99,7 +99,7 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
char *vtrack;
unsigned int tnum = 0;
TagBuilder tag_builder;
while ((vtrack = plugin.container_scan(pathname.c_str(), ++tnum)) != nullptr) {
while ((vtrack = plugin.container_scan(pathname, ++tnum)) != nullptr) {
Song *song = Song::NewFile(vtrack, *contdir);
// shouldn't be necessary but it's there..
......@@ -107,7 +107,7 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
const auto child_path_fs = AllocatedPath::Build(pathname,
vtrack);
plugin.ScanFile(child_path_fs.c_str(),
plugin.ScanFile(child_path_fs,
add_tag_handler, &tag_builder);
tag_builder.Commit(song->tag);
......
......@@ -25,6 +25,7 @@
struct config_param;
struct InputStream;
struct tag_handler;
class Path;
/**
* Opaque handle which the decoder plugin passes to the functions in
......@@ -65,14 +66,14 @@ struct DecoderPlugin {
*
* Either implement this method or stream_decode().
*/
void (*file_decode)(Decoder &decoder, const char *path_fs);
void (*file_decode)(Decoder &decoder, Path path_fs);
/**
* Scan metadata of a file.
*
* @return false if the operation has failed
*/
bool (*scan_file)(const char *path_fs,
bool (*scan_file)(Path path_fs,
const struct tag_handler *handler,
void *handler_ctx);
......@@ -95,7 +96,7 @@ struct DecoderPlugin {
* a filename for every single track according to tnum (param 2)
* do not include full pathname here, just the "virtual" file
*/
char* (*container_scan)(const char *path_fs, const unsigned int tnum);
char* (*container_scan)(Path path_fs, const unsigned int tnum);
/* last element in these arrays must always be a nullptr: */
const char *const*suffixes;
......@@ -133,14 +134,16 @@ struct DecoderPlugin {
/**
* Decode a file.
*/
void FileDecode(Decoder &decoder, const char *path_fs) const {
template<typename P>
void FileDecode(Decoder &decoder, P path_fs) const {
file_decode(decoder, path_fs);
}
/**
* Read the tag of a file.
*/
bool ScanFile(const char *path_fs,
template<typename P>
bool ScanFile(P path_fs,
const tag_handler &handler, void *handler_ctx) const {
return scan_file != nullptr
? scan_file(path_fs, &handler, handler_ctx)
......@@ -160,7 +163,8 @@ struct DecoderPlugin {
/**
* return "virtual" tracks in a container
*/
char *ContainerScan(const char *path, const unsigned int tnum) const {
template<typename P>
char *ContainerScan(P path, const unsigned int tnum) const {
return container_scan(path, tnum);
}
......
......@@ -143,13 +143,13 @@ decoder_stream_decode(const DecoderPlugin &plugin,
static bool
decoder_file_decode(const DecoderPlugin &plugin,
Decoder &decoder, const char *path)
Decoder &decoder, Path path)
{
assert(plugin.file_decode != nullptr);
assert(decoder.stream_tag == nullptr);
assert(decoder.decoder_tag == nullptr);
assert(path != nullptr);
assert(PathTraitsFS::IsAbsolute(path));
assert(!path.IsNull());
assert(path.IsAbsolute());
assert(decoder.dc.state == DecoderState::START);
FormatDebug(decoder_thread_domain, "probing plugin %s", plugin.name);
......@@ -300,7 +300,7 @@ TryDecoderFile(Decoder &decoder, Path path_fs, const char *suffix,
if (plugin.file_decode != nullptr) {
dc.Lock();
if (decoder_file_decode(plugin, decoder, path_fs.c_str()))
if (decoder_file_decode(plugin, decoder, path_fs))
return true;
dc.Unlock();
......
......@@ -22,6 +22,7 @@
#include "tag/TagHandler.hxx"
#include "../DecoderAPI.hxx"
#include "CheckAudioFormat.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Macros.hxx"
#include "Log.hxx"
......@@ -48,12 +49,12 @@ adplug_init(const config_param &param)
}
static void
adplug_file_decode(Decoder &decoder, const char *path_fs)
adplug_file_decode(Decoder &decoder, Path path_fs)
{
CEmuopl opl(sample_rate, true, true);
opl.init();
CPlayer *player = CAdPlug::factory(path_fs, &opl);
CPlayer *player = CAdPlug::factory(path_fs.c_str(), &opl);
if (player == nullptr)
return;
......@@ -90,13 +91,13 @@ adplug_scan_tag(TagType type, const std::string &value,
}
static bool
adplug_scan_file(const char *path_fs,
adplug_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
CEmuopl opl(sample_rate, true, true);
opl.init();
CPlayer *player = CAdPlug::factory(path_fs, &opl);
CPlayer *player = CAdPlug::factory(path_fs.c_str(), &opl);
if (player == nullptr)
return false;
......
......@@ -23,6 +23,7 @@
#include "input/InputStream.hxx"
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
......@@ -37,10 +38,12 @@
static constexpr Domain audiofile_domain("audiofile");
static int audiofile_get_duration(const char *file)
gcc_pure
static int
audiofile_get_duration(Path path_fs)
{
int total_time;
AFfilehandle af_fp = afOpenFile(file, "r", nullptr);
AFfilehandle af_fp = afOpenFile(path_fs.c_str(), "r", nullptr);
if (af_fp == AF_NULL_FILEHANDLE) {
return -1;
}
......@@ -227,15 +230,15 @@ audiofile_stream_decode(Decoder &decoder, InputStream &is)
}
static bool
audiofile_scan_file(const char *file,
audiofile_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
int total_time = audiofile_get_duration(file);
int total_time = audiofile_get_duration(path_fs);
if (total_time < 0) {
FormatWarning(audiofile_domain,
"Failed to get total song time from: %s",
file);
path_fs.c_str());
return false;
}
......
......@@ -23,6 +23,7 @@
#include "FlacCommon.hxx"
#include "FlacMetadata.hxx"
#include "OggCodec.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "Log.hxx"
......@@ -79,11 +80,11 @@ flac_write_cb(const FLAC__StreamDecoder *dec, const FLAC__Frame *frame,
}
static bool
flac_scan_file(const char *file,
flac_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
FlacMetadataChain chain;
if (!chain.Read(file)) {
if (!chain.Read(path_fs.c_str())) {
FormatDebug(flac_domain,
"Failed to read FLAC tags: %s",
chain.GetStatusString());
......@@ -293,11 +294,11 @@ oggflac_init(gcc_unused const config_param &param)
}
static bool
oggflac_scan_file(const char *file,
oggflac_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
FlacMetadataChain chain;
if (!chain.ReadOgg(file)) {
if (!chain.ReadOgg(path_fs.c_str())) {
FormatDebug(flac_domain,
"Failed to read OggFLAC tags: %s",
chain.GetStatusString());
......
......@@ -21,6 +21,7 @@
#include "FluidsynthDecoderPlugin.hxx"
#include "../DecoderAPI.hxx"
#include "CheckAudioFormat.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/Macros.hxx"
......@@ -92,7 +93,7 @@ fluidsynth_init(const config_param &param)
}
static void
fluidsynth_file_decode(Decoder &decoder, const char *path_fs)
fluidsynth_file_decode(Decoder &decoder, Path path_fs)
{
char setting_sample_rate[] = "synth.sample-rate";
/*
......@@ -141,7 +142,7 @@ fluidsynth_file_decode(Decoder &decoder, const char *path_fs)
return;
}
ret = fluid_player_add(player, path_fs);
ret = fluid_player_add(player, path_fs.c_str());
if (ret != 0) {
LogWarning(fluidsynth_domain, "fluid_player_add() failed");
delete_fluid_player(player);
......@@ -198,11 +199,11 @@ fluidsynth_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
fluidsynth_scan_file(const char *file,
fluidsynth_scan_file(Path path_fs,
gcc_unused const struct tag_handler *handler,
gcc_unused void *handler_ctx)
{
return fluid_is_midifile(file);
return fluid_is_midifile(path_fs.c_str());
}
static const char *const fluidsynth_suffixes[] = {
......
......@@ -22,6 +22,7 @@
#include "../DecoderAPI.hxx"
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
#include "util/Alloc.hxx"
#include "util/FormatString.hxx"
#include "util/UriUtil.hxx"
......@@ -51,10 +52,10 @@ static constexpr unsigned GME_BUFFER_SAMPLES =
* suffix
*/
static char *
get_container_name(const char *path_fs)
get_container_name(Path path_fs)
{
const char *subtune_suffix = uri_get_suffix(path_fs);
char *path_container = xstrdup(path_fs);
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
char *path_container = xstrdup(path_fs.c_str());
char pat[64];
snprintf(pat, sizeof(pat), "%s%s",
......@@ -80,9 +81,9 @@ get_container_name(const char *path_fs)
* is appended.
*/
static int
get_song_num(const char *path_fs)
get_song_num(Path path_fs)
{
const char *subtune_suffix = uri_get_suffix(path_fs);
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
char pat[64];
snprintf(pat, sizeof(pat), "%s%s",
......@@ -91,8 +92,8 @@ get_song_num(const char *path_fs)
GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
if (g_pattern_match(path_with_subtune,
strlen(path_fs), path_fs, nullptr)) {
char *sub = g_strrstr(path_fs, "/" SUBTUNE_PREFIX);
path_fs.length(), path_fs.data(), nullptr)) {
char *sub = g_strrstr(path_fs.c_str(), "/" SUBTUNE_PREFIX);
g_pattern_spec_free(path_with_subtune);
if (!sub)
return 0;
......@@ -108,10 +109,11 @@ get_song_num(const char *path_fs)
}
static char *
gme_container_scan(const char *path_fs, const unsigned int tnum)
gme_container_scan(Path path_fs, const unsigned int tnum)
{
Music_Emu *emu;
const char *gme_err = gme_open_file(path_fs, &emu, GME_SAMPLE_RATE);
const char *gme_err = gme_open_file(path_fs.c_str(), &emu,
GME_SAMPLE_RATE);
if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err);
return nullptr;
......@@ -122,7 +124,7 @@ gme_container_scan(const char *path_fs, const unsigned int tnum)
if (num_songs < 2)
return nullptr;
const char *subtune_suffix = uri_get_suffix(path_fs);
const char *subtune_suffix = uri_get_suffix(path_fs.c_str());
if (tnum <= num_songs){
return FormatNew(SUBTUNE_PREFIX "%03u.%s",
tnum, subtune_suffix);
......@@ -131,7 +133,7 @@ gme_container_scan(const char *path_fs, const unsigned int tnum)
}
static void
gme_file_decode(Decoder &decoder, const char *path_fs)
gme_file_decode(Decoder &decoder, Path path_fs)
{
char *path_container = get_container_name(path_fs);
......@@ -207,7 +209,7 @@ gme_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
gme_scan_file(const char *path_fs,
gme_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
char *path_container = get_container_name(path_fs);
......
......@@ -22,6 +22,7 @@
#include "../DecoderAPI.hxx"
#include "tag/TagHandler.hxx"
#include "system/FatalError.hxx"
#include "fs/Path.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
......@@ -146,11 +147,11 @@ mikmod_decoder_finish(void)
}
static void
mikmod_decoder_file_decode(Decoder &decoder, const char *path_fs)
mikmod_decoder_file_decode(Decoder &decoder, Path path_fs)
{
/* deconstify the path because libmikmod wants a non-const
string pointer */
char *const path2 = const_cast<char *>(path_fs);
char *const path2 = const_cast<char *>(path_fs.c_str());
MODULE *handle;
int ret;
......@@ -160,7 +161,7 @@ mikmod_decoder_file_decode(Decoder &decoder, const char *path_fs)
if (handle == nullptr) {
FormatError(mikmod_domain,
"failed to open mod: %s", path_fs);
"failed to open mod: %s", path_fs.c_str());
return;
}
......@@ -184,18 +185,18 @@ mikmod_decoder_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
mikmod_decoder_scan_file(const char *path_fs,
mikmod_decoder_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
/* deconstify the path because libmikmod wants a non-const
string pointer */
char *const path2 = const_cast<char *>(path_fs);
char *const path2 = const_cast<char *>(path_fs.c_str());
MODULE *handle = Player_Load(path2, 128, 0);
if (handle == nullptr) {
FormatDebug(mikmod_domain,
"Failed to open file: %s", path_fs);
"Failed to open file: %s", path_fs.c_str());
return false;
}
......
......@@ -22,6 +22,7 @@
#include "../DecoderAPI.hxx"
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
......@@ -103,7 +104,7 @@ mpd_mpg123_open(mpg123_handle *handle, const char *path_fs,
}
static void
mpd_mpg123_file_decode(Decoder &decoder, const char *path_fs)
mpd_mpg123_file_decode(Decoder &decoder, Path path_fs)
{
mpg123_handle *handle;
int error;
......@@ -121,7 +122,7 @@ mpd_mpg123_file_decode(Decoder &decoder, const char *path_fs)
}
AudioFormat audio_format;
if (!mpd_mpg123_open(handle, path_fs, audio_format)) {
if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format)) {
mpg123_delete(handle);
return;
}
......@@ -199,7 +200,7 @@ mpd_mpg123_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
mpd_mpg123_scan_file(const char *path_fs,
mpd_mpg123_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
mpg123_handle *handle;
......@@ -215,7 +216,7 @@ mpd_mpg123_scan_file(const char *path_fs,
}
AudioFormat audio_format;
if (!mpd_mpg123_open(handle, path_fs, audio_format)) {
if (!mpd_mpg123_open(handle, path_fs.c_str(), audio_format)) {
mpg123_delete(handle);
return false;
}
......
......@@ -21,6 +21,7 @@
#include "SidplayDecoderPlugin.hxx"
#include "../DecoderAPI.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
#include "util/Alloc.hxx"
#include "util/Domain.hxx"
#include "system/ByteOrder.hxx"
......@@ -120,9 +121,9 @@ sidplay_finish()
* suffix
*/
static char *
get_container_name(const char *path_fs)
get_container_name(Path path_fs)
{
char *path_container = strdup(path_fs);
char *path_container = strdup(path_fs.c_str());
if(!g_pattern_match(path_with_subtune,
strlen(path_container), path_container, nullptr))
......@@ -159,7 +160,7 @@ get_song_num(const char *path_fs)
/* get the song length in seconds */
static int
get_song_length(const char *path_fs)
get_song_length(Path path_fs)
{
if (songlength_database == nullptr)
return -1;
......@@ -175,7 +176,7 @@ get_song_length(const char *path_fs)
char md5sum[SIDTUNE_MD5_LENGTH+1];
tune.createMD5(md5sum);
const unsigned song_num = get_song_num(path_fs);
const unsigned song_num = get_song_num(path_fs.c_str());
gsize num_items;
gchar **values=g_key_file_get_string_list(songlength_database,
......@@ -202,7 +203,7 @@ get_song_length(const char *path_fs)
}
static void
sidplay_file_decode(Decoder &decoder, const char *path_fs)
sidplay_file_decode(Decoder &decoder, Path path_fs)
{
int channels;
......@@ -216,7 +217,7 @@ sidplay_file_decode(Decoder &decoder, const char *path_fs)
return;
}
int song_num=get_song_num(path_fs);
const int song_num = get_song_num(path_fs.c_str());
tune.selectSong(song_num);
int song_len=get_song_length(path_fs);
......@@ -340,10 +341,10 @@ sidplay_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
sidplay_scan_file(const char *path_fs,
sidplay_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
int song_num=get_song_num(path_fs);
const int song_num = get_song_num(path_fs.c_str());
char *path_container=get_container_name(path_fs);
SidTune tune(path_container, nullptr, true);
......@@ -389,9 +390,9 @@ sidplay_scan_file(const char *path_fs,
}
static char *
sidplay_container_scan(const char *path_fs, const unsigned int tnum)
sidplay_container_scan(Path path_fs, const unsigned int tnum)
{
SidTune tune(path_fs, nullptr, true);
SidTune tune(path_fs.c_str(), nullptr, true);
if (!tune)
return nullptr;
......
......@@ -23,6 +23,7 @@
#include "input/InputStream.hxx"
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
......@@ -173,7 +174,7 @@ sndfile_stream_decode(Decoder &decoder, InputStream &is)
}
static bool
sndfile_scan_file(const char *path_fs,
sndfile_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
SNDFILE *sf;
......@@ -182,14 +183,14 @@ sndfile_scan_file(const char *path_fs,
info.format = 0;
sf = sf_open(path_fs, SFM_READ, &info);
sf = sf_open(path_fs.c_str(), SFM_READ, &info);
if (sf == nullptr)
return false;
if (!audio_valid_sample_rate(info.samplerate)) {
sf_close(sf);
FormatWarning(sndfile_domain,
"Invalid sample rate in %s", path_fs);
"Invalid sample rate in %s", path_fs.c_str());
return false;
}
......
......@@ -24,6 +24,7 @@
#include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx"
#include "tag/ApeTag.hxx"
#include "fs/Path.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "util/Macros.hxx"
......@@ -269,15 +270,16 @@ wavpack_scan_pair(WavpackContext *wpc, const char *name,
* Reads metainfo from the specified file.
*/
static bool
wavpack_scan_file(const char *fname,
wavpack_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
char error[ERRORLEN];
WavpackContext *wpc = WavpackOpenFileInput(fname, error, OPEN_TAGS, 0);
WavpackContext *wpc = WavpackOpenFileInput(path_fs.c_str(), error,
OPEN_TAGS, 0);
if (wpc == nullptr) {
FormatError(wavpack_domain,
"failed to open WavPack file \"%s\": %s",
fname, error);
path_fs.c_str(), error);
return false;
}
......@@ -525,16 +527,16 @@ wavpack_streamdecode(Decoder &decoder, InputStream &is)
* Decodes a file.
*/
static void
wavpack_filedecode(Decoder &decoder, const char *fname)
wavpack_filedecode(Decoder &decoder, Path path_fs)
{
char error[ERRORLEN];
WavpackContext *wpc = WavpackOpenFileInput(fname, error,
WavpackContext *wpc = WavpackOpenFileInput(path_fs.c_str(), error,
OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE,
23);
if (wpc == nullptr) {
FormatWarning(wavpack_domain,
"failed to open WavPack file \"%s\": %s",
fname, error);
path_fs.c_str(), error);
return;
}
......
......@@ -25,6 +25,7 @@
#include "util/Domain.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/FileSystem.hxx"
#include "fs/Path.hxx"
#include "system/FatalError.hxx"
#include "Log.hxx"
......@@ -65,7 +66,7 @@ wildmidi_finish(void)
}
static void
wildmidi_file_decode(Decoder &decoder, const char *path_fs)
wildmidi_file_decode(Decoder &decoder, Path path_fs)
{
static constexpr AudioFormat audio_format = {
WILDMIDI_SAMPLE_RATE,
......@@ -75,7 +76,7 @@ wildmidi_file_decode(Decoder &decoder, const char *path_fs)
midi *wm;
const struct _WM_Info *info;
wm = WildMidi_Open(path_fs);
wm = WildMidi_Open(path_fs.c_str());
if (wm == nullptr)
return;
......@@ -118,10 +119,10 @@ wildmidi_file_decode(Decoder &decoder, const char *path_fs)
}
static bool
wildmidi_scan_file(const char *path_fs,
wildmidi_scan_file(Path path_fs,
const struct tag_handler *handler, void *handler_ctx)
{
midi *wm = WildMidi_Open(path_fs);
midi *wm = WildMidi_Open(path_fs.c_str());
if (wm == nullptr)
return false;
......
......@@ -72,7 +72,7 @@ static const struct tag_handler print_handler = {
int main(int argc, char **argv)
{
const char *decoder_name, *path;
const char *decoder_name;
const struct DecoderPlugin *plugin;
#ifdef HAVE_LOCALE_H
......@@ -86,7 +86,7 @@ int main(int argc, char **argv)
}
decoder_name = argv[1];
path = argv[2];
const Path path = Path::FromFS(argv[2]);
#if !GLIB_CHECK_VERSION(2,32,0)
g_thread_init(NULL);
......@@ -114,10 +114,11 @@ int main(int argc, char **argv)
Mutex mutex;
Cond cond;
InputStream *is = InputStream::OpenReady(path, mutex, cond,
InputStream *is = InputStream::OpenReady(path.c_str(),
mutex, cond,
error);
if (is == NULL) {
FormatError(error, "Failed to open %s", path);
FormatError(error, "Failed to open %s", path.c_str());
return EXIT_FAILURE;
}
......@@ -135,9 +136,9 @@ int main(int argc, char **argv)
}
if (empty) {
tag_ape_scan2(Path::FromFS(path), &print_handler, NULL);
tag_ape_scan2(path, &print_handler, NULL);
if (empty)
tag_id3_scan(Path::FromFS(path), &print_handler, NULL);
tag_id3_scan(path, &print_handler, NULL);
}
return 0;
......
......@@ -23,6 +23,7 @@
#include "decoder/DecoderAPI.hxx"
#include "input/Init.hxx"
#include "input/InputStream.hxx"
#include "fs/Path.hxx"
#include "AudioFormat.hxx"
#include "util/Error.hxx"
#include "thread/Cond.hxx"
......@@ -211,7 +212,7 @@ int main(int argc, char **argv)
decoder.initialized = false;
if (decoder.plugin->file_decode != NULL) {
decoder.plugin->FileDecode(decoder, decoder.uri);
decoder.plugin->FileDecode(decoder, Path::FromFS(decoder.uri));
} else if (decoder.plugin->stream_decode != NULL) {
Mutex mutex;
Cond cond;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment