foobar2000 SDK  2015-01-14
file_info.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
3 #ifndef _MSC_VER
4 #define strcat_s strcat
5 #define _atoi64 atoll
6 #endif
7 
8 t_size file_info::meta_find_ex(const char * p_name,t_size p_name_length) const
9 {
10  t_size n, m = meta_get_count();
11  for(n=0;n<m;n++)
12  {
13  if (pfc::stricmp_ascii_ex(meta_enum_name(n),pfc_infinite,p_name,p_name_length) == 0) return n;
14  }
15  return pfc_infinite;
16 }
17 
18 bool file_info::meta_exists_ex(const char * p_name,t_size p_name_length) const
19 {
20  return meta_find_ex(p_name,p_name_length) != pfc_infinite;
21 }
22 
23 void file_info::meta_remove_field_ex(const char * p_name,t_size p_name_length)
24 {
25  t_size index = meta_find_ex(p_name,p_name_length);
26  if (index!=pfc_infinite) meta_remove_index(index);
27 }
28 
29 
31 {
33 }
34 
36 {
38 }
39 
41 {
42  meta_remove_values(p_index,bit_array_one(p_value));
43 }
44 
45 t_size file_info::meta_get_count_by_name_ex(const char * p_name,t_size p_name_length) const
46 {
47  t_size index = meta_find_ex(p_name,p_name_length);
48  if (index == pfc_infinite) return 0;
49  return meta_enum_value_count(index);
50 }
51 
52 t_size file_info::info_find_ex(const char * p_name,t_size p_name_length) const
53 {
54  t_size n, m = info_get_count();
55  for(n=0;n<m;n++) {
56  if (pfc::stricmp_ascii_ex(info_enum_name(n),pfc_infinite,p_name,p_name_length) == 0) return n;
57  }
58  return pfc_infinite;
59 }
60 
61 bool file_info::info_exists_ex(const char * p_name,t_size p_name_length) const
62 {
63  return info_find_ex(p_name,p_name_length) != pfc_infinite;
64 }
65 
67 {
69 }
70 
72 {
74 }
75 
76 bool file_info::info_remove_ex(const char * p_name,t_size p_name_length)
77 {
78  t_size index = info_find_ex(p_name,p_name_length);
79  if (index != pfc_infinite)
80  {
81  info_remove_index(index);
82  return true;
83  }
84  else return false;
85 }
86 
87 void file_info::overwrite_meta(const file_info & p_source) {
88  const t_size total = p_source.meta_get_count();
89  for(t_size walk = 0; walk < total; ++walk) {
90  copy_meta_single(p_source, walk);
91  }
92 }
93 
94 void file_info::copy_meta_single(const file_info & p_source,t_size p_index)
95 {
96  copy_meta_single_rename(p_source,p_index,p_source.meta_enum_name(p_index));
97 }
98 
100 {
101  const char * name = p_source.meta_enum_name(p_index);
102  t_size n, m = p_source.meta_enum_value_count(p_index);
103  t_size new_index = pfc_infinite;
104  for(n=0;n<m;n++)
105  {
106  const char * value = p_source.meta_enum_value(p_index,n);
107  if (n == 0) new_index = meta_set_nocheck(name,value);
108  else meta_add_value(new_index,value);
109  }
110 }
111 
112 void file_info::copy_meta_single_by_name_ex(const file_info & p_source,const char * p_name,t_size p_name_length)
113 {
114  t_size index = p_source.meta_find_ex(p_name,p_name_length);
115  if (index != pfc_infinite) copy_meta_single(p_source,index);
116 }
117 
118 void file_info::copy_info_single_by_name_ex(const file_info & p_source,const char * p_name,t_size p_name_length)
119 {
120  t_size index = p_source.info_find_ex(p_name,p_name_length);
121  if (index != pfc_infinite) copy_info_single(p_source,index);
122 }
123 
124 void file_info::copy_meta_single_by_name_nocheck_ex(const file_info & p_source,const char * p_name,t_size p_name_length)
125 {
126  t_size index = p_source.meta_find_ex(p_name,p_name_length);
127  if (index != pfc_infinite) copy_meta_single_nocheck(p_source,index);
128 }
129 
130 void file_info::copy_info_single_by_name_nocheck_ex(const file_info & p_source,const char * p_name,t_size p_name_length)
131 {
132  t_size index = p_source.info_find_ex(p_name,p_name_length);
133  if (index != pfc_infinite) copy_info_single_nocheck(p_source,index);
134 }
135 
136 void file_info::copy_info_single(const file_info & p_source,t_size p_index)
137 {
138  info_set(p_source.info_enum_name(p_index),p_source.info_enum_value(p_index));
139 }
140 
142 {
143  info_set_nocheck(p_source.info_enum_name(p_index),p_source.info_enum_value(p_index));
144 }
145 
146 void file_info::copy_meta(const file_info & p_source)
147 {
148  if (&p_source != this) {
149  meta_remove_all();
150  t_size n, m = p_source.meta_get_count();
151  for(n=0;n<m;n++)
152  copy_meta_single_nocheck(p_source,n);
153  }
154 }
155 
156 void file_info::copy_info(const file_info & p_source)
157 {
158  if (&p_source != this) {
159  info_remove_all();
160  t_size n, m = p_source.info_get_count();
161  for(n=0;n<m;n++)
162  copy_info_single_nocheck(p_source,n);
163  }
164 }
165 
166 void file_info::copy(const file_info & p_source)
167 {
168  if (&p_source != this) {
169  copy_meta(p_source);
170  copy_info(p_source);
171  set_length(p_source.get_length());
172  set_replaygain(p_source.get_replaygain());
173  }
174 }
175 
176 
177 const char * file_info::meta_get_ex(const char * p_name,t_size p_name_length,t_size p_index) const
178 {
179  t_size index = meta_find_ex(p_name,p_name_length);
180  if (index == pfc_infinite) return 0;
181  t_size max = meta_enum_value_count(index);
182  if (p_index >= max) return 0;
183  return meta_enum_value(index,p_index);
184 }
185 
186 const char * file_info::info_get_ex(const char * p_name,t_size p_name_length) const
187 {
188  t_size index = info_find_ex(p_name,p_name_length);
189  if (index == pfc_infinite) return 0;
190  return info_enum_value(index);
191 }
192 
193 t_int64 file_info::info_get_int(const char * name) const
194 {
195  PFC_ASSERT(pfc::is_valid_utf8(name));
196  const char * val = info_get(name);
197  if (val==0) return 0;
198  return _atoi64(val);
199 }
200 
202 {
203  t_int64 ret = 0;
204  double len = get_length();
205  t_int64 srate = info_get_int("samplerate");
206 
207  if (srate>0 && len>0)
208  {
209  ret = audio_math::time_to_samples(len,(unsigned)srate);
210  }
211  return ret;
212 }
213 
214 double file_info::info_get_float(const char * name) const
215 {
216  const char * ptr = info_get(name);
217  if (ptr) return pfc::string_to_float(ptr);
218  else return 0;
219 }
220 
221 void file_info::info_set_int(const char * name,t_int64 value)
222 {
223  PFC_ASSERT(pfc::is_valid_utf8(name));
224  info_set(name,pfc::format_int(value));
225 }
226 
227 void file_info::info_set_float(const char * name,double value,unsigned precision,bool force_sign,const char * unit)
228 {
229  PFC_ASSERT(pfc::is_valid_utf8(name));
230  PFC_ASSERT(unit==0 || strlen(unit) <= 64);
231  char temp[128];
232  pfc::float_to_string(temp,64,value,precision,force_sign);
233  temp[63] = 0;
234  if (unit)
235  {
236  strcat_s(temp," ");
237  strcat_s(temp,unit);
238  }
239  info_set(name,temp);
240 }
241 
242 
244 {
246  temp.m_album_gain = value;
247  set_replaygain(temp);
248 }
249 
251 {
253  temp.m_album_peak = value;
254  set_replaygain(temp);
255 }
256 
258 {
260  temp.m_track_gain = value;
261  set_replaygain(temp);
262 }
263 
265 {
267  temp.m_track_peak = value;
268  set_replaygain(temp);
269 }
270 
271 
272 static bool is_valid_bps(t_int64 val)
273 {
274  return val>0 && val<=256;
275 }
276 
278 {
279  t_int64 val = info_get_int("decoded_bitspersample");
280  if (is_valid_bps(val)) return (unsigned)val;
281  val = info_get_int("bitspersample");
282  if (is_valid_bps(val)) return (unsigned)val;
283  return 0;
284 
285 }
286 
288 {
289  info_remove_all();
290  meta_remove_all();
291  set_length(0);
293 }
294 
296 {
297  replaygain_info temp;
298  temp.reset();
299  set_replaygain(temp);
300 }
301 
302 void file_info::copy_meta_single_rename_ex(const file_info & p_source,t_size p_index,const char * p_new_name,t_size p_new_name_length)
303 {
304  t_size n, m = p_source.meta_enum_value_count(p_index);
305  t_size new_index = pfc_infinite;
306  for(n=0;n<m;n++)
307  {
308  const char * value = p_source.meta_enum_value(p_index,n);
309  if (n == 0) new_index = meta_set_ex(p_new_name,p_new_name_length,value,pfc_infinite);
310  else meta_add_value(new_index,value);
311  }
312 }
313 
314 t_size file_info::meta_add_ex(const char * p_name,t_size p_name_length,const char * p_value,t_size p_value_length)
315 {
316  t_size index = meta_find_ex(p_name,p_name_length);
317  if (index == pfc_infinite) return meta_set_nocheck_ex(p_name,p_name_length,p_value,p_value_length);
318  else
319  {
320  meta_add_value_ex(index,p_value,p_value_length);
321  return index;
322  }
323 }
324 
325 void file_info::meta_add_value_ex(t_size p_index,const char * p_value,t_size p_value_length)
326 {
327  meta_insert_value_ex(p_index,meta_enum_value_count(p_index),p_value,p_value_length);
328 }
329 
330 
332 {
333  t_size n, m = meta_get_count(), ret = 0;
334  for(n=0;n<m;n++) ret += meta_enum_value_count(n);
335  return ret;
336 }
337 
338 bool file_info::info_set_replaygain_ex(const char * p_name,t_size p_name_len,const char * p_value,t_size p_value_len)
339 {
341  if (temp.set_from_meta_ex(p_name,p_name_len,p_value,p_value_len))
342  {
343  set_replaygain(temp);
344  return true;
345  }
346  else return false;
347 }
348 
349 void file_info::info_set_replaygain_auto_ex(const char * p_name,t_size p_name_len,const char * p_value,t_size p_value_len)
350 {
351  if (!info_set_replaygain_ex(p_name,p_name_len,p_value,p_value_len))
352  info_set_ex(p_name,p_name_len,p_value,p_value_len);
353 }
354 
356 {
357  return item1.m_album_gain == item2.m_album_gain &&
358  item1.m_track_gain == item2.m_track_gain &&
359  item1.m_album_peak == item2.m_album_peak &&
360  item1.m_track_peak == item2.m_track_peak;
361 }
362 
364 {
365  const t_size count = meta_enum_value_count(p_index1);
366  if (count != meta_enum_value_count(p_index2)) return false;
367  t_size n;
368  for(n=0;n<count;n++)
369  {
370  if (strcmp(meta_enum_value(p_index1,n),meta_enum_value(p_index2,n))) return false;
371  }
372  return true;
373 }
374 
375 
376 void file_info::meta_format_entry(t_size index, pfc::string_base & out, const char * separator) const {
377  out.reset();
378  t_size val, count = meta_enum_value_count(index);
379  PFC_ASSERT( count > 0);
380  for(val=0;val<count;val++)
381  {
382  if (val > 0) out += separator;
383  out += meta_enum_value(index,val);
384  }
385 }
386 
387 bool file_info::meta_format(const char * p_name,pfc::string_base & p_out, const char * separator) const {
388  p_out.reset();
389  t_size index = meta_find(p_name);
390  if (index == pfc_infinite) return false;
391  meta_format_entry(index, p_out, separator);
392  return true;
393 }
394 
395 void file_info::info_calculate_bitrate(t_filesize p_filesize,double p_length)
396 {
397  if (p_filesize > 0 && p_length > 0) info_set_bitrate((unsigned)floor((double)p_filesize * 8 / (p_length * 1000) + 0.5));
398 }
399 
401  const char * encoding = info_get("encoding");
402  if (encoding != NULL) {
403  if (pfc::stricmp_ascii(encoding,"lossy") == 0 /*|| pfc::stricmp_ascii(encoding,"hybrid") == 0*/) return true;
404  } else {
405  //the old way
406  //disabled: don't whine if we're not sure what we're dealing with - might be a file with info not-yet-loaded in oddball cases or a mod file
407  //if (info_get("bitspersample") == NULL) return true;
408  }
409  return false;
410 }
411 
412 bool file_info::g_is_meta_equal(const file_info & p_item1,const file_info & p_item2) {
413  const t_size count = p_item1.meta_get_count();
414  if (count != p_item2.meta_get_count()) {
415  //uDebugLog() << "meta count mismatch";
416  return false;
417  }
419  for(t_size n=0; n<count; n++) {
420  item2_meta_map.set(p_item2.meta_enum_name(n),n);
421  }
422  for(t_size n1=0; n1<count; n1++) {
423  t_size n2;
424  if (!item2_meta_map.query(p_item1.meta_enum_name(n1),n2)) {
425  //uDebugLog() << "item2 doesn't have " << p_item1.meta_enum_name(n1);
426  return false;
427  }
428  t_size value_count = p_item1.meta_enum_value_count(n1);
429  if (value_count != p_item2.meta_enum_value_count(n2)) {
430  //uDebugLog() << "meta value count mismatch: " << p_item1.meta_enum_name(n1) << " : " << value_count << " vs " << p_item2.meta_enum_value_count(n2);
431  return false;
432  }
433  for(t_size v = 0; v < value_count; v++) {
434  if (strcmp(p_item1.meta_enum_value(n1,v),p_item2.meta_enum_value(n2,v)) != 0) {
435  //uDebugLog() << "meta mismatch: " << p_item1.meta_enum_name(n1) << " : " << p_item1.meta_enum_value(n1,v) << " vs " << p_item2.meta_enum_value(n2,v);
436  return false;
437  }
438  }
439  }
440  return true;
441 }
442 
443 bool file_info::g_is_meta_equal_debug(const file_info & p_item1,const file_info & p_item2) {
444  const t_size count = p_item1.meta_get_count();
445  if (count != p_item2.meta_get_count()) {
446  FB2K_DebugLog() << "meta count mismatch";
447  return false;
448  }
450  for(t_size n=0; n<count; n++) {
451  item2_meta_map.set(p_item2.meta_enum_name(n),n);
452  }
453  for(t_size n1=0; n1<count; n1++) {
454  t_size n2;
455  if (!item2_meta_map.query(p_item1.meta_enum_name(n1),n2)) {
456  FB2K_DebugLog() << "item2 doesn't have " << p_item1.meta_enum_name(n1);
457  return false;
458  }
459  t_size value_count = p_item1.meta_enum_value_count(n1);
460  if (value_count != p_item2.meta_enum_value_count(n2)) {
461  FB2K_DebugLog() << "meta value count mismatch: " << p_item1.meta_enum_name(n1) << " : " << (uint32_t)value_count << " vs " << (uint32_t)p_item2.meta_enum_value_count(n2);
462  return false;
463  }
464  for(t_size v = 0; v < value_count; v++) {
465  if (strcmp(p_item1.meta_enum_value(n1,v),p_item2.meta_enum_value(n2,v)) != 0) {
466  FB2K_DebugLog() << "meta mismatch: " << p_item1.meta_enum_name(n1) << " : " << p_item1.meta_enum_value(n1,v) << " vs " << p_item2.meta_enum_value(n2,v);
467  return false;
468  }
469  }
470  }
471  return true;
472 }
473 
474 bool file_info::g_is_info_equal(const file_info & p_item1,const file_info & p_item2) {
475  t_size count = p_item1.info_get_count();
476  if (count != p_item2.info_get_count()) {
477  //uDebugLog() << "info count mismatch";
478  return false;
479  }
480  for(t_size n1=0; n1<count; n1++) {
481  t_size n2 = p_item2.info_find(p_item1.info_enum_name(n1));
482  if (n2 == pfc_infinite) {
483  //uDebugLog() << "item2 does not have " << p_item1.info_enum_name(n1);
484  return false;
485  }
486  if (strcmp(p_item1.info_enum_value(n1),p_item2.info_enum_value(n2)) != 0) {
487  //uDebugLog() << "value mismatch: " << p_item1.info_enum_name(n1);
488  return false;
489  }
490  }
491  return true;
492 }
493 
494 static bool is_valid_field_name_char(char p_char) {
495  return p_char >= 32 && p_char < 127 && p_char != '=' && p_char != '%' && p_char != '<' && p_char != '>';
496 }
497 
498 bool file_info::g_is_valid_field_name(const char * p_name,t_size p_length) {
499  t_size walk;
500  for(walk = 0; walk < p_length && p_name[walk] != 0; walk++) {
501  if (!is_valid_field_name_char(p_name[walk])) return false;
502  }
503  return walk > 0;
504 }
505 
506 void file_info::to_formatter(pfc::string_formatter& out) const {
507  out << "File info dump:\n";
508  if (get_length() > 0) out<< "Duration: " << pfc::format_time_ex(get_length(), 6) << "\n";
509  pfc::string_formatter temp;
510  for(t_size metaWalk = 0; metaWalk < meta_get_count(); ++metaWalk) {
511  meta_format_entry(metaWalk, temp);
512  out << "Meta: " << meta_enum_name(metaWalk) << " = " << temp << "\n";
513  }
514  for(t_size infoWalk = 0; infoWalk < info_get_count(); ++infoWalk) {
515  out << "Info: " << info_enum_name(infoWalk) << " = " << info_enum_value(infoWalk) << "\n";
516  }
517 }
518 
519 void file_info::to_console() const {
520  FB2K_console_formatter() << "File info dump:";
521  if (get_length() > 0) FB2K_console_formatter() << "Duration: " << pfc::format_time_ex(get_length(), 6);
522  pfc::string_formatter temp;
523  for(t_size metaWalk = 0; metaWalk < meta_get_count(); ++metaWalk) {
524  meta_format_entry(metaWalk, temp);
525  FB2K_console_formatter() << "Meta: " << meta_enum_name(metaWalk) << " = " << temp;
526  }
527  for(t_size infoWalk = 0; infoWalk < info_get_count(); ++infoWalk) {
528  FB2K_console_formatter() << "Info: " << info_enum_name(infoWalk) << " = " << info_enum_value(infoWalk);
529  }
530 }
531 
532 void file_info::info_set_wfx_chanMask(uint32_t val) {
533  switch(val) {
534  case 0:
535  case 4:
536  case 3:
537  break;
538  default:
539  info_set ("WAVEFORMATEXTENSIBLE_CHANNEL_MASK", PFC_string_formatter() << "0x" << pfc::format_hex(val) );
540  break;
541  }
542 }
543 
544 uint32_t file_info::info_get_wfx_chanMask() const {
545  const char * str = this->info_get("WAVEFORMATEXTENSIBLE_CHANNEL_MASK");
546  if (str == NULL) return 0;
547  if (pfc::strcmp_partial( str, "0x") != 0) return 0;
548  try {
549  return pfc::atohex<uint32_t>( str + 2, strlen(str+2) );
550  } catch(...) { return 0;}
551 }
552 
553 bool file_info::field_is_person(const char * fieldName) {
554  return field_name_equals(fieldName, "artist") ||
555  field_name_equals(fieldName, "album artist") ||
556  field_name_equals(fieldName, "composer") ||
557  field_name_equals(fieldName, "performer") ||
558  field_name_equals(fieldName, "conductor") ||
559  field_name_equals(fieldName, "orchestra") ||
560  field_name_equals(fieldName, "ensemble") ||
561  field_name_equals(fieldName, "engineer");
562 }
563 
564 bool file_info::field_is_title(const char * fieldName) {
565  return field_name_equals(fieldName, "title") || field_name_equals(fieldName, "album");
566 }
567 
568 
569 void file_info::to_stream( stream_writer * stream, abort_callback & abort ) const {
570  stream_writer_formatter<> out(* stream, abort );
571 
572  out << this->get_length();
573 
574  {
575  const auto rg = this->get_replaygain();
576  out << rg.m_track_gain << rg.m_album_gain << rg.m_track_peak << rg.m_album_peak;
577  }
578 
579 
580  {
581  const uint32_t metaCount = pfc::downcast_guarded<uint32_t>( this->meta_get_count() );
582  for(uint32_t metaWalk = 0; metaWalk < metaCount; ++metaWalk) {
583  const char * name = this->meta_enum_name( metaWalk );
584  if (*name) {
585  out.write_string_nullterm( this->meta_enum_name( metaWalk ) );
586  const size_t valCount = this->meta_enum_value_count( metaWalk );
587  for(size_t valWalk = 0; valWalk < valCount; ++valWalk) {
588  const char * value = this->meta_enum_value( metaWalk, valWalk );
589  if (*value) {
590  out.write_string_nullterm( value );
591  }
592  }
593  out.write_int<char>(0);
594  }
595  }
596  out.write_int<char>(0);
597  }
598 
599  {
600  const uint32_t infoCount = pfc::downcast_guarded<uint32_t>( this->info_get_count() );
601  for(uint32_t infoWalk = 0; infoWalk < infoCount; ++infoWalk) {
602  const char * name = this->info_enum_name( infoWalk );
603  const char * value = this->info_enum_value( infoWalk );
604  if (*name && *value) {
605  out.write_string_nullterm(name); out.write_string_nullterm(value);
606  }
607  }
608  out.write_int<char>(0);
609  }
610 }
611 
612 void file_info::from_stream( stream_reader * stream, abort_callback & abort ) {
613  stream_reader_formatter<> in( *stream, abort );
614  pfc::string_formatter tempName, tempValue;
615  {
616  double len; in >> len; this->set_length( len );
617  }
618  {
619  replaygain_info rg;
620  in >> rg.m_track_gain >> rg.m_album_gain >> rg.m_track_peak >> rg.m_album_peak;
621  }
622 
623  {
624  this->meta_remove_all();
625  for(;;) {
626  in.read_string_nullterm( tempName );
627  if (tempName.length() == 0) break;
628  size_t metaIndex = pfc_infinite;
629  for(;;) {
630  in.read_string_nullterm( tempValue );
631  if (tempValue.length() == 0) break;
632  if (metaIndex == pfc_infinite) metaIndex = this->meta_add( tempName, tempValue );
633  else this->meta_add_value( metaIndex, tempValue );
634  }
635  }
636  }
637  {
638  this->info_remove_all();
639  for(;;) {
640  in.read_string_nullterm( tempName );
641  if (tempName.length() == 0) break;
642  in.read_string_nullterm( tempValue );
643  this->info_set( tempName, tempValue );
644  }
645  }
646 }
647 
648 static const char * _readString( const uint8_t * & ptr, size_t & remaining ) {
649  const char * rv = (const char*)ptr;
650  for(;;) {
651  if (remaining == 0) throw exception_io_data();
652  uint8_t byte = *ptr++; --remaining;
653  if (byte == 0) break;
654  }
655  return rv;
656 }
657 
658 template<typename int_t> void _readInt( int_t & out, const uint8_t * &ptr, size_t & remaining) {
659  if (remaining < sizeof(out)) throw exception_io_data();
660  pfc::decode_little_endian( out, ptr ); ptr += sizeof(out); remaining -= sizeof(out);
661 }
662 
663 template<typename float_t> static void _readFloat(float_t & out, const uint8_t * &ptr, size_t & remaining) {
664  union {
665  typename pfc::sized_int_t<sizeof(float_t)>::t_unsigned i;
666  float_t f;
667  } u;
668  _readInt(u.i, ptr, remaining);
669  out = u.f;
670 }
671 
672 void file_info::from_mem( const void * memPtr, size_t memSize ) {
673  size_t remaining = memSize;
674  const uint8_t * walk = (const uint8_t*) memPtr;
675 
676  {
677  double len; _readFloat(len, walk, remaining);
678  this->set_length( len );
679  }
680 
681  {
682  replaygain_info rg;
683  _readFloat(rg.m_track_gain, walk, remaining );
684  _readFloat(rg.m_album_gain, walk, remaining );
685  _readFloat(rg.m_track_peak, walk, remaining );
686  _readFloat(rg.m_album_peak, walk, remaining );
687  this->set_replaygain( rg );
688  }
689 
690  {
691  this->meta_remove_all();
692  for(;;) {
693  const char * metaName = _readString( walk, remaining );
694  if (*metaName == 0) break;
695  size_t metaIndex = pfc_infinite;
696  for(;;) {
697  const char * metaValue = _readString( walk, remaining );
698  if (*metaValue == 0) break;
699  if (metaIndex == pfc_infinite) metaIndex = this->meta_add( metaName, metaValue );
700  else this->meta_add_value( metaIndex, metaName );
701  }
702  }
703  }
704  {
705  this->info_remove_all();
706  for(;;) {
707  const char * infoName = _readString( walk, remaining );
708  if (*infoName == 0) break;
709  const char * infoValue = _readString( walk, remaining );
710  this->info_set( infoName, infoValue );
711  }
712  }
713 }
714 
715 audio_chunk::spec_t file_info::audio_chunk_spec() const
716 {
717  audio_chunk::spec_t rv = {};
718  rv.sampleRate = (uint32_t)this->info_get_int("samplerate");
719  rv.chanCount = (uint32_t)this->info_get_int("channels");
720  rv.chanMask = (uint32_t)this->info_get_wfx_chanMask();
721  if (audio_chunk::g_count_channels( rv.chanMask ) != rv.chanCount ) {
722  rv.chanMask = audio_chunk::g_guess_channel_config( rv.chanCount );
723  }
724  return rv;
725 }
void info_set_bitrate(t_int64 val)
Definition: file_info.h:206
virtual t_size meta_set_nocheck_ex(const char *p_name, t_size p_name_length, const char *p_value, t_size p_value_length)=0
unsigned info_get_decoded_bps() const
Definition: file_info.cpp:277
Definition: map.h:16
void copy_meta_single_rename(const file_info &p_source, t_size p_index, const char *p_new_name)
Definition: file_info.h:189
virtual double get_length() const =0
Retrieves audio duration, in seconds. Note that the reported duration should not be assumed to be th...
double info_get_float(const char *name) const
Definition: file_info.cpp:214
t_size meta_get_count_by_name_ex(const char *p_name, t_size p_name_length) const
Definition: file_info.cpp:45
void copy_info_single_by_name_ex(const file_info &p_source, const char *p_name, t_size p_name_length)
Definition: file_info.cpp:118
virtual t_size meta_set_ex(const char *p_name, t_size p_name_length, const char *p_value, t_size p_value_length)=0
Creates a new metadata entry of specified name with specified value. If an entry of same name already...
static bool g_is_info_equal(const file_info &p_item1, const file_info &p_item2)
Definition: file_info.cpp:474
void copy_meta_single_by_name_nocheck_ex(const file_info &p_source, const char *p_name, t_size p_name_length)
Definition: file_info.cpp:124
virtual void info_remove_mask(const bit_array &p_mask)=0
Removes technical info entries indicated by specified bit mask.
bool meta_exists_ex(const char *p_name, t_size p_name_length) const
Definition: file_info.cpp:18
virtual void meta_remove_mask(const bit_array &p_mask)=0
Removes metadata entries according to specified bit mask.
float m_track_gain
Definition: file_info.h:4
static bool g_is_meta_equal(const file_info &p_item1, const file_info &p_item2)
Definition: file_info.cpp:412
bool is_encoding_lossy() const
Definition: file_info.cpp:400
double string_to_float(const char *src, t_size max)
t_size meta_add_ex(const char *p_name, t_size p_name_length, const char *p_value, t_size p_value_length)
Definition: file_info.cpp:314
virtual void copy_meta(const file_info &p_source)
Copies metadata from specified file_info object.
Definition: file_info.cpp:146
const char * info_get_ex(const char *p_name, t_size p_name_length) const
Definition: file_info.cpp:186
void meta_remove_value(t_size p_index, t_size p_value)
Definition: file_info.cpp:40
float m_album_peak
Definition: file_info.h:5
virtual t_size meta_enum_value_count(t_size p_index) const =0
Retrieves count of values in metadata entry of specified index. The value is always equal to or great...
void info_remove_all()
Definition: file_info.cpp:71
const char * info_get(const char *p_name) const
Definition: file_info.h:171
void meta_remove_field_ex(const char *p_name, t_size p_name_length)
Definition: file_info.cpp:23
void meta_add_value_ex(t_size p_index, const char *p_value, t_size p_value_length)
Definition: file_info.cpp:325
int stricmp_ascii_ex(const char *const s1, t_size const len1, const char *const s2, t_size const len2)
virtual const char * info_enum_value(t_size p_index) const =0
Retrieves the value of specified technical info entry. Return value is a null-terminated UTF-8 encode...
void overwrite_meta(const file_info &p_source)
Definition: file_info.cpp:87
static bool g_equal(const replaygain_info &item1, const replaygain_info &item2)
Definition: file_info.cpp:355
virtual const char * meta_enum_value(t_size p_index, t_size p_value_number) const =0
Retrieves specified value from specified metadata entry. Return value is a null-terminated UTF-8 enco...
virtual void meta_insert_value_ex(t_size p_index, t_size p_value_index, const char *p_value, t_size p_value_length)=0
Inserts a new value into specified metadata entry.
void info_set_replaygain_album_gain(float value)
Definition: file_info.cpp:243
void meta_add_value(t_size p_index, const char *p_value)
Definition: file_info.h:159
Structure containing ReplayGain scan results from some playable object, also providing various helper...
Definition: file_info.h:2
static bool g_is_meta_equal_debug(const file_info &p_item1, const file_info &p_item2)
Definition: file_info.cpp:443
void info_set_int(const char *name, t_int64 value)
Definition: file_info.cpp:221
t_size meta_set_nocheck(const char *p_name, const char *p_value)
Definition: file_info.h:277
void meta_format_entry(t_size index, pfc::string_base &p_out, const char *separator=", ") const
Definition: file_info.cpp:376
bool info_remove_ex(const char *p_name, t_size p_name_length)
Definition: file_info.cpp:76
virtual t_size info_set_ex(const char *p_name, t_size p_name_length, const char *p_value, t_size p_value_length)=0
Creates a new technical info entry with specified name and specified value. If an entry of the same n...
Main interface class for information about some playable object.
Definition: file_info.h:73
const char * meta_get_ex(const char *p_name, t_size p_name_length, t_size p_index) const
Definition: file_info.cpp:177
virtual void copy(const file_info &p_source)
Copies entire file_info contents from specified file_info object.
Definition: file_info.cpp:166
size_t t_size
Definition: int_types.h:48
t_size info_set_nocheck(const char *p_name, const char *p_value)
Definition: file_info.h:278
void reset()
Definition: file_info.cpp:287
virtual t_size meta_get_count() const =0
Retrieves count of metadata entries.
void copy_info_single_nocheck(const file_info &p_source, t_size p_index)
Definition: file_info.cpp:141
virtual void copy_info(const file_info &p_source)
Copies technical info from specified file_info object.
Definition: file_info.cpp:156
virtual t_size info_find_ex(const char *p_name, t_size p_name_length) const
Finds technical info entry of specified name. Returns index of found entry on success, infinite on failure.
Definition: file_info.cpp:52
void copy_meta_single_by_name_ex(const file_info &p_source, const char *p_name, t_size p_name_length)
Definition: file_info.cpp:112
void meta_remove_index(t_size p_index)
Definition: file_info.cpp:30
void copy_meta_single_rename_ex(const file_info &p_source, t_size p_index, const char *p_new_name, t_size p_new_name_length)
Definition: file_info.cpp:302
t_size meta_calc_total_value_count() const
Definition: file_info.cpp:331
void copy_meta_single(const file_info &p_source, t_size p_index)
Definition: file_info.cpp:94
t_size info_set(const char *p_name, const char *p_value)
Definition: file_info.h:167
void info_set_replaygain_track_gain(float value)
Definition: file_info.cpp:257
virtual void set_replaygain(const replaygain_info &p_info)=0
Sets ReplayGain information.
static bool is_valid_field_name_char(char p_char)
Definition: file_info.cpp:494
virtual void meta_remove_values(t_size p_index, const bit_array &p_mask)=0
Removes values according to specified bit mask from specified metadata entry. If all values are remov...
t_int64 info_get_int(const char *name) const
Definition: file_info.cpp:193
t_int64 info_get_length_samples() const
Definition: file_info.cpp:201
void set(const _t_key &p_key, const _t_value &p_value)
Definition: map.h:22
void info_set_replaygain_album_peak(float value)
Definition: file_info.cpp:250
void copy_info_single(const file_info &p_source, t_size p_index)
Definition: file_info.cpp:136
virtual t_size meta_find_ex(const char *p_name, t_size p_name_length) const
Finds index of metadata entry of specified name. Returns infinite when not found. ...
Definition: file_info.cpp:8
t_size info_find(const char *p_name) const
Definition: file_info.h:168
void float_to_string(char *out, t_size out_max, double val, unsigned precision, bool b_sign)
bool is_valid_utf8(const char *param, t_size max=~0)
Definition: utf8.cpp:264
t_uint64 t_filesize
Type used for file size related variables.
Definition: filesystem.h:8
void meta_remove_all()
Definition: file_info.cpp:35
bool set_from_meta_ex(const char *p_name, t_size p_name_len, const char *p_value, t_size p_value_len)
int stricmp_ascii(const char *s1, const char *s2)
static bool is_valid_bps(t_int64 val)
Definition: file_info.cpp:272
float m_album_gain
Definition: file_info.h:4
void info_set_float(const char *name, double value, unsigned precision, bool force_sign=false, const char *unit=0)
Definition: file_info.cpp:227
void copy_meta_single_nocheck(const file_info &p_source, t_size p_index)
Definition: file_info.cpp:99
bool meta_format(const char *p_name, pfc::string_base &p_out, const char *separator=", ") const
Definition: file_info.cpp:387
bool info_set_replaygain_ex(const char *p_name, t_size p_name_len, const char *p_value, t_size p_value_len)
Definition: file_info.cpp:338
bool are_meta_fields_identical(t_size p_index1, t_size p_index2) const
Definition: file_info.cpp:363
void info_remove_index(t_size p_index)
Definition: file_info.cpp:66
virtual replaygain_info get_replaygain() const =0
Retrieves ReplayGain information.
void reset_replaygain()
Definition: file_info.cpp:295
void copy_info_single_by_name_nocheck_ex(const file_info &p_source, const char *p_name, t_size p_name_length)
Definition: file_info.cpp:130
void info_calculate_bitrate(t_filesize p_filesize, double p_length)
Definition: file_info.cpp:395
t_uint64 time_to_samples(double p_time, t_uint32 p_sample_rate)
Definition: audio_sample.h:33
float m_track_peak
Definition: file_info.h:5
void info_set_replaygain_track_peak(float value)
Definition: file_info.cpp:264
virtual const char * info_enum_name(t_size p_index) const =0
Retrieves the name of specified technical info entry. Return value is a null-terminated UTF-8 encoded...
void info_set_replaygain_auto_ex(const char *p_name, t_size p_name_len, const char *p_value, t_size p_value_len)
Definition: file_info.cpp:349
virtual void set_length(double p_length)=0
Sets audio duration, in seconds. Note that the reported duration should not be assumed to be the exa...
t_size meta_find(const char *p_name) const
Definition: file_info.h:154
bool info_exists_ex(const char *p_name, t_size p_name_length) const
Definition: file_info.cpp:61
virtual t_size info_get_count() const =0
Retrieves number of technical info entries.
int64_t t_int64
Definition: int_types.h:2
bool query(const _t_key &p_key, _t_value &p_value) const
Definition: map.h:44
virtual const char * meta_enum_name(t_size p_index) const =0
Retrieves the name of metadata entry of specified index. Return value is a null-terminated UTF-8 enco...