Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/SDK/playlist.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 "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 } |
