Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/helpers/input_fix_seeking.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/helpers/input_fix_seeking.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,65 @@ +#pragma once + +#include "duration_counter.h" + +// Wrapper to implement input_flag_allow_inaccurate_seeking semantics with decoders that do not implement seeking properly. +// If input_flag_allow_inaccurate_seeking is not specified, brute force seeking is used. +template<typename base_t> +class input_fix_seeking : public base_t { +public: + input_fix_seeking() : m_active() {} + + void decode_initialize(unsigned p_flags,abort_callback & p_abort) { + base_t::decode_initialize( p_flags, p_abort ); + m_active = ( p_flags & input_flag_allow_inaccurate_seeking ) == 0; + m_position = 0; + m_decodeFrom = 0; + } + + void decode_initialize(t_uint32 p_subsong,unsigned p_flags,abort_callback & p_abort) { + base_t::decode_initialize( p_subsong, p_flags, p_abort ); + m_active = ( p_flags & input_flag_allow_inaccurate_seeking ) == 0; + m_position = 0; + } + + bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort) { + if ( ! m_active ) { + return base_t::decode_run ( p_chunk, p_abort ); + } + for ( ;; ) { + p_abort.check(); + if (! base_t::decode_run( p_chunk, p_abort ) ) return false; + + double p = m_position.query(); + m_position += p_chunk; + if ( m_decodeFrom > p ) { + auto skip = audio_math::time_to_samples( m_decodeFrom - p, p_chunk.get_sample_rate() ); + if ( skip >= p_chunk.get_sample_count() ) continue; + if ( skip > 0 ) { + p_chunk.skip_first_samples( (size_t) skip ); + } + } + return true; + } + } + + void decode_seek(double p_seconds,abort_callback & p_abort) { + if ( m_active ) { + if ( ! this->decode_can_seek() ) throw exception_io_object_not_seekable(); + m_decodeFrom = p_seconds; + if ( m_decodeFrom < m_position.query() ) { + base_t::decode_seek(0, p_abort); m_position.reset(); + } + } else { + base_t::decode_seek(p_seconds, p_abort); + } + } + + bool decode_run_raw(audio_chunk & p_chunk, mem_block_container & p_raw, abort_callback & p_abort) { + throw pfc::exception_not_implemented(); // shitformats that need this class are not likely to care + } +private: + bool m_active; + duration_counter m_position; + double m_decodeFrom; +};
