decoder/Plugin: simplify compile-time initialization

Add a `constexpr` constructor and several `constexpr` methods to
construct a DecoderPlugin at compile time, in a way which allows
adding new methods later without having to edit each plugin.
This commit is contained in:
Max Kellermann 2019-06-15 14:44:37 +02:00
parent aebb1baad8
commit 527642a90b
23 changed files with 171 additions and 286 deletions

View File

@ -42,13 +42,13 @@ struct DecoderPlugin {
* @return true if the plugin was initialized successfully, * @return true if the plugin was initialized successfully,
* false if the plugin is not available * false if the plugin is not available
*/ */
bool (*init)(const ConfigBlock &block); bool (*init)(const ConfigBlock &block) = nullptr;
/** /**
* Deinitialize a decoder plugin which was initialized * Deinitialize a decoder plugin which was initialized
* successfully. Optional method. * successfully. Optional method.
*/ */
void (*finish)() noexcept; void (*finish)() noexcept = nullptr;
/** /**
* Decode a stream (data read from an #InputStream object). * Decode a stream (data read from an #InputStream object).
@ -57,28 +57,28 @@ struct DecoderPlugin {
* possible, it is recommended to implement this method, * possible, it is recommended to implement this method,
* because it is more versatile. * because it is more versatile.
*/ */
void (*stream_decode)(DecoderClient &client, InputStream &is); void (*stream_decode)(DecoderClient &client, InputStream &is) = nullptr;
/** /**
* Decode a local file. * Decode a local file.
* *
* Either implement this method or stream_decode(). * Either implement this method or stream_decode().
*/ */
void (*file_decode)(DecoderClient &client, Path path_fs); void (*file_decode)(DecoderClient &client, Path path_fs) = nullptr;
/** /**
* Scan metadata of a file. * Scan metadata of a file.
* *
* @return false if the operation has failed * @return false if the operation has failed
*/ */
bool (*scan_file)(Path path_fs, TagHandler &handler) noexcept; bool (*scan_file)(Path path_fs, TagHandler &handler) noexcept = nullptr;
/** /**
* Scan metadata of a file. * Scan metadata of a file.
* *
* @return false if the operation has failed * @return false if the operation has failed
*/ */
bool (*scan_stream)(InputStream &is, TagHandler &handler) noexcept; bool (*scan_stream)(InputStream &is, TagHandler &handler) noexcept = nullptr;
/** /**
* @brief Return a "virtual" filename for subtracks in * @brief Return a "virtual" filename for subtracks in
@ -89,11 +89,67 @@ struct DecoderPlugin {
* a filename for every single track; * a filename for every single track;
* do not include full pathname here, just the "virtual" file * do not include full pathname here, just the "virtual" file
*/ */
std::forward_list<DetachedSong> (*container_scan)(Path path_fs); std::forward_list<DetachedSong> (*container_scan)(Path path_fs) = nullptr;
/* last element in these arrays must always be a nullptr: */ /* last element in these arrays must always be a nullptr: */
const char *const*suffixes; const char *const*suffixes = nullptr;
const char *const*mime_types; const char *const*mime_types = nullptr;
constexpr DecoderPlugin(const char *_name,
void (*_file_decode)(DecoderClient &client,
Path path_fs),
bool (*_scan_file)(Path path_fs,
TagHandler &handler) noexcept) noexcept
:name(_name),
file_decode(_file_decode), scan_file(_scan_file) {}
constexpr DecoderPlugin(const char *_name,
void (*_stream_decode)(DecoderClient &client,
InputStream &is),
bool (*_scan_stream)(InputStream &is, TagHandler &handler) noexcept) noexcept
:name(_name),
stream_decode(_stream_decode),
scan_stream(_scan_stream) {}
constexpr DecoderPlugin(const char *_name,
void (*_stream_decode)(DecoderClient &client,
InputStream &is),
bool (*_scan_stream)(InputStream &is, TagHandler &handler) noexcept,
void (*_file_decode)(DecoderClient &client,
Path path_fs),
bool (*_scan_file)(Path path_fs,
TagHandler &handler) noexcept) noexcept
:name(_name),
stream_decode(_stream_decode),
file_decode(_file_decode),
scan_file(_scan_file),
scan_stream(_scan_stream) {}
constexpr auto WithInit(bool (*_init)(const ConfigBlock &block),
void (*_finish)() noexcept = nullptr) noexcept {
auto copy = *this;
copy.init = _init;
copy.finish = _finish;
return copy;
}
constexpr auto WithContainer(std::forward_list<DetachedSong> (*_container_scan)(Path path_fs)) noexcept {
auto copy = *this;
copy.container_scan = _container_scan;
return copy;
}
constexpr auto WithSuffixes(const char *const*_suffixes) noexcept {
auto copy = *this;
copy.suffixes = _suffixes;
return copy;
}
constexpr auto WithMimeTypes(const char *const*_mime_types) noexcept {
auto copy = *this;
copy.mime_types = _mime_types;
return copy;
}
/** /**
* Initialize a decoder plugin. * Initialize a decoder plugin.

View File

@ -125,15 +125,7 @@ static const char *const adplug_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin adplug_decoder_plugin = { constexpr DecoderPlugin adplug_decoder_plugin =
"adplug", DecoderPlugin("adplug", adplug_file_decode, adplug_scan_file)
adplug_init, .WithInit(adplug_init)
nullptr, .WithSuffixes(adplug_suffixes);
nullptr,
adplug_file_decode,
adplug_scan_file,
nullptr,
nullptr,
adplug_suffixes,
nullptr,
};

View File

@ -274,15 +274,9 @@ static const char *const audiofile_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin audiofile_decoder_plugin = { constexpr DecoderPlugin audiofile_decoder_plugin =
"audiofile", DecoderPlugin("audiofile",
audiofile_init, audiofile_stream_decode, audiofile_scan_stream)
nullptr, .WithInit(audiofile_init)
audiofile_stream_decode, .WithSuffixes(audiofile_suffixes)
nullptr, .WithMimeTypes(audiofile_mime_types);
nullptr,
audiofile_scan_stream,
nullptr,
audiofile_suffixes,
audiofile_mime_types,
};

View File

@ -488,15 +488,8 @@ static const char *const dsdiff_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin dsdiff_decoder_plugin = { constexpr DecoderPlugin dsdiff_decoder_plugin =
"dsdiff", DecoderPlugin("dsdiff", dsdiff_stream_decode, dsdiff_scan_stream)
dsdiff_init, .WithInit(dsdiff_init)
nullptr, .WithSuffixes(dsdiff_suffixes)
dsdiff_stream_decode, .WithMimeTypes(dsdiff_mime_types);
nullptr,
nullptr,
dsdiff_scan_stream,
nullptr,
dsdiff_suffixes,
dsdiff_mime_types,
};

View File

@ -361,15 +361,7 @@ static const char *const dsf_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin dsf_decoder_plugin = { constexpr DecoderPlugin dsf_decoder_plugin =
"dsf", DecoderPlugin("dsf", dsf_stream_decode, dsf_scan_stream)
nullptr, .WithSuffixes(dsf_suffixes)
nullptr, .WithMimeTypes(dsf_mime_types);
dsf_stream_decode,
nullptr,
nullptr,
dsf_scan_stream,
nullptr,
dsf_suffixes,
dsf_mime_types,
};

View File

@ -430,15 +430,7 @@ static const char *const faad_mime_types[] = {
"audio/aac", "audio/aacp", nullptr "audio/aac", "audio/aacp", nullptr
}; };
const DecoderPlugin faad_decoder_plugin = { constexpr DecoderPlugin faad_decoder_plugin =
"faad", DecoderPlugin("faad", faad_stream_decode, faad_scan_stream)
nullptr, .WithSuffixes(faad_suffixes)
nullptr, .WithMimeTypes(faad_mime_types);
faad_stream_decode,
nullptr,
nullptr,
faad_scan_stream,
nullptr,
faad_suffixes,
faad_mime_types,
};

View File

@ -774,15 +774,8 @@ static const char *const ffmpeg_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin ffmpeg_decoder_plugin = { constexpr DecoderPlugin ffmpeg_decoder_plugin =
"ffmpeg", DecoderPlugin("ffmpeg", ffmpeg_decode, ffmpeg_scan_stream)
ffmpeg_init, .WithInit(ffmpeg_init, ffmpeg_finish)
ffmpeg_finish, .WithSuffixes(ffmpeg_suffixes)
ffmpeg_decode, .WithMimeTypes(ffmpeg_mime_types);
nullptr,
nullptr,
ffmpeg_scan_stream,
nullptr,
ffmpeg_suffixes,
ffmpeg_mime_types
};

View File

@ -368,18 +368,12 @@ static const char *const oggflac_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin oggflac_decoder_plugin = { constexpr DecoderPlugin oggflac_decoder_plugin =
"oggflac", DecoderPlugin("oggflac", oggflac_decode, oggflac_scan_stream,
oggflac_init, nullptr, oggflac_scan_file)
nullptr, .WithInit(oggflac_init)
oggflac_decode, .WithSuffixes(oggflac_suffixes)
nullptr, .WithMimeTypes(oggflac_mime_types);
oggflac_scan_file,
oggflac_scan_stream,
nullptr,
oggflac_suffixes,
oggflac_mime_types,
};
static const char *const flac_suffixes[] = { "flac", nullptr }; static const char *const flac_suffixes[] = { "flac", nullptr };
static const char *const flac_mime_types[] = { static const char *const flac_mime_types[] = {
@ -390,15 +384,8 @@ static const char *const flac_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin flac_decoder_plugin = { constexpr DecoderPlugin flac_decoder_plugin =
"flac", DecoderPlugin("flac", flac_decode, flac_scan_stream,
nullptr, nullptr, flac_scan_file)
nullptr, .WithSuffixes(flac_suffixes)
flac_decode, .WithMimeTypes(flac_mime_types);
nullptr,
flac_scan_file,
flac_scan_stream,
nullptr,
flac_suffixes,
flac_mime_types,
};

View File

@ -207,15 +207,8 @@ static const char *const fluidsynth_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin fluidsynth_decoder_plugin = { constexpr DecoderPlugin fluidsynth_decoder_plugin =
"fluidsynth", DecoderPlugin("fluidsynth",
fluidsynth_init, fluidsynth_file_decode, fluidsynth_scan_file)
nullptr, .WithInit(fluidsynth_init)
nullptr, .WithSuffixes(fluidsynth_suffixes);
fluidsynth_file_decode,
fluidsynth_scan_file,
nullptr,
nullptr,
fluidsynth_suffixes,
nullptr,
};

View File

@ -324,15 +324,8 @@ static const char *const gme_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin gme_decoder_plugin = { constexpr DecoderPlugin gme_decoder_plugin =
"gme", DecoderPlugin("gme", gme_file_decode, gme_scan_file)
gme_plugin_init, .WithInit(gme_plugin_init)
nullptr, .WithContainer(gme_container_scan)
nullptr, .WithSuffixes(gme_suffixes);
gme_file_decode,
gme_scan_file,
nullptr,
gme_container_scan,
gme_suffixes,
nullptr,
};

View File

@ -266,17 +266,9 @@ static const char *const hybrid_dsd_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin hybrid_dsd_decoder_plugin = { constexpr DecoderPlugin hybrid_dsd_decoder_plugin =
"hybrid_dsd",
InitHybridDsdDecoder,
nullptr,
HybridDsdDecode,
nullptr,
nullptr,
/* no scan method here; the FFmpeg plugin will do that for us, /* no scan method here; the FFmpeg plugin will do that for us,
and we only do the decoding */ and we only do the decoding */
nullptr, DecoderPlugin("hybrid_dsd", HybridDsdDecode, nullptr)
nullptr, .WithInit(InitHybridDsdDecoder)
hybrid_dsd_suffixes, .WithSuffixes(hybrid_dsd_suffixes);
nullptr,
};

