Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/input_impl.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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include "input.h" | |
| 4 #include "mem_block_container.h" | |
| 5 | |
| 6 enum t_input_open_reason { | |
| 7 input_open_info_read, | |
| 8 input_open_decode, | |
| 9 input_open_info_write | |
| 10 }; | |
| 11 | |
| 12 //! Helper function for input implementation use; ensures that file is open with relevant access mode. This is typically called from input_impl::open() and such. | |
| 13 //! @param p_file File object pointer to process. If passed pointer is non-null, the function does nothing and always succeeds; otherwise it attempts to open the file using filesystem API methods. | |
| 14 //! @param p_path Path to the file. | |
| 15 //! @param p_reason Type of input operation requested. See: input_impl::open() parameters. | |
| 16 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 17 void input_open_file_helper(service_ptr_t<file> & p_file,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort); | |
| 18 | |
| 19 | |
| 20 //! This is a class that just declares prototypes of functions that each input needs to implement. See input_decoder / input_info_reader / input_info_writer interfaces for full descriptions of member functions. Since input implementation class is instantiated using a template, you don't need to derive from input_impl as virtual functions are not used on implementation class level. Use input_factory_t template to register input class based on input_impl. | |
| 21 class input_impl | |
| 22 { | |
| 23 public: | |
| 24 //! Opens specified file for info read / decoding / info write. This is called only once, immediately after object creation, before any other methods, and no other methods are called if open() fails. | |
| 25 //! @param p_filehint Optional; passes file object to use for the operation; if set to null, the implementation should handle opening file by itself. Note that not all inputs operate on physical files that can be reached through filesystem API, some of them require this parameter to be set to null (tone and silence generators for an example). Typically, an input implementation that requires file access calls input_open_file_helper() function to ensure that file is open with relevant access mode (read or read/write). | |
| 26 //! @param p_path URL of resource being opened. | |
| 27 //! @param p_reason Type of operation requested. Possible values are: \n | |
| 28 //! - input_open_info_read - info retrieval methods are valid; \n | |
| 29 //! - input_open_decode - info retrieval and decoding methods are valid; \n | |
| 30 //! - input_open_info_write - info retrieval and retagging methods are valid; \n | |
| 31 //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. \n | |
| 32 //! If your implementation does not support writing tags, throw exception_tagging_unsupported in response to input_open_info_write and do not implement other tag writing methods (they will not be called). | |
| 33 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 34 void open(service_ptr_t<file> p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort); | |
| 35 | |
| 36 //! See: input_info_reader::get_subsong_count(). Valid after open() with any reason. | |
| 37 unsigned get_subsong_count(); | |
| 38 //! See: input_info_reader::get_subsong(). Valid after open() with any reason. | |
| 39 t_uint32 get_subsong(unsigned p_index); | |
| 40 //! See: input_info_reader::get_info(). Valid after open() with any reason. | |
| 41 void get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort); | |
| 42 //! See: input_info_reader_v2::get_stats2(). Valid after open() with any reason. | |
| 43 t_filestats2 get_stats2(uint32_t, abort_callback & p_abort); | |
| 44 | |
| 45 //! See: input_decoder::initialize(). Valid after open() with input_open_decode reason. | |
| 46 void decode_initialize(t_uint32 p_subsong,unsigned p_flags,abort_callback & p_abort); | |
| 47 //! See: input_decoder::run(). Valid after decode_initialize(). | |
| 48 bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort); | |
| 49 //! See: input_decoder::seek(). Valid after decode_initialize(). | |
| 50 void decode_seek(double p_seconds,abort_callback & p_abort); | |
| 51 //! See: input_decoder::can_seek(). Valid after decode_initialize(). | |
| 52 bool decode_can_seek(); | |
| 53 //! See: input_decoder::get_dynamic_info(). Valid after decode_initialize(). | |
| 54 bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta); | |
| 55 //! See: input_decoder::get_dynamic_info_track(). Valid after decode_initialize(). | |
| 56 bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta); | |
| 57 //! Obsolete, do not use, do not rely on. | |
| 58 void decode_on_idle(abort_callback & p_abort); | |
| 59 | |
| 60 //! See: input_info_writer::set_info(). Valid after open() with input_open_info_write reason. \n | |
| 61 //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag_* methods will never be called. | |
| 62 void retag_set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort); | |
| 63 //! See: input_info_writer::commit(). Valid after open() with input_open_info_write reason. \n | |
| 64 //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag_* methods will never be called. | |
| 65 void retag_commit(abort_callback & p_abort); | |
| 66 | |
| 67 //! See: input_info_writer_v2::remove_tags(). Valid after open() with input_open_info_write reason. \n | |
| 68 //! If possible, entirely remove tags from the file (truncate ID3/APE tags away etc); otherwise set blank metadata. \n | |
| 69 //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and remove_tags() will never be called. | |
| 70 void remove_tags(abort_callback & p_abort); | |
| 71 | |
| 72 //! See: input_entry::is_our_content_type(). | |
| 73 static bool g_is_our_content_type(const char * p_content_type); | |
| 74 //! See: input_entry::is_our_path(). | |
| 75 static bool g_is_our_path(const char * p_path,const char * p_extension); | |
| 76 | |
| 77 //! See: input_entry::get_guid(). | |
| 78 static GUID g_get_guid(); | |
| 79 //! See: input_entry::get_name(). | |
| 80 static const char * g_get_name(); | |
| 81 //! See: input_entry::get_preferences_guid(). | |
| 82 static GUID g_get_preferences_guid(); | |
| 83 //! See: input_entry::is_low_merit(). | |
| 84 static bool g_is_low_merit(); | |
| 85 | |
| 86 //! See: input_decoder_v2::run_raw(). Relevant only when implementing input_decoder_v2. Valid after decode_initialize(). | |
| 87 bool decode_run_raw(audio_chunk & p_chunk, mem_block_container & p_raw, abort_callback & p_abort); | |
| 88 | |
| 89 //! OLD way: may be called at any time from input_decoder_v2 \n | |
| 90 //! NEW way (1.5): called prior to open(). | |
| 91 void set_logger(event_logger::ptr ptr); | |
| 92 protected: | |
| 93 input_impl() {} | |
| 94 ~input_impl() {} | |
| 95 }; | |
| 96 | |
| 97 //! A base class that provides stub implementations of all optional input methods. \n | |
| 98 //! Inherit from this and you implement input_decoder_v4 without having to provide all the methods you don't actually need. | |
| 99 class input_stubs { | |
| 100 public: | |
| 101 bool decode_run_raw(audio_chunk& p_chunk, mem_block_container& p_raw, abort_callback& p_abort) { (void)p_chunk; (void)p_raw; (void)p_abort; throw pfc::exception_not_implemented(); } | |
| 102 void set_logger(event_logger::ptr ptr) { (void)ptr; } | |
| 103 void set_pause(bool paused) { (void)paused; } | |
| 104 bool flush_on_pause() { return false; } | |
| 105 size_t extended_param(const GUID& type, size_t arg1, void* arg2, size_t arg2size) { (void)type, (void)arg1; (void)arg2; (void)arg2size; return 0; } | |
| 106 static GUID g_get_preferences_guid() {return pfc::guid_null;} | |
| 107 static bool g_is_low_merit() { return false; } | |
| 108 static bool g_fallback_is_our_payload(const void* bytes, size_t bytesAvail, t_filesize bytesWhole) { (void)bytes; (void)bytesAvail; (void)bytes; (void)bytesWhole; return false; } | |
| 109 | |
| 110 bool decode_get_dynamic_info(file_info& p_out, double& p_timestamp_delta) { (void)p_out; (void)p_timestamp_delta; return false; } | |
| 111 bool decode_get_dynamic_info_track(file_info& p_out, double& p_timestamp_delta) { (void)p_out; (void)p_timestamp_delta; return false; } | |
| 112 void decode_on_idle(abort_callback& p_abort) { (void)p_abort; } | |
| 113 | |
| 114 | |
| 115 //! These typedefs indicate which interfaces your class actually supports. You can override them to support non default input API interfaces without specifying input_factory parameters. | |
| 116 typedef input_decoder_v4 interface_decoder_t; | |
| 117 typedef input_info_reader_v2 interface_info_reader_t; | |
| 118 typedef input_info_writer_v2 interface_info_writer_t; | |
| 119 }; | |
| 120 | |
| 121 //! This is a class that just declares prototypes of functions that each non-multitrack-enabled input needs to implement. See input_decoder / input_info_reader / input_info_writer interfaces for full descriptions of member functions. Since input implementation class is instantiated using a template, you don't need to derive from input_singletrack_impl as virtual functions are not used on implementation class level. Use input_singletrack_factory_t template to register input class based on input_singletrack_impl. | |
| 122 class input_singletrack_impl | |
| 123 { | |
| 124 public: | |
| 125 //! Opens specified file for info read / decoding / info write. This is called only once, immediately after object creation, before any other methods, and no other methods are called if open() fails. | |
| 126 //! @param p_filehint Optional; passes file object to use for the operation; if set to null, the implementation should handle opening file by itself. Note that not all inputs operate on physical files that can be reached through filesystem API, some of them require this parameter to be set to null (tone and silence generators for an example). Typically, an input implementation that requires file access calls input_open_file_helper() function to ensure that file is open with relevant access mode (read or read/write). | |
| 127 //! @param p_path URL of resource being opened. | |
| 128 //! @param p_reason Type of operation requested. Possible values are: \n | |
| 129 //! - input_open_info_read - info retrieval methods are valid; \n | |
| 130 //! - input_open_decode - info retrieval and decoding methods are valid; \n | |
| 131 //! - input_open_info_write - info retrieval and retagging methods are valid; \n | |
| 132 //! Note that info retrieval methods are valid in all cases, and they may be called at any point of decoding/retagging process. Results of info retrieval methods (other than get_subsong_count() / get_subsong()) between retag_set_info() and retag_commit() are undefined however; those should not be called during that period. \n | |
| 133 //! If your implementation does not support writing tags, throw exception_tagging_unsupported in response to input_open_info_write and do not implement other tag writing methods (they will not be called). | |
| 134 //! @param p_abort abort_callback object signaling user aborting the operation. | |
| 135 void open(service_ptr_t<file> p_filehint,const char * p_path,t_input_open_reason p_reason,abort_callback & p_abort); | |
| 136 | |
| 137 //! See: input_info_reader::get_info(). Valid after open() with any reason. \n | |
| 138 //! Implementation warning: this is typically also called immediately after tag update and should return newly written content then. | |
| 139 void get_info(file_info & p_info,abort_callback & p_abort); | |
| 140 //! See: input_info_reader_v2::get_stats2(). Valid after open() with any reason. \n | |
| 141 //! Implementation warning: this is typically also called immediately after tag update and should return new values then. | |
| 142 t_filestats2 get_stats2(uint32_t, abort_callback&); | |
| 143 | |
| 144 //! See: input_decoder::initialize(). Valid after open() with input_open_decode reason. | |
| 145 void decode_initialize(unsigned p_flags,abort_callback & p_abort); | |
| 146 //! See: input_decoder::run(). Valid after decode_initialize(). | |
| 147 bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort); | |
| 148 //! See: input_decoder::seek(). Valid after decode_initialize(). | |
| 149 void decode_seek(double p_seconds,abort_callback & p_abort); | |
| 150 //! See: input_decoder::can_seek(). Valid after decode_initialize(). | |
| 151 bool decode_can_seek(); | |
| 152 //! See: input_decoder::get_dynamic_info(). Valid after decode_initialize(). | |
| 153 bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta); | |
| 154 //! See: input_decoder::get_dynamic_info_track(). Valid after decode_initialize(). | |
| 155 bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta); | |
| 156 //! Obsolete, do not use, do not rely on. | |
| 157 void decode_on_idle(abort_callback & p_abort); | |
| 158 | |
| 159 //! See: input_info_writer::set_info(). Note that input_info_writer::commit() call isn't forwarded because it's useless in case of non-multitrack-enabled inputs. Valid after open() with input_open_info_write reason. \n | |
| 160 //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and retag() will never be called. | |
| 161 void retag(const file_info & p_info,abort_callback & p_abort); | |
| 162 | |
| 163 //! See: input_info_writer_v2::remove_tags(). Valid after open() with input_open_info_write reason. \n | |
| 164 //! If possible, entirely remove tags from the file (truncate ID3/APE tags away etc); otherwise set blank metadata. \n | |
| 165 //! If your implementation does not support writing tags, throw exception_tagging_unsupported from open() and remove_tags() will never be called. | |
| 166 void remove_tags(abort_callback & p_abort); | |
| 167 | |
| 168 //! See: input_entry::is_our_content_type(). | |
| 169 static bool g_is_our_content_type(const char * p_content_type); | |
| 170 //! See: input_entry::is_our_path(). | |
| 171 static bool g_is_our_path(const char * p_path,const char * p_extension); | |
| 172 | |
| 173 protected: | |
| 174 input_singletrack_impl() {} | |
| 175 ~input_singletrack_impl() {} | |
| 176 }; | |
| 177 | |
| 178 | |
| 179 //! Used internally by standard input_entry implementation; do not use directly. Translates input_decoder / input_info_reader / input_info_writer calls to input_impl calls. | |
| 180 template<typename I, typename interface_t> | |
| 181 class input_impl_interface_wrapper_t : public interface_t | |
| 182 { | |
| 183 public: | |
| 184 template<typename ... args_t> | |
| 185 void open( args_t && ... args) { | |
| 186 m_instance.open(std::forward<args_t>(args) ... ); | |
| 187 } | |
| 188 | |
| 189 // input_info_reader methods | |
| 190 | |
| 191 t_uint32 get_subsong_count() { | |
| 192 return m_instance.get_subsong_count(); | |
| 193 } | |
| 194 | |
| 195 t_uint32 get_subsong(t_uint32 p_index) { | |
| 196 return m_instance.get_subsong(p_index); | |
| 197 } | |
| 198 | |
| 199 | |
| 200 void get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) { | |
| 201 m_instance.get_info(p_subsong,p_info,p_abort); | |
| 202 } | |
| 203 | |
| 204 t_filestats get_file_stats(abort_callback& p_abort) { | |
| 205 return get_stats2(stats2_legacy, p_abort).to_legacy(); | |
| 206 } | |
| 207 t_filestats2 get_stats2(uint32_t f, abort_callback& a) { | |
| 208 return m_instance.get_stats2(f, a); | |
| 209 } | |
| 210 | |
| 211 // input_decoder methods | |
| 212 | |
| 213 void initialize(t_uint32 p_subsong,unsigned p_flags,abort_callback & p_abort) { | |
| 214 m_instance.decode_initialize(p_subsong,p_flags,p_abort); | |
| 215 #if PFC_DEBUG | |
| 216 m_eof = false; | |
| 217 m_decoding = true; | |
| 218 #endif | |
| 219 } | |
| 220 | |
| 221 bool run(audio_chunk & p_chunk,abort_callback & p_abort) { | |
| 222 #if PFC_DEBUG | |
| 223 PFC_ASSERT( !m_eof ); | |
| 224 PFC_ASSERT(m_decoding); | |
| 225 // Complain if run()/run_raw() gets called again after having returned EOF, this means a logic error on caller's side | |
| 226 #endif | |
| 227 bool ret = m_instance.decode_run(p_chunk,p_abort); | |
| 228 #if PFC_DEBUG | |
| 229 if ( !ret ) m_eof = true; | |
| 230 #endif | |
| 231 return ret; | |
| 232 } | |
| 233 | |
| 234 bool run_raw(audio_chunk & p_chunk, mem_block_container & p_raw, abort_callback & p_abort) { | |
| 235 #if PFC_DEBUG | |
| 236 // Complain if run()/run_raw() gets called again after having returned EOF, this means a logic error on caller's side | |
| 237 PFC_ASSERT(!m_eof); | |
| 238 PFC_ASSERT(m_decoding); | |
| 239 #endif | |
| 240 bool ret = m_instance.decode_run_raw(p_chunk, p_raw, p_abort); | |
| 241 #if PFC_DEBUG | |
| 242 if ( !ret ) m_eof = true; | |
| 243 #endif | |
| 244 return ret; | |
| 245 } | |
| 246 | |
| 247 void seek(double p_seconds,abort_callback & p_abort) { | |
| 248 #if PFC_DEBUG | |
| 249 PFC_ASSERT(m_decoding); | |
| 250 #endif | |
| 251 m_instance.decode_seek(p_seconds,p_abort); | |
| 252 #if PFC_DEBUG | |
| 253 m_eof = false; | |
| 254 #endif | |
| 255 } | |
| 256 | |
| 257 bool can_seek() { | |
| 258 return m_instance.decode_can_seek(); | |
| 259 } | |
| 260 | |
| 261 bool get_dynamic_info(file_info & p_out, double & p_timestamp_delta) { | |
| 262 return m_instance.decode_get_dynamic_info(p_out,p_timestamp_delta); | |
| 263 } | |
| 264 | |
| 265 bool get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) { | |
| 266 return m_instance.decode_get_dynamic_info_track(p_out,p_timestamp_delta); | |
| 267 } | |
| 268 | |
| 269 void on_idle(abort_callback & p_abort) { | |
| 270 m_instance.decode_on_idle(p_abort); | |
| 271 } | |
| 272 | |
| 273 void set_logger(event_logger::ptr ptr) { | |
| 274 m_instance.set_logger(ptr); | |
| 275 } | |
| 276 | |
| 277 void set_pause(bool paused) { | |
| 278 // obsolete | |
| 279 // m_instance.set_pause(paused); | |
| 280 } | |
| 281 | |
| 282 bool flush_on_pause() { | |
| 283 return m_instance.flush_on_pause(); | |
| 284 } | |
| 285 | |
| 286 size_t extended_param(const GUID & type, size_t arg1, void * arg2, size_t arg2size) { | |
| 287 return m_instance.extended_param(type, arg1, arg2, arg2size); | |
| 288 } | |
| 289 | |
| 290 // input_info_writer methods | |
| 291 | |
| 292 void set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort) { | |
| 293 m_instance.retag_set_info(p_subsong,p_info,p_abort); | |
| 294 } | |
| 295 | |
| 296 void commit(abort_callback & p_abort) { | |
| 297 m_instance.retag_commit(p_abort); | |
| 298 } | |
| 299 void remove_tags(abort_callback & p_abort) { | |
| 300 m_instance.remove_tags(p_abort); | |
| 301 } | |
| 302 | |
| 303 private: | |
| 304 I m_instance; | |
| 305 | |
| 306 #if PFC_DEBUG | |
| 307 // Report illegal API calls in debug build | |
| 308 bool m_eof = false; | |
| 309 bool m_decoding = false; | |
| 310 #endif | |
| 311 }; | |
| 312 | |
| 313 template<typename input_t> | |
| 314 class input_forward_static_methods : public input_stubs { | |
| 315 public: | |
| 316 static bool g_is_our_content_type(const char * p_content_type) { return input_t::g_is_our_content_type(p_content_type); } | |
| 317 static bool g_is_our_path(const char * p_path, const char * p_extension) { return input_t::g_is_our_path(p_path, p_extension); } | |
| 318 static GUID g_get_preferences_guid() { return input_t::g_get_preferences_guid(); } | |
| 319 static GUID g_get_guid() { return input_t::g_get_guid(); } | |
| 320 static const char * g_get_name() { return input_t::g_get_name(); } | |
| 321 static bool g_is_low_merit() { return input_t::g_is_low_merit(); } | |
| 322 static bool g_fallback_is_our_payload(const void* bytes, size_t bytesAvail, t_filesize bytesWhole) { return input_t::g_fallback_is_our_payload(bytes, bytesAvail, bytesWhole); } | |
| 323 | |
| 324 typedef typename input_t::interface_decoder_t interface_decoder_t; | |
| 325 typedef typename input_t::interface_info_reader_t interface_info_reader_t; | |
| 326 typedef typename input_t::interface_info_writer_t interface_info_writer_t; | |
| 327 | |
| 328 }; | |
| 329 | |
| 330 //! Helper used by input_singletrack_factory_t, do not use directly. Translates input_impl calls to input_singletrack_impl calls. | |
| 331 template<typename I> | |
| 332 class input_wrapper_singletrack_t : public input_forward_static_methods<I> | |
| 333 { | |
| 334 public: | |
| 335 input_wrapper_singletrack_t() {} | |
| 336 | |
| 337 template<typename ... args_t> | |
| 338 void open( args_t && ... args) { | |
| 339 m_instance.open(std::forward<args_t>(args) ... ); | |
| 340 } | |
| 341 | |
| 342 void get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) { | |
| 343 if (p_subsong != 0) throw exception_io_bad_subsong_index(); | |
| 344 m_instance.get_info(p_info,p_abort); | |
| 345 } | |
| 346 | |
| 347 t_uint32 get_subsong_count() { | |
| 348 return 1; | |
| 349 } | |
| 350 | |
| 351 t_uint32 get_subsong(t_uint32 p_index) { | |
| 352 PFC_ASSERT(p_index == 0); | |
| 353 return 0; | |
| 354 } | |
| 355 | |
| 356 t_filestats get_file_stats(abort_callback& p_abort) { | |
| 357 return get_stats2(stats2_legacy, p_abort).to_legacy(); | |
| 358 } | |
| 359 t_filestats2 get_stats2(uint32_t f, abort_callback& a) { | |
| 360 return m_instance.get_stats2(f, a); | |
| 361 } | |
| 362 | |
| 363 void decode_initialize(t_uint32 p_subsong,unsigned p_flags,abort_callback & p_abort) { | |
| 364 if (p_subsong != 0) throw exception_io_bad_subsong_index(); | |
| 365 m_instance.decode_initialize(p_flags,p_abort); | |
| 366 #if PFC_DEBUG | |
| 367 m_decoding = true; m_eof = false; | |
| 368 #endif | |
| 369 } | |
| 370 | |
| 371 bool decode_run(audio_chunk & p_chunk,abort_callback & p_abort) { | |
| 372 #if PFC_DEBUG | |
| 373 PFC_ASSERT(!m_eof); | |
| 374 PFC_ASSERT(m_decoding); | |
| 375 #endif | |
| 376 bool rv = m_instance.decode_run(p_chunk,p_abort); | |
| 377 #if PFC_DEBUG | |
| 378 if (!rv) m_eof = true; | |
| 379 #endif | |
| 380 return rv; | |
| 381 } | |
| 382 void decode_seek(double p_seconds,abort_callback & p_abort) { | |
| 383 #if PFC_DEBUG | |
| 384 PFC_ASSERT(m_decoding); | |
| 385 #endif | |
| 386 m_instance.decode_seek(p_seconds,p_abort); | |
| 387 #if PFC_DEBUG | |
| 388 m_eof = false; | |
| 389 #endif | |
| 390 } | |
| 391 bool decode_can_seek() {return m_instance.decode_can_seek();} | |
| 392 bool decode_get_dynamic_info(file_info & p_out, double & p_timestamp_delta) {return m_instance.decode_get_dynamic_info(p_out,p_timestamp_delta);} | |
| 393 bool decode_get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) {return m_instance.decode_get_dynamic_info_track(p_out,p_timestamp_delta);} | |
| 394 void decode_on_idle(abort_callback & p_abort) {m_instance.decode_on_idle(p_abort);} | |
| 395 | |
| 396 void retag_set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort) { | |
| 397 if (p_subsong != 0) throw exception_io_bad_subsong_index(); | |
| 398 m_instance.retag(p_info,p_abort); | |
| 399 } | |
| 400 | |
| 401 bool decode_run_raw(audio_chunk & p_chunk, mem_block_container & p_raw, abort_callback & p_abort) { | |
| 402 #if PFC_DEBUG | |
| 403 PFC_ASSERT(!m_eof); | |
| 404 PFC_ASSERT(m_decoding); | |
| 405 #endif | |
| 406 bool rv = m_instance.decode_run_raw(p_chunk, p_raw, p_abort); | |
| 407 #if PFC_DEBUG | |
| 408 if (!rv) m_eof = true; | |
| 409 #endif | |
| 410 return rv; | |
| 411 } | |
| 412 | |
| 413 void set_logger(event_logger::ptr ptr) {m_instance.set_logger(ptr);} | |
| 414 | |
| 415 void set_pause(bool paused) { | |
| 416 // m_instance.set_pause(paused); | |
| 417 } | |
| 418 bool flush_on_pause() { | |
| 419 return m_instance.flush_on_pause(); | |
| 420 } | |
| 421 size_t extended_param(const GUID & type, size_t arg1, void * arg2, size_t arg2size) { | |
| 422 return m_instance.extended_param(type, arg1, arg2, arg2size); | |
| 423 } | |
| 424 void retag_commit(abort_callback & p_abort) {} | |
| 425 | |
| 426 void remove_tags(abort_callback & p_abort) { | |
| 427 m_instance.remove_tags(p_abort); | |
| 428 } | |
| 429 private: | |
| 430 I m_instance; | |
| 431 | |
| 432 #if PFC_DEBUG | |
| 433 // Report illegal API calls in debug build | |
| 434 bool m_eof = false; | |
| 435 bool m_decoding = false; | |
| 436 #endif | |
| 437 }; | |
| 438 | |
| 439 //! Helper; standard input_entry implementation. Do not instantiate this directly, use input_factory_t or one of other input_*_factory_t helpers instead. | |
| 440 template<typename I,unsigned t_flags, typename t_decoder = typename I::interface_decoder_t, typename t_inforeader = typename I::interface_info_reader_t, typename t_infowriter = typename I::interface_info_writer_t> | |
| 441 class input_entry_impl_t : public input_entry_v4 | |
| 442 { | |
| 443 public: | |
| 444 bool is_our_content_type(const char * p_type) override {return I::g_is_our_content_type(p_type);} | |
| 445 bool is_our_path(const char * p_full_path,const char * p_extension) override {return I::g_is_our_path(p_full_path,p_extension);} | |
| 446 | |
| 447 template<typename interface_t, typename outInterace_t, typename ... args_t> | |
| 448 void open_ex(service_ptr_t<outInterace_t> & p_instance,args_t && ... args) | |
| 449 { | |
| 450 auto temp = fb2k::service_new<input_impl_interface_wrapper_t<I,interface_t> >(); | |
| 451 temp->open(std::forward<args_t>(args) ... ); | |
| 452 p_instance = temp.get_ptr(); | |
| 453 } | |
| 454 | |
| 455 service_ptr open_v3(const GUID & whatFor, file::ptr hint, const char * path, event_logger::ptr logger, abort_callback & aborter) override { | |
| 456 if ( whatFor == input_decoder::class_guid ) { | |
| 457 auto obj = fb2k::service_new< input_impl_interface_wrapper_t<I, service_multi_inherit<t_decoder, t_inforeader> > > (); | |
| 458 if ( logger.is_valid() ) obj->set_logger(logger); | |
| 459 obj->open( hint, path, input_open_decode, aborter ); | |
| 460 input_decoder_vrequired* p = obj.get_ptr(); | |
| 461 return p; | |
| 462 } | |
| 463 if ( whatFor == input_info_reader::class_guid ) { | |
| 464 auto obj = fb2k::service_new < input_impl_interface_wrapper_t<I, t_inforeader> >(); | |
| 465 if (logger.is_valid()) obj->set_logger(logger); | |
| 466 obj->open(hint, path, input_open_info_read, aborter); | |
| 467 input_info_reader_vrequired* p = obj.get_ptr(); | |
| 468 return p; | |
| 469 } | |
| 470 if ( whatFor == input_info_writer::class_guid ) { | |
| 471 auto obj = fb2k::service_new < input_impl_interface_wrapper_t<I, service_multi_inherit<t_infowriter, t_inforeader> > >(); | |
| 472 if (logger.is_valid()) obj->set_logger(logger); | |
| 473 obj->open(hint, path, input_open_info_write, aborter); | |
| 474 input_info_writer_vrequired* p = obj.get_ptr(); | |
| 475 return p; | |
| 476 } | |
| 477 throw pfc::exception_not_implemented(); | |
| 478 } | |
| 479 | |
| 480 void get_extended_data(service_ptr_t<file> p_filehint,const playable_location & p_location,const GUID & p_guid,mem_block_container & p_out,abort_callback & p_abort) override { | |
| 481 p_out.reset(); | |
| 482 } | |
| 483 | |
| 484 unsigned get_flags() override {return t_flags;} | |
| 485 | |
| 486 GUID get_guid() override { | |
| 487 return I::g_get_guid(); | |
| 488 } | |
| 489 const char * get_name() override { | |
| 490 return I::g_get_name(); | |
| 491 } | |
| 492 | |
| 493 GUID get_preferences_guid() override { | |
| 494 return I::g_get_preferences_guid(); | |
| 495 } | |
| 496 bool is_low_merit() override { | |
| 497 return I::g_is_low_merit(); | |
| 498 } | |
| 499 bool fallback_is_our_payload(const void* bytes, size_t bytesAvail, t_filesize bytesWhole) override { | |
| 500 return I::g_fallback_is_our_payload(bytes, bytesAvail, bytesWhole); | |
| 501 } | |
| 502 }; | |
| 503 | |
| 504 | |
| 505 //! Stardard input factory. For reference of functions that must be supported by registered class, see input_impl.\n Usage: static input_factory_t<myinputclass> g_myinputclass_factory;\n Note that input classes can't be registered through service_factory_t template directly. | |
| 506 template<typename T, unsigned t_flags = 0> | |
| 507 class input_factory_t : public service_factory_single_t<input_entry_impl_t<T, t_flags> > {}; | |
| 508 | |
| 509 //! Non-multitrack-enabled input factory (helper) - hides multitrack management functions from input implementation; use this for inputs that handle file types where each physical file can contain only one user-visible playable track. For reference of functions that must be supported by registered class, see input_singletrack_impl.\n Usage: static input_singletrack_factory_t<myinputclass> g_myinputclass_factory;\n Note that input classes can't be registered through service_factory_t template directly.template<class T> | |
| 510 template<typename T, unsigned t_flags = 0> | |
| 511 class input_singletrack_factory_t : public service_factory_single_t<input_entry_impl_t<input_wrapper_singletrack_t<T>,t_flags> > {}; |
