annotate foosdk/sdk/foobar2000/helpers/meta_table_builder.h @ 1:20d02a178406 default tip

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