|
1
|
1 #include "foobar2000-sdk-pch.h"
|
|
|
2 #include "playlist.h"
|
|
|
3
|
|
|
4 namespace {
|
|
|
5 class enum_items_callback_func : public playlist_manager::enum_items_callback {
|
|
|
6 public:
|
|
|
7 bool on_item(t_size p_index, const metadb_handle_ptr& p_location, bool b_selected) override { return f(p_index, p_location, b_selected); }
|
|
|
8 playlist_manager::enum_items_func f;
|
|
|
9 };
|
|
|
10 class enum_items_callback_retrieve_item : public playlist_manager::enum_items_callback
|
|
|
11 {
|
|
|
12 metadb_handle_ptr m_item;
|
|
|
13 public:
|
|
|
14 enum_items_callback_retrieve_item() : m_item(0) {}
|
|
|
15 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
16 {
|
|
|
17 (void)p_index; (void)b_selected;
|
|
|
18 PFC_ASSERT(m_item.is_empty());
|
|
|
19 m_item = p_location;
|
|
|
20 return false;
|
|
|
21 }
|
|
|
22 inline const metadb_handle_ptr & get_item() {return m_item;}
|
|
|
23 };
|
|
|
24
|
|
|
25 class enum_items_callback_retrieve_selection : public playlist_manager::enum_items_callback
|
|
|
26 {
|
|
|
27 bool m_state;
|
|
|
28 public:
|
|
|
29 enum_items_callback_retrieve_selection() : m_state(false) {}
|
|
|
30 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
31 {
|
|
|
32 (void)p_index; (void)p_location;
|
|
|
33 m_state = b_selected;
|
|
|
34 return false;
|
|
|
35 }
|
|
|
36 inline bool get_state() {return m_state;}
|
|
|
37 };
|
|
|
38
|
|
|
39 class enum_items_callback_retrieve_selection_mask : public playlist_manager::enum_items_callback
|
|
|
40 {
|
|
|
41 bit_array_var & m_out;
|
|
|
42 public:
|
|
|
43 enum_items_callback_retrieve_selection_mask(bit_array_var & p_out) : m_out(p_out) {}
|
|
|
44 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
45 {
|
|
|
46 (void)p_location;
|
|
|
47 m_out.set(p_index,b_selected);
|
|
|
48 return true;
|
|
|
49 }
|
|
|
50 };
|
|
|
51
|
|
|
52 class enum_items_callback_retrieve_all_items : public playlist_manager::enum_items_callback
|
|
|
53 {
|
|
|
54 pfc::list_base_t<metadb_handle_ptr> & m_out;
|
|
|
55 public:
|
|
|
56 enum_items_callback_retrieve_all_items(pfc::list_base_t<metadb_handle_ptr> & p_out) : m_out(p_out) {m_out.remove_all();}
|
|
|
57 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
58 {
|
|
|
59 (void)p_index; (void)b_selected;
|
|
|
60 m_out.add_item(p_location);
|
|
|
61 return true;
|
|
|
62 }
|
|
|
63 };
|
|
|
64
|
|
|
65 class enum_items_callback_retrieve_selected_items : public playlist_manager::enum_items_callback
|
|
|
66 {
|
|
|
67 pfc::list_base_t<metadb_handle_ptr> & m_out;
|
|
|
68 public:
|
|
|
69 enum_items_callback_retrieve_selected_items(pfc::list_base_t<metadb_handle_ptr> & p_out) : m_out(p_out) {m_out.remove_all();}
|
|
|
70 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
71 {
|
|
|
72 (void)p_index;
|
|
|
73 if (b_selected) m_out.add_item(p_location);
|
|
|
74 return true;
|
|
|
75 }
|
|
|
76 };
|
|
|
77
|
|
|
78 class enum_items_callback_count_selection : public playlist_manager::enum_items_callback
|
|
|
79 {
|
|
|
80 t_size m_counter,m_max;
|
|
|
81 public:
|
|
|
82 enum_items_callback_count_selection(t_size p_max) : m_max(p_max), m_counter(0) {}
|
|
|
83 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected)
|
|
|
84 {
|
|
|
85 (void)p_index; (void)p_location;
|
|
|
86 if (b_selected)
|
|
|
87 {
|
|
|
88 if (++m_counter >= m_max) return false;
|
|
|
89 }
|
|
|
90 return true;
|
|
|
91 }
|
|
|
92
|
|
|
93 inline t_size get_count() {return m_counter;}
|
|
|
94 };
|
|
|
95
|
|
|
96 }
|
|
|
97
|
|
|
98 void playlist_manager::playlist_get_all_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out)
|
|
|
99 {
|
|
|
100 playlist_get_items(p_playlist,out, pfc::bit_array_true());
|
|
|
101 }
|
|
|
102
|
|
|
103 void playlist_manager::playlist_get_selected_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out)
|
|
|
104 {
|
|
|
105 enum_items_callback_retrieve_selected_items cb(out);
|
|
|
106 playlist_enum_items(p_playlist,cb,pfc::bit_array_true());
|
|
|
107 }
|
|
|
108
|
|
|
109 void playlist_manager::playlist_get_selection_mask(t_size p_playlist,bit_array_var & out)
|
|
|
110 {
|
|
|
111 enum_items_callback_retrieve_selection_mask cb(out);
|
|
|
112 playlist_enum_items(p_playlist,cb,pfc::bit_array_true());
|
|
|
113 }
|
|
|
114
|
|
|
115 bool playlist_manager::playlist_is_item_selected(t_size p_playlist,t_size p_item)
|
|
|
116 {
|
|
|
117 enum_items_callback_retrieve_selection callback;
|
|
|
118 playlist_enum_items(p_playlist,callback,pfc::bit_array_one(p_item));
|
|
|
119 return callback.get_state();
|
|
|
120 }
|
|
|
121
|
|
|
122 metadb_handle_ptr playlist_manager::playlist_get_item_handle(t_size playlist, t_size item) {
|
|
|
123 metadb_handle_ptr temp;
|
|
|
124 if (!playlist_get_item_handle(temp, playlist, item)) throw pfc::exception_invalid_params();
|
|
|
125 PFC_ASSERT( temp.is_valid() );
|
|
|
126 return temp;
|
|
|
127
|
|
|
128 }
|
|
|
129 bool playlist_manager::playlist_get_item_handle(metadb_handle_ptr & p_out,t_size p_playlist,t_size p_item)
|
|
|
130 {
|
|
|
131 enum_items_callback_retrieve_item callback;
|
|
|
132 playlist_enum_items(p_playlist,callback,pfc::bit_array_one(p_item));
|
|
|
133 p_out = callback.get_item();
|
|
|
134 return p_out.is_valid();
|
|
|
135 }
|
|
|
136
|
|
|
137 void playlist_manager::g_make_selection_move_permutation(t_size * p_output,t_size p_count,const bit_array & p_selection,int p_delta) {
|
|
|
138 pfc::create_move_items_permutation(p_output,p_count,p_selection,p_delta);
|
|
|
139 }
|
|
|
140
|
|
|
141 bool playlist_manager::playlist_move_selection(t_size p_playlist,int p_delta) {
|
|
|
142 if (p_delta==0) return true;
|
|
|
143
|
|
|
144 t_size count = playlist_get_item_count(p_playlist);
|
|
|
145
|
|
|
146 pfc::array_t<t_size> order; order.set_size(count);
|
|
|
147 pfc::array_t<bool> selection; selection.set_size(count);
|
|
|
148
|
|
|
149 pfc::bit_array_var_table mask(selection.get_ptr(),selection.get_size());
|
|
|
150 playlist_get_selection_mask(p_playlist, mask);
|
|
|
151 g_make_selection_move_permutation(order.get_ptr(),count,mask,p_delta);
|
|
|
152 return playlist_reorder_items(p_playlist,order.get_ptr(),count);
|
|
|
153 }
|
|
|
154
|
|
|
155 //retrieving status
|
|
|
156 t_size playlist_manager::activeplaylist_get_item_count()
|
|
|
157 {
|
|
|
158 t_size playlist = get_active_playlist();
|
|
|
159 if (playlist == SIZE_MAX) return 0;
|
|
|
160 else return playlist_get_item_count(playlist);
|
|
|
161 }
|
|
|
162
|
|
|
163 void playlist_manager::playlist_enum_items(size_t which, enum_items_func f, const bit_array& mask) {
|
|
|
164 enum_items_callback_func cb; cb.f = f;
|
|
|
165 this->playlist_enum_items(which, cb, mask);
|
|
|
166 }
|
|
|
167
|
|
|
168 void playlist_manager::activeplaylist_enum_items(enum_items_callback & p_callback,const bit_array & p_mask)
|
|
|
169 {
|
|
|
170 t_size playlist = get_active_playlist();
|
|
|
171 if (playlist != SIZE_MAX) playlist_enum_items(playlist,p_callback,p_mask);
|
|
|
172 }
|
|
|
173 void playlist_manager::activeplaylist_enum_items(enum_items_func f, const bit_array& mask) {
|
|
|
174 size_t playlist = get_active_playlist();
|
|
|
175 if (playlist != SIZE_MAX) playlist_enum_items(playlist, f, mask);
|
|
|
176 }
|
|
|
177 t_size playlist_manager::activeplaylist_get_focus_item()
|
|
|
178 {
|
|
|
179 t_size playlist = get_active_playlist();
|
|
|
180 if (playlist == SIZE_MAX) return SIZE_MAX;
|
|
|
181 else return playlist_get_focus_item(playlist);
|
|
|
182 }
|
|
|
183
|
|
|
184 bool playlist_manager::activeplaylist_get_name(pfc::string_base & p_out)
|
|
|
185 {
|
|
|
186 t_size playlist = get_active_playlist();
|
|
|
187 if (playlist == SIZE_MAX) return false;
|
|
|
188 else return playlist_get_name(playlist,p_out);
|
|
|
189 }
|
|
|
190
|
|
|
191 //modifying playlist
|
|
|
192 bool playlist_manager::activeplaylist_reorder_items(const t_size * order,t_size count)
|
|
|
193 {
|
|
|
194 t_size playlist = get_active_playlist();
|
|
|
195 if (playlist != SIZE_MAX) return playlist_reorder_items(playlist,order,count);
|
|
|
196 else return false;
|
|
|
197 }
|
|
|
198
|
|
|
199 void playlist_manager::activeplaylist_set_selection(const bit_array & affected,const bit_array & status)
|
|
|
200 {
|
|
|
201 t_size playlist = get_active_playlist();
|
|
|
202 if (playlist != SIZE_MAX) playlist_set_selection(playlist,affected,status);
|
|
|
203 }
|
|
|
204
|
|
|
205 bool playlist_manager::activeplaylist_remove_items(const bit_array & mask)
|
|
|
206 {
|
|
|
207 t_size playlist = get_active_playlist();
|
|
|
208 if (playlist != SIZE_MAX) return playlist_remove_items(playlist,mask);
|
|
|
209 else return false;
|
|
|
210 }
|
|
|
211
|
|
|
212 bool playlist_manager::activeplaylist_replace_item(t_size p_item,const metadb_handle_ptr & p_new_item)
|
|
|
213 {
|
|
|
214 t_size playlist = get_active_playlist();
|
|
|
215 if (playlist != SIZE_MAX) return playlist_replace_item(playlist,p_item,p_new_item);
|
|
|
216 else return false;
|
|
|
217 }
|
|
|
218
|
|
|
219 void playlist_manager::activeplaylist_set_focus_item(t_size p_item)
|
|
|
220 {
|
|
|
221 t_size playlist = get_active_playlist();
|
|
|
222 if (playlist != SIZE_MAX) playlist_set_focus_item(playlist,p_item);
|
|
|
223 }
|
|
|
224
|
|
|
225 t_size playlist_manager::activeplaylist_insert_items(t_size p_base,const pfc::list_base_const_t<metadb_handle_ptr> & data,const bit_array & p_selection)
|
|
|
226 {
|
|
|
227 t_size playlist = get_active_playlist();
|
|
|
228 if (playlist != SIZE_MAX) return playlist_insert_items(playlist,p_base,data,p_selection);
|
|
|
229 else return SIZE_MAX;
|
|
|
230 }
|
|
|
231
|
|
|
232 void playlist_manager::activeplaylist_ensure_visible(t_size p_item)
|
|
|
233 {
|
|
|
234 t_size playlist = get_active_playlist();
|
|
|
235 if (playlist != SIZE_MAX) playlist_ensure_visible(playlist,p_item);
|
|
|
236 }
|
|
|
237
|
|
|
238 bool playlist_manager::activeplaylist_rename(const char * p_name,t_size p_name_len)
|
|
|
239 {
|
|
|
240 t_size playlist = get_active_playlist();
|
|
|
241 if (playlist != SIZE_MAX) return playlist_rename(playlist,p_name,p_name_len);
|
|
|
242 else return false;
|
|
|
243 }
|
|
|
244
|
|
|
245 bool playlist_manager::activeplaylist_is_item_selected(t_size p_item)
|
|
|
246 {
|
|
|
247 t_size playlist = get_active_playlist();
|
|
|
248 if (playlist != pfc_infinite) return playlist_is_item_selected(playlist,p_item);
|
|
|
249 else return false;
|
|
|
250 }
|
|
|
251
|
|
|
252 metadb_handle_ptr playlist_manager::activeplaylist_get_item_handle(t_size p_item) {
|
|
|
253 metadb_handle_ptr temp;
|
|
|
254 if (!activeplaylist_get_item_handle(temp, p_item)) throw pfc::exception_invalid_params();
|
|
|
255 PFC_ASSERT( temp.is_valid() );
|
|
|
256 return temp;
|
|
|
257 }
|
|
|
258 bool playlist_manager::activeplaylist_get_item_handle(metadb_handle_ptr & p_out,t_size p_item)
|
|
|
259 {
|
|
|
260 t_size playlist = get_active_playlist();
|
|
|
261 if (playlist != SIZE_MAX) return playlist_get_item_handle(p_out,playlist,p_item);
|
|
|
262 else return false;
|
|
|
263 }
|
|
|
264
|
|
|
265 void playlist_manager::activeplaylist_move_selection(int p_delta)
|
|
|
266 {
|
|
|
267 t_size playlist = get_active_playlist();
|
|
|
268 if (playlist != SIZE_MAX) playlist_move_selection(playlist,p_delta);
|
|
|
269 }
|
|
|
270
|
|
|
271 void playlist_manager::activeplaylist_get_selection_mask(bit_array_var & out)
|
|
|
272 {
|
|
|
273 t_size playlist = get_active_playlist();
|
|
|
274 if (playlist != SIZE_MAX) playlist_get_selection_mask(playlist,out);
|
|
|
275 }
|
|
|
276
|
|
|
277 void playlist_manager::activeplaylist_get_all_items(pfc::list_base_t<metadb_handle_ptr> & out)
|
|
|
278 {
|
|
|
279 t_size playlist = get_active_playlist();
|
|
|
280 if (playlist != SIZE_MAX) playlist_get_all_items(playlist,out);
|
|
|
281 }
|
|
|
282
|
|
|
283 void playlist_manager::activeplaylist_get_selected_items(pfc::list_base_t<metadb_handle_ptr> & out)
|
|
|
284 {
|
|
|
285 t_size playlist = get_active_playlist();
|
|
|
286 if (playlist != SIZE_MAX) playlist_get_selected_items(playlist,out);
|
|
|
287 }
|
|
|
288
|
|
|
289 bool playlist_manager::remove_playlist(t_size idx)
|
|
|
290 {
|
|
|
291 return remove_playlists(pfc::bit_array_one(idx));
|
|
|
292 }
|
|
|
293
|
|
|
294 bool playlist_incoming_item_filter::process_location(const char * url,pfc::list_base_t<metadb_handle_ptr> & out,bool filter,const char * p_mask,const char * p_exclude,fb2k::hwnd_t p_parentwnd)
|
|
|
295 {
|
|
|
296 return process_locations(pfc::list_single_ref_t<const char*>(url),out,filter,p_mask,p_exclude,p_parentwnd);
|
|
|
297 }
|
|
|
298
|
|
|
299 void playlist_manager::playlist_clear(t_size p_playlist)
|
|
|
300 {
|
|
|
301 playlist_remove_items(p_playlist, pfc::bit_array_true());
|
|
|
302 }
|
|
|
303
|
|
|
304 void playlist_manager::activeplaylist_clear()
|
|
|
305 {
|
|
|
306 t_size playlist = get_active_playlist();
|
|
|
307 if (playlist != SIZE_MAX) playlist_clear(playlist);
|
|
|
308 }
|
|
|
309
|
|
|
310 bool playlist_manager::playlist_update_content(t_size playlist, metadb_handle_list_cref content, bool bUndoBackup) {
|
|
|
311 metadb_handle_list old;
|
|
|
312 playlist_get_all_items(playlist, old);
|
|
|
313 if (old.get_size() == 0) {
|
|
|
314 if (content.get_size() == 0) return false;
|
|
|
315 if (bUndoBackup) playlist_undo_backup(playlist);
|
|
|
316 playlist_add_items(playlist, content, pfc::bit_array_false());
|
|
|
317 return true;
|
|
|
318 }
|
|
|
319 pfc::avltree_t<metadb_handle::nnptr> itemsOld, itemsNew;
|
|
|
320
|
|
|
321 for(t_size walk = 0; walk < old.get_size(); ++walk) itemsOld += old[walk];
|
|
|
322 for(t_size walk = 0; walk < content.get_size(); ++walk) itemsNew += content[walk];
|
|
|
323 pfc::bit_array_bittable removeMask(old.get_size());
|
|
|
324 pfc::bit_array_bittable filterMask(content.get_size());
|
|
|
325 bool gotNew = false, filterNew = false, gotRemove = false;
|
|
|
326 for(t_size walk = 0; walk < content.get_size(); ++walk) {
|
|
|
327 const bool state = !itemsOld.have_item(content[walk]);
|
|
|
328 if (state) gotNew = true;
|
|
|
329 else filterNew = true;
|
|
|
330 filterMask.set(walk, state);
|
|
|
331 }
|
|
|
332 for(t_size walk = 0; walk < old.get_size(); ++walk) {
|
|
|
333 const bool state = !itemsNew.have_item(old[walk]);
|
|
|
334 if (state) gotRemove = true;
|
|
|
335 removeMask.set(walk, state);
|
|
|
336 }
|
|
|
337 if (!gotNew && !gotRemove) return false;
|
|
|
338 if (bUndoBackup) playlist_undo_backup(playlist);
|
|
|
339 if (gotRemove) {
|
|
|
340 playlist_remove_items(playlist, removeMask);
|
|
|
341 }
|
|
|
342 if (gotNew) {
|
|
|
343 if (filterNew) {
|
|
|
344 metadb_handle_list temp(content);
|
|
|
345 temp.filter_mask(filterMask);
|
|
|
346 playlist_add_items(playlist, temp, pfc::bit_array_false());
|
|
|
347 } else {
|
|
|
348 playlist_add_items(playlist, content, pfc::bit_array_false());
|
|
|
349 }
|
|
|
350 }
|
|
|
351
|
|
|
352 {
|
|
|
353 playlist_get_all_items(playlist, old);
|
|
|
354 pfc::array_t<t_size> order;
|
|
|
355 if (pfc::guess_reorder_pattern<pfc::list_base_const_t<metadb_handle_ptr> >(order, old, content)) {
|
|
|
356 playlist_reorder_items(playlist, order.get_ptr(), order.get_size());
|
|
|
357 }
|
|
|
358 }
|
|
|
359 return true;
|
|
|
360 }
|
|
|
361 bool playlist_manager::playlist_add_items(t_size playlist,const pfc::list_base_const_t<metadb_handle_ptr> & data,const bit_array & p_selection)
|
|
|
362 {
|
|
|
363 return playlist_insert_items(playlist, SIZE_MAX, data, p_selection) != SIZE_MAX;
|
|
|
364 }
|
|
|
365
|
|
|
366 bool playlist_manager::activeplaylist_add_items(const pfc::list_base_const_t<metadb_handle_ptr> & data,const bit_array & p_selection)
|
|
|
367 {
|
|
|
368 t_size playlist = get_active_playlist();
|
|
|
369 if (playlist != SIZE_MAX) return playlist_add_items(playlist,data,p_selection);
|
|
|
370 else return false;
|
|
|
371 }
|
|
|
372
|
|
|
373 bool playlist_manager::playlist_insert_items_filter(t_size p_playlist,t_size p_base,const pfc::list_base_const_t<metadb_handle_ptr> & p_data,bool p_select)
|
|
|
374 {
|
|
|
375 metadb_handle_list temp;
|
|
|
376 if (!playlist_incoming_item_filter::get()->filter_items(p_data,temp))
|
|
|
377 return false;
|
|
|
378 return playlist_insert_items(p_playlist,p_base,temp, pfc::bit_array_val(p_select)) != SIZE_MAX;
|
|
|
379 }
|
|
|
380
|
|
|
381 bool playlist_manager::activeplaylist_insert_items_filter(t_size p_base,const pfc::list_base_const_t<metadb_handle_ptr> & p_data,bool p_select)
|
|
|
382 {
|
|
|
383 t_size playlist = get_active_playlist();
|
|
|
384 if (playlist != SIZE_MAX) return playlist_insert_items_filter(playlist,p_base,p_data,p_select);
|
|
|
385 else return false;
|
|
|
386 }
|
|
|
387
|
|
|
388 bool playlist_manager::playlist_insert_locations(t_size p_playlist,t_size p_base,const pfc::list_base_const_t<const char*> & p_urls,bool p_select,fb2k::hwnd_t p_parentwnd)
|
|
|
389 {
|
|
|
390 metadb_handle_list temp;
|
|
|
391 if (!playlist_incoming_item_filter::get()->process_locations(p_urls,temp,true,0,0,p_parentwnd)) return false;
|
|
|
392 return playlist_insert_items(p_playlist,p_base,temp, pfc::bit_array_val(p_select)) != SIZE_MAX;
|
|
|
393 }
|
|
|
394
|
|
|
395 bool playlist_manager::activeplaylist_insert_locations(t_size p_base,const pfc::list_base_const_t<const char*> & p_urls,bool p_select,fb2k::hwnd_t p_parentwnd)
|
|
|
396 {
|
|
|
397 t_size playlist = get_active_playlist();
|
|
|
398 if (playlist != SIZE_MAX) return playlist_insert_locations(playlist,p_base,p_urls,p_select,p_parentwnd);
|
|
|
399 else return false;
|
|
|
400 }
|
|
|
401
|
|
|
402 bool playlist_manager::playlist_add_items_filter(t_size p_playlist,const pfc::list_base_const_t<metadb_handle_ptr> & p_data,bool p_select)
|
|
|
403 {
|
|
|
404 return playlist_insert_items_filter(p_playlist,SIZE_MAX,p_data,p_select);
|
|
|
405 }
|
|
|
406
|
|
|
407 bool playlist_manager::activeplaylist_add_items_filter(const pfc::list_base_const_t<metadb_handle_ptr> & p_data,bool p_select)
|
|
|
408 {
|
|
|
409 return activeplaylist_insert_items_filter(SIZE_MAX,p_data,p_select);
|
|
|
410 }
|
|
|
411
|
|
|
412 bool playlist_manager::playlist_add_locations(t_size p_playlist,const pfc::list_base_const_t<const char*> & p_urls,bool p_select,fb2k::hwnd_t p_parentwnd)
|
|
|
413 {
|
|
|
414 return playlist_insert_locations(p_playlist,SIZE_MAX,p_urls,p_select,p_parentwnd);
|
|
|
415 }
|
|
|
416 bool playlist_manager::activeplaylist_add_locations(const pfc::list_base_const_t<const char*> & p_urls,bool p_select,fb2k::hwnd_t p_parentwnd)
|
|
|
417 {
|
|
|
418 return activeplaylist_insert_locations(SIZE_MAX,p_urls,p_select,p_parentwnd);
|
|
|
419 }
|
|
|
420
|
|
|
421 void playlist_manager::reset_playing_playlist()
|
|
|
422 {
|
|
|
423 set_playing_playlist(get_active_playlist());
|
|
|
424 }
|
|
|
425
|
|
|
426 void playlist_manager::playlist_clear_selection(t_size p_playlist)
|
|
|
427 {
|
|
|
428 playlist_set_selection(p_playlist, pfc::bit_array_true(), pfc::bit_array_false());
|
|
|
429 }
|
|
|
430
|
|
|
431 void playlist_manager::activeplaylist_clear_selection()
|
|
|
432 {
|
|
|
433 t_size playlist = get_active_playlist();
|
|
|
434 if (playlist != SIZE_MAX) playlist_clear_selection(playlist);
|
|
|
435 }
|
|
|
436
|
|
|
437 void playlist_manager::activeplaylist_undo_backup()
|
|
|
438 {
|
|
|
439 t_size playlist = get_active_playlist();
|
|
|
440 if (playlist != SIZE_MAX) playlist_undo_backup(playlist);
|
|
|
441 }
|
|
|
442
|
|
|
443 bool playlist_manager::activeplaylist_undo_restore()
|
|
|
444 {
|
|
|
445 t_size playlist = get_active_playlist();
|
|
|
446 if (playlist != SIZE_MAX) return playlist_undo_restore(playlist);
|
|
|
447 else return false;
|
|
|
448 }
|
|
|
449
|
|
|
450 bool playlist_manager::activeplaylist_redo_restore()
|
|
|
451 {
|
|
|
452 t_size playlist = get_active_playlist();
|
|
|
453 if (playlist != SIZE_MAX) return playlist_redo_restore(playlist);
|
|
|
454 else return false;
|
|
|
455 }
|
|
|
456
|
|
|
457 void playlist_manager::playlist_remove_selection(t_size p_playlist,bool p_crop)
|
|
|
458 {
|
|
|
459 pfc::bit_array_bittable table(playlist_get_item_count(p_playlist));
|
|
|
460 playlist_get_selection_mask(p_playlist,table);
|
|
|
461 if (p_crop) playlist_remove_items(p_playlist, pfc::bit_array_not(table));
|
|
|
462 else playlist_remove_items(p_playlist,table);
|
|
|
463 }
|
|
|
464
|
|
|
465 void playlist_manager::activeplaylist_remove_selection(bool p_crop)
|
|
|
466 {
|
|
|
467 t_size playlist = get_active_playlist();
|
|
|
468 if (playlist != SIZE_MAX) playlist_remove_selection(playlist,p_crop);
|
|
|
469 }
|
|
|
470
|
|
|
471 void playlist_manager::activeplaylist_item_format_title(t_size p_item,titleformat_hook * p_hook,pfc::string_base & out,const service_ptr_t<titleformat_object> & p_script,titleformat_text_filter * p_filter,play_control::t_display_level p_playback_info_level)
|
|
|
472 {
|
|
|
473 t_size playlist = get_active_playlist();
|
|
|
474 if (playlist == SIZE_MAX) out = "NJET";
|
|
|
475 else playlist_item_format_title(playlist,p_item,p_hook,out,p_script,p_filter,p_playback_info_level);
|
|
|
476 }
|
|
|
477
|
|
|
478 void playlist_manager::playlist_set_selection_single(t_size p_playlist,t_size p_item,bool p_state)
|
|
|
479 {
|
|
|
480 playlist_set_selection(p_playlist, pfc::bit_array_one(p_item), pfc::bit_array_val(p_state));
|
|
|
481 }
|
|
|
482
|
|
|
483 void playlist_manager::activeplaylist_set_selection_single(t_size p_item,bool p_state)
|
|
|
484 {
|
|
|
485 t_size playlist = get_active_playlist();
|
|
|
486 if (playlist != SIZE_MAX) playlist_set_selection_single(playlist,p_item,p_state);
|
|
|
487 }
|
|
|
488
|
|
|
489 t_size playlist_manager::playlist_get_selection_count(t_size p_playlist,t_size p_max)
|
|
|
490 {
|
|
|
491 enum_items_callback_count_selection callback(p_max);
|
|
|
492 playlist_enum_items(p_playlist,callback, pfc::bit_array_true());
|
|
|
493 return callback.get_count();
|
|
|
494 }
|
|
|
495
|
|
|
496 t_size playlist_manager::activeplaylist_get_selection_count(t_size p_max)
|
|
|
497 {
|
|
|
498 t_size playlist = get_active_playlist();
|
|
|
499 if (playlist != SIZE_MAX) return playlist_get_selection_count(playlist,p_max);
|
|
|
500 else return 0;
|
|
|
501 }
|
|
|
502
|
|
|
503 bool playlist_manager::playlist_get_focus_item_handle(metadb_handle_ptr & p_out,t_size p_playlist)
|
|
|
504 {
|
|
|
505 t_size index = playlist_get_focus_item(p_playlist);
|
|
|
506 if (index == SIZE_MAX) return false;
|
|
|
507 return playlist_get_item_handle(p_out,p_playlist,index);
|
|
|
508 }
|
|
|
509
|
|
|
510 bool playlist_manager::activeplaylist_get_focus_item_handle(metadb_handle_ptr & p_out)
|
|
|
511 {
|
|
|
512 t_size playlist = get_active_playlist();
|
|
|
513 if (playlist != SIZE_MAX) return playlist_get_focus_item_handle(p_out,playlist);
|
|
|
514 else return false;
|
|
|
515 }
|
|
|
516
|
|
|
517 t_size playlist_manager::find_playlist(const char * p_name,t_size p_name_length)
|
|
|
518 {
|
|
|
519 t_size n, m = get_playlist_count();
|
|
|
520 pfc::string_formatter temp;
|
|
|
521 for(n=0;n<m;n++) {
|
|
|
522 if (!playlist_get_name(n,temp)) break;
|
|
|
523 if (stricmp_utf8_ex(temp,temp.length(),p_name,p_name_length) == 0) return n;
|
|
|
524 }
|
|
|
525 return SIZE_MAX;
|
|
|
526 }
|
|
|
527
|
|
|
528 t_size playlist_manager::find_or_create_playlist_unlocked(const char * p_name, t_size p_name_length) {
|
|
|
529 t_size n, m = get_playlist_count();
|
|
|
530 pfc::string_formatter temp;
|
|
|
531 for(n=0;n<m;n++) {
|
|
|
532 if (!playlist_lock_is_present(n) && playlist_get_name(n,temp)) {
|
|
|
533 if (stricmp_utf8_ex(temp,SIZE_MAX,p_name,p_name_length) == 0) return n;
|
|
|
534 }
|
|
|
535 }
|
|
|
536 return create_playlist(p_name,p_name_length, SIZE_MAX);
|
|
|
537 }
|
|
|
538 t_size playlist_manager::find_or_create_playlist(const char * p_name,t_size p_name_length)
|
|
|
539 {
|
|
|
540 t_size index = find_playlist(p_name,p_name_length);
|
|
|
541 if (index != SIZE_MAX) return index;
|
|
|
542 return create_playlist(p_name,p_name_length, SIZE_MAX);
|
|
|
543 }
|
|
|
544
|
|
|
545 t_size playlist_manager::create_playlist_autoname(t_size p_index) {
|
|
|
546 static const char new_playlist_text[] = "New Playlist";
|
|
|
547 if (find_playlist(new_playlist_text, SIZE_MAX) == SIZE_MAX) return create_playlist(new_playlist_text,SIZE_MAX,p_index);
|
|
|
548 for(t_size walk = 2; ; walk++) {
|
|
|
549 pfc::string_fixed_t<64> namebuffer;
|
|
|
550 namebuffer << new_playlist_text << " (" << walk << ")";
|
|
|
551 if (find_playlist(namebuffer, SIZE_MAX) == SIZE_MAX) return create_playlist(namebuffer,SIZE_MAX,p_index);
|
|
|
552 }
|
|
|
553 }
|
|
|
554
|
|
|
555 bool playlist_manager::activeplaylist_sort_by_format(const char * spec,bool p_sel_only)
|
|
|
556 {
|
|
|
557 t_size playlist = get_active_playlist();
|
|
|
558 if (playlist != pfc_infinite) return playlist_sort_by_format(playlist,spec,p_sel_only);
|
|
|
559 else return false;
|
|
|
560 }
|
|
|
561
|
|
|
562 bool playlist_manager::highlight_playing_item()
|
|
|
563 {
|
|
|
564 t_size playlist,item;
|
|
|
565 if (!get_playing_item_location(&playlist,&item)) return false;
|
|
|
566 set_active_playlist(playlist);
|
|
|
567 playlist_set_focus_item(playlist,item);
|
|
|
568 playlist_set_selection(playlist, pfc::bit_array_true(), pfc::bit_array_one(item));
|
|
|
569 playlist_ensure_visible(playlist,item);
|
|
|
570 return true;
|
|
|
571 }
|
|
|
572
|
|
|
573 void playlist_manager::playlist_get_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out,const bit_array & p_mask)
|
|
|
574 {
|
|
|
575 enum_items_callback_retrieve_all_items cb(out);
|
|
|
576 playlist_enum_items(p_playlist,cb,p_mask);
|
|
|
577 }
|
|
|
578
|
|
|
579 void playlist_manager::activeplaylist_get_items(pfc::list_base_t<metadb_handle_ptr> & out,const bit_array & p_mask)
|
|
|
580 {
|
|
|
581 t_size playlist = get_active_playlist();
|
|
|
582 if (playlist != pfc_infinite) playlist_get_items(playlist,out,p_mask);
|
|
|
583 else out.remove_all();
|
|
|
584 }
|
|
|
585
|
|
|
586 void playlist_manager::active_playlist_fix()
|
|
|
587 {
|
|
|
588 t_size playlist = get_active_playlist();
|
|
|
589 if (playlist == pfc_infinite)
|
|
|
590 {
|
|
|
591 t_size max = get_playlist_count();
|
|
|
592 if (max == 0)
|
|
|
593 {
|
|
|
594 create_playlist_autoname();
|
|
|
595 }
|
|
|
596 set_active_playlist(0);
|
|
|
597 }
|
|
|
598 }
|
|
|
599
|
|
|
600 namespace {
|
|
|
601 class enum_items_callback_remove_list : public playlist_manager::enum_items_callback
|
|
|
602 {
|
|
|
603 const metadb_handle_list & m_data;
|
|
|
604 bit_array_var & m_table;
|
|
|
605 t_size m_found;
|
|
|
606 public:
|
|
|
607 enum_items_callback_remove_list(const metadb_handle_list & p_data,bit_array_var & p_table) : m_data(p_data), m_table(p_table), m_found(0) {}
|
|
|
608 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override
|
|
|
609 {
|
|
|
610 (void)b_selected;
|
|
|
611 bool found = m_data.bsearch_by_pointer(p_location) != pfc_infinite;
|
|
|
612 m_table.set(p_index,found);
|
|
|
613 if (found) m_found++;
|
|
|
614 return true;
|
|
|
615 }
|
|
|
616
|
|
|
617 inline t_size get_found() const {return m_found;}
|
|
|
618 };
|
|
|
619 }
|
|
|
620
|
|
|
621 void playlist_manager::remove_items_from_all_playlists(const pfc::list_base_const_t<metadb_handle_ptr> & p_data)
|
|
|
622 {
|
|
|
623 t_size playlist_num, playlist_max = get_playlist_count();
|
|
|
624 if (playlist_max != pfc_infinite)
|
|
|
625 {
|
|
|
626 metadb_handle_list temp;
|
|
|
627 temp.add_items(p_data);
|
|
|
628 temp.sort_by_pointer();
|
|
|
629 for(playlist_num = 0; playlist_num < playlist_max; playlist_num++ )
|
|
|
630 {
|
|
|
631 t_size playlist_item_count = playlist_get_item_count(playlist_num);
|
|
|
632 if (playlist_item_count == pfc_infinite) break;
|
|
|
633 pfc::bit_array_bittable table(playlist_item_count);
|
|
|
634 enum_items_callback_remove_list callback(temp,table);
|
|
|
635 playlist_enum_items(playlist_num,callback, pfc::bit_array_true());
|
|
|
636 if (callback.get_found()>0)
|
|
|
637 playlist_remove_items(playlist_num,table);
|
|
|
638 }
|
|
|
639 }
|
|
|
640 }
|
|
|
641
|
|
|
642 bool playlist_manager::get_all_items(pfc::list_base_t<metadb_handle_ptr> & out)
|
|
|
643 {
|
|
|
644 t_size n, m = get_playlist_count();
|
|
|
645 if (m == pfc_infinite) return false;
|
|
|
646 enum_items_callback_retrieve_all_items callback(out);
|
|
|
647 for(n=0;n<m;n++)
|
|
|
648 {
|
|
|
649 playlist_enum_items(n,callback,pfc::bit_array_true());
|
|
|
650 }
|
|
|
651 return true;
|
|
|
652 }
|
|
|
653
|
|
|
654 t_uint32 playlist_manager::activeplaylist_lock_get_filter_mask()
|
|
|
655 {
|
|
|
656 t_size playlist = get_active_playlist();
|
|
|
657 if (playlist == SIZE_MAX) return UINT32_MAX;
|
|
|
658 else return playlist_lock_get_filter_mask(playlist);
|
|
|
659 }
|
|
|
660
|
|
|
661 bool playlist_manager::activeplaylist_is_undo_available()
|
|
|
662 {
|
|
|
663 t_size playlist = get_active_playlist();
|
|
|
664 if (playlist == pfc_infinite) return false;
|
|
|
665 else return playlist_is_undo_available(playlist);
|
|
|
666 }
|
|
|
667
|
|
|
668 bool playlist_manager::activeplaylist_is_redo_available()
|
|
|
669 {
|
|
|
670 t_size playlist = get_active_playlist();
|
|
|
671 if (playlist == pfc_infinite) return false;
|
|
|
672 else return playlist_is_redo_available(playlist);
|
|
|
673 }
|
|
|
674
|
|
|
675 bool playlist_manager::remove_playlist_user() {
|
|
|
676 size_t a = this->get_active_playlist();
|
|
|
677 if (a == SIZE_MAX) {
|
|
|
678 // FIX ME implement toast
|
|
|
679 #ifdef _WIN32
|
|
|
680 MessageBeep(0);
|
|
|
681 #endif
|
|
|
682 return false;
|
|
|
683 }
|
|
|
684 return this->remove_playlist_user(a);
|
|
|
685 }
|
|
|
686
|
|
|
687 bool playlist_manager::remove_playlist_user(size_t which) {
|
|
|
688 if (this->get_playlist_count() == 1) {
|
|
|
689 // FIX ME implement toast
|
|
|
690 #ifdef _WIN32
|
|
|
691 MessageBeep(0);
|
|
|
692 #endif
|
|
|
693 return false;
|
|
|
694 }
|
|
|
695
|
|
|
696 if (!this->remove_playlist_switch(which)) {
|
|
|
697 // FIX ME implement toast
|
|
|
698 #ifdef _WIN32
|
|
|
699 MessageBeep(0);
|
|
|
700 #endif
|
|
|
701 return false;
|
|
|
702 }
|
|
|
703 return true;
|
|
|
704 }
|
|
|
705
|
|
|
706 bool playlist_manager::remove_playlist_switch(t_size idx)
|
|
|
707 {
|
|
|
708 bool need_switch = get_active_playlist() == idx;
|
|
|
709 if (remove_playlist(idx))
|
|
|
710 {
|
|
|
711 if (need_switch)
|
|
|
712 {
|
|
|
713 t_size total = get_playlist_count();
|
|
|
714 if (total > 0)
|
|
|
715 {
|
|
|
716 if (idx >= total) idx = total-1;
|
|
|
717 set_active_playlist(idx);
|
|
|
718 }
|
|
|
719 }
|
|
|
720 return true;
|
|
|
721 }
|
|
|
722 else return false;
|
|
|
723 }
|
|
|
724
|
|
|
725
|
|
|
726
|
|
|
727 bool t_playback_queue_item::operator==(const t_playback_queue_item & p_item) const
|
|
|
728 {
|
|
|
729 return m_handle == p_item.m_handle && m_playlist == p_item.m_playlist && m_item == p_item.m_item;
|
|
|
730 }
|
|
|
731
|
|
|
732 bool t_playback_queue_item::operator!=(const t_playback_queue_item & p_item) const
|
|
|
733 {
|
|
|
734 return m_handle != p_item.m_handle || m_playlist != p_item.m_playlist || m_item != p_item.m_item;
|
|
|
735 }
|
|
|
736
|
|
|
737
|
|
|
738
|
|
|
739 bool playlist_manager::activeplaylist_execute_default_action(t_size p_item) {
|
|
|
740 t_size idx = get_active_playlist();
|
|
|
741 if (idx == pfc_infinite) return false;
|
|
|
742 else return playlist_execute_default_action(idx,p_item);
|
|
|
743 }
|
|
|
744
|
|
|
745 namespace {
|
|
|
746 class completion_notify_dfd : public completion_notify {
|
|
|
747 public:
|
|
|
748 completion_notify_dfd(const pfc::list_base_const_t<metadb_handle_ptr> & p_data,service_ptr_t<process_locations_notify> p_notify) : m_data(p_data), m_notify(p_notify) {}
|
|
|
749 void on_completion(unsigned p_code) {
|
|
|
750 switch(p_code) {
|
|
|
751 case metadb_io::load_info_aborted:
|
|
|
752 m_notify->on_aborted();
|
|
|
753 break;
|
|
|
754 default:
|
|
|
755 m_notify->on_completion(m_data);
|
|
|
756 break;
|
|
|
757 }
|
|
|
758 }
|
|
|
759 private:
|
|
|
760 metadb_handle_list m_data;
|
|
|
761 service_ptr_t<process_locations_notify> m_notify;
|
|
|
762 };
|
|
|
763 };
|
|
|
764
|
|
|
765 void dropped_files_data_impl::to_handles_async_ex(t_uint32 p_op_flags,fb2k::hwnd_t p_parentwnd,service_ptr_t<process_locations_notify> p_notify) {
|
|
|
766 if (m_is_paths) {
|
|
|
767 playlist_incoming_item_filter_v2::get()->process_locations_async(
|
|
|
768 m_paths,
|
|
|
769 p_op_flags,
|
|
|
770 NULL,
|
|
|
771 NULL,
|
|
|
772 p_parentwnd,
|
|
|
773 p_notify);
|
|
|
774 } else {
|
|
|
775 t_uint32 flags = 0;
|
|
|
776 if (p_op_flags & playlist_incoming_item_filter_v2::op_flag_background) flags |= metadb_io_v2::op_flag_background;
|
|
|
777 if (p_op_flags & playlist_incoming_item_filter_v2::op_flag_delay_ui) flags |= metadb_io_v2::op_flag_delay_ui;
|
|
|
778 metadb_io_v2::get()->load_info_async(m_handles,metadb_io::load_info_default,p_parentwnd,flags,new service_impl_t<completion_notify_dfd>(m_handles,p_notify));
|
|
|
779 }
|
|
|
780 }
|
|
|
781 void dropped_files_data_impl::to_handles_async(bool p_filter,fb2k::hwnd_t p_parentwnd,service_ptr_t<process_locations_notify> p_notify) {
|
|
|
782 to_handles_async_ex(p_filter ? 0 : playlist_incoming_item_filter_v2::op_flag_no_filter,p_parentwnd,p_notify);
|
|
|
783 }
|
|
|
784
|
|
|
785 bool dropped_files_data_impl::to_handles(pfc::list_base_t<metadb_handle_ptr> & p_out,bool p_filter,fb2k::hwnd_t p_parentwnd) {
|
|
|
786 if (m_is_paths) {
|
|
|
787 return playlist_incoming_item_filter::get()->process_locations(m_paths,p_out,p_filter,NULL,NULL,p_parentwnd);
|
|
|
788 } else {
|
|
|
789 if (metadb_io::get()->load_info_multi(m_handles,metadb_io::load_info_default,p_parentwnd,true) == metadb_io::load_info_aborted) return false;
|
|
|
790 p_out = m_handles;
|
|
|
791 return true;
|
|
|
792 }
|
|
|
793 }
|
|
|
794
|
|
|
795 void playlist_manager::playlist_activate_delta(int p_delta) {
|
|
|
796 const t_size total = get_playlist_count();
|
|
|
797 if (total > 0) {
|
|
|
798 t_size active = get_active_playlist();
|
|
|
799
|
|
|
800 //clip p_delta to -(total-1)...(total-1) range
|
|
|
801 if (p_delta < 0) {
|
|
|
802 p_delta = - ( (-p_delta) % (t_ssize)total );
|
|
|
803 } else {
|
|
|
804 p_delta = p_delta % total;
|
|
|
805 }
|
|
|
806 if (p_delta != 0) {
|
|
|
807 if (active == pfc_infinite) {
|
|
|
808 //special case when no playlist is active
|
|
|
809 if (p_delta > 0) {
|
|
|
810 active = (t_size)(p_delta - 1);
|
|
|
811 } else {
|
|
|
812 active = (total + p_delta);//p_delta is negative
|
|
|
813 }
|
|
|
814 } else {
|
|
|
815 active = (t_size) (active + total + p_delta) % total;
|
|
|
816 }
|
|
|
817 set_active_playlist(active % total);
|
|
|
818 }
|
|
|
819 }
|
|
|
820 }
|
|
|
821 namespace {
|
|
|
822 class enum_items_callback_get_selected_count : public playlist_manager::enum_items_callback {
|
|
|
823 public:
|
|
|
824 enum_items_callback_get_selected_count() : m_found() {}
|
|
|
825 t_size get_count() const {return m_found;}
|
|
|
826 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override {
|
|
|
827 (void)p_index; (void)p_location;
|
|
|
828 if (b_selected) m_found++;
|
|
|
829 return true;
|
|
|
830 }
|
|
|
831 private:
|
|
|
832 t_size m_found;
|
|
|
833 };
|
|
|
834 }
|
|
|
835 t_size playlist_manager::playlist_get_selected_count(t_size p_playlist,bit_array const & p_mask) {
|
|
|
836 enum_items_callback_get_selected_count callback;
|
|
|
837 playlist_enum_items(p_playlist,callback,p_mask);
|
|
|
838 return callback.get_count();
|
|
|
839 }
|
|
|
840
|
|
|
841 namespace {
|
|
|
842 class enum_items_callback_find_item : public playlist_manager::enum_items_callback {
|
|
|
843 public:
|
|
|
844 enum_items_callback_find_item(metadb_handle_ptr p_lookingFor) : m_lookingFor(p_lookingFor) {}
|
|
|
845 t_size result() const {return m_result;}
|
|
|
846 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override {
|
|
|
847 (void)b_selected;
|
|
|
848 if (p_location == m_lookingFor) {
|
|
|
849 m_result = p_index;
|
|
|
850 return false;
|
|
|
851 } else {
|
|
|
852 return true;
|
|
|
853 }
|
|
|
854 }
|
|
|
855 private:
|
|
|
856 metadb_handle_ptr m_lookingFor;
|
|
|
857 size_t m_result = SIZE_MAX;
|
|
|
858 };
|
|
|
859 class enum_items_callback_find_item_selected : public playlist_manager::enum_items_callback {
|
|
|
860 public:
|
|
|
861 enum_items_callback_find_item_selected(metadb_handle_ptr p_lookingFor) : m_lookingFor(p_lookingFor) {}
|
|
|
862 t_size result() const {return m_result;}
|
|
|
863 bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) {
|
|
|
864 if (b_selected && p_location == m_lookingFor) {
|
|
|
865 m_result = p_index;
|
|
|
866 return false;
|
|
|
867 } else {
|
|
|
868 return true;
|
|
|
869 }
|
|
|
870 }
|
|
|
871 private:
|
|
|
872 metadb_handle_ptr m_lookingFor;
|
|
|
873 size_t m_result = SIZE_MAX;
|
|
|
874 };
|
|
|
875 }
|
|
|
876
|
|
|
877 bool playlist_manager::playlist_find_item(t_size p_playlist,metadb_handle_ptr p_item,t_size & p_result) {
|
|
|
878 enum_items_callback_find_item callback(p_item);
|
|
|
879 playlist_enum_items(p_playlist,callback,pfc::bit_array_true());
|
|
|
880 t_size result = callback.result();
|
|
|
881 if (result == SIZE_MAX) return false;
|
|
|
882 p_result = result;
|
|
|
883 return true;
|
|
|
884 }
|
|
|
885 bool playlist_manager::playlist_find_item_selected(t_size p_playlist,metadb_handle_ptr p_item,t_size & p_result) {
|
|
|
886 enum_items_callback_find_item_selected callback(p_item);
|
|
|
887 playlist_enum_items(p_playlist,callback,pfc::bit_array_true());
|
|
|
888 t_size result = callback.result();
|
|
|
889 if (result == SIZE_MAX) return false;
|
|
|
890 p_result = result;
|
|
|
891 return true;
|
|
|
892 }
|
|
|
893 t_size playlist_manager::playlist_set_focus_by_handle(t_size p_playlist,metadb_handle_ptr p_item) {
|
|
|
894 t_size index;
|
|
|
895 if (!playlist_find_item(p_playlist,p_item,index)) index = SIZE_MAX;
|
|
|
896 playlist_set_focus_item(p_playlist,index);
|
|
|
897 return index;
|
|
|
898 }
|
|
|
899 bool playlist_manager::activeplaylist_find_item(metadb_handle_ptr p_item,t_size & p_result) {
|
|
|
900 t_size playlist = get_active_playlist();
|
|
|
901 if (playlist == SIZE_MAX) return false;
|
|
|
902 return playlist_find_item(playlist,p_item,p_result);
|
|
|
903 }
|
|
|
904 t_size playlist_manager::activeplaylist_set_focus_by_handle(metadb_handle_ptr p_item) {
|
|
|
905 t_size playlist = get_active_playlist();
|
|
|
906 if (playlist == SIZE_MAX) return SIZE_MAX;
|
|
|
907 return playlist_set_focus_by_handle(playlist,p_item);
|
|
|
908 }
|
|
|
909
|
|
|
910 #ifdef _WIN32
|
|
|
911 pfc::com_ptr_t<interface IDataObject> playlist_incoming_item_filter::create_dataobject_ex(metadb_handle_list_cref data) {
|
|
|
912 pfc::com_ptr_t<interface IDataObject> temp; temp.attach( create_dataobject(data) ); PFC_ASSERT( temp.is_valid() ); return temp;
|
|
|
913 }
|
|
|
914 #endif
|
|
|
915
|
|
|
916 void playlist_manager_v3::recycler_restore_by_id(t_uint32 id) {
|
|
|
917 t_size which = recycler_find_by_id(id);
|
|
|
918 if (which != ~0) recycler_restore(which);
|
|
|
919 }
|
|
|
920
|
|
|
921 t_size playlist_manager_v3::recycler_find_by_id(t_uint32 id) {
|
|
|
922 const t_size total = recycler_get_count();
|
|
|
923 for(t_size walk = 0; walk < total; ++walk) {
|
|
|
924 if (id == recycler_get_id(walk)) return walk;
|
|
|
925 }
|
|
|
926 return SIZE_MAX;
|
|
|
927 }
|
|
|
928
|
|
|
929
|
|
|
930
|
|
|
931 typedef pfc::map_t< const char*, metadb_handle_list, metadb::path_comparator > byPath_t;
|
|
|
932 static void rechapter_worker(playlist_manager* api, byPath_t const& byPath) {
|
|
|
933 if (byPath.get_count() == 0) return;
|
|
|
934 const size_t numPlaylists = api->get_playlist_count();
|
|
|
935 for (size_t walkPlaylist = 0; walkPlaylist < numPlaylists; ++walkPlaylist) {
|
|
|
936 if (!api->playlist_lock_is_present(walkPlaylist)) {
|
|
|
937 auto itemCount = [=] {
|
|
|
938 return api->playlist_get_item_count(walkPlaylist);
|
|
|
939 };
|
|
|
940 auto itemHandle = [=](size_t item) -> metadb_handle_ptr {
|
|
|
941 return api->playlist_get_item_handle(walkPlaylist, item);
|
|
|
942 };
|
|
|
943
|
|
|
944 for (size_t walkItem = 0; walkItem < itemCount(); ) {
|
|
|
945 auto item = itemHandle(walkItem);
|
|
|
946 auto itemPath = item->get_path();
|
|
|
947 auto match = byPath.find(itemPath);
|
|
|
948 if (match.is_valid() ) {
|
|
|
949 pfc::avltree_t<uint32_t> subsongs;
|
|
|
950 auto base = walkItem;
|
|
|
951 bool bSel = false;
|
|
|
952 for (++walkItem; walkItem < itemCount(); ++walkItem) {
|
|
|
953 auto handle = itemHandle(walkItem);
|
|
|
954 if (metadb::path_compare(itemPath, handle->get_path()) != 0) break;
|
|
|
955 if (!subsongs.add_item_check(handle->get_subsong_index())) break;
|
|
|
956
|
|
|
957 bSel = bSel || api->playlist_is_item_selected(walkPlaylist, walkItem);
|
|
|
958 }
|
|
|
959
|
|
|
960 const auto& newItems = match->m_value;
|
|
|
961 // REMOVE base ... walkItem range and insert newHandles at base
|
|
|
962 api->playlist_remove_items(walkPlaylist, pfc::bit_array_range(base, walkItem - base));
|
|
|
963 api->playlist_insert_items(walkPlaylist, base, newItems, pfc::bit_array_val(bSel));
|
|
|
964 walkItem = base + newItems.get_size();
|
|
|
965 }
|
|
|
966 else {
|
|
|
967 ++walkItem;
|
|
|
968 }
|
|
|
969 }
|
|
|
970 }
|
|
|
971 }
|
|
|
972 }
|
|
|
973
|
|
|
974 void playlist_manager::on_files_rechaptered( metadb_handle_list_cref newHandles ) {
|
|
|
975 pfc::map_t< const char*, metadb_handle_list, metadb::path_comparator > byPath;
|
|
|
976
|
|
|
977 const size_t total = newHandles.get_count();
|
|
|
978 for( size_t w = 0; w < total; ++w ) {
|
|
|
979 auto handle = newHandles[w];
|
|
|
980 byPath[ handle->get_path() ] += handle;
|
|
|
981 }
|
|
|
982
|
|
|
983 rechapter_worker(this, byPath);
|
|
|
984 }
|
|
|
985
|
|
|
986 void playlist_manager::on_file_rechaptered(const char* path, metadb_handle_list_cref newItems) {
|
|
|
987 // obsolete method
|
|
|
988 (void)path;
|
|
|
989 on_files_rechaptered(newItems);
|
|
|
990 }
|
|
|
991
|
|
|
992 namespace {
|
|
|
993 class process_locations_notify_lambda : public process_locations_notify {
|
|
|
994 public:
|
|
|
995 process_locations_notify::func_t f;
|
|
|
996 void on_completion(metadb_handle_list_cref p_items) override {
|
|
|
997 PFC_ASSERT(f != nullptr);
|
|
|
998 f(p_items);
|
|
|
999 }
|
|
|
1000 void on_aborted() override {}
|
|
|
1001 };
|
|
|
1002 }
|
|
|
1003 process_locations_notify::ptr process_locations_notify::create(func_t arg) {
|
|
|
1004 PFC_ASSERT(arg != nullptr);
|
|
|
1005 auto ret = fb2k::service_new< process_locations_notify_lambda >();
|
|
|
1006 ret->f = arg;
|
|
|
1007 return ret;
|
|
|
1008 } |