foobar2000 SDK  2015-01-14
tag_processor.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
4 {
5  write(p_file,p_info,flag_id3v1,p_abort);
6 }
7 
9 {
10  write(p_file,p_info,flag_apev2,p_abort);
11 }
12 
14 {
15  write(p_file,p_info,flag_id3v1|flag_apev2,p_abort);
16 }
17 
18 
19 
20 
21 enum {
22  g_flag_id3v1 = 1<<0,
23  g_flag_id3v2 = 1<<1,
24  g_flag_apev2 = 1<<2
25 };
26 
27 static void tagtype_list_append(pfc::string_base & p_out,const char * p_name)
28 {
29  if (!p_out.is_empty()) p_out += "|";
30  p_out += p_name;
31 }
32 
33 static void g_write_tags_ex(tag_write_callback & p_callback,unsigned p_flags,const service_ptr_t<file> & p_file,const file_info * p_info,abort_callback & p_abort) {
34  PFC_ASSERT( p_flags == 0 || p_info != 0 );
35 
36 
37  if (p_flags & (g_flag_id3v1 | g_flag_apev2)) {
38  switch(p_flags & (g_flag_id3v1 | g_flag_apev2)) {
41  break;
42  case g_flag_id3v1:
43  static_api_ptr_t<tag_processor_trailing>()->write_id3v1(p_file,*p_info,p_abort);
44  break;
45  case g_flag_apev2:
46  static_api_ptr_t<tag_processor_trailing>()->write_apev2(p_file,*p_info,p_abort);
47  break;
48  default:
49  throw exception_io_data();
50  }
51  } else {
52  static_api_ptr_t<tag_processor_trailing>()->remove(p_file,p_abort);
53  }
54 
55  if (p_flags & g_flag_id3v2)
56  {
57  static_api_ptr_t<tag_processor_id3v2>()->write_ex(p_callback,p_file,*p_info,p_abort);
58  }
59  else
60  {
61  t_uint64 dummy;
62  tag_processor_id3v2::g_remove_ex(p_callback,p_file,dummy,p_abort);
63  }
64 }
65 
66 static void g_write_tags(unsigned p_flags,const service_ptr_t<file> & p_file,const file_info * p_info,abort_callback & p_abort) {
68  g_write_tags_ex(cb,p_flags,p_file,p_info,p_abort);
69 }
70 
71 
72 void tag_processor::write_multi(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort,bool p_write_id3v1,bool p_write_id3v2,bool p_write_apev2) {
73  unsigned flags = 0;
74  if (p_write_id3v1) flags |= g_flag_id3v1;
75  if (p_write_id3v2) flags |= g_flag_id3v2;
76  if (p_write_apev2) flags |= g_flag_apev2;
77  g_write_tags(flags,p_file,&p_info,p_abort);
78 }
79 
80 void tag_processor::write_multi_ex(tag_write_callback & p_callback,const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort,bool p_write_id3v1,bool p_write_id3v2,bool p_write_apev2) {
81  unsigned flags = 0;
82  if (p_write_id3v1) flags |= g_flag_id3v1;
83  if (p_write_id3v2) flags |= g_flag_id3v2;
84  if (p_write_apev2) flags |= g_flag_apev2;
85  g_write_tags_ex(p_callback,flags,p_file,&p_info,p_abort);
86 }
87 
88 void tag_processor::write_id3v1(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort) {
89  g_write_tags(g_flag_id3v1,p_file,&p_info,p_abort);
90 }
91 
92 void tag_processor::write_apev2(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort) {
93  g_write_tags(g_flag_apev2,p_file,&p_info,p_abort);
94 }
95 
96 void tag_processor::write_apev2_id3v1(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort) {
97  g_write_tags(g_flag_apev2|g_flag_id3v1,p_file,&p_info,p_abort);
98 }
99 
100 void tag_processor::write_id3v2(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort) {
101  g_write_tags(g_flag_id3v2,p_file,&p_info,p_abort);
102 }
103 
104 void tag_processor::write_id3v2_id3v1(const service_ptr_t<file> & p_file,const file_info & p_info,abort_callback & p_abort) {
105  g_write_tags(g_flag_id3v2|g_flag_id3v1,p_file,&p_info,p_abort);
106 }
107 
109  return static_api_ptr_t<tag_processor_trailing>()->remove(p_file,p_abort);
110 }
111 
113  t_uint64 dummy = 0;
114  tag_processor_id3v2::g_remove(p_file,dummy,p_abort);
115  return dummy > 0;
116 }
117 
119  remove_id3v2(p_file,p_abort);
120  remove_trailing(p_file,p_abort);
121 }
122 
124  static_api_ptr_t<tag_processor_trailing>()->read(p_file,p_info,p_abort);
125 }
126 
127 void tag_processor::read_trailing_ex(const service_ptr_t<file> & p_file,file_info & p_info,t_uint64 & p_tagoffset,abort_callback & p_abort) {
128  static_api_ptr_t<tag_processor_trailing>()->read_ex(p_file,p_info,p_tagoffset,p_abort);
129 }
130 
132  static_api_ptr_t<tag_processor_id3v2>()->read(p_file,p_info,p_abort);
133 }
134 
136 {
137  file_info_impl id3v2, trailing;
138  bool have_id3v2 = true, have_trailing = true;
139  try {
140  read_id3v2(p_file,id3v2,p_abort);
141  } catch(exception_io_data) {
142  have_id3v2 = false;
143  }
144  if (!have_id3v2 || !p_file->is_remote()) try {
145  read_trailing(p_file,trailing,p_abort);
146  } catch(exception_io_data) {
147  have_trailing = false;
148  }
149 
150  if (!have_id3v2 && !have_trailing) throw exception_tag_not_found();
151 
152  if (have_id3v2) {
153  p_info._set_tag(id3v2);
154  if (have_trailing) p_info._add_tag(trailing);
155  } else {
156  p_info._set_tag(trailing);
157  }
158 }
159 
160 void tag_processor::skip_id3v2(const service_ptr_t<file> & p_file,t_uint64 & p_size_skipped,abort_callback & p_abort) {
161  tag_processor_id3v2::g_skip(p_file,p_size_skipped,p_abort);
162 }
163 
165 {
167 }
168 
170 {
172 }
static void g_remove(const service_ptr_t< file > &p_file, t_filesize &p_size_removed, abort_callback &p_abort)
void read(const service_ptr_t< file > &p_file, abort_callback &p_abort, pfc::string_base &p_out, bool &is_utf8)
void write_id3v1(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Strips all recognized tags from the file and writes an ID3v1 tag with specified info.
void write_id3v2_id3v1(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Strips all recognized tags from the file and writes ID3v1+ID3v2 tags with specified info...
void remove_id3v2_trailing(const service_ptr_t< file > &p_file, abort_callback &p_abort)
Removes ID3v2 and trailing tags from specified file (not to be confused with trailing ID3v2 which are...
void read_trailing(const service_ptr_t< file > &p_file, file_info &p_info, abort_callback &p_abort)
Reads trailing tags from the file.
uint64_t t_uint64
Definition: int_types.h:3
void _set_tag(const file_info &tag)
Callback interface for write-tags-to-temp-file-and-swap scheme, used for ID3v2 tag updates and such w...
Definition: tag_processor.h:6
void write_multi_ex(tag_write_callback &p_callback, const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort, bool p_write_id3v1, bool p_write_id3v2, bool p_write_apev2)
Strips all recognized tags from the file and writes new tags with specified info according to paramet...
void write_apev2(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Strips all recognized tags from the file and writes an APEv2 tag with specified info.
void write_id3v2(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Strips all recognized tags from the file and writes an ID3v2 tag with specified info.
static void g_skip(const service_ptr_t< file > &p_file, t_filesize &p_size_skipped, abort_callback &p_abort)
void write_apev2_id3v1(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Strips all recognized tags from the file and writes ID3v1+APEv2 tags with specified info...
void read_trailing_ex(const service_ptr_t< file > &p_file, file_info &p_info, t_filesize &p_tagoffset, abort_callback &p_abort)
Reads trailing tags from the file. Extended version, returns offset at which parsed tags start...
static void g_write_tags(unsigned p_flags, const service_ptr_t< file > &p_file, const file_info *p_info, abort_callback &p_abort)
static void g_write_tags_ex(tag_write_callback &p_callback, unsigned p_flags, const service_ptr_t< file > &p_file, const file_info *p_info, abort_callback &p_abort)
Main interface class for information about some playable object.
Definition: file_info.h:73
void remove_trailing(const service_ptr_t< file > &p_file, abort_callback &p_abort)
Removes trailing tags from the file.
virtual void write(const service_ptr_t< file > &p_file, const file_info &p_info, unsigned p_flags, abort_callback &p_abort)=0
void read_id3v2(const service_ptr_t< file > &p_file, file_info &p_info, abort_callback &p_abort)
Reads ID3v2 tags from specified file.
bool remove_id3v2(const service_ptr_t< file > &p_file, abort_callback &p_abort)
Removes ID3v2 tags from the file. Returns true when a tag was removed, false when the file was not al...
void truncate_to_id3v1(file_info &p_info)
bool is_id3v1_sufficient(const file_info &p_info)
static void g_remove_ex(tag_write_callback &p_callback, const service_ptr_t< file > &p_file, t_filesize &p_size_removed, abort_callback &p_abort)
static void tagtype_list_append(pfc::string_base &p_out, const char *p_name)
bool is_empty() const
Definition: string_base.h:212
void skip_id3v2(const service_ptr_t< file > &p_file, t_filesize &p_size_skipped, abort_callback &p_abort)
void _add_tag(const file_info &otherTag)
Implements file_info.
void write_apev2_id3v1(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
Helper template used to easily access core services. Usage: static_api_ptr_t api; api->doso...
Definition: service.h:533
void read_id3v2_trailing(const service_ptr_t< file > &p_file, file_info &p_info, abort_callback &p_abort)
Reads ID3v2 and trailing tags from specified file (not to be confused with trailing ID3v2 which are n...
void write_multi(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort, bool p_write_id3v1, bool p_write_id3v2, bool p_write_apev2)
Strips all recognized tags from the file and writes new tags with specified info according to paramet...
void write_apev2(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)
void write_id3v1(const service_ptr_t< file > &p_file, const file_info &p_info, abort_callback &p_abort)