View File

@ -1014,15 +1014,8 @@ mad_decoder_scan_stream(InputStream &is, TagHandler &handler) noexcept
static const char *const mp3_suffixes[] = { "mp3", "mp2", nullptr }; static const char *const mp3_suffixes[] = { "mp3", "mp2", nullptr };
static const char *const mp3_mime_types[] = { "audio/mpeg", nullptr }; static const char *const mp3_mime_types[] = { "audio/mpeg", nullptr };
const struct DecoderPlugin mad_decoder_plugin = { constexpr DecoderPlugin mad_decoder_plugin =
"mad", DecoderPlugin("mad", mp3_decode, mad_decoder_scan_stream)
mp3_plugin_init, .WithInit(mp3_plugin_init)
nullptr, .WithSuffixes(mp3_suffixes)
mp3_decode, .WithMimeTypes(mp3_mime_types);
nullptr,
nullptr,
mad_decoder_scan_stream,
nullptr,
mp3_suffixes,
mp3_mime_types,
};

View File

@ -223,15 +223,8 @@ static const char *const mikmod_decoder_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin mikmod_decoder_plugin = { constexpr DecoderPlugin mikmod_decoder_plugin =
"mikmod", DecoderPlugin("mikmod",
mikmod_decoder_init, mikmod_decoder_file_decode, mikmod_decoder_scan_file)
mikmod_decoder_finish, .WithInit(mikmod_decoder_init, mikmod_decoder_finish)
nullptr, .WithSuffixes(mikmod_decoder_suffixes);
mikmod_decoder_file_decode,
mikmod_decoder_scan_file,
nullptr,
nullptr,
mikmod_decoder_suffixes,
nullptr,
};

