#include "foobar2000.h" static t_size merge_tags_calc_rating_by_index(const file_info & p_info,t_size p_index) { t_size n,m = p_info.meta_enum_value_count(p_index); t_size ret = 0; for(n=0;ninfo_get(field); if (val) to->info_set(field,val); } #endif namespace { struct meta_merge_entry { meta_merge_entry() : m_rating(0) {} t_size m_rating; pfc::array_t m_data; }; class meta_merge_map_enumerator { public: meta_merge_map_enumerator(file_info & p_out) : m_out(p_out) { m_out.meta_remove_all(); } void operator() (const char * p_name, const meta_merge_entry & p_entry) { if (p_entry.m_data.get_size() > 0) { t_size index = m_out.__meta_add_unsafe(p_name,p_entry.m_data[0]); for(t_size walk = 1; walk < p_entry.m_data.get_size(); ++walk) { m_out.meta_add_value(index,p_entry.m_data[walk]); } } } private: file_info & m_out; }; } static void merge_meta(file_info & p_out,const pfc::list_base_const_t & p_in) { pfc::map_t map; for(t_size in_walk = 0; in_walk < p_in.get_count(); in_walk++) { const file_info & in = * p_in[in_walk]; for(t_size meta_walk = 0, meta_count = in.meta_get_count(); meta_walk < meta_count; meta_walk++ ) { meta_merge_entry & entry = map.find_or_add(in.meta_enum_name(meta_walk)); t_size rating = merge_tags_calc_rating_by_index(in,meta_walk); if (rating > entry.m_rating) { entry.m_rating = rating; const t_size value_count = in.meta_enum_value_count(meta_walk); entry.m_data.set_size(value_count); for(t_size value_walk = 0; value_walk < value_count; value_walk++ ) { entry.m_data[value_walk] = in.meta_enum_value(meta_walk,value_walk); } } } } meta_merge_map_enumerator en(p_out); map.enumerate(en); } void file_info::merge(const pfc::list_base_const_t & p_in) { t_size in_count = p_in.get_count(); if (in_count == 0) { meta_remove_all(); return; } else if (in_count == 1) { const file_info * info = p_in[0]; copy_meta(*info); set_replaygain(replaygain_info::g_merge(get_replaygain(),info->get_replaygain())); overwrite_info(*info); //copy_info_single_by_name(*info,"tagtype"); return; } merge_meta(*this,p_in); { pfc::string8_fastalloc tagtype; replaygain_info rg = get_replaygain(); t_size in_ptr; for(in_ptr = 0; in_ptr < in_count; in_ptr++ ) { const file_info * info = p_in[in_ptr]; rg = replaygain_info::g_merge(rg, info->get_replaygain()); t_size field_ptr, field_max = info->info_get_count(); for(field_ptr = 0; field_ptr < field_max; field_ptr++ ) { const char * field_name = info->info_enum_name(field_ptr), * field_value = info->info_enum_value(field_ptr); if (*field_value) { if (!pfc::stricmp_ascii(field_name,"tagtype")) { if (!tagtype.is_empty()) tagtype += "|"; tagtype += field_value; } } } } if (!tagtype.is_empty()) info_set("tagtype",tagtype); set_replaygain(rg); } } void file_info::overwrite_info(const file_info & p_source) { t_size count = p_source.info_get_count(); for(t_size n=0;ncopy_meta(tag); this->set_replaygain( replaygain_info::g_merge( this->get_replaygain(), tag.get_replaygain() ) ); const size_t iCount = tag.info_get_count(); for( size_t iWalk = 0; iWalk < iCount; ++iWalk ) { auto n = tag.info_enum_name(iWalk); if ( pfc::stringEqualsI_ascii( n, _tagtype ) || isSC(n) ) { this->info_set(n, tag.info_enum_value( iWalk ) ); } } } void file_info::_add_tag(const file_info & otherTag) { this->set_replaygain( replaygain_info::g_merge( this->get_replaygain(), otherTag.get_replaygain() ) ); const char * tt1 = this->info_get(_tagtype); const char * tt2 = otherTag.info_get(_tagtype); if (tt2) { if (tt1) { this->info_set(_tagtype, PFC_string_formatter() << tt1 << "|" << tt2); } else { this->info_set(_tagtype, tt2); } } { const size_t iCount = otherTag.info_get_count(); for( size_t w = 0; w < iCount; ++ w ) { auto n = otherTag.info_enum_name(w); if (isSC(n) && !this->info_get(n)) { this->info_set( n, otherTag.info_enum_value(w) ); } } } }