4 if (arg > 0 && !filesystem::g_is_remote_or_unrecognized(p_path)) {
6 p_file = a.
open(p_path, p_abort, p_file, arg);
11 if (arg > 0 && !filesystem::g_is_remote_or_unrecognized(p_path)) {
12 if (p_file.
is_empty()) filesystem::g_open_read( p_file, p_path, p_abort );
13 if (!p_file->is_in_memory() && !p_file->is_remote() && p_file->can_seek()) {
14 file_cached::g_create( p_file, p_file, p_abort, (
size_t) arg );
21 open(p_filehint,p_location->get_location(),p_flags,p_abort,p_from_redirect,p_skip_hints);
41 TRACK_CODE(
"input_entry::g_open_for_decoding",
49 }
catch(exception_io_data) {
52 if (l_file.
is_valid()) l_file->reopen(p_abort);
53 TRACK_CODE(
"input_entry::g_open_for_decoding",
64 TRACK_CODE(
"input_decoder::initialize",
m_input->initialize(subsong,flags,p_abort));
81 this->
open( p_location, p_abort, o );
94 input_decoder_v3::ptr v3;
95 if (
m_input->service_query_t(v3)) v3->set_pause(state);
98 input_decoder_v3::ptr v3;
99 if (
m_input->service_query_t(v3))
return v3->flush_on_pause();
105 input_decoder_v2::ptr v2;
106 if (
m_input->service_query_t(v2)) v2->set_logger(ptr);
110 input_decoder_v2::ptr v2;
111 if (!
m_input->service_query_t(v2))
throw pfc::exception_not_implemented();
112 return v2->run_raw(p_chunk, p_raw, p_abort);
116 TRACK_CODE(
"input_decoder::run",
return m_input->run(p_chunk,p_abort));
120 TRACK_CODE(
"input_decoder::seek",
m_input->seek(seconds,p_abort));
139 TRACK_CODE(
"input_decoder::on_idle",
m_input->on_idle(p_abort));
144 TRACK_CODE(
"input_decoder::get_dynamic_info",
return m_input->get_dynamic_info(p_out,p_timestamp_delta));
148 TRACK_CODE(
"input_decoder::get_dynamic_info_track",
return m_input->get_dynamic_info_track(p_out,p_timestamp_delta));
152 TRACK_CODE(
"input_decoder::get_info",
m_input->get_info(p_subsong,p_info,p_abort));
175 instance->commit(p_abort);
186 if (is_aborting())
return false;
187 on_progress(pathidx,path_list.
get_count());
189 const char * path = path_list[pathidx];
191 if (filesystem::g_is_remote_safe(path)) {
200 t_uint32 count = reader->get_subsong_count();
201 for(
t_uint32 n=0;n<count && !is_aborting();n++) {
203 t_uint32 index = reader->get_subsong(n);
211 if (is_aborting())
return false;
217 p_mask.
set(listidx,dead);
219 return !is_aborting();
227 inline dead_item_filter_impl_simple(
abort_callback & p_abort) : m_abort(p_abort) {}
228 bool is_aborting()
const {
return m_abort.is_aborting();}
239 dead_item_filter_impl_simple filter(p_abort);
240 return filter.run(p_list,p_mask);
255 TRACK_CODE(
"input_info_reader::get_file_stats",p_stats =
m_input->get_file_stats(p_abort));
262 t_filestats newstats;
263 TRACK_CODE(
"input_info_reader::get_file_stats",newstats =
m_input->get_file_stats(p_abort));
283 m_dynamic_info_trigger =
false;
284 m_dynamic_info_track_trigger =
false;
286 m_input.open(p_filehint,p_location,p_flags,p_abort,
true,
true);
288 if (!
m_input.can_seek())
throw exception_io_object_not_seekable();
298 m_input.get_info(0,temp,p_abort);
300 if (ref_length <= 0)
throw exception_io_data();
301 m_length = ref_length - m_start + p_length ;
302 if (m_length <= 0)
throw exception_io_data();
311 return m_input.run(p_chunk, p_abort);
313 return m_input.run_raw(p_chunk, *p_raw, p_abort);
320 if (m_position >= m_length)
return false;
322 if (!_m_input_run(p_chunk, p_raw, p_abort))
return false;
324 m_dynamic_info_trigger =
true;
325 m_dynamic_info_track_trigger =
true;
330 m_position = m_length;
340 PFC_ASSERT( rawSize % samples == 0 );
343 m_position = m_length;
353 if (!_m_input_run(p_chunk, p_raw, p_abort))
return false;
359 return _run(p_chunk, &p_raw, p_abort);
363 return _run(p_chunk, NULL, p_abort);
368 m_dynamic_info_trigger =
false;
369 m_dynamic_info_track_trigger =
false;
370 if (m_length <= 0 || p_seconds < m_length) {
371 m_input.seek(p_seconds + m_start,p_abort);
372 m_position = p_seconds;
374 m_position = m_length;
385 if (m_dynamic_info_trigger) {
386 m_dynamic_info_trigger =
false;
387 return m_input.get_dynamic_info(p_out,p_timestamp_delta);
394 if (m_dynamic_info_track_trigger) {
395 m_dynamic_info_track_trigger =
false;
396 return m_input.get_dynamic_info_track(p_out,p_timestamp_delta);
418 m_length = -1; m_lengthKnown =
false;
421 m_seekable = bSeekable && m_decoder->can_seek();
422 reopenDecoder(aborter);
423 readChunk(aborter,
true);
429 if (m_chunk.get_sample_count() > 0 && m_chunkBytesPtr == m_currentPosition) {
430 m_currentPosition = 0;
436 reopenDecoder(aborter);
443 #if FOOBAR2000_TARGET_VERSION >= 2000 445 t_filestats fs = m_decoder->get_file_stats(aborter);
451 return m_decoder->get_file_stats(p_abort).m_timestamp;
455 m_decoder->on_idle(p_abort);
464 if (!m_seekable)
throw exception_io_object_not_seekable();
468 t_filesize chunkBegin = m_currentPosition - m_chunkBytesPtr;
469 t_filesize chunkEnd = chunkBegin + curChunkBytes();
470 if (p_position >= chunkBegin && p_position < chunkEnd) {
471 m_chunkBytesPtr = (size_t)(p_position - chunkBegin);
472 m_currentPosition = p_position;
481 if (p_position > s)
throw exception_io_seek_out_of_range();
482 if (p_position == s) {
485 m_currentPosition = p_position;
494 const size_t row = m_spec.chanCount *
sizeof(
audio_sample);
496 const double seekTime = audio_math::samples_to_time(samples, m_spec.sampleRate);
497 m_decoder->seek(seekTime, p_abort);
499 if (!this->readChunk(p_abort)) {
500 throw std::runtime_error(PFC_string_formatter() <<
"Premature EOF in referenced audio file at " <<
pfc::format_time_ex(seekTime, 6) <<
" out of " <<
pfc::format_time_ex(length(p_abort), 6));
502 m_chunkBytesPtr = p_position % row;
503 if (m_chunkBytesPtr > curChunkBytes()) {
506 throw std::runtime_error(
"Decoder returned invalid data");
509 m_currentPosition = p_position;
514 const double l = length(aborter);
516 return audio_math::time_to_samples(l, m_spec.sampleRate) * m_spec.chanCount *
sizeof(
audio_sample);
519 return m_currentPosition;
526 const size_t inChunk = curChunkBytes();
527 const size_t inChunkRemaining = inChunk - m_chunkBytesPtr;
528 const size_t delta = pfc::min_t<size_t>(inChunkRemaining, (p_bytes - done));
529 memcpy((uint8_t*)p_buffer + done, (
const uint8_t*)m_chunk.get_data() + m_chunkBytesPtr, delta);
530 m_chunkBytesPtr += delta;
532 m_currentPosition += delta;
534 if (done == p_bytes)
break;
536 if (!readChunk(p_abort))
break;
543 uint32_t flags = input_flag_no_looping;
544 if (!m_seekable) flags |= input_flag_no_seeking;
545 m_decoder->initialize(m_subsong, flags, aborter);
547 m_currentPosition = 0;
549 size_t curChunkBytes()
const {
555 if (m_eof || !m_decoder->run(m_chunk, aborter)) {
556 if (initial)
throw std::runtime_error(
"Decoder produced no data");
561 if (m_chunk.is_valid())
break;
564 if (initial) m_spec = spec;
565 else if (m_spec != spec)
throw std::runtime_error(
"Sample format change in mid stream");
569 if (!m_lengthKnown) {
571 m_decoder->get_info(m_subsong, temp, aborter);
573 m_lengthKnown =
true;
578 size_t m_chunkBytesPtr;
584 input_decoder::ptr m_decoder;
593 f->init(loc, bSeekable, fileHint, aborter);
void read(const service_ptr_t< file > &p_file, abort_callback &p_abort, pfc::string_base &p_out, bool &is_utf8)
virtual void set_size(t_size p_size)=0
t_filesize get_size(HANDLE p_handle)
Implementation of audio_chunk. Takes pfc allocator template as template parameter.
Template implementing reference-counting features of service_base. Intended for dynamic instantiation...
virtual t_uint32 get_subsong() const =0
double get_length() const
Retrieves audio duration, in seconds. Note that the reported duration should not be assumed to be th...
pfc::eventHandle_t abort_callback_event
unsigned get_sample_rate() const
Helper, same as get_srate().
Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation.
static const t_filesize filesize_invalid
Invalid/unknown file size constant. Also see: t_filesize.
virtual const char * get_path() const =0
static void g_open_for_info_write(service_ptr_t< input_info_writer > &p_instance, service_ptr_t< file > p_filehint, const char *p_path, abort_callback &p_abort, bool p_from_redirect=false)
static void g_open_for_info_read(service_ptr_t< input_info_reader > &p_instance, service_ptr_t< file > p_filehint, const char *p_path, abort_callback &p_abort, bool p_from_redirect=false)
virtual void set(t_size n, bool val)=0
Main interface class for information about some playable object.
t_size add_item(const T &item)
virtual t_size get_count() const =0
Bit array interface class, variable version (you can both set and retrieve values). As with the constant version, valid index range depends on the context.
t_uint32 get_subsong_index() const
t_uint64 t_filetimestamp
Type used for file timestamp related variables. 64-bit value representing the number of 100-nanosecon...
static void g_open_for_decoding(service_ptr_t< input_decoder > &p_instance, service_ptr_t< file > p_filehint, const char *p_path, abort_callback &p_abort, bool p_from_redirect=false)
bool run(const pfc::list_base_const_t< metadb_handle_ptr > &p_list, bit_array_var &p_mask)
t_uint64 t_filesize
Type used for file size related variables.
Generic interface for a memory block; used by various other interfaces to return memory blocks while ...
Helper template used to easily access core services. Usage: static_api_ptr_t<myclass> api; api->doso...
double get_duration() const
Retrieves duration of contained audio data, in seconds.
file::ptr open(const char *path, abort_callback &abort, file::ptr hint, t_filesize sizeMax=1024 *1024 *256)
virtual t_size get_sample_count() const =0
Retrieves number of valid samples in the buffer. Note that a "sample" means a unit of interleaved PC...
virtual void set_sample_count(t_size val)=0
Sets number of valid samples in the buffer. WARNING: sample count * channel count should never be abo...
virtual t_size get_size() const =0