foobar2000 SDK  2015-08-03
input_helpers.cpp
Go to the documentation of this file.
1 #include "stdafx.h"
2 
3 static void _input_helper_io_filter_fullbuffer(service_ptr_t<file> & p_file,const char * p_path, t_filesize arg,abort_callback & p_abort) {
4  if (arg > 0 && !filesystem::g_is_remote_or_unrecognized(p_path)) {
6  p_file = a.open(p_path, p_abort, p_file, arg);
7  }
8 }
9 
10 static void _input_helper_io_filter_blockbuffer(service_ptr_t<file> & p_file,const char * p_path, t_filesize arg,abort_callback & p_abort) {
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 );
15  }
16  }
17 }
18 
19 void input_helper::open(service_ptr_t<file> p_filehint,metadb_handle_ptr p_location,unsigned p_flags,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints)
20 {
21  open(p_filehint,p_location->get_location(),p_flags,p_abort,p_from_redirect,p_skip_hints);
22 }
23 
24 void input_helper::process_fullbuffer(service_ptr_t<file> & p_file,const char * p_path,abort_callback & p_abort) {
25  if (m_ioFilter != NULL) m_ioFilter(p_file, p_path, m_ioFilterArg, p_abort);
26 }
27 
28 bool input_helper::need_file_reopen(const char * newPath) const {
29  return m_input.is_empty() || metadb::path_compare(m_path, newPath) != 0;
30 }
31 
32 bool input_helper::open_path(file::ptr p_filehint,const char * path,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
33  p_abort.check();
34 
35  if (!need_file_reopen(path)) return false;
36  m_input.release();
37 
38  service_ptr_t<file> l_file = p_filehint;
39  process_fullbuffer(l_file,path,p_abort);
40 
41  TRACK_CODE("input_entry::g_open_for_decoding",
42  input_entry::g_open_for_decoding(m_input,l_file,path,p_abort,p_from_redirect)
43  );
44 
45 
46  if (!p_skip_hints) {
47  try {
48  static_api_ptr_t<metadb_io>()->hint_reader(m_input.get_ptr(),path,p_abort);
49  } catch(exception_io_data) {
50  //Don't fail to decode when this barfs, might be barfing when reading info from another subsong than the one we're trying to decode etc.
51  m_input.release();
52  if (l_file.is_valid()) l_file->reopen(p_abort);
53  TRACK_CODE("input_entry::g_open_for_decoding",
54  input_entry::g_open_for_decoding(m_input,l_file,path,p_abort,p_from_redirect)
55  );
56  }
57  }
58 
59  m_path = path;
60  return true;
61 }
62 
64  TRACK_CODE("input_decoder::initialize",m_input->initialize(subsong,flags,p_abort));
65 }
66 
67 void input_helper::open(const playable_location & location, abort_callback & abort, decodeOpen_t const & other) {
68  open_path(other.m_hint, location.get_path(), abort, other.m_from_redirect, other.m_skip_hints);
69 
70  set_logger( other.m_logger );
71 
72  open_decoding(location.get_subsong(), other.m_flags, abort);
73 }
74 
75 void input_helper::open(service_ptr_t<file> p_filehint,const playable_location & p_location,unsigned p_flags,abort_callback & p_abort,bool p_from_redirect,bool p_skip_hints) {
76  decodeOpen_t o;
77  o.m_hint = p_filehint;
78  o.m_flags = p_flags;
79  o.m_from_redirect = p_from_redirect;
80  o.m_skip_hints = p_skip_hints;
81  this->open( p_location, p_abort, o );
82 }
83 
84 
86  m_input.release();
87 }
88 
90  return m_input.is_valid();
91 }
92 
93 void input_helper::set_pause(bool state) {
94  input_decoder_v3::ptr v3;
95  if (m_input->service_query_t(v3)) v3->set_pause(state);
96 }
98  input_decoder_v3::ptr v3;
99  if (m_input->service_query_t(v3)) return v3->flush_on_pause();
100  else return false;
101 }
102 
103 
104 void input_helper::set_logger(event_logger::ptr ptr) {
105  input_decoder_v2::ptr v2;
106  if (m_input->service_query_t(v2)) v2->set_logger(ptr);
107 }
108 
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);
113 }
114 
115 bool input_helper::run(audio_chunk & p_chunk,abort_callback & p_abort) {
116  TRACK_CODE("input_decoder::run",return m_input->run(p_chunk,p_abort));
117 }
118 
119 void input_helper::seek(double seconds,abort_callback & p_abort) {
120  TRACK_CODE("input_decoder::seek",m_input->seek(seconds,p_abort));
121 }
122 
124  return m_input->can_seek();
125 }
126 
129  m_ioFilterArg = val;
130 }
131 
134  m_ioFilterArg = val;
135 }
136 
138  if (m_input.is_valid()) {
139  TRACK_CODE("input_decoder::on_idle",m_input->on_idle(p_abort));
140  }
141 }
142 
143 bool input_helper::get_dynamic_info(file_info & p_out,double & p_timestamp_delta) {
144  TRACK_CODE("input_decoder::get_dynamic_info",return m_input->get_dynamic_info(p_out,p_timestamp_delta));
145 }
146 
147 bool input_helper::get_dynamic_info_track(file_info & p_out,double & p_timestamp_delta) {
148  TRACK_CODE("input_decoder::get_dynamic_info_track",return m_input->get_dynamic_info_track(p_out,p_timestamp_delta));
149 }
150 
151 void input_helper::get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) {
152  TRACK_CODE("input_decoder::get_info",m_input->get_info(p_subsong,p_info,p_abort));
153 }
154 
155 const char * input_helper::get_path() const {
156  return m_path;
157 }
158 
159 
161 {
162 }
163 
164 
165 void input_helper::g_get_info(const playable_location & p_location,file_info & p_info,abort_callback & p_abort,bool p_from_redirect) {
167  input_entry::g_open_for_info_read(instance,0,p_location.get_path(),p_abort,p_from_redirect);
168  instance->get_info(p_location.get_subsong_index(),p_info,p_abort);
169 }
170 
171 void input_helper::g_set_info(const playable_location & p_location,file_info & p_info,abort_callback & p_abort,bool p_from_redirect) {
173  input_entry::g_open_for_info_write(instance,0,p_location.get_path(),p_abort,p_from_redirect);
174  instance->set_info(p_location.get_subsong_index(),p_info,p_abort);
175  instance->commit(p_abort);
176 }
177 
178 
181  path_list.init_from_list(p_list);
182  metadb_handle_list valid_handles;
183  static_api_ptr_t<metadb> l_metadb;
184  for(t_size pathidx=0;pathidx<path_list.get_count();pathidx++)
185  {
186  if (is_aborting()) return false;
187  on_progress(pathidx,path_list.get_count());
188 
189  const char * path = path_list[pathidx];
190 
191  if (filesystem::g_is_remote_safe(path)) {
192  metadb_handle_ptr temp;
193  l_metadb->handle_create(temp,make_playable_location(path,0));
194  valid_handles.add_item(temp);
195  } else {
196  try {
198 
199  input_entry::g_open_for_info_read(reader,0,path,*this);
200  t_uint32 count = reader->get_subsong_count();
201  for(t_uint32 n=0;n<count && !is_aborting();n++) {
202  metadb_handle_ptr ptr;
203  t_uint32 index = reader->get_subsong(n);
204  l_metadb->handle_create(ptr,make_playable_location(path,index));
205  valid_handles.add_item(ptr);
206  }
207  } catch(...) {}
208  }
209  }
210 
211  if (is_aborting()) return false;
212 
213  valid_handles.sort_by_pointer();
214  for(t_size listidx=0;listidx<p_list.get_count();listidx++) {
215  bool dead = valid_handles.bsearch_by_pointer(p_list[listidx]) == ~0;
216  if (dead) console::formatter() << "Dead item: " << p_list[listidx];
217  p_mask.set(listidx,dead);
218  }
219  return !is_aborting();
220 }
221 
222 namespace {
223 
224 class dead_item_filter_impl_simple : public dead_item_filter
225 {
226 public:
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();}
229  abort_callback_event get_abort_event() const {return m_abort.get_abort_event();}
230  void on_progress(t_size p_position,t_size p_total) {}
231 private:
232  abort_callback & m_abort;
233 };
234 
235 }
236 
238 {
239  dead_item_filter_impl_simple filter(p_abort);
240  return filter.run(p_list,p_mask);
241 }
242 
243 void input_info_read_helper::open(const char * p_path,abort_callback & p_abort) {
244  if (m_input.is_empty() || metadb::path_compare(m_path,p_path) != 0)
245  {
246  TRACK_CODE("input_entry::g_open_for_info_read",input_entry::g_open_for_info_read(m_input,0,p_path,p_abort));
247 
248  m_path = p_path;
249  }
250 }
251 
252 void input_info_read_helper::get_info(const playable_location & p_location,file_info & p_info,t_filestats & p_stats,abort_callback & p_abort) {
253  open(p_location.get_path(),p_abort);
254 
255  TRACK_CODE("input_info_reader::get_file_stats",p_stats = m_input->get_file_stats(p_abort));
256 
257  TRACK_CODE("input_info_reader::get_info",m_input->get_info(p_location.get_subsong_index(),p_info,p_abort));
258 }
259 
260 void input_info_read_helper::get_info_check(const playable_location & p_location,file_info & p_info,t_filestats & p_stats,bool & p_reloaded,abort_callback & p_abort) {
261  open(p_location.get_path(),p_abort);
262  t_filestats newstats;
263  TRACK_CODE("input_info_reader::get_file_stats",newstats = m_input->get_file_stats(p_abort));
264  if (metadb_handle::g_should_reload(p_stats,newstats,true)) {
265  p_stats = newstats;
266  TRACK_CODE("input_info_reader::get_info",m_input->get_info(p_location.get_subsong_index(),p_info,p_abort));
267  p_reloaded = true;
268  } else {
269  p_reloaded = false;
270  }
271 }
272 
273 
274 
275 
276 
277 
278 void input_helper_cue::open(service_ptr_t<file> p_filehint,const playable_location & p_location,unsigned p_flags,abort_callback & p_abort,double p_start,double p_length) {
279  p_abort.check();
280 
281  m_start = p_start;
282  m_position = 0;
283  m_dynamic_info_trigger = false;
284  m_dynamic_info_track_trigger = false;
285 
286  m_input.open(p_filehint,p_location,p_flags,p_abort,true,true);
287 
288  if (!m_input.can_seek()) throw exception_io_object_not_seekable();
289 
290  if (m_start > 0) {
291  m_input.seek(m_start,p_abort);
292  }
293 
294  if (p_length > 0) {
295  m_length = p_length;
296  } else {
297  file_info_impl temp;
298  m_input.get_info(0,temp,p_abort);
299  double ref_length = temp.get_length();
300  if (ref_length <= 0) throw exception_io_data();
301  m_length = ref_length - m_start + p_length /* negative or zero */;
302  if (m_length <= 0) throw exception_io_data();
303  }
304 }
305 
307 bool input_helper_cue::is_open() {return m_input.is_open();}
308 
310  if (p_raw == NULL) {
311  return m_input.run(p_chunk, p_abort);
312  } else {
313  return m_input.run_raw(p_chunk, *p_raw, p_abort);
314  }
315 }
317  p_abort.check();
318 
319  if (m_length > 0) {
320  if (m_position >= m_length) return false;
321 
322  if (!_m_input_run(p_chunk, p_raw, p_abort)) return false;
323 
324  m_dynamic_info_trigger = true;
325  m_dynamic_info_track_trigger = true;
326 
327  t_uint64 max = (t_uint64) audio_math::time_to_samples(m_length - m_position, p_chunk.get_sample_rate());
328  if (max == 0)
329  {//handle rounding accidents, this normally shouldn't trigger
330  m_position = m_length;
331  return false;
332  }
333 
334  t_size samples = p_chunk.get_sample_count();
335  if ((t_uint64)samples > max)
336  {
337  p_chunk.set_sample_count((unsigned)max);
338  if (p_raw != NULL) {
339  const t_size rawSize = p_raw->get_size();
340  PFC_ASSERT( rawSize % samples == 0 );
341  p_raw->set_size( (t_size) ( (t_uint64) rawSize * max / samples ) );
342  }
343  m_position = m_length;
344  }
345  else
346  {
347  m_position += p_chunk.get_duration();
348  }
349  return true;
350  }
351  else
352  {
353  if (!_m_input_run(p_chunk, p_raw, p_abort)) return false;
354  m_position += p_chunk.get_duration();
355  return true;
356  }
357 }
359  return _run(p_chunk, &p_raw, p_abort);
360 }
361 
363  return _run(p_chunk, NULL, p_abort);
364 }
365 
366 void input_helper_cue::seek(double p_seconds,abort_callback & p_abort)
367 {
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;
373  } else {
374  m_position = m_length;
375  }
376 }
377 
378 bool input_helper_cue::can_seek() {return true;}
379 
380 void input_helper_cue::set_full_buffer(t_filesize val) {m_input.set_full_buffer(val);}
381 
382 void input_helper_cue::on_idle(abort_callback & p_abort) {m_input.on_idle(p_abort);}
383 
384 bool input_helper_cue::get_dynamic_info(file_info & p_out,double & p_timestamp_delta) {
385  if (m_dynamic_info_trigger) {
386  m_dynamic_info_trigger = false;
387  return m_input.get_dynamic_info(p_out,p_timestamp_delta);
388  } else {
389  return false;
390  }
391 }
392 
393 bool input_helper_cue::get_dynamic_info_track(file_info & p_out,double & 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);
397  } else {
398  return false;
399  }
400 }
401 
402 const char * input_helper_cue::get_path() const {return m_input.get_path();}
403 
404 void input_helper_cue::get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) {m_input.get_info(p_subsong,p_info,p_abort);}
405 
406 
407 
408 
409 
410 
411 // openAudioData code
412 
413 namespace {
414 
415  class file_decodedaudio : public file_readonly {
416  public:
417  void init(const playable_location & loc, bool bSeekable, file::ptr fileHint, abort_callback & aborter) {
418  m_length = -1; m_lengthKnown = false;
419  m_subsong = loc.get_subsong();
420  input_entry::g_open_for_decoding(m_decoder, fileHint, loc.get_path(), aborter);
421  m_seekable = bSeekable && m_decoder->can_seek();
422  reopenDecoder(aborter);
423  readChunk(aborter, true);
424  }
425 
426  void reopen(abort_callback & aborter) {
427 
428  // Have valid chunk and it is the first chunk in the stream? Reset read pointers and bail, no need to reopen
429  if (m_chunk.get_sample_count() > 0 && m_chunkBytesPtr == m_currentPosition) {
430  m_currentPosition = 0;
431  m_chunkBytesPtr = 0;
432  m_eof = false;
433  return;
434  }
435 
436  reopenDecoder(aborter);
437  readChunk(aborter);
438  }
439 
440  bool is_remote() {
441  return false;
442  }
443 #if FOOBAR2000_TARGET_VERSION >= 2000
444  t_filestats get_stats(abort_callback & aborter) {
445  t_filestats fs = m_decoder->get_file_stats(aborter);
446  fs.m_size = get_size(aborter);
447  return fs;
448  }
449 #else
450  t_filetimestamp get_timestamp(abort_callback & p_abort) {
451  return m_decoder->get_file_stats(p_abort).m_timestamp;
452  }
453 #endif
454  void on_idle(abort_callback & p_abort) {
455  m_decoder->on_idle(p_abort);
456  }
457  bool get_content_type(pfc::string_base & p_out) {
458  return false;
459  }
460  bool can_seek() {
461  return m_seekable;
462  }
463  void seek(t_filesize p_position, abort_callback & p_abort) {
464  if (!m_seekable) throw exception_io_object_not_seekable();
465 
466 
467  {
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;
473  m_eof = false;
474  return;
475  }
476  }
477 
478  {
479  t_filesize s = get_size(p_abort);
480  if (s != filesize_invalid) {
481  if (p_position > s) throw exception_io_seek_out_of_range();
482  if (p_position == s) {
483  m_chunk.reset();
484  m_chunkBytesPtr = 0;
485  m_currentPosition = p_position;
486  m_eof = true;
487  return;
488  }
489  }
490  }
491 
492 
493 
494  const size_t row = m_spec.chanCount * sizeof(audio_sample);
495  t_filesize samples = p_position / row;
496  const double seekTime = audio_math::samples_to_time(samples, m_spec.sampleRate);
497  m_decoder->seek(seekTime, p_abort);
498  m_eof = false; // do this before readChunk
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));
501  }
502  m_chunkBytesPtr = p_position % row;
503  if (m_chunkBytesPtr > curChunkBytes()) {
504  // Should not ever happen
505  m_chunkBytesPtr = 0;
506  throw std::runtime_error("Decoder returned invalid data");
507  }
508 
509  m_currentPosition = p_position;
510  m_eof = false;
511  }
512 
513  t_filesize get_size(abort_callback & aborter) {
514  const double l = length(aborter);
515  if (l <= 0) return filesize_invalid;
516  return audio_math::time_to_samples(l, m_spec.sampleRate) * m_spec.chanCount * sizeof(audio_sample);
517  }
518  t_filesize get_position(abort_callback & p_abort) {
519  return m_currentPosition;
520  }
521  t_size read(void * p_buffer, t_size p_bytes, abort_callback & p_abort) {
522  size_t done = 0;
523  for (;;) {
524  p_abort.check();
525  {
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;
531  done += delta;
532  m_currentPosition += delta;
533 
534  if (done == p_bytes) break;
535  }
536  if (!readChunk(p_abort)) break;
537  }
538  return done;
539  }
540  audio_chunk::spec_t const & get_spec() const { return m_spec; }
541  private:
542  void reopenDecoder(abort_callback & aborter) {
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);
546  m_eof = false;
547  m_currentPosition = 0;
548  }
549  size_t curChunkBytes() const {
550  return m_chunk.get_used_size() * sizeof(audio_sample);
551  }
552  bool readChunk(abort_callback & aborter, bool initial = false) {
553  m_chunkBytesPtr = 0;
554  for (;;) {
555  if (m_eof || !m_decoder->run(m_chunk, aborter)) {
556  if (initial) throw std::runtime_error("Decoder produced no data");
557  m_eof = true;
558  m_chunk.reset();
559  return false;
560  }
561  if (m_chunk.is_valid()) break;
562  }
563  audio_chunk::spec_t spec = m_chunk.get_spec();
564  if (initial) m_spec = spec;
565  else if (m_spec != spec) throw std::runtime_error("Sample format change in mid stream");
566  return true;
567  }
568  double length(abort_callback & aborter) {
569  if (!m_lengthKnown) {
570  file_info_impl temp;
571  m_decoder->get_info(m_subsong, temp, aborter);
572  m_length = temp.get_length();
573  m_lengthKnown = true;
574  }
575  return m_length;
576  }
577  audio_chunk_fast_impl m_chunk;
578  size_t m_chunkBytesPtr;
579  audio_chunk::spec_t m_spec;
580  double m_length;
581  bool m_lengthKnown;
582  bool m_seekable;
583  uint32_t m_subsong;
584  input_decoder::ptr m_decoder;
585  bool m_eof;
586  t_filesize m_currentPosition;
587  };
588 
589 }
590 
591 openAudioData_t openAudioData(playable_location const & loc, bool bSeekable, file::ptr fileHint, abort_callback & aborter) {
593  f->init(loc, bSeekable, fileHint, aborter);
594 
595  openAudioData_t oad = {};
596  oad.audioData = f;
597  oad.audioSpec = f->get_spec();
598  return oad;
599 }
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.
Definition: audio_chunk.h:242
void open(service_ptr_t< file > p_filehint, const playable_location &p_location, unsigned p_flags, abort_callback &p_abort, double p_start, double p_length)
static void _input_helper_io_filter_fullbuffer(service_ptr_t< file > &p_file, const char *p_path, t_filesize arg, abort_callback &p_abort)
Template implementing reference-counting features of service_base. Intended for dynamic instantiation...
Definition: service_impl.h:4
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...
uint64_t t_uint64
Definition: int_types.h:3
bool is_empty() const
Definition: service.h:120
T * get_ptr() const
Definition: service.h:117
pfc::eventHandle_t abort_callback_event
Definition: abort_callback.h:8
bool _run(audio_chunk &p_chunk, mem_block_container *p_raw, abort_callback &p_abort)
static void g_get_info(const playable_location &p_location, file_info &p_info, abort_callback &p_abort, bool p_from_redirect=false)
unsigned get_sample_rate() const
Helper, same as get_srate().
Definition: audio_chunk.h:103
static void g_set_info(const playable_location &p_location, file_info &p_info, abort_callback &p_abort, bool p_from_redirect=false)
bool need_file_reopen(const char *newPath) const
void get_info_check(const playable_location &p_location, file_info &p_info, t_filestats &p_stats, bool &p_reloaded, abort_callback &p_abort)
void set_pause(bool state)
pfc::string8 m_path
Definition: input_helpers.h:64
Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation.
Definition: audio_chunk.h:5
static const t_filesize filesize_invalid
Invalid/unknown file size constant. Also see: t_filesize.
Definition: filesystem.h:16
virtual const char * get_path() const =0
Usage: console::formatter() << "blah " << somenumber << " asdf" << somestring;.
Definition: console.h:17
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)
Definition: input.cpp:189
bool run(audio_chunk &p_chunk, abort_callback &p_abort)
void set_block_buffer(size_t val)
bool flush_on_pause()
bool is_valid() const
Definition: service.h:119
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)
Definition: input.cpp:175
void seek(double seconds, abort_callback &p_abort)
_input_helper_io_filter m_ioFilter
Definition: input_helpers.h:65
virtual void set(t_size n, bool val)=0
Main interface class for information about some playable object.
Definition: file_info.h:73
file::ptr audioData
bool get_dynamic_info_track(file_info &p_out, double &p_timestamp_delta)
bool run_raw(audio_chunk &p_chunk, mem_block_container &p_raw, abort_callback &p_abort)
void on_idle(abort_callback &p_abort)
event_logger::ptr m_logger
Definition: input_helpers.h:12
openAudioData_t openAudioData(playable_location const &loc, bool bSeekable, file::ptr fileHint, abort_callback &aborter)
Opens the specified location as a stream of audio_samples. Returns a file object that allows you to ...
size_t t_size
Definition: int_types.h:48
t_size add_item(const T &item)
Definition: list.h:522
virtual t_size get_count() const =0
void init_from_list(const list_base_const_t< metadb_handle_ptr > &p_list)
void release()
Definition: service.h:109
void process_fullbuffer(service_ptr_t< file > &p_file, const char *p_path, abort_callback &p_abort)
void open(service_ptr_t< file > p_filehint, metadb_handle_ptr p_location, unsigned p_flags, abort_callback &p_abort, bool p_from_redirect=false, bool p_skip_hints=false)
t_filesize m_ioFilterArg
Definition: input_helpers.h:66
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.
Definition: bit_array.h:40
bool open_path(file::ptr p_filehint, const char *path, abort_callback &p_abort, bool p_from_redirect, bool p_skip_hints)
Multilevel open helpers.
static int path_compare(const char *p1, const char *p2)
Definition: metadb.h:245
static bool g_should_reload(const t_filestats &p_old_stats, const t_filestats &p_new_stats, bool p_fresh)
void seek(double seconds, abort_callback &p_abort)
bool _m_input_run(audio_chunk &p_chunk, mem_block_container *p_raw, abort_callback &p_abort)
void set_full_buffer(t_filesize val)
const char * get_path() const
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...
Definition: filesystem.h:12
float audio_sample
Definition: audio_sample.h:6
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)
Definition: input.cpp:160
bool run(const pfc::list_base_const_t< metadb_handle_ptr > &p_list, bit_array_var &p_mask)
bool get_dynamic_info(file_info &p_out, double &p_timestamp_delta)
t_uint64 t_filesize
Type used for file size related variables.
Definition: filesystem.h:8
t_size bsearch_by_pointer(const metadb_handle_ptr &val) const
const char * get_path() const
Retrieves path of currently open file.
void get_info(t_uint32 p_subsong, file_info &p_info, abort_callback &p_abort)
Retrieves info about specific subsong of currently open file.
bool get_dynamic_info_track(file_info &p_out, double &p_timestamp_delta)
openAudioData return value, see openAudioData()
void set_logger(event_logger::ptr ptr)
void on_idle(abort_callback &p_abort)
Implements file_info.
Generic interface for a memory block; used by various other interfaces to return memory blocks while ...
bool run_raw(audio_chunk &p_chunk, mem_block_container &p_raw, abort_callback &p_abort)
service_ptr_t< input_decoder > m_input
Definition: input_helpers.h:63
Helper template used to easily access core services. Usage: static_api_ptr_t<myclass> api; api->doso...
Definition: service.h:533
bool get_dynamic_info(file_info &p_out, double &p_timestamp_delta)
void open_decoding(t_uint32 subsong, t_uint32 flags, abort_callback &p_abort)
Multilevel open helpers.
static bool g_mark_dead(const pfc::list_base_const_t< metadb_handle_ptr > &p_list, bit_array_var &p_mask, abort_callback &p_abort)
double get_duration() const
Retrieves duration of contained audio data, in seconds.
Definition: audio_chunk.h:116
file::ptr open(const char *path, abort_callback &abort, file::ptr hint, t_filesize sizeMax=1024 *1024 *256)
Definition: fullFileBuffer.h:9
void get_info(const playable_location &p_location, file_info &p_info, t_filestats &p_stats, abort_callback &p_abort)
static void _input_helper_io_filter_blockbuffer(service_ptr_t< file > &p_file, const char *p_path, t_filesize arg, abort_callback &p_abort)
void open(const char *p_path, abort_callback &p_abort)
audio_chunk::spec_t audioSpec
void set_full_buffer(t_filesize val)
bool run(audio_chunk &p_chunk, abort_callback &p_abort)
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
uint32_t t_uint32
Definition: int_types.h:5
void get_info(t_uint32 p_subsong, file_info &p_info, abort_callback &p_abort)