Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/titleformat.cpp @ 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 |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "foobar2000-sdk-pch.h" | |
| 2 #include "titleformat.h" | |
| 3 | |
| 4 | |
| 5 #define tf_profiler(x) // profiler(x) | |
| 6 | |
| 7 void titleformat_compiler::remove_color_marks(const char * src,pfc::string_base & out)//helper | |
| 8 { | |
| 9 out.reset(); | |
| 10 while(*src) | |
| 11 { | |
| 12 if (*src==3) | |
| 13 { | |
| 14 src++; | |
| 15 while(*src && *src!=3) src++; | |
| 16 if (*src==3) src++; | |
| 17 } | |
| 18 else out.add_byte(*src++); | |
| 19 } | |
| 20 } | |
| 21 | |
| 22 static bool test_for_bad_char(const char * source,t_size source_char_len,const char * reserved) | |
| 23 { | |
| 24 return pfc::strstr_ex(reserved,(t_size)(-1),source,source_char_len) != (t_size)(-1); | |
| 25 } | |
| 26 | |
| 27 void titleformat_compiler::remove_forbidden_chars(titleformat_text_out * p_out,const GUID & p_inputtype,const char * p_source,t_size p_source_len,const char * p_reserved_chars) | |
| 28 { | |
| 29 if (p_reserved_chars == 0 || *p_reserved_chars == 0) | |
| 30 { | |
| 31 p_out->write(p_inputtype,p_source,p_source_len); | |
| 32 } | |
| 33 else | |
| 34 { | |
| 35 p_source_len = pfc::strlen_max(p_source,p_source_len); | |
| 36 t_size index = 0; | |
| 37 t_size good_byte_count = 0; | |
| 38 while(index < p_source_len) | |
| 39 { | |
| 40 t_size delta = pfc::utf8_char_len(p_source + index,p_source_len - index); | |
| 41 if (delta == 0) break; | |
| 42 if (test_for_bad_char(p_source+index,delta,p_reserved_chars)) | |
| 43 { | |
| 44 if (good_byte_count > 0) {p_out->write(p_inputtype,p_source+index-good_byte_count,good_byte_count);good_byte_count=0;} | |
| 45 p_out->write(p_inputtype,"_",1); | |
| 46 } | |
| 47 else | |
| 48 { | |
| 49 good_byte_count += delta; | |
| 50 } | |
| 51 index += delta; | |
| 52 } | |
| 53 if (good_byte_count > 0) {p_out->write(p_inputtype,p_source+index-good_byte_count,good_byte_count);good_byte_count=0;} | |
| 54 } | |
| 55 } | |
| 56 | |
| 57 void titleformat_compiler::remove_forbidden_chars_string_append(pfc::string_receiver & p_out,const char * p_source,t_size p_source_len,const char * p_reserved_chars) | |
| 58 { | |
| 59 titleformat_text_out_impl_string tfout(p_out); | |
| 60 remove_forbidden_chars(&tfout,pfc::guid_null,p_source,p_source_len,p_reserved_chars); | |
| 61 } | |
| 62 | |
| 63 void titleformat_compiler::remove_forbidden_chars_string(pfc::string_base & p_out,const char * p_source,t_size p_source_len,const char * p_reserved_chars) | |
| 64 { | |
| 65 p_out.reset(); | |
| 66 remove_forbidden_chars_string_append(p_out,p_source,p_source_len,p_reserved_chars); | |
| 67 } | |
| 68 | |
| 69 bool titleformat_hook_impl_file_info::process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) { | |
| 70 return m_api->process_field(*m_info,m_location,p_out,p_name,p_name_length,p_found_flag); | |
| 71 } | |
| 72 bool titleformat_hook_impl_file_info::process_function(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,titleformat_hook_function_params * p_params,bool & p_found_flag) { | |
| 73 return m_api->process_function(*m_info,m_location,p_out,p_name,p_name_length,p_params,p_found_flag); | |
| 74 } | |
| 75 | |
| 76 void titleformat_object::run_hook(const playable_location & p_location,const file_info * p_source,titleformat_hook * p_hook,pfc::string_base & p_out,titleformat_text_filter * p_filter) | |
| 77 { | |
| 78 if (p_hook) | |
| 79 { | |
| 80 titleformat_hook_impl_file_info hook1(p_location, p_source); | |
| 81 titleformat_hook_impl_splitter hook2(p_hook, &hook1); | |
| 82 run(&hook2,p_out,p_filter); | |
| 83 } | |
| 84 else | |
| 85 { | |
| 86 titleformat_hook_impl_file_info hook(p_location, p_source); | |
| 87 run(&hook,p_out,p_filter); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void titleformat_object::run_simple(const playable_location & p_location,const file_info * p_source,pfc::string_base & p_out) | |
| 92 { | |
| 93 titleformat_hook_impl_file_info hook(p_location, p_source); | |
| 94 run(&hook,p_out,NULL); | |
| 95 } | |
| 96 | |
| 97 t_size titleformat_hook_function_params::get_param_uint(t_size index) | |
| 98 { | |
| 99 const char * str; | |
| 100 t_size str_len; | |
| 101 get_param(index,str,str_len); | |
| 102 return pfc::atoui_ex(str,str_len); | |
| 103 } | |
| 104 | |
| 105 | |
| 106 void titleformat_text_out_impl_filter_chars::write(const GUID & p_inputtype,const char * p_data,t_size p_data_length) | |
| 107 { | |
| 108 titleformat_compiler::remove_forbidden_chars(m_chain,p_inputtype,p_data,p_data_length,m_restricted_chars); | |
| 109 } | |
| 110 | |
| 111 bool titleformat_hook_impl_splitter::process_field(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,bool & p_found_flag) | |
| 112 { | |
| 113 p_found_flag = false; | |
| 114 if (m_hook1 && m_hook1->process_field(p_out,p_name,p_name_length,p_found_flag)) return true; | |
| 115 p_found_flag = false; | |
| 116 if (m_hook2 && m_hook2->process_field(p_out,p_name,p_name_length,p_found_flag)) return true; | |
| 117 p_found_flag = false; | |
| 118 return false; | |
| 119 } | |
| 120 | |
| 121 bool titleformat_hook_impl_splitter::process_function(titleformat_text_out * p_out,const char * p_name,t_size p_name_length,titleformat_hook_function_params * p_params,bool & p_found_flag) | |
| 122 { | |
| 123 p_found_flag = false; | |
| 124 if (m_hook1 && m_hook1->process_function(p_out,p_name,p_name_length,p_params,p_found_flag)) return true; | |
| 125 p_found_flag = false; | |
| 126 if (m_hook2 && m_hook2->process_function(p_out,p_name,p_name_length,p_params,p_found_flag)) return true; | |
| 127 p_found_flag = false; | |
| 128 return false; | |
| 129 } | |
| 130 | |
| 131 void titleformat_text_out::write_int_padded(const GUID & p_inputtype,t_int64 val,t_int64 maxval) | |
| 132 { | |
| 133 unsigned width = 0; | |
| 134 while(maxval > 0) {maxval/=10;width++;} | |
| 135 write(p_inputtype,pfc::format_int(val,width)); | |
| 136 } | |
| 137 | |
| 138 void titleformat_text_out::write_int(const GUID & p_inputtype,t_int64 val) | |
| 139 { | |
| 140 write(p_inputtype,pfc::format_int(val)); | |
| 141 } | |
| 142 void titleformat_text_filter_impl_reserved_chars::write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length) | |
| 143 { | |
| 144 if (p_inputtype == titleformat_inputtypes::meta) titleformat_compiler::remove_forbidden_chars_string_append(p_out,p_data,p_data_length,m_reserved_chars); | |
| 145 else p_out.add_string(p_data,p_data_length); | |
| 146 } | |
| 147 | |
| 148 void titleformat_compiler::run(titleformat_hook * p_source,pfc::string_base & p_out,const char * p_spec) | |
| 149 { | |
| 150 service_ptr_t<titleformat_object> ptr; | |
| 151 if (!compile(ptr,p_spec)) p_out = "[COMPILATION ERROR]"; | |
| 152 else ptr->run(p_source,p_out,NULL); | |
| 153 } | |
| 154 | |
| 155 void titleformat_compiler::compile_safe(titleformat_object::ptr & p_out,const char * p_spec) | |
| 156 { | |
| 157 compile_safe_ex(p_out, p_spec, "%filename%"); | |
| 158 } | |
| 159 | |
| 160 | |
| 161 namespace titleformat_inputtypes { | |
| 162 const GUID meta = { 0xcd839c8e, 0x5c66, 0x4ae1, { 0x8d, 0xad, 0x71, 0x1f, 0x86, 0x0, 0xa, 0xe3 } }; | |
| 163 const GUID unknown = { 0x673aa1cd, 0xa7a8, 0x40c8, { 0xbf, 0x9b, 0x34, 0x37, 0x99, 0x29, 0x16, 0x3b } }; | |
| 164 }; | |
| 165 | |
| 166 void titleformat_text_filter_impl_filename_chars::write(const GUID & p_inputType,pfc::string_receiver & p_out,const char * p_data,t_size p_dataLength) { | |
| 167 if (p_inputType == titleformat_inputtypes::meta) { | |
| 168 //slightly inefficient... | |
| 169 p_out.add_string( pfc::io::path::replaceIllegalNameChars(pfc::string(p_data,p_dataLength)).ptr()); | |
| 170 } else p_out.add_string(p_data,p_dataLength); | |
| 171 } | |
| 172 | |
| 173 void titleformat_compiler::compile_safe_ex(titleformat_object::ptr & p_out,const char * p_spec,const char * p_fallback) { | |
| 174 if (!compile(p_out,p_spec)) compile_force(p_out,p_fallback); | |
| 175 } | |
| 176 | |
| 177 | |
| 178 void titleformat_text_filter_nontext_chars::write(const GUID & p_inputtype,pfc::string_receiver & p_out,const char * p_data,t_size p_data_length) { | |
| 179 (void)p_inputtype; | |
| 180 for(t_size walk = 0;;) { | |
| 181 t_size base = walk; | |
| 182 while(walk < p_data_length && !isReserved(p_data[walk]) && p_data[walk] != 0) walk++; | |
| 183 p_out.add_string(p_data+base,walk-base); | |
| 184 if (walk >= p_data_length || p_data[walk] == 0) break; | |
| 185 p_out.add_byte('_'); walk++; | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 titleformat_object::ptr titleformat_compiler::compile(const char* spec) { | |
| 190 titleformat_object::ptr ret; | |
| 191 this->compile(ret, spec); | |
| 192 return ret; | |
| 193 } | |
| 194 titleformat_object::ptr titleformat_compiler::compile_force(const char* spec) { | |
| 195 titleformat_object::ptr ret; | |
| 196 this->compile_force(ret, spec); | |
| 197 return ret; | |
| 198 } | |
| 199 titleformat_object::ptr titleformat_compiler::compile_fallback(const char* spec, const char* fallback) { | |
| 200 auto ret = compile(spec); | |
| 201 if (ret.is_empty()) ret = compile(fallback); | |
| 202 return ret; | |
| 203 } | |
| 204 | |
| 205 bool titleformat_object::requires_metadb_info_() { | |
| 206 #if FOOBAR2000_TARGET_VERSION >= 81 | |
| 207 return static_cast<titleformat_object_v2*>(this)->requires_metadb_info(); | |
| 208 #else | |
| 209 titleformat_object_v2::ptr v2; | |
| 210 if (v2 &= this) return v2->requires_metadb_info(); | |
| 211 return true; | |
| 212 #endif | |
| 213 } | |
| 214 | |
| 215 const char * titleformat_patterns::patternAlbumSplit() { | |
| 216 return "$if2(%album artist%,$directory_path(%path%))\t$if2(%album%,%title%)\t%discnumber%"; | |
| 217 } | |
| 218 | |
| 219 const char * titleformat_patterns::patternSortTracks() { | |
| 220 return "%album artist% | %album% | %discnumber% | %tracknumber% | %title% | %path%"; | |
| 221 } |
