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,
* 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
* successfully. Optional method.
*/
void (*finish)() noexcept;
void (*finish)() noexcept = nullptr;
/**
* Decode a stream (data read from an #InputStream object).
@ -57,28 +57,28 @@ struct DecoderPlugin {
* possible, it is recommended to implement this method,
* because it is more versatile.
*/
void (*stream_decode)(DecoderClient &client, InputStream &is);
void (*stream_decode)(DecoderClient &client, InputStream &is) = nullptr;
/**
* Decode a local file.
*
* 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.
*
* @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.
*
* @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
@ -89,11 +89,67 @@ struct DecoderPlugin {
* a filename for every single track;
* 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: */
const char *const*suffixes;
const char *const*mime_types;
const char *const*suffixes = nullptr;
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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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_mime_types[] = { "audio/mpeg", nullptr };
const struct DecoderPlugin mad_decoder_plugin = {
"mad",
mp3_plugin_init,
nullptr,
mp3_decode,
nullptr,
nullptr,
mad_decoder_scan_stream,
nullptr,
mp3_suffixes,
mp3_mime_types,
};
constexpr DecoderPlugin mad_decoder_plugin =
DecoderPlugin("mad", mp3_decode, mad_decoder_scan_stream)
.WithInit(mp3_plugin_init)
.WithSuffixes(mp3_suffixes)
.WithMimeTypes(mp3_mime_types);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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