View File

@ -199,15 +199,7 @@ static const char *const mod_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin modplug_decoder_plugin = { constexpr DecoderPlugin modplug_decoder_plugin =
"modplug", DecoderPlugin("modplug", mod_decode, modplug_scan_stream)
modplug_decoder_init, .WithInit(modplug_decoder_init)
nullptr, .WithSuffixes(mod_suffixes);
mod_decode,
nullptr,
nullptr,
modplug_scan_stream,
nullptr,
mod_suffixes,
nullptr,
};

View File

@ -268,15 +268,6 @@ mpcdec_scan_stream(InputStream &is, TagHandler &handler) noexcept
static const char *const mpcdec_suffixes[] = { "mpc", nullptr }; static const char *const mpcdec_suffixes[] = { "mpc", nullptr };
const struct DecoderPlugin mpcdec_decoder_plugin = { constexpr DecoderPlugin mpcdec_decoder_plugin =
"mpcdec", DecoderPlugin("mpcdec", mpcdec_decode, mpcdec_scan_stream)
nullptr, .WithSuffixes(mpcdec_suffixes);
nullptr,
mpcdec_decode,
nullptr,
nullptr,
mpcdec_scan_stream,
nullptr,
mpcdec_suffixes,
nullptr,
};

View File

@ -316,16 +316,7 @@ static const char *const mpg123_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin mpg123_decoder_plugin = { constexpr DecoderPlugin mpg123_decoder_plugin =
"mpg123", DecoderPlugin("mpg123", mpd_mpg123_file_decode, mpd_mpg123_scan_file)
mpd_mpg123_init, .WithInit(mpd_mpg123_init, mpd_mpg123_finish)
mpd_mpg123_finish, .WithSuffixes(mpg123_suffixes);
/* streaming not yet implemented */
nullptr,
mpd_mpg123_file_decode,
mpd_mpg123_scan_file,
nullptr,
nullptr,
mpg123_suffixes,
nullptr,
};

