diff foosdk/sdk/foobar2000/SDK/track_property.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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/SDK/track_property.cpp	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,161 @@
+#include "foobar2000-sdk-pch.h"
+
+#include "track_property.h"
+#include "metadb_info_container_impl.h"
+
+namespace {
+	class track_property_provider_v3_info_source_impl : public track_property_provider_v3_info_source {
+	public:
+		track_property_provider_v3_info_source_impl(trackListRef items) : m_items(items) {}
+		trackInfoContainer::ptr get_info(size_t index) { 
+			return trackGetInfoRef(m_items, index);
+		}
+	private:
+		trackListRef m_items;
+	};
+
+	class track_property_callback_v2_proxy : public track_property_callback_v2 {
+	public:
+		track_property_callback_v2_proxy(track_property_callback & callback) : m_callback(callback) {}
+		void set_property(const char * p_group, double p_sortpriority, const char * p_name, const char * p_value) { m_callback.set_property(p_group, p_sortpriority, p_name, p_value); }
+		bool is_group_wanted(const char*) { return true; }
+
+	private:
+		track_property_callback & m_callback;
+	};
+
+
+}
+
+void track_property_provider_v3::enumerate_properties(trackListRef p_tracks, track_property_callback & p_out) { 
+	track_property_provider_v3_info_source_impl src(p_tracks); track_property_callback_v2_proxy cb(p_out); enumerate_properties_v3(p_tracks, src, cb); 
+}
+
+void track_property_provider_v3::enumerate_properties_v2(trackListRef p_tracks, track_property_callback_v2 & p_out) {
+	track_property_provider_v3_info_source_impl src(p_tracks); enumerate_properties_v3(p_tracks, src, p_out); 
+}
+
+void track_property_provider_v4::enumerate_properties_v3(trackListRef items, track_property_provider_v3_info_source & info, track_property_callback_v2 & callback) {
+	this->enumerate_properties_v4(items, info, callback, fb2k::noAbort );
+}
+namespace {
+	class track_property_provider_v5_info_source_wrap : public track_property_provider_v5_info_source {
+	public:
+		track_property_provider_v5_info_source_wrap(track_property_provider_v3_info_source& chain, trackListRef items) : m_chain(chain), m_items(items) {}
+		track_property_provider_v3_info_source & m_chain;
+		trackListRef m_items;
+		
+		// Not very efficient but gets the job done
+		metadb_v2_rec_t get_info(size_t index) override {
+			auto ret = m_items[index]->query_v2_();
+			ret.info = m_chain.get_info(index);
+			return ret;
+		}
+	};
+}
+void track_property_provider_v5::enumerate_properties_v4(trackListRef items, track_property_provider_v3_info_source& info, track_property_callback_v2& callback, abort_callback& abort) {
+	track_property_provider_v5_info_source_wrap wrap(info, items);
+	this->enumerate_properties_v5(items, wrap, callback, abort);
+}
+
+namespace {
+	class track_property_provider_v3_info_source_wrap_v5 : public track_property_provider_v3_info_source {
+	public:
+		track_property_provider_v5_info_source* chain;
+		trackInfoContainer::ptr get_info(size_t index) override {
+			auto ret = chain->get_info(index).info;
+			if (ret.is_empty()) {
+				ret = m_blank;
+			}
+			return ret;
+		}
+		metadb_info_container::ptr m_blank = fb2k::service_new<metadb_info_container_const_impl>();
+	};
+}
+metadb_v2_rec_t track_property_provider_v5_info_source_impl::get_info(size_t index) {
+#if FOOBAR2000_TARGET_VERSION >= 81
+	return m_infos[index];
+#else
+	if (index < m_infos.get_size()) return m_infos[index];
+	else if (index < m_tracks.get_size()) return m_tracks[index]->query_v2_();
+	else uBugCheck();
+#endif
+}
+
+track_property_provider_v5_info_source_impl::track_property_provider_v5_info_source_impl(trackListRef items, abort_callback & a) {
+	
+#if FOOBAR2000_TARGET_VERSION >= 81
+	m_infos.resize(items.get_count()); 
+	metadb_v2::get()->queryMultiParallel_(items, [this, &a](size_t idx, metadb_v2_rec_t const& rec) {a.check(); this->m_infos[idx] = rec; });
+#else
+	auto api = metadb_v2::tryGet();
+	if (api.is_valid()) {
+		m_infos.resize(items.get_count());
+		api->queryMultiParallel_(items, [this](size_t idx, metadb_v2_rec_t const& rec) {this->m_infos[idx] = rec; });
+		return;
+	}
+	// pre-2.0 metadb, talking to metadb directly is OK, no need to get info preemptively
+	m_tracks = items;
+#endif
+}
+
+void track_property_provider::enumerate_properties_helper(trackListRef items, track_property_provider_v5_info_source* info, track_property_callback_v2& callback, abort_callback& abort) {
+
+	if (info == nullptr) {
+		this->enumerate_properties_helper(items, nullptr, callback, abort);
+	} else {
+		{
+			track_property_provider_v5::ptr v5;
+			if (v5 &= this) {
+				v5->enumerate_properties_v5(items, *info, callback, abort);
+				return;
+			}
+		}
+
+		track_property_provider_v3_info_source_wrap_v5 wrap;
+		wrap.chain = info;
+		this->enumerate_properties_helper(items, &wrap, callback, abort);
+	}
+}
+
+void track_property_provider::enumerate_properties_helper(trackListRef items, std::nullptr_t, track_property_callback_v2& callback, abort_callback& abort) {
+	track_property_provider_v5::ptr v5;
+	if (v5 &= this) {
+		track_property_provider_v5_info_source_impl infoImpl(items, abort);
+		v5->enumerate_properties_v5(items, infoImpl, callback, abort);
+		return;
+	}
+	track_property_provider_v3_info_source* dummy = nullptr;
+	this->enumerate_properties_helper(items, dummy, callback, abort);
+}
+
+void track_property_provider::enumerate_properties_helper(trackListRef items, track_property_provider_v3_info_source * info, track_property_callback_v2 & callback, abort_callback & abort) {
+
+	abort.check();
+
+	track_property_provider_v2::ptr v2;
+	if ( ! this->cast( v2 ) ) {
+		// no v2
+		PFC_ASSERT(core_api::is_main_thread());
+		this->enumerate_properties( items, callback ); return;
+	}
+
+	track_property_provider_v3::ptr v3;
+	if ( ! (v3 &= v2 ) ) {
+		// no v3
+		PFC_ASSERT(core_api::is_main_thread());
+		v2->enumerate_properties_v2( items, callback ); return;
+	}
+
+	track_property_provider_v3_info_source_impl infoFallback ( items );
+	if ( info == nullptr ) info = & infoFallback;
+
+	track_property_provider_v4::ptr v4;
+	if (! ( v4 &= v3 ) ) {
+		// no v4
+		PFC_ASSERT( core_api::is_main_thread() );
+		v3->enumerate_properties_v3( items, *info, callback );
+	} else {
+		v4->enumerate_properties_v4( items, *info, callback, abort );
+	}
+}