|
1
|
1 #include "foobar2000-sdk-pch.h"
|
|
|
2
|
|
|
3 #include "track_property.h"
|
|
|
4 #include "metadb_info_container_impl.h"
|
|
|
5
|
|
|
6 namespace {
|
|
|
7 class track_property_provider_v3_info_source_impl : public track_property_provider_v3_info_source {
|
|
|
8 public:
|
|
|
9 track_property_provider_v3_info_source_impl(trackListRef items) : m_items(items) {}
|
|
|
10 trackInfoContainer::ptr get_info(size_t index) {
|
|
|
11 return trackGetInfoRef(m_items, index);
|
|
|
12 }
|
|
|
13 private:
|
|
|
14 trackListRef m_items;
|
|
|
15 };
|
|
|
16
|
|
|
17 class track_property_callback_v2_proxy : public track_property_callback_v2 {
|
|
|
18 public:
|
|
|
19 track_property_callback_v2_proxy(track_property_callback & callback) : m_callback(callback) {}
|
|
|
20 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); }
|
|
|
21 bool is_group_wanted(const char*) { return true; }
|
|
|
22
|
|
|
23 private:
|
|
|
24 track_property_callback & m_callback;
|
|
|
25 };
|
|
|
26
|
|
|
27
|
|
|
28 }
|
|
|
29
|
|
|
30 void track_property_provider_v3::enumerate_properties(trackListRef p_tracks, track_property_callback & p_out) {
|
|
|
31 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);
|
|
|
32 }
|
|
|
33
|
|
|
34 void track_property_provider_v3::enumerate_properties_v2(trackListRef p_tracks, track_property_callback_v2 & p_out) {
|
|
|
35 track_property_provider_v3_info_source_impl src(p_tracks); enumerate_properties_v3(p_tracks, src, p_out);
|
|
|
36 }
|
|
|
37
|
|
|
38 void track_property_provider_v4::enumerate_properties_v3(trackListRef items, track_property_provider_v3_info_source & info, track_property_callback_v2 & callback) {
|
|
|
39 this->enumerate_properties_v4(items, info, callback, fb2k::noAbort );
|
|
|
40 }
|
|
|
41 namespace {
|
|
|
42 class track_property_provider_v5_info_source_wrap : public track_property_provider_v5_info_source {
|
|
|
43 public:
|
|
|
44 track_property_provider_v5_info_source_wrap(track_property_provider_v3_info_source& chain, trackListRef items) : m_chain(chain), m_items(items) {}
|
|
|
45 track_property_provider_v3_info_source & m_chain;
|
|
|
46 trackListRef m_items;
|
|
|
47
|
|
|
48 // Not very efficient but gets the job done
|
|
|
49 metadb_v2_rec_t get_info(size_t index) override {
|
|
|
50 auto ret = m_items[index]->query_v2_();
|
|
|
51 ret.info = m_chain.get_info(index);
|
|
|
52 return ret;
|
|
|
53 }
|
|
|
54 };
|
|
|
55 }
|
|
|
56 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) {
|
|
|
57 track_property_provider_v5_info_source_wrap wrap(info, items);
|
|
|
58 this->enumerate_properties_v5(items, wrap, callback, abort);
|
|
|
59 }
|
|
|
60
|
|
|
61 namespace {
|
|
|
62 class track_property_provider_v3_info_source_wrap_v5 : public track_property_provider_v3_info_source {
|
|
|
63 public:
|
|
|
64 track_property_provider_v5_info_source* chain;
|
|
|
65 trackInfoContainer::ptr get_info(size_t index) override {
|
|
|
66 auto ret = chain->get_info(index).info;
|
|
|
67 if (ret.is_empty()) {
|
|
|
68 ret = m_blank;
|
|
|
69 }
|
|
|
70 return ret;
|
|
|
71 }
|
|
|
72 metadb_info_container::ptr m_blank = fb2k::service_new<metadb_info_container_const_impl>();
|
|
|
73 };
|
|
|
74 }
|
|
|
75 metadb_v2_rec_t track_property_provider_v5_info_source_impl::get_info(size_t index) {
|
|
|
76 #if FOOBAR2000_TARGET_VERSION >= 81
|
|
|
77 return m_infos[index];
|
|
|
78 #else
|
|
|
79 if (index < m_infos.get_size()) return m_infos[index];
|
|
|
80 else if (index < m_tracks.get_size()) return m_tracks[index]->query_v2_();
|
|
|
81 else uBugCheck();
|
|
|
82 #endif
|
|
|
83 }
|
|
|
84
|
|
|
85 track_property_provider_v5_info_source_impl::track_property_provider_v5_info_source_impl(trackListRef items, abort_callback & a) {
|
|
|
86
|
|
|
87 #if FOOBAR2000_TARGET_VERSION >= 81
|
|
|
88 m_infos.resize(items.get_count());
|
|
|
89 metadb_v2::get()->queryMultiParallel_(items, [this, &a](size_t idx, metadb_v2_rec_t const& rec) {a.check(); this->m_infos[idx] = rec; });
|
|
|
90 #else
|
|
|
91 auto api = metadb_v2::tryGet();
|
|
|
92 if (api.is_valid()) {
|
|
|
93 m_infos.resize(items.get_count());
|
|
|
94 api->queryMultiParallel_(items, [this](size_t idx, metadb_v2_rec_t const& rec) {this->m_infos[idx] = rec; });
|
|
|
95 return;
|
|
|
96 }
|
|
|
97 // pre-2.0 metadb, talking to metadb directly is OK, no need to get info preemptively
|
|
|
98 m_tracks = items;
|
|
|
99 #endif
|
|
|
100 }
|
|
|
101
|
|
|
102 void track_property_provider::enumerate_properties_helper(trackListRef items, track_property_provider_v5_info_source* info, track_property_callback_v2& callback, abort_callback& abort) {
|
|
|
103
|
|
|
104 if (info == nullptr) {
|
|
|
105 this->enumerate_properties_helper(items, nullptr, callback, abort);
|
|
|
106 } else {
|
|
|
107 {
|
|
|
108 track_property_provider_v5::ptr v5;
|
|
|
109 if (v5 &= this) {
|
|
|
110 v5->enumerate_properties_v5(items, *info, callback, abort);
|
|
|
111 return;
|
|
|
112 }
|
|
|
113 }
|
|
|
114
|
|
|
115 track_property_provider_v3_info_source_wrap_v5 wrap;
|
|
|
116 wrap.chain = info;
|
|
|
117 this->enumerate_properties_helper(items, &wrap, callback, abort);
|
|
|
118 }
|
|
|
119 }
|
|
|
120
|
|
|
121 void track_property_provider::enumerate_properties_helper(trackListRef items, std::nullptr_t, track_property_callback_v2& callback, abort_callback& abort) {
|
|
|
122 track_property_provider_v5::ptr v5;
|
|
|
123 if (v5 &= this) {
|
|
|
124 track_property_provider_v5_info_source_impl infoImpl(items, abort);
|
|
|
125 v5->enumerate_properties_v5(items, infoImpl, callback, abort);
|
|
|
126 return;
|
|
|
127 }
|
|
|
128 track_property_provider_v3_info_source* dummy = nullptr;
|
|
|
129 this->enumerate_properties_helper(items, dummy, callback, abort);
|
|
|
130 }
|
|
|
131
|
|
|
132 void track_property_provider::enumerate_properties_helper(trackListRef items, track_property_provider_v3_info_source * info, track_property_callback_v2 & callback, abort_callback & abort) {
|
|
|
133
|
|
|
134 abort.check();
|
|
|
135
|
|
|
136 track_property_provider_v2::ptr v2;
|
|
|
137 if ( ! this->cast( v2 ) ) {
|
|
|
138 // no v2
|
|
|
139 PFC_ASSERT(core_api::is_main_thread());
|
|
|
140 this->enumerate_properties( items, callback ); return;
|
|
|
141 }
|
|
|
142
|
|
|
143 track_property_provider_v3::ptr v3;
|
|
|
144 if ( ! (v3 &= v2 ) ) {
|
|
|
145 // no v3
|
|
|
146 PFC_ASSERT(core_api::is_main_thread());
|
|
|
147 v2->enumerate_properties_v2( items, callback ); return;
|
|
|
148 }
|
|
|
149
|
|
|
150 track_property_provider_v3_info_source_impl infoFallback ( items );
|
|
|
151 if ( info == nullptr ) info = & infoFallback;
|
|
|
152
|
|
|
153 track_property_provider_v4::ptr v4;
|
|
|
154 if (! ( v4 &= v3 ) ) {
|
|
|
155 // no v4
|
|
|
156 PFC_ASSERT( core_api::is_main_thread() );
|
|
|
157 v3->enumerate_properties_v3( items, *info, callback );
|
|
|
158 } else {
|
|
|
159 v4->enumerate_properties_v4( items, *info, callback, abort );
|
|
|
160 }
|
|
|
161 }
|