View File

@ -384,15 +384,8 @@ static const char *const opus_mime_types[] = {
} /* anonymous namespace */ } /* anonymous namespace */
const struct DecoderPlugin opus_decoder_plugin = { constexpr DecoderPlugin opus_decoder_plugin =
"opus", DecoderPlugin("opus", mpd_opus_stream_decode, mpd_opus_scan_stream)
mpd_opus_init, .WithInit(mpd_opus_init)
nullptr, .WithSuffixes(opus_suffixes)
mpd_opus_stream_decode, .WithMimeTypes(opus_mime_types);
nullptr,
nullptr,
mpd_opus_scan_stream,
nullptr,
opus_suffixes,
opus_mime_types,
};

View File

@ -251,15 +251,6 @@ static const char *const pcm_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin pcm_decoder_plugin = { constexpr DecoderPlugin pcm_decoder_plugin =
"pcm", DecoderPlugin("pcm", pcm_stream_decode, nullptr)
nullptr, .WithMimeTypes(pcm_mime_types);
nullptr,
pcm_stream_decode,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
pcm_mime_types,
};

View File

@ -568,15 +568,8 @@ static const char *const sidplay_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin sidplay_decoder_plugin = { constexpr DecoderPlugin sidplay_decoder_plugin =
"sidplay", DecoderPlugin("sidplay", sidplay_file_decode, sidplay_scan_file)
sidplay_init, .WithInit(sidplay_init, sidplay_finish)
sidplay_finish, .WithContainer(sidplay_container_scan)
nullptr, /* stream_decode() */ .WithSuffixes(sidplay_suffixes);
sidplay_file_decode,
sidplay_scan_file,
nullptr, /* stream_tag() */
sidplay_container_scan,
sidplay_suffixes,
nullptr, /* mime_types */
};

