Mercurial > foo_out_sdl
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/SDK/playlist.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,1008 @@ +#include "foobar2000-sdk-pch.h" +#include "playlist.h" + +namespace { + class enum_items_callback_func : public playlist_manager::enum_items_callback { + public: + 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); } + playlist_manager::enum_items_func f; + }; + class enum_items_callback_retrieve_item : public playlist_manager::enum_items_callback + { + metadb_handle_ptr m_item; + public: + enum_items_callback_retrieve_item() : m_item(0) {} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_index; (void)b_selected; + PFC_ASSERT(m_item.is_empty()); + m_item = p_location; + return false; + } + inline const metadb_handle_ptr & get_item() {return m_item;} + }; + + class enum_items_callback_retrieve_selection : public playlist_manager::enum_items_callback + { + bool m_state; + public: + enum_items_callback_retrieve_selection() : m_state(false) {} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_index; (void)p_location; + m_state = b_selected; + return false; + } + inline bool get_state() {return m_state;} + }; + + class enum_items_callback_retrieve_selection_mask : public playlist_manager::enum_items_callback + { + bit_array_var & m_out; + public: + enum_items_callback_retrieve_selection_mask(bit_array_var & p_out) : m_out(p_out) {} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_location; + m_out.set(p_index,b_selected); + return true; + } + }; + + class enum_items_callback_retrieve_all_items : public playlist_manager::enum_items_callback + { + pfc::list_base_t<metadb_handle_ptr> & m_out; + public: + enum_items_callback_retrieve_all_items(pfc::list_base_t<metadb_handle_ptr> & p_out) : m_out(p_out) {m_out.remove_all();} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_index; (void)b_selected; + m_out.add_item(p_location); + return true; + } + }; + + class enum_items_callback_retrieve_selected_items : public playlist_manager::enum_items_callback + { + pfc::list_base_t<metadb_handle_ptr> & m_out; + public: + enum_items_callback_retrieve_selected_items(pfc::list_base_t<metadb_handle_ptr> & p_out) : m_out(p_out) {m_out.remove_all();} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_index; + if (b_selected) m_out.add_item(p_location); + return true; + } + }; + + class enum_items_callback_count_selection : public playlist_manager::enum_items_callback + { + t_size m_counter,m_max; + public: + enum_items_callback_count_selection(t_size p_max) : m_max(p_max), m_counter(0) {} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) + { + (void)p_index; (void)p_location; + if (b_selected) + { + if (++m_counter >= m_max) return false; + } + return true; + } + + inline t_size get_count() {return m_counter;} + }; + +} + +void playlist_manager::playlist_get_all_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out) +{ + playlist_get_items(p_playlist,out, pfc::bit_array_true()); +} + +void playlist_manager::playlist_get_selected_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out) +{ + enum_items_callback_retrieve_selected_items cb(out); + playlist_enum_items(p_playlist,cb,pfc::bit_array_true()); +} + +void playlist_manager::playlist_get_selection_mask(t_size p_playlist,bit_array_var & out) +{ + enum_items_callback_retrieve_selection_mask cb(out); + playlist_enum_items(p_playlist,cb,pfc::bit_array_true()); +} + +bool playlist_manager::playlist_is_item_selected(t_size p_playlist,t_size p_item) +{ + enum_items_callback_retrieve_selection callback; + playlist_enum_items(p_playlist,callback,pfc::bit_array_one(p_item)); + return callback.get_state(); +} + +metadb_handle_ptr playlist_manager::playlist_get_item_handle(t_size playlist, t_size item) { + metadb_handle_ptr temp; + if (!playlist_get_item_handle(temp, playlist, item)) throw pfc::exception_invalid_params(); + PFC_ASSERT( temp.is_valid() ); + return temp; + +} +bool playlist_manager::playlist_get_item_handle(metadb_handle_ptr & p_out,t_size p_playlist,t_size p_item) +{ + enum_items_callback_retrieve_item callback; + playlist_enum_items(p_playlist,callback,pfc::bit_array_one(p_item)); + p_out = callback.get_item(); + return p_out.is_valid(); +} + +void playlist_manager::g_make_selection_move_permutation(t_size * p_output,t_size p_count,const bit_array & p_selection,int p_delta) { + pfc::create_move_items_permutation(p_output,p_count,p_selection,p_delta); +} + +bool playlist_manager::playlist_move_selection(t_size p_playlist,int p_delta) { + if (p_delta==0) return true; + + t_size count = playlist_get_item_count(p_playlist); + + pfc::array_t<t_size> order; order.set_size(count); + pfc::array_t<bool> selection; selection.set_size(count); + + pfc::bit_array_var_table mask(selection.get_ptr(),selection.get_size()); + playlist_get_selection_mask(p_playlist, mask); + g_make_selection_move_permutation(order.get_ptr(),count,mask,p_delta); + return playlist_reorder_items(p_playlist,order.get_ptr(),count); +} + +//retrieving status +t_size playlist_manager::activeplaylist_get_item_count() +{ + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return 0; + else return playlist_get_item_count(playlist); +} + +void playlist_manager::playlist_enum_items(size_t which, enum_items_func f, const bit_array& mask) { + enum_items_callback_func cb; cb.f = f; + this->playlist_enum_items(which, cb, mask); +} + +void playlist_manager::activeplaylist_enum_items(enum_items_callback & p_callback,const bit_array & p_mask) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_enum_items(playlist,p_callback,p_mask); +} +void playlist_manager::activeplaylist_enum_items(enum_items_func f, const bit_array& mask) { + size_t playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_enum_items(playlist, f, mask); +} +t_size playlist_manager::activeplaylist_get_focus_item() +{ + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return SIZE_MAX; + else return playlist_get_focus_item(playlist); +} + +bool playlist_manager::activeplaylist_get_name(pfc::string_base & p_out) +{ + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return false; + else return playlist_get_name(playlist,p_out); +} + +//modifying playlist +bool playlist_manager::activeplaylist_reorder_items(const t_size * order,t_size count) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_reorder_items(playlist,order,count); + else return false; +} + +void playlist_manager::activeplaylist_set_selection(const bit_array & affected,const bit_array & status) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_set_selection(playlist,affected,status); +} + +bool playlist_manager::activeplaylist_remove_items(const bit_array & mask) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_remove_items(playlist,mask); + else return false; +} + +bool playlist_manager::activeplaylist_replace_item(t_size p_item,const metadb_handle_ptr & p_new_item) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_replace_item(playlist,p_item,p_new_item); + else return false; +} + +void playlist_manager::activeplaylist_set_focus_item(t_size p_item) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_set_focus_item(playlist,p_item); +} + +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) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_insert_items(playlist,p_base,data,p_selection); + else return SIZE_MAX; +} + +void playlist_manager::activeplaylist_ensure_visible(t_size p_item) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_ensure_visible(playlist,p_item); +} + +bool playlist_manager::activeplaylist_rename(const char * p_name,t_size p_name_len) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_rename(playlist,p_name,p_name_len); + else return false; +} + +bool playlist_manager::activeplaylist_is_item_selected(t_size p_item) +{ + t_size playlist = get_active_playlist(); + if (playlist != pfc_infinite) return playlist_is_item_selected(playlist,p_item); + else return false; +} + +metadb_handle_ptr playlist_manager::activeplaylist_get_item_handle(t_size p_item) { + metadb_handle_ptr temp; + if (!activeplaylist_get_item_handle(temp, p_item)) throw pfc::exception_invalid_params(); + PFC_ASSERT( temp.is_valid() ); + return temp; +} +bool playlist_manager::activeplaylist_get_item_handle(metadb_handle_ptr & p_out,t_size p_item) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_get_item_handle(p_out,playlist,p_item); + else return false; +} + +void playlist_manager::activeplaylist_move_selection(int p_delta) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_move_selection(playlist,p_delta); +} + +void playlist_manager::activeplaylist_get_selection_mask(bit_array_var & out) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_get_selection_mask(playlist,out); +} + +void playlist_manager::activeplaylist_get_all_items(pfc::list_base_t<metadb_handle_ptr> & out) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_get_all_items(playlist,out); +} + +void playlist_manager::activeplaylist_get_selected_items(pfc::list_base_t<metadb_handle_ptr> & out) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_get_selected_items(playlist,out); +} + +bool playlist_manager::remove_playlist(t_size idx) +{ + return remove_playlists(pfc::bit_array_one(idx)); +} + +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) +{ + return process_locations(pfc::list_single_ref_t<const char*>(url),out,filter,p_mask,p_exclude,p_parentwnd); +} + +void playlist_manager::playlist_clear(t_size p_playlist) +{ + playlist_remove_items(p_playlist, pfc::bit_array_true()); +} + +void playlist_manager::activeplaylist_clear() +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_clear(playlist); +} + +bool playlist_manager::playlist_update_content(t_size playlist, metadb_handle_list_cref content, bool bUndoBackup) { + metadb_handle_list old; + playlist_get_all_items(playlist, old); + if (old.get_size() == 0) { + if (content.get_size() == 0) return false; + if (bUndoBackup) playlist_undo_backup(playlist); + playlist_add_items(playlist, content, pfc::bit_array_false()); + return true; + } + pfc::avltree_t<metadb_handle::nnptr> itemsOld, itemsNew; + + for(t_size walk = 0; walk < old.get_size(); ++walk) itemsOld += old[walk]; + for(t_size walk = 0; walk < content.get_size(); ++walk) itemsNew += content[walk]; + pfc::bit_array_bittable removeMask(old.get_size()); + pfc::bit_array_bittable filterMask(content.get_size()); + bool gotNew = false, filterNew = false, gotRemove = false; + for(t_size walk = 0; walk < content.get_size(); ++walk) { + const bool state = !itemsOld.have_item(content[walk]); + if (state) gotNew = true; + else filterNew = true; + filterMask.set(walk, state); + } + for(t_size walk = 0; walk < old.get_size(); ++walk) { + const bool state = !itemsNew.have_item(old[walk]); + if (state) gotRemove = true; + removeMask.set(walk, state); + } + if (!gotNew && !gotRemove) return false; + if (bUndoBackup) playlist_undo_backup(playlist); + if (gotRemove) { + playlist_remove_items(playlist, removeMask); + } + if (gotNew) { + if (filterNew) { + metadb_handle_list temp(content); + temp.filter_mask(filterMask); + playlist_add_items(playlist, temp, pfc::bit_array_false()); + } else { + playlist_add_items(playlist, content, pfc::bit_array_false()); + } + } + + { + playlist_get_all_items(playlist, old); + pfc::array_t<t_size> order; + if (pfc::guess_reorder_pattern<pfc::list_base_const_t<metadb_handle_ptr> >(order, old, content)) { + playlist_reorder_items(playlist, order.get_ptr(), order.get_size()); + } + } + return true; +} +bool playlist_manager::playlist_add_items(t_size playlist,const pfc::list_base_const_t<metadb_handle_ptr> & data,const bit_array & p_selection) +{ + return playlist_insert_items(playlist, SIZE_MAX, data, p_selection) != SIZE_MAX; +} + +bool playlist_manager::activeplaylist_add_items(const pfc::list_base_const_t<metadb_handle_ptr> & data,const bit_array & p_selection) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_add_items(playlist,data,p_selection); + else return false; +} + +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) +{ + metadb_handle_list temp; + if (!playlist_incoming_item_filter::get()->filter_items(p_data,temp)) + return false; + return playlist_insert_items(p_playlist,p_base,temp, pfc::bit_array_val(p_select)) != SIZE_MAX; +} + +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) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_insert_items_filter(playlist,p_base,p_data,p_select); + else return false; +} + +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) +{ + metadb_handle_list temp; + if (!playlist_incoming_item_filter::get()->process_locations(p_urls,temp,true,0,0,p_parentwnd)) return false; + return playlist_insert_items(p_playlist,p_base,temp, pfc::bit_array_val(p_select)) != SIZE_MAX; +} + +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) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_insert_locations(playlist,p_base,p_urls,p_select,p_parentwnd); + else return false; +} + +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) +{ + return playlist_insert_items_filter(p_playlist,SIZE_MAX,p_data,p_select); +} + +bool playlist_manager::activeplaylist_add_items_filter(const pfc::list_base_const_t<metadb_handle_ptr> & p_data,bool p_select) +{ + return activeplaylist_insert_items_filter(SIZE_MAX,p_data,p_select); +} + +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) +{ + return playlist_insert_locations(p_playlist,SIZE_MAX,p_urls,p_select,p_parentwnd); +} +bool playlist_manager::activeplaylist_add_locations(const pfc::list_base_const_t<const char*> & p_urls,bool p_select,fb2k::hwnd_t p_parentwnd) +{ + return activeplaylist_insert_locations(SIZE_MAX,p_urls,p_select,p_parentwnd); +} + +void playlist_manager::reset_playing_playlist() +{ + set_playing_playlist(get_active_playlist()); +} + +void playlist_manager::playlist_clear_selection(t_size p_playlist) +{ + playlist_set_selection(p_playlist, pfc::bit_array_true(), pfc::bit_array_false()); +} + +void playlist_manager::activeplaylist_clear_selection() +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_clear_selection(playlist); +} + +void playlist_manager::activeplaylist_undo_backup() +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_undo_backup(playlist); +} + +bool playlist_manager::activeplaylist_undo_restore() +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_undo_restore(playlist); + else return false; +} + +bool playlist_manager::activeplaylist_redo_restore() +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_redo_restore(playlist); + else return false; +} + +void playlist_manager::playlist_remove_selection(t_size p_playlist,bool p_crop) +{ + pfc::bit_array_bittable table(playlist_get_item_count(p_playlist)); + playlist_get_selection_mask(p_playlist,table); + if (p_crop) playlist_remove_items(p_playlist, pfc::bit_array_not(table)); + else playlist_remove_items(p_playlist,table); +} + +void playlist_manager::activeplaylist_remove_selection(bool p_crop) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_remove_selection(playlist,p_crop); +} + +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) +{ + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) out = "NJET"; + else playlist_item_format_title(playlist,p_item,p_hook,out,p_script,p_filter,p_playback_info_level); +} + +void playlist_manager::playlist_set_selection_single(t_size p_playlist,t_size p_item,bool p_state) +{ + playlist_set_selection(p_playlist, pfc::bit_array_one(p_item), pfc::bit_array_val(p_state)); +} + +void playlist_manager::activeplaylist_set_selection_single(t_size p_item,bool p_state) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) playlist_set_selection_single(playlist,p_item,p_state); +} + +t_size playlist_manager::playlist_get_selection_count(t_size p_playlist,t_size p_max) +{ + enum_items_callback_count_selection callback(p_max); + playlist_enum_items(p_playlist,callback, pfc::bit_array_true()); + return callback.get_count(); +} + +t_size playlist_manager::activeplaylist_get_selection_count(t_size p_max) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_get_selection_count(playlist,p_max); + else return 0; +} + +bool playlist_manager::playlist_get_focus_item_handle(metadb_handle_ptr & p_out,t_size p_playlist) +{ + t_size index = playlist_get_focus_item(p_playlist); + if (index == SIZE_MAX) return false; + return playlist_get_item_handle(p_out,p_playlist,index); +} + +bool playlist_manager::activeplaylist_get_focus_item_handle(metadb_handle_ptr & p_out) +{ + t_size playlist = get_active_playlist(); + if (playlist != SIZE_MAX) return playlist_get_focus_item_handle(p_out,playlist); + else return false; +} + +t_size playlist_manager::find_playlist(const char * p_name,t_size p_name_length) +{ + t_size n, m = get_playlist_count(); + pfc::string_formatter temp; + for(n=0;n<m;n++) { + if (!playlist_get_name(n,temp)) break; + if (stricmp_utf8_ex(temp,temp.length(),p_name,p_name_length) == 0) return n; + } + return SIZE_MAX; +} + +t_size playlist_manager::find_or_create_playlist_unlocked(const char * p_name, t_size p_name_length) { + t_size n, m = get_playlist_count(); + pfc::string_formatter temp; + for(n=0;n<m;n++) { + if (!playlist_lock_is_present(n) && playlist_get_name(n,temp)) { + if (stricmp_utf8_ex(temp,SIZE_MAX,p_name,p_name_length) == 0) return n; + } + } + return create_playlist(p_name,p_name_length, SIZE_MAX); +} +t_size playlist_manager::find_or_create_playlist(const char * p_name,t_size p_name_length) +{ + t_size index = find_playlist(p_name,p_name_length); + if (index != SIZE_MAX) return index; + return create_playlist(p_name,p_name_length, SIZE_MAX); +} + +t_size playlist_manager::create_playlist_autoname(t_size p_index) { + static const char new_playlist_text[] = "New Playlist"; + if (find_playlist(new_playlist_text, SIZE_MAX) == SIZE_MAX) return create_playlist(new_playlist_text,SIZE_MAX,p_index); + for(t_size walk = 2; ; walk++) { + pfc::string_fixed_t<64> namebuffer; + namebuffer << new_playlist_text << " (" << walk << ")"; + if (find_playlist(namebuffer, SIZE_MAX) == SIZE_MAX) return create_playlist(namebuffer,SIZE_MAX,p_index); + } +} + +bool playlist_manager::activeplaylist_sort_by_format(const char * spec,bool p_sel_only) +{ + t_size playlist = get_active_playlist(); + if (playlist != pfc_infinite) return playlist_sort_by_format(playlist,spec,p_sel_only); + else return false; +} + +bool playlist_manager::highlight_playing_item() +{ + t_size playlist,item; + if (!get_playing_item_location(&playlist,&item)) return false; + set_active_playlist(playlist); + playlist_set_focus_item(playlist,item); + playlist_set_selection(playlist, pfc::bit_array_true(), pfc::bit_array_one(item)); + playlist_ensure_visible(playlist,item); + return true; +} + +void playlist_manager::playlist_get_items(t_size p_playlist,pfc::list_base_t<metadb_handle_ptr> & out,const bit_array & p_mask) +{ + enum_items_callback_retrieve_all_items cb(out); + playlist_enum_items(p_playlist,cb,p_mask); +} + +void playlist_manager::activeplaylist_get_items(pfc::list_base_t<metadb_handle_ptr> & out,const bit_array & p_mask) +{ + t_size playlist = get_active_playlist(); + if (playlist != pfc_infinite) playlist_get_items(playlist,out,p_mask); + else out.remove_all(); +} + +void playlist_manager::active_playlist_fix() +{ + t_size playlist = get_active_playlist(); + if (playlist == pfc_infinite) + { + t_size max = get_playlist_count(); + if (max == 0) + { + create_playlist_autoname(); + } + set_active_playlist(0); + } +} + +namespace { + class enum_items_callback_remove_list : public playlist_manager::enum_items_callback + { + const metadb_handle_list & m_data; + bit_array_var & m_table; + t_size m_found; + public: + 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) {} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override + { + (void)b_selected; + bool found = m_data.bsearch_by_pointer(p_location) != pfc_infinite; + m_table.set(p_index,found); + if (found) m_found++; + return true; + } + + inline t_size get_found() const {return m_found;} + }; +} + +void playlist_manager::remove_items_from_all_playlists(const pfc::list_base_const_t<metadb_handle_ptr> & p_data) +{ + t_size playlist_num, playlist_max = get_playlist_count(); + if (playlist_max != pfc_infinite) + { + metadb_handle_list temp; + temp.add_items(p_data); + temp.sort_by_pointer(); + for(playlist_num = 0; playlist_num < playlist_max; playlist_num++ ) + { + t_size playlist_item_count = playlist_get_item_count(playlist_num); + if (playlist_item_count == pfc_infinite) break; + pfc::bit_array_bittable table(playlist_item_count); + enum_items_callback_remove_list callback(temp,table); + playlist_enum_items(playlist_num,callback, pfc::bit_array_true()); + if (callback.get_found()>0) + playlist_remove_items(playlist_num,table); + } + } +} + +bool playlist_manager::get_all_items(pfc::list_base_t<metadb_handle_ptr> & out) +{ + t_size n, m = get_playlist_count(); + if (m == pfc_infinite) return false; + enum_items_callback_retrieve_all_items callback(out); + for(n=0;n<m;n++) + { + playlist_enum_items(n,callback,pfc::bit_array_true()); + } + return true; +} + +t_uint32 playlist_manager::activeplaylist_lock_get_filter_mask() +{ + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return UINT32_MAX; + else return playlist_lock_get_filter_mask(playlist); +} + +bool playlist_manager::activeplaylist_is_undo_available() +{ + t_size playlist = get_active_playlist(); + if (playlist == pfc_infinite) return false; + else return playlist_is_undo_available(playlist); +} + +bool playlist_manager::activeplaylist_is_redo_available() +{ + t_size playlist = get_active_playlist(); + if (playlist == pfc_infinite) return false; + else return playlist_is_redo_available(playlist); +} + +bool playlist_manager::remove_playlist_user() { + size_t a = this->get_active_playlist(); + if (a == SIZE_MAX) { + // FIX ME implement toast +#ifdef _WIN32 + MessageBeep(0); +#endif + return false; + } + return this->remove_playlist_user(a); +} + +bool playlist_manager::remove_playlist_user(size_t which) { + if (this->get_playlist_count() == 1) { + // FIX ME implement toast +#ifdef _WIN32 + MessageBeep(0); +#endif + return false; + } + + if (!this->remove_playlist_switch(which)) { + // FIX ME implement toast +#ifdef _WIN32 + MessageBeep(0); +#endif + return false; + } + return true; +} + +bool playlist_manager::remove_playlist_switch(t_size idx) +{ + bool need_switch = get_active_playlist() == idx; + if (remove_playlist(idx)) + { + if (need_switch) + { + t_size total = get_playlist_count(); + if (total > 0) + { + if (idx >= total) idx = total-1; + set_active_playlist(idx); + } + } + return true; + } + else return false; +} + + + +bool t_playback_queue_item::operator==(const t_playback_queue_item & p_item) const +{ + return m_handle == p_item.m_handle && m_playlist == p_item.m_playlist && m_item == p_item.m_item; +} + +bool t_playback_queue_item::operator!=(const t_playback_queue_item & p_item) const +{ + return m_handle != p_item.m_handle || m_playlist != p_item.m_playlist || m_item != p_item.m_item; +} + + + +bool playlist_manager::activeplaylist_execute_default_action(t_size p_item) { + t_size idx = get_active_playlist(); + if (idx == pfc_infinite) return false; + else return playlist_execute_default_action(idx,p_item); +} + +namespace { + class completion_notify_dfd : public completion_notify { + public: + 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) {} + void on_completion(unsigned p_code) { + switch(p_code) { + case metadb_io::load_info_aborted: + m_notify->on_aborted(); + break; + default: + m_notify->on_completion(m_data); + break; + } + } + private: + metadb_handle_list m_data; + service_ptr_t<process_locations_notify> m_notify; + }; +}; + +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) { + if (m_is_paths) { + playlist_incoming_item_filter_v2::get()->process_locations_async( + m_paths, + p_op_flags, + NULL, + NULL, + p_parentwnd, + p_notify); + } else { + t_uint32 flags = 0; + if (p_op_flags & playlist_incoming_item_filter_v2::op_flag_background) flags |= metadb_io_v2::op_flag_background; + if (p_op_flags & playlist_incoming_item_filter_v2::op_flag_delay_ui) flags |= metadb_io_v2::op_flag_delay_ui; + 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)); + } +} +void dropped_files_data_impl::to_handles_async(bool p_filter,fb2k::hwnd_t p_parentwnd,service_ptr_t<process_locations_notify> p_notify) { + to_handles_async_ex(p_filter ? 0 : playlist_incoming_item_filter_v2::op_flag_no_filter,p_parentwnd,p_notify); +} + +bool dropped_files_data_impl::to_handles(pfc::list_base_t<metadb_handle_ptr> & p_out,bool p_filter,fb2k::hwnd_t p_parentwnd) { + if (m_is_paths) { + return playlist_incoming_item_filter::get()->process_locations(m_paths,p_out,p_filter,NULL,NULL,p_parentwnd); + } else { + if (metadb_io::get()->load_info_multi(m_handles,metadb_io::load_info_default,p_parentwnd,true) == metadb_io::load_info_aborted) return false; + p_out = m_handles; + return true; + } +} + +void playlist_manager::playlist_activate_delta(int p_delta) { + const t_size total = get_playlist_count(); + if (total > 0) { + t_size active = get_active_playlist(); + + //clip p_delta to -(total-1)...(total-1) range + if (p_delta < 0) { + p_delta = - ( (-p_delta) % (t_ssize)total ); + } else { + p_delta = p_delta % total; + } + if (p_delta != 0) { + if (active == pfc_infinite) { + //special case when no playlist is active + if (p_delta > 0) { + active = (t_size)(p_delta - 1); + } else { + active = (total + p_delta);//p_delta is negative + } + } else { + active = (t_size) (active + total + p_delta) % total; + } + set_active_playlist(active % total); + } + } +} +namespace { + class enum_items_callback_get_selected_count : public playlist_manager::enum_items_callback { + public: + enum_items_callback_get_selected_count() : m_found() {} + t_size get_count() const {return m_found;} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override { + (void)p_index; (void)p_location; + if (b_selected) m_found++; + return true; + } + private: + t_size m_found; + }; +} +t_size playlist_manager::playlist_get_selected_count(t_size p_playlist,bit_array const & p_mask) { + enum_items_callback_get_selected_count callback; + playlist_enum_items(p_playlist,callback,p_mask); + return callback.get_count(); +} + +namespace { + class enum_items_callback_find_item : public playlist_manager::enum_items_callback { + public: + enum_items_callback_find_item(metadb_handle_ptr p_lookingFor) : m_lookingFor(p_lookingFor) {} + t_size result() const {return m_result;} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) override { + (void)b_selected; + if (p_location == m_lookingFor) { + m_result = p_index; + return false; + } else { + return true; + } + } + private: + metadb_handle_ptr m_lookingFor; + size_t m_result = SIZE_MAX; + }; + class enum_items_callback_find_item_selected : public playlist_manager::enum_items_callback { + public: + enum_items_callback_find_item_selected(metadb_handle_ptr p_lookingFor) : m_lookingFor(p_lookingFor) {} + t_size result() const {return m_result;} + bool on_item(t_size p_index,const metadb_handle_ptr & p_location,bool b_selected) { + if (b_selected && p_location == m_lookingFor) { + m_result = p_index; + return false; + } else { + return true; + } + } + private: + metadb_handle_ptr m_lookingFor; + size_t m_result = SIZE_MAX; + }; +} + +bool playlist_manager::playlist_find_item(t_size p_playlist,metadb_handle_ptr p_item,t_size & p_result) { + enum_items_callback_find_item callback(p_item); + playlist_enum_items(p_playlist,callback,pfc::bit_array_true()); + t_size result = callback.result(); + if (result == SIZE_MAX) return false; + p_result = result; + return true; +} +bool playlist_manager::playlist_find_item_selected(t_size p_playlist,metadb_handle_ptr p_item,t_size & p_result) { + enum_items_callback_find_item_selected callback(p_item); + playlist_enum_items(p_playlist,callback,pfc::bit_array_true()); + t_size result = callback.result(); + if (result == SIZE_MAX) return false; + p_result = result; + return true; +} +t_size playlist_manager::playlist_set_focus_by_handle(t_size p_playlist,metadb_handle_ptr p_item) { + t_size index; + if (!playlist_find_item(p_playlist,p_item,index)) index = SIZE_MAX; + playlist_set_focus_item(p_playlist,index); + return index; +} +bool playlist_manager::activeplaylist_find_item(metadb_handle_ptr p_item,t_size & p_result) { + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return false; + return playlist_find_item(playlist,p_item,p_result); +} +t_size playlist_manager::activeplaylist_set_focus_by_handle(metadb_handle_ptr p_item) { + t_size playlist = get_active_playlist(); + if (playlist == SIZE_MAX) return SIZE_MAX; + return playlist_set_focus_by_handle(playlist,p_item); +} + +#ifdef _WIN32 +pfc::com_ptr_t<interface IDataObject> playlist_incoming_item_filter::create_dataobject_ex(metadb_handle_list_cref data) { + pfc::com_ptr_t<interface IDataObject> temp; temp.attach( create_dataobject(data) ); PFC_ASSERT( temp.is_valid() ); return temp; +} +#endif + +void playlist_manager_v3::recycler_restore_by_id(t_uint32 id) { + t_size which = recycler_find_by_id(id); + if (which != ~0) recycler_restore(which); +} + +t_size playlist_manager_v3::recycler_find_by_id(t_uint32 id) { + const t_size total = recycler_get_count(); + for(t_size walk = 0; walk < total; ++walk) { + if (id == recycler_get_id(walk)) return walk; + } + return SIZE_MAX; +} + + + +typedef pfc::map_t< const char*, metadb_handle_list, metadb::path_comparator > byPath_t; +static void rechapter_worker(playlist_manager* api, byPath_t const& byPath) { + if (byPath.get_count() == 0) return; + const size_t numPlaylists = api->get_playlist_count(); + for (size_t walkPlaylist = 0; walkPlaylist < numPlaylists; ++walkPlaylist) { + if (!api->playlist_lock_is_present(walkPlaylist)) { + auto itemCount = [=] { + return api->playlist_get_item_count(walkPlaylist); + }; + auto itemHandle = [=](size_t item) -> metadb_handle_ptr { + return api->playlist_get_item_handle(walkPlaylist, item); + }; + + for (size_t walkItem = 0; walkItem < itemCount(); ) { + auto item = itemHandle(walkItem); + auto itemPath = item->get_path(); + auto match = byPath.find(itemPath); + if (match.is_valid() ) { + pfc::avltree_t<uint32_t> subsongs; + auto base = walkItem; + bool bSel = false; + for (++walkItem; walkItem < itemCount(); ++walkItem) { + auto handle = itemHandle(walkItem); + if (metadb::path_compare(itemPath, handle->get_path()) != 0) break; + if (!subsongs.add_item_check(handle->get_subsong_index())) break; + + bSel = bSel || api->playlist_is_item_selected(walkPlaylist, walkItem); + } + + const auto& newItems = match->m_value; + // REMOVE base ... walkItem range and insert newHandles at base + api->playlist_remove_items(walkPlaylist, pfc::bit_array_range(base, walkItem - base)); + api->playlist_insert_items(walkPlaylist, base, newItems, pfc::bit_array_val(bSel)); + walkItem = base + newItems.get_size(); + } + else { + ++walkItem; + } + } + } + } +} + +void playlist_manager::on_files_rechaptered( metadb_handle_list_cref newHandles ) { + pfc::map_t< const char*, metadb_handle_list, metadb::path_comparator > byPath; + + const size_t total = newHandles.get_count(); + for( size_t w = 0; w < total; ++w ) { + auto handle = newHandles[w]; + byPath[ handle->get_path() ] += handle; + } + + rechapter_worker(this, byPath); +} + +void playlist_manager::on_file_rechaptered(const char* path, metadb_handle_list_cref newItems) { + // obsolete method + (void)path; + on_files_rechaptered(newItems); +} + +namespace { + class process_locations_notify_lambda : public process_locations_notify { + public: + process_locations_notify::func_t f; + void on_completion(metadb_handle_list_cref p_items) override { + PFC_ASSERT(f != nullptr); + f(p_items); + } + void on_aborted() override {} + }; +} +process_locations_notify::ptr process_locations_notify::create(func_t arg) { + PFC_ASSERT(arg != nullptr); + auto ret = fb2k::service_new< process_locations_notify_lambda >(); + ret->f = arg; + return ret; +} \ No newline at end of file
