|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 #include <functional>
|
|
|
4 #include "metadb_handle.h"
|
|
|
5
|
|
|
6 class file_info_filter; // forward decl; file_info_filter moved to file_info_filter.h
|
|
|
7
|
|
|
8 class metadb_io_callback_dynamic; class metadb_io_callback_v2_dynamic;
|
|
|
9
|
|
|
10
|
|
|
11 //! API for tag read/write operations. Legal to call from main thread only, except for hint_multi_async() / hint_async() / hint_reader().\n
|
|
|
12 //! Implemented only by core, do not reimplement.\n
|
|
|
13 //! Use static_api_ptr_t template to access metadb_io methods.\n
|
|
|
14 //! WARNING: Methods that perform file access (tag reads/writes) run a modal message loop. They SHOULD NOT be called from global callbacks and such.
|
|
|
15 class NOVTABLE metadb_io : public service_base
|
|
|
16 {
|
|
|
17 public:
|
|
|
18 enum t_load_info_type {
|
|
|
19 load_info_default,
|
|
|
20 load_info_force,
|
|
|
21 load_info_check_if_changed
|
|
|
22 };
|
|
|
23
|
|
|
24 enum t_update_info_state {
|
|
|
25 update_info_success,
|
|
|
26 update_info_aborted,
|
|
|
27 update_info_errors,
|
|
|
28 };
|
|
|
29
|
|
|
30 enum t_load_info_state {
|
|
|
31 load_info_success,
|
|
|
32 load_info_aborted,
|
|
|
33 load_info_errors,
|
|
|
34 };
|
|
|
35
|
|
|
36 //! No longer used - returns false always.
|
|
|
37 FB2K_DEPRECATED virtual bool is_busy() = 0;
|
|
|
38 //! No longer used - returns false always.
|
|
|
39 FB2K_DEPRECATED virtual bool is_updating_disabled() = 0;
|
|
|
40 //! No longer used - returns false always.
|
|
|
41 FB2K_DEPRECATED virtual bool is_file_updating_blocked() = 0;
|
|
|
42 //! No longer used.
|
|
|
43 FB2K_DEPRECATED virtual void highlight_running_process() = 0;
|
|
|
44 //! Loads tags from multiple items. Use the async version in metadb_io_v2 instead if possible.
|
|
|
45 FB2K_DEPRECATED virtual t_load_info_state load_info_multi(metadb_handle_list_cref p_list,t_load_info_type p_type,fb2k::hwnd_t p_parent_window,bool p_show_errors) = 0;
|
|
|
46 //! Updates tags on multiple items. Use the async version in metadb_io_v2 instead if possible.
|
|
|
47 FB2K_DEPRECATED virtual t_update_info_state update_info_multi(metadb_handle_list_cref p_list,const pfc::list_base_const_t<file_info*> & p_new_info,fb2k::hwnd_t p_parent_window,bool p_show_errors) = 0;
|
|
|
48 //! Rewrites tags on multiple items. Use the async version in metadb_io_v2 instead if possible.
|
|
|
49 FB2K_DEPRECATED virtual t_update_info_state rewrite_info_multi(metadb_handle_list_cref p_list,fb2k::hwnd_t p_parent_window,bool p_show_errors) = 0;
|
|
|
50 //! Removes tags from multiple items. Use the async version in metadb_io_v2 instead if possible.
|
|
|
51 FB2K_DEPRECATED virtual t_update_info_state remove_info_multi(metadb_handle_list_cref p_list,fb2k::hwnd_t p_parent_window,bool p_show_errors) = 0;
|
|
|
52
|
|
|
53 virtual void hint_multi(metadb_handle_list_cref p_list,const pfc::list_base_const_t<const file_info*> & p_infos,const pfc::list_base_const_t<t_filestats> & p_stats,const bit_array & p_fresh_mask) = 0;
|
|
|
54
|
|
|
55 virtual void hint_multi_async(metadb_handle_list_cref p_list,const pfc::list_base_const_t<const file_info*> & p_infos,const pfc::list_base_const_t<t_filestats> & p_stats,const bit_array & p_fresh_mask) = 0;
|
|
|
56
|
|
|
57 virtual void hint_reader(service_ptr_t<class input_info_reader> p_reader,const char * p_path,abort_callback & p_abort) = 0;
|
|
|
58
|
|
|
59 //! For internal use only.
|
|
|
60 virtual void path_to_handles_simple(const char * p_path, metadb_handle_list_ref p_out) = 0;
|
|
|
61
|
|
|
62 //! Dispatches metadb_io_callback calls with specified items. To be used with metadb_display_field_provider when your component needs specified items refreshed.
|
|
|
63 virtual void dispatch_refresh(metadb_handle_list_cref p_list) = 0;
|
|
|
64
|
|
|
65 void dispatch_refresh(metadb_handle_ptr const & handle) {dispatch_refresh(pfc::list_single_ref_t<metadb_handle_ptr>(handle));}
|
|
|
66
|
|
|
67 void hint_async(metadb_handle_ptr p_item,const file_info & p_info,const t_filestats & p_stats,bool p_fresh);
|
|
|
68
|
|
|
69 FB2K_DEPRECATED t_load_info_state load_info(metadb_handle_ptr p_item,t_load_info_type p_type,fb2k::hwnd_t p_parent_window,bool p_show_errors);
|
|
|
70 FB2K_DEPRECATED t_update_info_state update_info(metadb_handle_ptr p_item,file_info & p_info,fb2k::hwnd_t p_parent_window,bool p_show_errors);
|
|
|
71
|
|
|
72 FB2K_MAKE_SERVICE_COREAPI(metadb_io);
|
|
|
73 };
|
|
|
74
|
|
|
75 //! Advanced interface for passing infos read from files to metadb backend. Use metadb_io_v2::create_hint_list() to instantiate. \n
|
|
|
76 //! Thread safety: all methods other than on_done() are intended for worker threads. Instantiate and use the object in a worker thread, call on_done() in main thread to finalize. \n
|
|
|
77 //! Typical usage pattern: create a hint list (in any thread), hand infos to it from files that you work with (in a worker thread), call on_done() in main thread. \n
|
|
|
78 class NOVTABLE metadb_hint_list : public service_base {
|
|
|
79 FB2K_MAKE_SERVICE_INTERFACE(metadb_hint_list,service_base);
|
|
|
80 public:
|
|
|
81 //! Helper.
|
|
|
82 static metadb_hint_list::ptr create();
|
|
|
83 //! Adds a hint to the list.
|
|
|
84 //! @param p_location Location of the item the hint applies to.
|
|
|
85 //! @param p_info file_info object describing the item.
|
|
|
86 //! @param p_stats Information about the file containing item the hint applies to.
|
|
|
87 //! @param p_freshflag Set to true if the info has been directly read from the file, false if it comes from another source such as a playlist file.
|
|
|
88 virtual void add_hint(metadb_handle_ptr const & p_location,const file_info & p_info,const t_filestats & p_stats,bool p_freshflag) = 0;
|
|
|
89 //! Reads info from specified info reader instance and adds hints. May throw an exception in case info read has failed. \n
|
|
|
90 //! If the file has multiple subsongs, info from all the subsongs will be read and pssed to add_hint(). \n
|
|
|
91 //! Note that an input_info_writer is a subclass of input_info_reader - so any input_info_reader OR input_info_writer is a valid argument for add_hint_reader(). \n
|
|
|
92 //! This method is often called with your input_info_writer instance after committing tag updates, to notify metadb about altered tags.
|
|
|
93 virtual void add_hint_reader(const char * p_path,service_ptr_t<input_info_reader> const & p_reader,abort_callback & p_abort) = 0;
|
|
|
94 //! Call this when you're done working with this metadb_hint_list instance, to apply hints and dispatch callbacks. \n
|
|
|
95 //! If you don't call this, all added hints will be ignored. \n
|
|
|
96 //! As a general rule, you should add as many infos as possible - such as all the tracks involved in some operation that you perform - then call on_done() once. \n
|
|
|
97 //! on_done() is expensive because it not only updates the metadb, but tells all components about the changes made - refreshes playlists/autoplaylists, library viewers, etc. \n
|
|
|
98 //! Calling on_done() repeatedly is inefficient and should be avoided.
|
|
|
99 virtual void on_done() = 0;
|
|
|
100 };
|
|
|
101
|
|
|
102 //! \since 1.0
|
|
|
103 //! To obtain metadb_hint_list_v2, use service_query on a metadb_hint_list object. \n
|
|
|
104 //! Simplified: metadb_hint_list_v2::ptr v2; v2 ^= myHintList; ( causes bugcheck if old fb2k / no interface ).
|
|
|
105 class NOVTABLE metadb_hint_list_v2 : public metadb_hint_list {
|
|
|
106 FB2K_MAKE_SERVICE_INTERFACE(metadb_hint_list_v2, metadb_hint_list);
|
|
|
107 public:
|
|
|
108 //! Helper.
|
|
|
109 static metadb_hint_list_v2::ptr create();
|
|
|
110 //! Hint with browse info. \n
|
|
|
111 //! See: metadb_handle::get_browse_info() for browse info rationale.
|
|
|
112 //! @param p_location Location for which we're providing browse info.
|
|
|
113 //! @param p_info Browse info for this location.
|
|
|
114 //! @param browseTS timestamp of the browse info - such as last-modified time of the playlist file providing browse info.
|
|
|
115 virtual void add_hint_browse(metadb_handle_ptr const & p_location,const file_info & p_info, t_filetimestamp browseTS) = 0;
|
|
|
116 };
|
|
|
117
|
|
|
118 //! \since 1.3
|
|
|
119 //! To obtain metadb_hint_list_v3, use service_query on a metadb_hint_list object. \n
|
|
|
120 //! Simplified: metadb_hint_list_v3::ptr v3; v3 ^= myHintList; ( causes bugcheck if old fb2k / no interface ).
|
|
|
121 class NOVTABLE metadb_hint_list_v3 : public metadb_hint_list_v2 {
|
|
|
122 FB2K_MAKE_SERVICE_INTERFACE(metadb_hint_list_v3, metadb_hint_list_v2);
|
|
|
123 public:
|
|
|
124 //! Helper.
|
|
|
125 static metadb_hint_list_v3::ptr create();
|
|
|
126 //! Hint primary info with a metadb_info_container.
|
|
|
127 virtual void add_hint_v3(metadb_handle_ptr const & p_location, metadb_info_container::ptr info,bool p_freshflag) = 0;
|
|
|
128 //! Hint browse info with a metadb_info_container.
|
|
|
129 virtual void add_hint_browse_v3(metadb_handle_ptr const & p_location,metadb_info_container::ptr info) = 0;
|
|
|
130
|
|
|
131 //! Add a forced hint.\n
|
|
|
132 //! A normal hint may or may not cause metadb update - metadb is not updated if the file has not changed according to last modified time. \n
|
|
|
133 //! A forced hint always updates metadb regardless of timestamps.
|
|
|
134 virtual void add_hint_forced(metadb_handle_ptr const & p_location, const file_info & p_info,const t_filestats & p_stats,bool p_freshflag) = 0;
|
|
|
135 //! Add a forced hint, with metadb_info_container. \n
|
|
|
136 //! Forced hint rationale - see add_hint_forced().
|
|
|
137 virtual void add_hint_forced_v3(metadb_handle_ptr const & p_location, metadb_info_container::ptr info,bool p_freshflag) = 0;
|
|
|
138 //! Adds a forced hint, with an input_info_reader. \n
|
|
|
139 //! Forced hint rationale - see add_hint_forced(). \n
|
|
|
140 //! Info reader use rationale - see add_hint_reader().
|
|
|
141 virtual void add_hint_forced_reader(const char * p_path,service_ptr_t<input_info_reader> const & p_reader,abort_callback & p_abort) = 0;
|
|
|
142 };
|
|
|
143
|
|
|
144 //! \since 2.0
|
|
|
145 //! Allows dispatching of metadb_io_edit_callback from your code.
|
|
|
146 class NOVTABLE metadb_hint_list_v4 : public metadb_hint_list_v3 {
|
|
|
147 FB2K_MAKE_SERVICE_INTERFACE( metadb_hint_list_v4, metadb_hint_list_v3 );
|
|
|
148 public:
|
|
|
149 static metadb_hint_list_v4::ptr create();
|
|
|
150
|
|
|
151 virtual void before_edit( const char * path, service_ptr_t<input_info_reader> reader, abort_callback & a ) = 0;
|
|
|
152 virtual void after_edit( const char * path, service_ptr_t<input_info_reader> reader, abort_callback & a ) = 0;
|
|
|
153
|
|
|
154 };
|
|
|
155
|
|
|
156
|
|
|
157 //! New in 0.9.3. Extends metadb_io functionality with nonblocking versions of tag read/write functions, and some other utility features.
|
|
|
158 class NOVTABLE metadb_io_v2 : public metadb_io {
|
|
|
159 public:
|
|
|
160 enum {
|
|
|
161 //! By default, when some part of requested operation could not be performed for reasons other than user abort, a popup dialog with description of the problem is spawned.\n
|
|
|
162 //! Set this flag to disable error notification.
|
|
|
163 op_flag_no_errors = 1 << 0,
|
|
|
164 //! Set this flag to make the progress dialog not steal focus on creation.
|
|
|
165 op_flag_background = 1 << 1,
|
|
|
166 //! Set this flag to delay the progress dialog becoming visible, so it does not appear at all during short operations. Also implies op_flag_background effect.
|
|
|
167 op_flag_delay_ui = 1 << 2,
|
|
|
168
|
|
|
169 //! \since 1.3
|
|
|
170 //! Indicates that the caller is aware of the metadb partial info feature introduced at v1.3.
|
|
|
171 //! When not specified, affected info will be quietly preserved when updating tags.
|
|
|
172 //! Obsolete in 2.0
|
|
|
173 op_flag_partial_info_aware = 1 << 3,
|
|
|
174
|
|
|
175 //! \since 2.0
|
|
|
176 //! Do not show any user interface.
|
|
|
177 op_flag_silent = 1 << 4,
|
|
|
178
|
|
|
179 //! \since 2.0
|
|
|
180 op_flag_detect_rechapter = 1 << 5,
|
|
|
181 };
|
|
|
182
|
|
|
183 //! Preloads information from the specified tracks. \n
|
|
|
184 //! Use from main thread only (starts a threaded_process to show a progress dialog).
|
|
|
185 //! @param p_list List of items to process.
|
|
|
186 //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation.
|
|
|
187 //! @param p_notify Called when the task is completed. Status code is one of t_load_info_state values. Can be null if caller doesn't care.
|
|
|
188 virtual void load_info_async(metadb_handle_list_cref p_list,t_load_info_type p_type,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0;
|
|
|
189 //! Updates tags of the specified tracks. \n
|
|
|
190 //! Use from main thread only (starts a threaded_process to show a progress dialog).
|
|
|
191 //! @param p_list List of items to process.
|
|
|
192 //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation.
|
|
|
193 //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care.
|
|
|
194 //! @param p_filter Callback handling actual file_info alterations. Typically used to replace entire meta part of file_info, or to alter something else such as ReplayGain while leaving meta intact.
|
|
|
195 virtual void update_info_async(metadb_handle_list_cref p_list,service_ptr_t<file_info_filter> p_filter,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0;
|
|
|
196 //! Rewrites tags of the specified tracks; similar to update_info_async() but using last known/cached file_info values rather than values passed by caller. \n
|
|
|
197 //! Use from main thread only (starts a threaded_process to show a progress dialog).
|
|
|
198 //! @param p_list List of items to process.
|
|
|
199 //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation.
|
|
|
200 //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care.
|
|
|
201 virtual void rewrite_info_async(metadb_handle_list_cref p_list,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0;
|
|
|
202 //! Strips all tags / metadata fields from the specified tracks. \n
|
|
|
203 //! Use from main thread only (starts a threaded_process to show a progress dialog).
|
|
|
204 //! @param p_list List of items to process.
|
|
|
205 //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation.
|
|
|
206 //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care.
|
|
|
207 virtual void remove_info_async(metadb_handle_list_cref p_list,fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify) = 0;
|
|
|
208
|
|
|
209 //! Creates a metadb_hint_list object. \n
|
|
|
210 //! Contrary to other metadb_io methods, this can be safely called in a worker thread. You only need to call the hint list's on_done() method in main thread to finalize.
|
|
|
211 virtual metadb_hint_list::ptr create_hint_list() = 0;
|
|
|
212
|
|
|
213 //! Updates tags of the specified tracks. Helper; uses update_info_async internally. \n
|
|
|
214 //! Use from main thread only (starts a threaded_process to show a progress dialog).
|
|
|
215 //! @param p_list List of items to process.
|
|
|
216 //! @param p_op_flags Can be null, or one or more of op_flag_* enum values combined, altering behaviors of the operation.
|
|
|
217 //! @param p_notify Called when the task is completed. Status code is one of t_update_info values. Can be null if caller doesn't care.
|
|
|
218 //! @param p_new_info New infos to write to specified items.
|
|
|
219 void update_info_async_simple(metadb_handle_list_cref p_list,const pfc::list_base_const_t<const file_info*> & p_new_info, fb2k::hwnd_t p_parent_window,t_uint32 p_op_flags,completion_notify_ptr p_notify);
|
|
|
220
|
|
|
221 //! Helper to be called after a file has been rechaptered. \n
|
|
|
222 //! Forcibly reloads info then tells playlist_manager to update all affected playlists. \n
|
|
|
223 //! Call from main thread only.
|
|
|
224 void on_file_rechaptered( const char * path, metadb_handle_list_cref newItems );
|
|
|
225 //! Helper to be called after a file has been rechaptered. \n
|
|
|
226 //! Forcibly reloads info then tells playlist_manager to update all affected playlists. \n
|
|
|
227 //! Call from main thread only.
|
|
|
228 void on_files_rechaptered( metadb_handle_list_cref newHandles );
|
|
|
229
|
|
|
230 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v2,metadb_io);
|
|
|
231 };
|
|
|
232
|
|
|
233
|
|
|
234 //! \since 0.9.5
|
|
|
235 class NOVTABLE metadb_io_v3 : public metadb_io_v2 {
|
|
|
236 public:
|
|
|
237 //! Registers a callback object to receive notifications about metadb_io operations. \n
|
|
|
238 //! See: metadb_io_callback_dynamic \n
|
|
|
239 //! Call from main thread only.
|
|
|
240 virtual void register_callback(metadb_io_callback_dynamic * p_callback) = 0;
|
|
|
241 //! Unregisters a callback object to receive notifications about metadb_io operations. \n
|
|
|
242 //! See: metadb_io_callback_dynamic \n
|
|
|
243 //! Call from main thread only.
|
|
|
244 virtual void unregister_callback(metadb_io_callback_dynamic * p_callback) = 0;
|
|
|
245
|
|
|
246 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v3,metadb_io_v2);
|
|
|
247 };
|
|
|
248
|
|
|
249
|
|
|
250 class threaded_process_callback;
|
|
|
251
|
|
|
252 //! \since 1.5
|
|
|
253 class NOVTABLE metadb_io_v4 : public metadb_io_v3 {
|
|
|
254 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v4, metadb_io_v3);
|
|
|
255 public:
|
|
|
256 //! Creates an update-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n
|
|
|
257 //! May return null pointer if the operation has been refused (by user settings or such). \n
|
|
|
258 //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n
|
|
|
259 //! Main thread only.
|
|
|
260 virtual service_ptr_t<threaded_process_callback> spawn_update_info( metadb_handle_list_cref items, service_ptr_t<file_info_filter> p_filter, uint32_t opFlags, completion_notify_ptr reply ) = 0;
|
|
|
261 //! Creates an remove-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n
|
|
|
262 //! May return null pointer if the operation has been refused (by user settings or such). \n
|
|
|
263 //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n
|
|
|
264 //! Main thread only.
|
|
|
265 virtual service_ptr_t<threaded_process_callback> spawn_remove_info( metadb_handle_list_cref items, uint32_t opFlags, completion_notify_ptr reply) = 0;
|
|
|
266 //! Creates an load-info task, that can be either fed to threaded_process API, or invoked by yourself respecting threaded_process semantics. \n
|
|
|
267 //! May return null pointer if the operation has been refused (for an example no loading is needed for these items). \n
|
|
|
268 //! Useful for performing the operation with your own in-dialog progress display instead of the generic progress popup. \n
|
|
|
269 //! Main thread only.
|
|
|
270 virtual service_ptr_t<threaded_process_callback> spawn_load_info( metadb_handle_list_cref items, t_load_info_type opType, uint32_t opFlags, completion_notify_ptr reply) = 0;
|
|
|
271 };
|
|
|
272
|
|
|
273 // \since 2.0
|
|
|
274 class NOVTABLE metadb_io_v5 : public metadb_io_v4 {
|
|
|
275 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_io_v5, metadb_io_v4);
|
|
|
276 public:
|
|
|
277 //! Register a metadb_io_callback_v2_dynamic object to receive notifications about metadb_io events. \n
|
|
|
278 //! Main thread only.
|
|
|
279 virtual void register_callback_v2(metadb_io_callback_v2_dynamic*) = 0;
|
|
|
280 //! Unregister a metadb_io_callback_v2_dynamic object. \n
|
|
|
281 //! Main thread only.
|
|
|
282 virtual void unregister_callback_v2(metadb_io_callback_v2_dynamic*) = 0;
|
|
|
283 };
|
|
|
284
|
|
|
285
|
|
|
286 //! Entrypoint service for metadb_handle related operations.\n
|
|
|
287 //! Implemented only by core, do not reimplement.\n
|
|
|
288 //! Use metadb::get() to obtain an instance.
|
|
|
289 class NOVTABLE metadb : public service_base
|
|
|
290 {
|
|
|
291 protected:
|
|
|
292 //! OBSOLETE, DO NOT CALL
|
|
|
293 virtual void database_lock()=0;
|
|
|
294 //! OBSOLETE, DO NOT CALL
|
|
|
295 virtual void database_unlock()=0;
|
|
|
296 public:
|
|
|
297
|
|
|
298 //! Returns a metadb_handle object referencing the specified location. If one doesn't exist yet a new one is created. There can be only one metadb_handle object referencing specific location. \n
|
|
|
299 //! This function should never fail unless there's something critically wrong (can't allocate memory for the new object, etc). \n
|
|
|
300 //! Speed: O(log(n)) to total number of metadb_handles present. It's recommended to pass metadb_handles around whenever possible rather than pass playable_locations then retrieve metadb_handles on demand when needed.
|
|
|
301 //! @param p_out Receives the metadb_handle pointer.
|
|
|
302 //! @param p_location Location to create a metadb_handle for.
|
|
|
303 virtual void handle_create(metadb_handle_ptr & p_out,const playable_location & p_location)=0;
|
|
|
304
|
|
|
305 void handle_create_replace_path_canonical(metadb_handle_ptr & p_out,const metadb_handle_ptr & p_source,const char * p_new_path);
|
|
|
306 void handle_replace_path_canonical(metadb_handle_ptr & p_out,const char * p_new_path);
|
|
|
307 void handle_create_replace_path(metadb_handle_ptr & p_out,const metadb_handle_ptr & p_source,const char * p_new_path);
|
|
|
308
|
|
|
309 //! Helper function; attempts to retrieve a handle to any known playable location to be used for e.g. titleformatting script preview.\n
|
|
|
310 //! @returns True on success; false on failure (no known playable locations).
|
|
|
311 static bool g_get_random_handle(metadb_handle_ptr & p_out);
|
|
|
312
|
|
|
313 enum {case_sensitive = playable_location::case_sensitive};
|
|
|
314 typedef playable_location::path_comparator path_comparator;
|
|
|
315
|
|
|
316 inline static int path_compare_ex(const char * p1,t_size len1,const char * p2,t_size len2) {return case_sensitive ? pfc::strcmp_ex(p1,len1,p2,len2) : stricmp_utf8_ex(p1,len1,p2,len2);}
|
|
|
317 inline static int path_compare_nc(const char * p1, size_t len1, const char * p2, size_t len2) {return case_sensitive ? pfc::strcmp_nc(p1,len1,p2,len2) : stricmp_utf8_ex(p1,len1,p2,len2);}
|
|
|
318 inline static int path_compare(const char * p1,const char * p2) {return case_sensitive ? strcmp(p1,p2) : stricmp_utf8(p1,p2);}
|
|
|
319 inline static int path_compare_metadb_handle(const metadb_handle_ptr & p1,const metadb_handle_ptr & p2) {return path_compare(p1->get_path(),p2->get_path());}
|
|
|
320
|
|
|
321 metadb_handle_ptr handle_create(playable_location const & l) {metadb_handle_ptr temp; handle_create(temp, l); return temp;}
|
|
|
322 metadb_handle_ptr handle_create(const char * path, uint32_t subsong) {return handle_create(make_playable_location(path, subsong));}
|
|
|
323
|
|
|
324 FB2K_MAKE_SERVICE_COREAPI(metadb);
|
|
|
325 };
|
|
|
326
|
|
|
327
|
|
|
328
|
|
|
329
|
|
|
330 //! \since 2.0
|
|
|
331 class metadb_v2 : public metadb {
|
|
|
332 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(metadb_v2, metadb);
|
|
|
333 public:
|
|
|
334 typedef metadb_v2_rec_t rec_t;
|
|
|
335
|
|
|
336 //! Query info record by location, bypassing metadb_handle layer.
|
|
|
337 virtual rec_t query(playable_location const& loc) = 0;
|
|
|
338
|
|
|
339 //! Callback class for queryMulti(). See metadb_v2::queryMulti().
|
|
|
340 class queryMultiCallback_t {
|
|
|
341 public:
|
|
|
342 virtual void onInfo(size_t idx, const rec_t& rec) = 0;
|
|
|
343 };
|
|
|
344 //! Callback class for queryMultiParallel(). See metadb_v2::queryMultiParallel().
|
|
|
345 class queryMultiParallelCallback_t {
|
|
|
346 public:
|
|
|
347 virtual void* initThreadContext() { return nullptr; }
|
|
|
348 virtual void onInfo(size_t idx, const rec_t& rec, void * ctx) = 0;
|
|
|
349 virtual void clearThreadContext(void*) {}
|
|
|
350 };
|
|
|
351
|
|
|
352 //! Optimized multi-item metadb info query. Supply a callback to receive info records for all requested tracks. \n
|
|
|
353 //! This is considerably faster than reading info records one by one, batch database queries are used to speed operation up. \n
|
|
|
354 //! The infos may come in different order than requested - pay attention to idx argument of callback's onInfo(). \n
|
|
|
355 //! See also: queryMulti_(), using a lambda instead of a callback object.
|
|
|
356 virtual void queryMulti(metadb_handle_list_cref items, queryMultiCallback_t& cb) = 0;
|
|
|
357
|
|
|
358 //! Multi-thread optimized version of queryMulti(). \n
|
|
|
359 //! Faster if used with thousands of items, needs the callback to handle concurrent calls from many threads. \n
|
|
|
360 //! See also: queryMultiParallel_() and queryMultiParallelEx_(), helpers using lambdas and classes to implement the callback for you.
|
|
|
361 virtual void queryMultiParallel(metadb_handle_list_cref items, queryMultiParallelCallback_t& cb) = 0;
|
|
|
362
|
|
|
363 //! Format title without database access, use preloaded metadb v2 record.
|
|
|
364 virtual void formatTitle_v2( const metadb_handle_ptr & handle, const rec_t & rec, titleformat_hook* p_hook, pfc::string_base& p_out, const service_ptr_t<titleformat_object>& p_script, titleformat_text_filter* p_filter) = 0;
|
|
|
365
|
|
|
366 //! Helper around queryMulti(). Implements callback for you using passed lambda.
|
|
|
367 void queryMulti_(metadb_handle_list_cref items, std::function< void(size_t idx, const rec_t& rec) > f) {
|
|
|
368 class qmc_impl : public queryMultiCallback_t {
|
|
|
369 public:
|
|
|
370 void onInfo(size_t idx, const rec_t& rec) override { m_f(idx, rec); }
|
|
|
371 decltype(f) m_f;
|
|
|
372 };
|
|
|
373 qmc_impl cb; cb.m_f = f;
|
|
|
374 this->queryMulti(items, cb);
|
|
|
375 }
|
|
|
376
|
|
|
377 //! Simplified helper around queryMultiParallel(). No per-thread data object used. Implements callback for you using passed labmda.
|
|
|
378 void queryMultiParallel_(metadb_handle_list_cref items, std::function< void(size_t, const rec_t&) > f) {
|
|
|
379 class qmc_impl : public queryMultiParallelCallback_t {
|
|
|
380 public:
|
|
|
381 void onInfo(size_t idx, const rec_t& rec, void*) override {m_f(idx, rec);}
|
|
|
382
|
|
|
383 decltype(f) m_f;
|
|
|
384 };
|
|
|
385 qmc_impl cb; cb.m_f = f;
|
|
|
386 this->queryMultiParallel(items, cb);
|
|
|
387 }
|
|
|
388
|
|
|
389 //! Simplified helper around queryMultiParallel(). \n
|
|
|
390 //! instance_t implements per-thread context data, one will be created in each worker threads. \n
|
|
|
391 //! While lambda itself will be called from many threads at once, only one instance_t will be used in each thread, so instance_t can be accessed without thread safety measures.
|
|
|
392 template<typename instance_t> void queryMultiParallelEx_(metadb_handle_list_cref items, std::function<void(size_t, const rec_t&, instance_t&)> f) {
|
|
|
393 class qmc_impl : public queryMultiParallelCallback_t {
|
|
|
394 public:
|
|
|
395 void* initThreadContext() override {return reinterpret_cast<void*>(new instance_t);}
|
|
|
396 void onInfo(size_t idx, const rec_t& rec, void* ctx) override { m_f(idx, rec, * reinterpret_cast<instance_t*>(ctx)); }
|
|
|
397 void clearThreadContext(void* ctx) override { delete reinterpret_cast<instance_t*>(ctx); }
|
|
|
398
|
|
|
399 decltype(f) m_f;
|
|
|
400 };
|
|
|
401 qmc_impl cb; cb.m_f = f;
|
|
|
402 this->queryMultiParallel(items, cb);
|
|
|
403 }
|
|
|
404
|
|
|
405 //! Simplified helper for retrieving info of multiple tracks efficiently. \n
|
|
|
406 //! Uses the fastest way to pull info from thousands of tracks - queryMultiParallel(). \n
|
|
|
407 //! Keep in mind that it results in all affected info becoming loaded into application memory at once. \n
|
|
|
408 //! If possible, use methods with callbacks/lambdas instead and process info in callbacks instead of keeping it.
|
|
|
409 pfc::array_t<rec_t> queryMultiSimple(metadb_handle_list_cref items) {
|
|
|
410 pfc::array_t<rec_t> ret;
|
|
|
411 ret.resize(items.get_count());
|
|
|
412 this->queryMultiParallel_(items, [&](size_t idx, const rec_t& rec) {ret[idx] = rec;});
|
|
|
413 return ret;
|
|
|
414 }
|
|
|
415 };
|