View File

@ -331,15 +331,8 @@ static const char *const sndfile_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin sndfile_decoder_plugin = { constexpr DecoderPlugin sndfile_decoder_plugin =
"sndfile", DecoderPlugin("sndfile", sndfile_stream_decode, sndfile_scan_stream)
sndfile_init, .WithInit(sndfile_init)
nullptr, .WithSuffixes(sndfile_suffixes)
sndfile_stream_decode, .WithMimeTypes(sndfile_mime_types);
nullptr,
nullptr,
sndfile_scan_stream,
nullptr,
sndfile_suffixes,
sndfile_mime_types,
};

View File

@ -434,15 +434,8 @@ static const char *const vorbis_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin vorbis_decoder_plugin = { constexpr DecoderPlugin vorbis_decoder_plugin =
"vorbis", DecoderPlugin("vorbis", vorbis_stream_decode, vorbis_scan_stream)
vorbis_init, .WithInit(vorbis_init)
nullptr, .WithSuffixes(vorbis_suffixes)
vorbis_stream_decode, .WithMimeTypes(vorbis_mime_types);
nullptr,
nullptr,
vorbis_scan_stream,
nullptr,
vorbis_suffixes,
vorbis_mime_types
};

View File

@ -644,15 +644,8 @@ static char const *const wavpack_mime_types[] = {
nullptr nullptr
}; };
const struct DecoderPlugin wavpack_decoder_plugin = { constexpr DecoderPlugin wavpack_decoder_plugin =
"wavpack", DecoderPlugin("wavpack", wavpack_streamdecode, wavpack_scan_stream,
nullptr, wavpack_filedecode, wavpack_scan_file)
nullptr, .WithSuffixes(wavpack_suffixes)
wavpack_streamdecode, .WithMimeTypes(wavpack_mime_types);
wavpack_filedecode,
wavpack_scan_file,
wavpack_scan_stream,
nullptr,
wavpack_suffixes,
wavpack_mime_types
};

View File

@ -150,15 +150,7 @@ static const char *const wildmidi_suffixes[] = {
nullptr nullptr
}; };
const struct DecoderPlugin wildmidi_decoder_plugin = { constexpr DecoderPlugin wildmidi_decoder_plugin =
"wildmidi", DecoderPlugin("wildmidi", wildmidi_file_decode, wildmidi_scan_file)
wildmidi_init, .WithInit(wildmidi_init, wildmidi_finish)
wildmidi_finish, .WithSuffixes(wildmidi_suffixes);
nullptr,
wildmidi_file_decode,
wildmidi_scan_file,
nullptr,
nullptr,
wildmidi_suffixes,
nullptr,
};