Index: common/mptString.cpp =================================================================== --- common/mptString.cpp (revision 12302) +++ common/mptString.cpp (working copy) @@ -1533,7 +1533,7 @@ return 0; } -int CompareNoCaseAscii(const std::string &a, const std::string &b) +int CompareNoCaseAscii(std::string_view a, std::string_view b) { for(std::size_t i = 0; i < std::min(a.length(), b.length()); ++i) { @@ -1554,6 +1554,12 @@ return a.length() < b.length() ? -1 : 1; } +int CompareNoCaseAscii(const std::string &a, const std::string &b) +{ + return CompareNoCaseAscii(std::string_view(a), std::string_view(b)); +} + + #if defined(MODPLUG_TRACKER) mpt::ustring ToLowerCase(const mpt::ustring &s) Index: common/mptString.h =================================================================== --- common/mptString.h (revision 12302) +++ common/mptString.h (working copy) @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -545,8 +546,10 @@ std::string ToUpperCaseAscii(std::string s); int CompareNoCaseAscii(const char *a, const char *b, std::size_t n); +int CompareNoCaseAscii(std::string_view a, std::string_view b); int CompareNoCaseAscii(const std::string &a, const std::string &b); + #if defined(MODPLUG_TRACKER) mpt::ustring ToLowerCase(const mpt::ustring &s); Index: common/stdafx.h =================================================================== --- common/stdafx.h (revision 12302) +++ common/stdafx.h (working copy) @@ -115,6 +115,7 @@ // // // +// // // Index: libopenmpt/libopenmpt.h =================================================================== --- libopenmpt/libopenmpt.h (revision 12302) +++ libopenmpt/libopenmpt.h (working copy) @@ -1396,21 +1396,21 @@ * \param mod The module handle to work on. * \return A semicolon-separated list containing all supported ctl keys. * \remarks Currently supported ctl values are: - * - load.skip_samples: Set to "1" to avoid loading samples into memory - * - load.skip_patterns: Set to "1" to avoid loading patterns into memory - * - load.skip_plugins: Set to "1" to avoid loading plugins - * - load.skip_subsongs_init: Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. - * - seek.sync_samples: Set to "1" to sync sample playback when using openmpt_module_set_position_seconds or openmpt_module_set_position_order_row. - * - subsong: The current subsong. Setting it has identical semantics as openmpt_module_select_subsong(), getting it returns the currently selected subsong. - * - play.at_end: Chooses the behaviour when the end of song is reached: + * - load.skip_samples (boolean): Set to "1" to avoid loading samples into memory + * - load.skip_patterns (boolean): Set to "1" to avoid loading patterns into memory + * - load.skip_plugins (boolean): Set to "1" to avoid loading plugins + * - load.skip_subsongs_init (boolean): Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. + * - seek.sync_samples (boolean): Set to "1" to sync sample playback when using openmpt_module_set_position_seconds or openmpt_module_set_position_order_row. + * - subsong (integer): The current subsong. Setting it has identical semantics as openmpt_module_select_subsong(), getting it returns the currently selected subsong. + * - play.at_end (text): Chooses the behaviour when the end of song is reached: * - "fadeout": Fades the module out for a short while. Subsequent reads after the fadeout will return 0 rendered frames. * - "continue": Returns 0 rendered frames when the song end is reached. Subsequent reads will continue playing from the song start or loop start. * - "stop": Returns 0 rendered frames when the song end is reached. Subsequent reads will return 0 rendered frames. - * - play.tempo_factor: Set a floating point tempo factor. "1.0" is the default tempo. - * - play.pitch_factor: Set a floating point pitch factor. "1.0" is the default pitch. - * - render.resampler.emulate_amiga: Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. - * - render.opl.volume_factor: Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. - * - dither: Set the dither algorithm that is used for the 16 bit versions of openmpt_module_read. Supported values are: + * - play.tempo_factor (floatingpoint): Set a floating point tempo factor. "1.0" is the default tempo. + * - play.pitch_factor (floatingpoint): Set a floating point pitch factor. "1.0" is the default pitch. + * - render.resampler.emulate_amiga (boolean): Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. + * - render.opl.volume_factor (floatingpoint): Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. + * - dither (integer): Set the dither algorithm that is used for the 16 bit versions of openmpt_module_read. Supported values are: * - 0: No dithering. * - 1: Default mode. Chosen by OpenMPT code, might change. * - 2: Rectangular, 0.5 bit depth, no noise shaping (original ModPlug Tracker). @@ -1417,6 +1417,7 @@ * - 3: Rectangular, 1 bit depth, simple 1st order noise shaping */ LIBOPENMPT_API const char * openmpt_module_get_ctls( openmpt_module * mod ); + /*! \brief Get current ctl value * * \param mod The module handle to work on. @@ -1423,8 +1424,46 @@ * \param ctl The ctl key whose value should be retrieved. * \return The associated ctl value, or NULL on failure. * \sa openmpt_module_get_ctls + * \deprecated Please use openmpt_module_ctl_get_boolean(), openmpt_module_ctl_get_integer(), openmpt_module_ctl_get_floatingpoint(), or openmpt_module_ctl_get_text(). */ -LIBOPENMPT_API const char * openmpt_module_ctl_get( openmpt_module * mod, const char * ctl ); +LIBOPENMPT_API LIBOPENMPT_DEPRECATED const char * openmpt_module_ctl_get( openmpt_module * mod, const char * ctl ); +/*! \brief Get current ctl boolean value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be retrieved. + * \return The associated ctl value, or NULL on failure. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int openmpt_module_ctl_get_boolean( openmpt_module * mod, const char * ctl ); +/*! \brief Get current ctl integer value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be retrieved. + * \return The associated ctl value, or NULL on failure. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int64_t openmpt_module_ctl_get_integer( openmpt_module * mod, const char * ctl ); +/*! \brief Get current ctl floatingpoint value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be retrieved. + * \return The associated ctl value, or NULL on failure. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API double openmpt_module_ctl_get_floatingpoint( openmpt_module * mod, const char * ctl ); +/*! \brief Get current ctl string value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be retrieved. + * \return The associated ctl value, or NULL on failure. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API const char * openmpt_module_ctl_get_text( openmpt_module * mod, const char * ctl ); + /*! \brief Set ctl value * * \param mod The module handle to work on. @@ -1432,8 +1471,49 @@ * \param value The value that should be set. * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. * \sa openmpt_module_get_ctls + * \deprecated Please use openmpt_module_ctl_set_boolean(), openmpt_module_ctl_set_integer(), openmpt_module_ctl_set_floatingpoint(), or openmpt_module_ctl_set_text(). */ -LIBOPENMPT_API int openmpt_module_ctl_set( openmpt_module * mod, const char * ctl, const char * value ); +LIBOPENMPT_API LIBOPENMPT_DEPRECATED int openmpt_module_ctl_set( openmpt_module * mod, const char * ctl, const char * value ); +/*! \brief Set ctl boolean value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be set. + * \param value The value that should be set. + * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int openmpt_module_ctl_set_boolean( openmpt_module * mod, const char * ctl, int value ); +/*! \brief Set ctl integer value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be set. + * \param value The value that should be set. + * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int openmpt_module_ctl_set_integer( openmpt_module * mod, const char * ctl, int64_t value ); +/*! \brief Set ctl floatingpoint value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be set. + * \param value The value that should be set. + * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int openmpt_module_ctl_set_floatingpoint( openmpt_module * mod, const char * ctl, double value ); +/*! \brief Set ctl string value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be set. + * \param value The value that should be set. + * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. + * \sa openmpt_module_get_ctls + * \since 0.5.0 + */ +LIBOPENMPT_API int openmpt_module_ctl_set_text( openmpt_module * mod, const char * ctl, const char * value ); /* remember to add new functions to both C and C++ interfaces and to increase OPENMPT_API_VERSION_MINOR */ Index: libopenmpt/libopenmpt.hpp =================================================================== --- libopenmpt/libopenmpt.hpp (revision 12302) +++ libopenmpt/libopenmpt.hpp (working copy) @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -232,8 +233,16 @@ /*! \param extension file extension to query without a leading dot. The case is ignored. \return true if the extension is supported by libopenmpt, false otherwise. + \deprecated Please use openmpt::is_extension_supported2(). */ -LIBOPENMPT_CXX_API bool is_extension_supported( const std::string & extension ); +LIBOPENMPT_ATTR_DEPRECATED LIBOPENMPT_CXX_API bool is_extension_supported( const std::string & extension ); +//! Query whether a file extension is supported +/*! + \param extension file extension to query without a leading dot. The case is ignored. + \return true if the extension is supported by libopenmpt, false otherwise. + \since 0.5.0 +*/ +LIBOPENMPT_CXX_API bool is_extension_supported2( std::string_view extension ); //! Roughly scan the input stream to find out whether libopenmpt might be able to open it /*! @@ -1027,21 +1036,21 @@ /*! \return A vector containing all supported ctl keys. \remarks Currently supported ctl values are: - - load.skip_samples: Set to "1" to avoid loading samples into memory - - load.skip_patterns: Set to "1" to avoid loading patterns into memory - - load.skip_plugins: Set to "1" to avoid loading plugins - - load.skip_subsongs_init: Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. - - seek.sync_samples: Set to "1" to sync sample playback when using openmpt::module::set_position_seconds or openmpt::module::set_position_order_row. - - subsong: The current subsong. Setting it has identical semantics as openmpt::module::select_subsong(), getting it returns the currently selected subsong. - - play.at_end: Chooses the behaviour when the end of song is reached: + - load.skip_samples (boolean): Set to "1" to avoid loading samples into memory + - load.skip_patterns (boolean): Set to "1" to avoid loading patterns into memory + - load.skip_plugins (boolean): Set to "1" to avoid loading plugins + - load.skip_subsongs_init (boolean): Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. + - seek.sync_samples (boolean): Set to "1" to sync sample playback when using openmpt::module::set_position_seconds or openmpt::module::set_position_order_row. + - subsong (integer): The current subsong. Setting it has identical semantics as openmpt::module::select_subsong(), getting it returns the currently selected subsong. + - play.at_end (text): Chooses the behaviour when the end of song is reached: - "fadeout": Fades the module out for a short while. Subsequent reads after the fadeout will return 0 rendered frames. - "continue": Returns 0 rendered frames when the song end is reached. Subsequent reads will continue playing from the song start or loop start. - "stop": Returns 0 rendered frames when the song end is reached. Subsequent reads will return 0 rendered frames. - - play.tempo_factor: Set a floating point tempo factor. "1.0" is the default tempo. - - play.pitch_factor: Set a floating point pitch factor. "1.0" is the default pitch. - - render.resampler.emulate_amiga: Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. - - render.opl.volume_factor: Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. - - dither: Set the dither algorithm that is used for the 16 bit versions of openmpt::module::read. Supported values are: + - play.tempo_factor (floatingpoint): Set a floating point tempo factor. "1.0" is the default tempo. + - play.pitch_factor (floatingpoint): Set a floating point pitch factor. "1.0" is the default pitch. + - render.resampler.emulate_amiga (boolean): Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. + - render.opl.volume_factor (floatingpoint): Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. + - dither (integer): Set the dither algorithm that is used for the 16 bit versions of openmpt::module::read. Supported values are: - 0: No dithering. - 1: Default mode. Chosen by OpenMPT code, might change. - 2: Rectangular, 0.5 bit depth, no noise shaping (original ModPlug Tracker). @@ -1056,8 +1065,42 @@ \param ctl The ctl key whose value should be retrieved. \return The associated ctl value. \sa openmpt::module::get_ctls + \deprecated Please use openmpt::module::ctl_get_boolean(), openmpt::module::ctl_get_integer(), openmpt::module::ctl_get_floatingpoint(), or openmpt::module::ctl_get_text(). */ - std::string ctl_get( const std::string & ctl ) const; + LIBOPENMPT_ATTR_DEPRECATED std::string ctl_get( const std::string & ctl ) const; + //! Get current ctl boolean value + /*! + \param ctl The ctl key whose value should be retrieved. + \return The associated ctl value. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + bool ctl_get_boolean( std::string_view ctl ) const; + //! Get current ctl integer value + /*! + \param ctl The ctl key whose value should be retrieved. + \return The associated ctl value. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + std::int64_t ctl_get_integer( std::string_view ctl ) const; + //! Get current ctl floatingpoint value + /*! + \param ctl The ctl key whose value should be retrieved. + \return The associated ctl value. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + double ctl_get_floatingpoint( std::string_view ctl ) const; + //! Get current ctl text value + /*! + \param ctl The ctl key whose value should be retrieved. + \return The associated ctl value. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + std::string ctl_get_text( std::string_view ctl ) const; + //! Set ctl value /*! \param ctl The ctl key whose value should be set. @@ -1064,8 +1107,45 @@ \param value The value that should be set. \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. \sa openmpt::module::get_ctls + \deprecated Please use openmpt::module::ctl_set_bool(), openmpt::module::ctl_set_int(), openmpt::module::ctl_set_float(), or openmpt::module::ctl_set_string(). */ - void ctl_set( const std::string & ctl, const std::string & value ); + LIBOPENMPT_ATTR_DEPRECATED void ctl_set( const std::string & ctl, const std::string & value ); + //! Set ctl boolean value + /*! + \param ctl The ctl key whose value should be set. + \param value The value that should be set. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + void ctl_set_boolean( std::string_view ctl, bool value ); + //! Set ctl integer value + /*! + \param ctl The ctl key whose value should be set. + \param value The value that should be set. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + void ctl_set_integer( std::string_view ctl, std::int64_t value ); + //! Set ctl floatingpoint value + /*! + \param ctl The ctl key whose value should be set. + \param value The value that should be set. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + void ctl_set_floatingpoint( std::string_view ctl, double value ); + //! Set ctl text value + /*! + \param ctl The ctl key whose value should be set. + \param value The value that should be set. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. + \sa openmpt::module::get_ctls + \since 0.5.0 + */ + void ctl_set_text( std::string_view ctl, std::string_view value ); // remember to add new functions to both C and C++ interfaces and to increase OPENMPT_API_VERSION_MINOR Index: libopenmpt/libopenmpt_c.cpp =================================================================== --- libopenmpt/libopenmpt_c.cpp (revision 12302) +++ libopenmpt/libopenmpt_c.cpp (working copy) @@ -1278,6 +1278,46 @@ } return NULL; } +int openmpt_module_ctl_get_boolean( openmpt_module * mod, const char * ctl ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + return mod->impl->ctl_get_boolean( ctl ); + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} +int64_t openmpt_module_ctl_get_integer( openmpt_module * mod, const char * ctl ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + return mod->impl->ctl_get_integer( ctl ); + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} +double openmpt_module_ctl_get_floatingpoint( openmpt_module * mod, const char * ctl ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + return mod->impl->ctl_get_floatingpoint( ctl ); + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0.0; +} +const char * openmpt_module_ctl_get_text( openmpt_module * mod, const char * ctl ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + return openmpt::strdup( mod->impl->ctl_get_text( ctl ).c_str() ); + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return NULL; +} int openmpt_module_ctl_set( openmpt_module * mod, const char * ctl, const char * value ) { try { @@ -1291,8 +1331,52 @@ } return 0; } +int openmpt_module_ctl_set_boolean( openmpt_module * mod, const char * ctl, int value ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + mod->impl->ctl_set_boolean( ctl, value ); + return 1; + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} +int openmpt_module_ctl_set_integer( openmpt_module * mod, const char * ctl, int64_t value ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + mod->impl->ctl_set_integer( ctl, value ); + return 1; + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} +int openmpt_module_ctl_set_floatingpoint( openmpt_module * mod, const char * ctl, double value ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + mod->impl->ctl_set_floatingpoint( ctl, value ); + return 1; + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} +int openmpt_module_ctl_set_text( openmpt_module * mod, const char * ctl, const char * value ) { + try { + openmpt::interface::check_soundfile( mod ); + openmpt::interface::check_pointer( ctl ); + openmpt::interface::check_pointer( value ); + mod->impl->ctl_set_text( ctl, value ); + return 1; + } catch ( ... ) { + openmpt::report_exception( __func__, mod ); + } + return 0; +} - openmpt_module_ext * openmpt_module_ext_create( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ) { try { openmpt_module_ext * mod_ext = (openmpt_module_ext*)std::calloc( 1, sizeof( openmpt_module_ext ) ); Index: libopenmpt/libopenmpt_cxx.cpp =================================================================== --- libopenmpt/libopenmpt_cxx.cpp (revision 12302) +++ libopenmpt/libopenmpt_cxx.cpp (working copy) @@ -126,6 +126,9 @@ bool is_extension_supported( const std::string & extension ) { return openmpt::module_impl::is_extension_supported( extension ); } +bool is_extension_supported( std::string_view extension ) { + return openmpt::module_impl::is_extension_supported( extension ); +} double could_open_probability( std::istream & stream, double effort, std::ostream & log ) { return openmpt::module_impl::could_open_probability( stream, effort, openmpt::helper::make_unique( log ) ); @@ -403,12 +406,38 @@ std::vector module::get_ctls() const { return impl->get_ctls(); } + std::string module::ctl_get( const std::string & ctl ) const { return impl->ctl_get( ctl ); } +bool module::ctl_get_boolean( std::string_view ctl ) const { + return impl->ctl_get_boolean( ctl ); +} +std::int64_t module::ctl_get_integer( std::string_view ctl ) const { + return impl->ctl_get_integer( ctl ); +} +double module::ctl_get_floatingpoint( std::string_view ctl ) const { + return impl->ctl_get_floatingpoint( ctl ); +} +std::string module::ctl_get_text( std::string_view ctl ) const { + return impl->ctl_get_text( ctl ); +} + void module::ctl_set( const std::string & ctl, const std::string & value ) { impl->ctl_set( ctl, value ); } +void module::ctl_set_boolean( std::string_view ctl, bool value ) { + impl->ctl_set_boolean( ctl, value ); +} +void module::ctl_set_integer( std::string_view ctl, std::int64_t value ) { + impl->ctl_set_integer( ctl, value ); +} +void module::ctl_set_floatingpoint( std::string_view ctl, double value ) { + impl->ctl_set_floatingpoint( ctl, value ); +} +void module::ctl_set_text( std::string_view ctl, std::string_view value ) { + impl->ctl_set_text( ctl, value ); +} module_ext::module_ext( std::istream & stream, std::ostream & log, const std::map< std::string, std::string > & ctls ) : ext_impl(0) { ext_impl = new module_ext_impl( stream, openmpt::helper::make_unique( log ), ctls ); Index: libopenmpt/libopenmpt_impl.cpp =================================================================== --- libopenmpt/libopenmpt_impl.cpp (revision 12302) +++ libopenmpt/libopenmpt_impl.cpp (working copy) @@ -593,12 +593,9 @@ std::copy( extensions.begin(), extensions.end(), std::back_insert_iterator >( retval ) ); return retval; } -bool module_impl::is_extension_supported( const char * extension ) { +bool module_impl::is_extension_supported( std::string_view extension ) { return CSoundFile::IsExtensionSupported( extension ); } -bool module_impl::is_extension_supported( const std::string & extension ) { - return CSoundFile::IsExtensionSupported( extension.c_str() ); -} double module_impl::could_open_probability( const OpenMPT::FileReader & file, double effort, std::unique_ptr log ) { try { if ( effort >= 0.8 ) { @@ -1556,23 +1553,34 @@ return format_and_highlight_pattern_row_channel( p, r, c, width, pad ).second; } -std::vector module_impl::get_ctls() const { - return - { - "load.skip_samples", - "load.skip_patterns", - "load.skip_plugins", - "load.skip_subsongs_init", - "seek.sync_samples", - "subsong", - "play.tempo_factor", - "play.pitch_factor", - "play.at_end", - "render.resampler.emulate_amiga", - "render.opl.volume_factor", - "dither", +std::pair module_impl::get_ctl_infos() const { + static constexpr ctl_info ctl_infos[] = { + { "load.skip_samples", ctl_type::boolean }, + { "load.skip_patterns", ctl_type::boolean }, + { "load.skip_plugins", ctl_type::boolean }, + { "load.skip_subsongs_init", ctl_type::boolean }, + { "seek.sync_samples", ctl_type::boolean }, + { "subsong", ctl_type::integer }, + { "play.tempo_factor", ctl_type::floatingpoint }, + { "play.pitch_factor", ctl_type::floatingpoint }, + { "play.at_end", ctl_type::text }, + { "render.resampler.emulate_amiga", ctl_type::boolean }, + { "render.opl.volume_factor", ctl_type::floatingpoint }, + { "dither", ctl_type::integer } }; + return std::make_pair(std::begin(ctl_infos), std::end(ctl_infos)); } + +std::vector module_impl::get_ctls() const { + std::vector result; + auto ctl_infos = get_ctl_infos(); + result.reserve(std::distance(ctl_infos.first, ctl_infos.second)); + for ( std::ptrdiff_t i = 0; i < std::distance(ctl_infos.first, ctl_infos.second); ++i ) { + result.push_back(ctl_infos.first[i].name); + } + return result; +} + std::string module_impl::ctl_get( std::string ctl, bool throw_if_unknown ) const { if ( !ctl.empty() ) { // cppcheck false-positive @@ -1587,20 +1595,189 @@ ctl = ctl.substr( 0, ctl.length() - 1 ); } } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + ctl); + } else { + return std::string(); + } + } + std::string result; + switch ( found_ctl->type ) { + case ctl_type::boolean: + return mpt::fmt::val( ctl_get_boolean( ctl, throw_if_unknown ) ); + break; + case ctl_type::integer: + return mpt::fmt::val( ctl_get_integer( ctl, throw_if_unknown ) ); + break; + case ctl_type::floatingpoint: + return mpt::fmt::val( ctl_get_floatingpoint( ctl, throw_if_unknown ) ); + break; + case ctl_type::text: + return ctl_get_text( ctl, throw_if_unknown ); + break; + } + return result; +} +bool module_impl::ctl_get_boolean( std::string_view ctl, bool throw_if_unknown ) const { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl)); + } else { + return false; + } + } + if ( found_ctl->type != ctl_type::boolean ) { + throw openmpt::exception("wrong ctl value type"); + } if ( ctl == "" ) { throw openmpt::exception("empty ctl"); } else if ( ctl == "load.skip_samples" || ctl == "load_skip_samples" ) { - return mpt::fmt::val( m_ctl_load_skip_samples ); + return m_ctl_load_skip_samples; } else if ( ctl == "load.skip_patterns" || ctl == "load_skip_patterns" ) { - return mpt::fmt::val( m_ctl_load_skip_patterns ); + return m_ctl_load_skip_patterns; } else if ( ctl == "load.skip_plugins" ) { - return mpt::fmt::val( m_ctl_load_skip_plugins ); + return m_ctl_load_skip_plugins; } else if ( ctl == "load.skip_subsongs_init" ) { - return mpt::fmt::val( m_ctl_load_skip_subsongs_init ); + return m_ctl_load_skip_subsongs_init; } else if ( ctl == "seek.sync_samples" ) { - return mpt::fmt::val( m_ctl_seek_sync_samples ); + return m_ctl_seek_sync_samples; + } else if ( ctl == "render.resampler.emulate_amiga" ) { + return m_sndFile->m_Resampler.m_Settings.emulateAmiga; + } else { + MPT_ASSERT_NOTREACHED(); + return false; + } +} +std::int64_t module_impl::ctl_get_integer( std::string_view ctl, bool throw_if_unknown ) const { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl)); + } else { + return 0; + } + } + if ( found_ctl->type != ctl_type::integer ) { + throw openmpt::exception("wrong ctl value type"); + } + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); } else if ( ctl == "subsong" ) { - return mpt::fmt::val( get_selected_subsong() ); + return get_selected_subsong(); + } else if ( ctl == "dither" ) { + return static_cast( m_Dither->GetMode() ); + } else { + MPT_ASSERT_NOTREACHED(); + return 0; + } +} +double module_impl::ctl_get_floatingpoint( std::string_view ctl, bool throw_if_unknown ) const { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl)); + } else { + return 0.0; + } + } + if ( found_ctl->type != ctl_type::floatingpoint ) { + throw openmpt::exception("wrong ctl value type"); + } + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( ctl == "play.tempo_factor" ) { + if ( !is_loaded() ) { + return 1.0; + } + return 65536.0 / m_sndFile->m_nTempoFactor; + } else if ( ctl == "play.pitch_factor" ) { + if ( !is_loaded() ) { + return 1.0; + } + return m_sndFile->m_nFreqFactor / 65536.0; + } else if ( ctl == "render.opl.volume_factor" ) { + return static_cast( m_sndFile->m_OPLVolumeFactor ) / static_cast( m_sndFile->m_OPLVolumeFactorScale ); + } else { + MPT_ASSERT_NOTREACHED(); + return 0.0; + } +} +std::string module_impl::ctl_get_text( std::string_view ctl, bool throw_if_unknown ) const { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl)); + } else { + return std::string(); + } + } + if ( ctl == "" ) { + throw openmpt::exception("empty ctl"); } else if ( ctl == "play.at_end" ) { switch ( m_ctl_play_at_end ) { @@ -1613,31 +1790,52 @@ default: return std::string(); } - } else if ( ctl == "play.tempo_factor" ) { - if ( !is_loaded() ) { - return "1.0"; + } else { + MPT_ASSERT_NOTREACHED(); + return std::string(); + } +} + +void module_impl::ctl_set( std::string ctl, const std::string & value, bool throw_if_unknown ) { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); } - return mpt::fmt::val( 65536.0 / m_sndFile->m_nTempoFactor ); - } else if ( ctl == "play.pitch_factor" ) { - if ( !is_loaded() ) { - return "1.0"; - } - return mpt::fmt::val( m_sndFile->m_nFreqFactor / 65536.0 ); - } else if ( ctl == "render.resampler.emulate_amiga" ) { - return mpt::fmt::val( m_sndFile->m_Resampler.m_Settings.emulateAmiga ); - } else if ( ctl == "render.opl.volume_factor" ) { - return mpt::fmt::val( static_cast( m_sndFile->m_OPLVolumeFactor ) / static_cast( m_sndFile->m_OPLVolumeFactorScale ) ); - } else if ( ctl == "dither" ) { - return mpt::fmt::val( static_cast( m_Dither->GetMode() ) ); - } else { - if ( throw_if_unknown ) { - throw openmpt::exception("unknown ctl: " + ctl); + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + value); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + ctl + " := " + value); } else { - return std::string(); + return; } } + switch ( found_ctl->type ) { + case ctl_type::boolean: + ctl_set_boolean( ctl, ConvertStrTo( value ), throw_if_unknown ); + break; + case ctl_type::integer: + ctl_set_integer( ctl, ConvertStrTo( value ), throw_if_unknown ); + break; + case ctl_type::floatingpoint: + ctl_set_floatingpoint( ctl, ConvertStrTo( value ), throw_if_unknown ); + break; + case ctl_type::text: + ctl_set_text( ctl, value, throw_if_unknown ); + break; + } } -void module_impl::ctl_set( std::string ctl, const std::string & value, bool throw_if_unknown ) { +void module_impl::ctl_set_boolean( std::string_view ctl, bool value, bool throw_if_unknown ) { if ( !ctl.empty() ) { // cppcheck false-positive // cppcheck-suppress containerOutOfBounds @@ -1651,35 +1849,109 @@ ctl = ctl.substr( 0, ctl.length() - 1 ); } } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl) + " := " + mpt::fmt::val(value)); + } else { + return; + } + } if ( ctl == "" ) { - throw openmpt::exception("empty ctl: := " + value); + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); } else if ( ctl == "load.skip_samples" || ctl == "load_skip_samples" ) { - m_ctl_load_skip_samples = ConvertStrTo( value ); + m_ctl_load_skip_samples = value; } else if ( ctl == "load.skip_patterns" || ctl == "load_skip_patterns" ) { - m_ctl_load_skip_patterns = ConvertStrTo( value ); + m_ctl_load_skip_patterns = value; } else if ( ctl == "load.skip_plugins" ) { - m_ctl_load_skip_plugins = ConvertStrTo( value ); + m_ctl_load_skip_plugins = value; } else if ( ctl == "load.skip_subsongs_init" ) { - m_ctl_load_skip_subsongs_init = ConvertStrTo( value ); + m_ctl_load_skip_subsongs_init = value; } else if ( ctl == "seek.sync_samples" ) { - m_ctl_seek_sync_samples = ConvertStrTo( value ); + m_ctl_seek_sync_samples = value; + } else if ( ctl == "render.resampler.emulate_amiga" ) { + CResamplerSettings newsettings = m_sndFile->m_Resampler.m_Settings; + newsettings.emulateAmiga = value; + if ( newsettings != m_sndFile->m_Resampler.m_Settings ) { + m_sndFile->SetResamplerSettings( newsettings ); + } + } else { + MPT_ASSERT_NOTREACHED(); + } +} +void module_impl::ctl_set_integer( std::string_view ctl, std::int64_t value, bool throw_if_unknown ) { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl) + " := " + mpt::fmt::val(value)); + } else { + return; + } + } + + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); } else if ( ctl == "subsong" ) { - select_subsong( ConvertStrTo( value ) ); - } else if ( ctl == "play.at_end" ) { - if ( value == "fadeout" ) { - m_ctl_play_at_end = song_end_action::fadeout_song; - } else if(value == "continue") { - m_ctl_play_at_end = song_end_action::continue_song; - } else if(value == "stop") { - m_ctl_play_at_end = song_end_action::stop_song; + select_subsong( mpt::saturate_cast( value ) ); + } else if ( ctl == "dither" ) { + int dither = mpt::saturate_cast( value ); + if ( dither < 0 || dither >= NumDitherModes ) { + dither = DitherDefault; + } + m_Dither->SetMode( static_cast( dither ) ); + } else { + MPT_ASSERT_NOTREACHED(); + } +} +void module_impl::ctl_set_floatingpoint( std::string_view ctl, double value, bool throw_if_unknown ) { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); + } + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl) + " := " + mpt::fmt::val(value)); } else { - throw openmpt::exception("unknown song end action:" + value); + return; } + } + + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + mpt::fmt::val( value ) ); } else if ( ctl == "play.tempo_factor" ) { if ( !is_loaded() ) { return; } - double factor = ConvertStrTo( value ); + double factor = value; if ( factor <= 0.0 || factor > 4.0 ) { throw openmpt::exception("invalid tempo factor"); } @@ -1689,33 +1961,58 @@ if ( !is_loaded() ) { return; } - double factor = ConvertStrTo( value ); + double factor = value; if ( factor <= 0.0 || factor > 4.0 ) { throw openmpt::exception("invalid pitch factor"); } m_sndFile->m_nFreqFactor = mpt::saturate_round( 65536.0 * factor ); m_sndFile->RecalculateSamplesPerTick(); - } else if ( ctl == "render.resampler.emulate_amiga" ) { - CResamplerSettings newsettings = m_sndFile->m_Resampler.m_Settings; - newsettings.emulateAmiga = ConvertStrTo( value ); - if ( newsettings != m_sndFile->m_Resampler.m_Settings ) { - m_sndFile->SetResamplerSettings( newsettings ); - } } else if ( ctl == "render.opl.volume_factor" ) { - m_sndFile->m_OPLVolumeFactor = mpt::saturate_round( ConvertStrTo( value ) * static_cast( m_sndFile->m_OPLVolumeFactorScale ) ); - } else if ( ctl == "dither" ) { - int dither = ConvertStrTo( value ); - if ( dither < 0 || dither >= NumDitherModes ) { - dither = DitherDefault; + m_sndFile->m_OPLVolumeFactor = mpt::saturate_round( value * static_cast( m_sndFile->m_OPLVolumeFactorScale ) ); + } else { + MPT_ASSERT_NOTREACHED(); + } +} +void module_impl::ctl_set_text( std::string_view ctl, std::string_view value, bool throw_if_unknown ) { + if ( !ctl.empty() ) { + // cppcheck false-positive + // cppcheck-suppress containerOutOfBounds + char rightmost = ctl.back(); + if ( rightmost == '!' || rightmost == '?' ) { + if ( rightmost == '!' ) { + throw_if_unknown = true; + } else if ( rightmost == '?' ) { + throw_if_unknown = false; + } + ctl = ctl.substr( 0, ctl.length() - 1 ); } - m_Dither->SetMode( static_cast( dither ) ); - } else { - if ( throw_if_unknown ) { - throw openmpt::exception("unknown ctl: " + ctl + " := " + value); + } + auto found_ctl = std::find_if(get_ctl_infos().first, get_ctl_infos().second, [&](const ctl_info & info) -> bool { return info.name == ctl; }); + if ( found_ctl == get_ctl_infos().second ) { + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + std::string( value ) ); + } else if ( throw_if_unknown ) { + throw openmpt::exception("unknown ctl: " + std::string(ctl) + " := " + std::string(value)); } else { - // ignore + return; } } + + if ( ctl == "" ) { + throw openmpt::exception("empty ctl: := " + std::string( value ) ); + } else if ( ctl == "play.at_end" ) { + if ( value == "fadeout" ) { + m_ctl_play_at_end = song_end_action::fadeout_song; + } else if(value == "continue") { + m_ctl_play_at_end = song_end_action::continue_song; + } else if(value == "stop") { + m_ctl_play_at_end = song_end_action::stop_song; + } else { + throw openmpt::exception("unknown song end action:" + std::string(value)); + } + } else { + MPT_ASSERT_NOTREACHED(); + } } } // namespace openmpt Index: libopenmpt/libopenmpt_impl.hpp =================================================================== --- libopenmpt/libopenmpt_impl.hpp (revision 12302) +++ libopenmpt/libopenmpt_impl.hpp (working copy) @@ -15,6 +15,7 @@ #include #include +#include #if defined(_MSC_VER) #pragma warning(push) @@ -91,6 +92,17 @@ static const std::int32_t all_subsongs = -1; + enum class ctl_type { + boolean, + integer, + floatingpoint, + text, + }; + struct ctl_info { + const char * name; + ctl_type type; + }; + std::unique_ptr m_Log; std::unique_ptr m_LogForwarder; std::int32_t m_current_subsong; @@ -130,8 +142,7 @@ static double could_open_probability( const OpenMPT::FileReader & file, double effort, std::unique_ptr log ); public: static std::vector get_supported_extensions(); - static bool is_extension_supported( const char * extension ); - static bool is_extension_supported( const std::string & extension ); + static bool is_extension_supported( std::string_view extension ); static double could_open_probability( callback_stream_wrapper stream, double effort, std::unique_ptr log ); static double could_open_probability( std::istream & stream, double effort, std::unique_ptr log ); static std::size_t probe_file_header_get_recommended_size(); @@ -206,9 +217,18 @@ std::string highlight_pattern_row_channel_command( std::int32_t p, std::int32_t r, std::int32_t c, int cmd ) const; std::string format_pattern_row_channel( std::int32_t p, std::int32_t r, std::int32_t c, std::size_t width, bool pad ) const; std::string highlight_pattern_row_channel( std::int32_t p, std::int32_t r, std::int32_t c, std::size_t width, bool pad ) const; + std::pair get_ctl_infos() const; std::vector get_ctls() const; std::string ctl_get( std::string ctl, bool throw_if_unknown = true ) const; + bool ctl_get_boolean( std::string_view ctl, bool throw_if_unknown = true ) const; + std::int64_t ctl_get_integer( std::string_view ctl, bool throw_if_unknown = true ) const; + double ctl_get_floatingpoint( std::string_view ctl, bool throw_if_unknown = true ) const; + std::string ctl_get_text( std::string_view ctl, bool throw_if_unknown = true ) const; void ctl_set( std::string ctl, const std::string & value, bool throw_if_unknown = true ); + void ctl_set_boolean( std::string_view ctl, bool value, bool throw_if_unknown = true ); + void ctl_set_integer( std::string_view ctl, std::int64_t value, bool throw_if_unknown = true ); + void ctl_set_floatingpoint( std::string_view ctl, double value, bool throw_if_unknown = true ); + void ctl_set_text( std::string_view ctl, std::string_view value, bool throw_if_unknown = true ); }; // class module_impl namespace helper { Index: openmpt123/openmpt123.cpp =================================================================== --- openmpt123/openmpt123.cpp (revision 12302) +++ openmpt123/openmpt123.cpp (working copy) @@ -736,33 +736,6 @@ } -template < typename T, typename Tmod > -T ctl_get( Tmod & mod, const std::string & ctl ) { - T result = T(); - try { - std::istringstream str; - str.imbue( std::locale::classic() ); - str.str( mod.ctl_get( ctl ) ); - str >> std::fixed >> std::setprecision(16) >> result; - } catch ( const openmpt::exception & ) { - // ignore - } - return result; -} - -template < typename T, typename Tmod > -void ctl_set( Tmod & mod, const std::string & ctl, const T & val ) { - try { - std::ostringstream str; - str.imbue( std::locale::classic() ); - str << std::fixed << std::setprecision(16) << val; - mod.ctl_set( ctl, str.str() ); - } catch ( const openmpt::exception & ) { - // ignore - } - return; -} - template < typename Tmod > static void apply_mod_settings( commandlineflags & flags, Tmod & mod ) { flags.separation = std::max( flags.separation, std::int32_t( 0 ) ); @@ -778,12 +751,17 @@ mod.set_render_param( openmpt::module::RENDER_STEREOSEPARATION_PERCENT, flags.separation ); mod.set_render_param( openmpt::module::RENDER_INTERPOLATIONFILTER_LENGTH, flags.filtertaps ); mod.set_render_param( openmpt::module::RENDER_VOLUMERAMPING_STRENGTH, flags.ramping ); - ctl_set( mod, "play.tempo_factor", tempo_flag_to_double( flags.tempo ) ); - ctl_set( mod, "play.pitch_factor", pitch_flag_to_double( flags.pitch ) ); - std::ostringstream dither_str; - dither_str.imbue( std::locale::classic() ); - dither_str << flags.dither; - mod.ctl_set( "dither", dither_str.str() ); + try { + mod.ctl_set_floatingpoint( "play.tempo_factor", tempo_flag_to_double( flags.tempo ) ); + } catch ( const openmpt::exception & ) { + // ignore + } + try { + mod.ctl_set_floatingpoint( "play.pitch_factor", pitch_flag_to_double( flags.pitch ) ); + } catch ( const openmpt::exception & ) { + // ignore + } + mod.ctl_set_integer( "dither", flags.dither ); } struct prev_file { int count; prev_file( int c ) : count(c) { } }; Index: soundlib/Sndfile.h =================================================================== --- soundlib/Sndfile.h (revision 12302) +++ soundlib/Sndfile.h (working copy) @@ -824,7 +824,7 @@ bool ReadWAV(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); static std::vector GetSupportedExtensions(bool otherFormats); - static bool IsExtensionSupported(const char *ext); // UTF8, casing of ext is ignored + static bool IsExtensionSupported(std::string_view ext); // UTF8, casing of ext is ignored static mpt::ustring ModContainerTypeToString(MODCONTAINERTYPE containertype); static mpt::ustring ModContainerTypeToTracker(MODCONTAINERTYPE containertype); Index: soundlib/Tables.cpp =================================================================== --- soundlib/Tables.cpp (revision 12302) +++ soundlib/Tables.cpp (working copy) @@ -176,21 +176,19 @@ } -static bool IsEqualExtension(const char *a, const char *b) +static bool IsEqualExtension(std::string_view a, std::string_view b) { - std::size_t lena = std::strlen(a); - std::size_t lenb = std::strlen(b); - if(lena != lenb) + if(a.length() != b.length()) { return false; } - return mpt::CompareNoCaseAscii(a, b, lena) == 0; + return mpt::CompareNoCaseAscii(a, b) == 0; } -bool CSoundFile::IsExtensionSupported(const char *ext) +bool CSoundFile::IsExtensionSupported(std::string_view ext) { - if(ext == nullptr || ext[0] == 0) + if(ext.length() == 0) { return false; }