|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 class _meta_table_enum_wrapper {
|
|
|
4 public:
|
|
|
5 _meta_table_enum_wrapper(file_info & p_info) : m_info(p_info) {}
|
|
|
6 template<typename t_values>
|
|
|
7 void operator() (const char * p_name,const t_values & p_values) {
|
|
|
8 t_size index = ~0;
|
|
|
9 for(typename t_values::const_iterator iter = p_values.first(); iter.is_valid(); ++iter) {
|
|
|
10 if (index == ~0) index = m_info.__meta_add_unsafe(p_name,*iter);
|
|
|
11 else m_info.meta_add_value(index,*iter);
|
|
|
12 }
|
|
|
13 }
|
|
|
14 private:
|
|
|
15 file_info & m_info;
|
|
|
16 };
|
|
|
17
|
|
|
18 class _meta_table_enum_wrapper_RG {
|
|
|
19 public:
|
|
|
20 _meta_table_enum_wrapper_RG(file_info & p_info) : m_info(p_info) {}
|
|
|
21 template<typename t_values>
|
|
|
22 void operator() (const char * p_name,const t_values & p_values) {
|
|
|
23 if (p_values.get_count() > 0) {
|
|
|
24 if (!m_info.info_set_replaygain(p_name, *p_values.first())) {
|
|
|
25 t_size index = ~0;
|
|
|
26 for(typename t_values::const_iterator iter = p_values.first(); iter.is_valid(); ++iter) {
|
|
|
27 if (index == ~0) index = m_info.__meta_add_unsafe(p_name,*iter);
|
|
|
28 else m_info.meta_add_value(index,*iter);
|
|
|
29 }
|
|
|
30 }
|
|
|
31 }
|
|
|
32 }
|
|
|
33 private:
|
|
|
34 file_info & m_info;
|
|
|
35 };
|
|
|
36
|
|
|
37 //! Purpose: building a file_info metadata table from loose input without search-for-existing-entry bottleneck
|
|
|
38 class meta_table_builder {
|
|
|
39 public:
|
|
|
40 typedef pfc::chain_list_v2_t<pfc::string8> t_entry;
|
|
|
41 typedef pfc::map_t<pfc::string8,t_entry,file_info::field_name_comparator> t_content;
|
|
|
42
|
|
|
43 t_content & content() {return m_data;}
|
|
|
44 t_content const & content() const {return m_data;}
|
|
|
45
|
|
|
46 void add(const char * p_name,const char * p_value,t_size p_value_len = ~0) {
|
|
|
47 if (file_info::g_is_valid_field_name(p_name)) {
|
|
|
48 _add(p_name).insert_last()->set_string(p_value,p_value_len);
|
|
|
49 }
|
|
|
50 }
|
|
|
51
|
|
|
52 void remove(const char * p_name) {
|
|
|
53 m_data.remove(p_name);
|
|
|
54 }
|
|
|
55 void set(const char * p_name,const char * p_value,t_size p_value_len = ~0) {
|
|
|
56 if (file_info::g_is_valid_field_name(p_name)) {
|
|
|
57 t_entry & entry = _add(p_name);
|
|
|
58 entry.remove_all();
|
|
|
59 entry.insert_last()->set_string(p_value,p_value_len);
|
|
|
60 }
|
|
|
61 }
|
|
|
62 t_entry & add(const char * p_name) {
|
|
|
63 if (!file_info::g_is_valid_field_name(p_name)) uBugCheck();//we return a reference, nothing smarter to do
|
|
|
64 return _add(p_name);
|
|
|
65 }
|
|
|
66 void deduplicate(const char * name) {
|
|
|
67 t_entry * e;
|
|
|
68 if (!m_data.query_ptr(name, e)) return;
|
|
|
69 pfc::avltree_t<const char*, pfc::comparator_strcmp> found;
|
|
|
70 for(t_entry::iterator iter = e->first(); iter.is_valid(); ) {
|
|
|
71 t_entry::iterator next = iter; ++next;
|
|
|
72 const char * v = *iter;
|
|
|
73 if (!found.add_item_check(v)) e->remove(iter);
|
|
|
74 iter = next;
|
|
|
75 }
|
|
|
76 }
|
|
|
77 void keep_one(const char * name) {
|
|
|
78 t_entry * e;
|
|
|
79 if (!m_data.query_ptr(name, e)) return;
|
|
|
80 while(e->get_count() > 1) e->remove(e->last());
|
|
|
81 }
|
|
|
82 void tidy_VorbisComment() {
|
|
|
83 deduplicate("album artist");
|
|
|
84 deduplicate("publisher");
|
|
|
85 keep_one("totaltracks");
|
|
|
86 keep_one("totaldiscs");
|
|
|
87 }
|
|
|
88 void finalize(file_info & p_info) const {
|
|
|
89 p_info.meta_remove_all();
|
|
|
90 _meta_table_enum_wrapper e(p_info);
|
|
|
91 m_data.enumerate(e);
|
|
|
92 }
|
|
|
93 void finalize_withRG(file_info & p_info) const {
|
|
|
94 p_info.meta_remove_all(); p_info.set_replaygain(replaygain_info_invalid);
|
|
|
95 _meta_table_enum_wrapper_RG e(p_info);
|
|
|
96 m_data.enumerate(e);
|
|
|
97 }
|
|
|
98
|
|
|
99 void from_info(const file_info & p_info) {
|
|
|
100 m_data.remove_all();
|
|
|
101 from_info_overwrite(p_info);
|
|
|
102 }
|
|
|
103 void from_info_withRG(const file_info & p_info) {
|
|
|
104 m_data.remove_all();
|
|
|
105 from_info_overwrite(p_info);
|
|
|
106 from_RG_overwrite(p_info.get_replaygain());
|
|
|
107 }
|
|
|
108 void from_RG_overwrite(replaygain_info const & info) {
|
|
|
109 info.for_each([&](const char* key, const char* value) {
|
|
|
110 set(key, value);
|
|
|
111 });
|
|
|
112 }
|
|
|
113 void from_info_overwrite(const file_info & p_info) {
|
|
|
114 for(t_size metawalk = 0, metacount = p_info.meta_get_count(); metawalk < metacount; ++metawalk ) {
|
|
|
115 const t_size valuecount = p_info.meta_enum_value_count(metawalk);
|
|
|
116 if (valuecount > 0) {
|
|
|
117 t_entry & entry = add(p_info.meta_enum_name(metawalk));
|
|
|
118 entry.remove_all();
|
|
|
119 for(t_size valuewalk = 0; valuewalk < valuecount; ++valuewalk) {
|
|
|
120 entry.insert_last(p_info.meta_enum_value(metawalk,valuewalk));
|
|
|
121 }
|
|
|
122 }
|
|
|
123 }
|
|
|
124 }
|
|
|
125 void reset() {m_data.remove_all();}
|
|
|
126
|
|
|
127 void fix_itunes_compilation() {
|
|
|
128 auto entry = m_data.find("itunescompilation");
|
|
|
129 if (entry.is_valid()) {
|
|
|
130 auto val = entry->m_value.first();
|
|
|
131 if (val.is_valid()) {
|
|
|
132 if (atoi(val->c_str()) != 0) {
|
|
|
133 // m_data.remove(cmp);
|
|
|
134 if (!m_data.have_item("album artist")) add("album artist", "Various Artists");
|
|
|
135 }
|
|
|
136 }
|
|
|
137 }
|
|
|
138 }
|
|
|
139 private:
|
|
|
140
|
|
|
141 t_entry & _add(const char * p_name) {
|
|
|
142 return m_data.find_or_add(p_name);
|
|
|
143 }
|
|
|
144
|
|
|
145 t_content m_data;
|
|
|
146 };
|