comparison foosdk/sdk/foobar2000/SDK/input.h @ 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 #pragma once
2 #include <functional>
3 #include "event_logger.h"
4 #include "audio_chunk.h"
5 #include "album_art.h"
6
7 PFC_DECLARE_EXCEPTION(exception_tagging_unsupported, exception_io_data, "Tagging of this file format is not supported")
8
9 enum {
10 // Seek commands won't be issued, can skip initializing seektables etc that sequential decode doesn't need.
11 input_flag_no_seeking = 1 << 0,
12 // Do not loop, also ignore user looping settings.
13 input_flag_no_looping = 1 << 1,
14 // Opening for actual playback, not for conversion/scan/test.
15 input_flag_playback = 1 << 2,
16 // Testing integrity, perform additional checks and report errors. Not mutually exlusive with input_flag_playback!
17 input_flag_testing_integrity = 1 << 3,
18 // OK to perform cheap but inaccurate seeking.
19 // Note that seeking should be ALWAYS sample accurate. This setting is a hint for decoding formats that are expensive to seek properly, indicating that no obvious harm will come from taking shortcuts.
20 input_flag_allow_inaccurate_seeking = 1 << 4,
21 // Suppress decode_postprocessor use. Handled by decode_postprocessor framework.
22 input_flag_no_postproc = 1 << 5,
23 // DSD decoders only: Send DSD as DoP. If not set, DSD should be decimated to PCM.
24 input_flag_dop = 1 << 6,
25 // Auotmated test suite running, disregard user options if possible
26 input_flag_canonical_decode = 1 << 7,
27
28 input_flag_simpledecode = input_flag_no_seeking|input_flag_no_looping,
29 };
30
31 //! Class providing interface for retrieval of information (metadata, duration, replaygain, other tech infos) from files. Also see: file_info. \n
32 //! Instantiating: see input_entry.\n
33 //! Implementing: see input_impl.
34
35 class NOVTABLE input_info_reader : public service_base {
36 FB2K_MAKE_SERVICE_INTERFACE(input_info_reader, service_base);
37 public:
38 //! Retrieves count of subsongs in the file. 1 for non-multisubsong-enabled inputs.
39 //! Note: multi-subsong handling is disabled for remote files (see: filesystem::is_remote) for performance reasons. Remote files are always assumed to be single-subsong, with null index.
40 virtual t_uint32 get_subsong_count() = 0;
41
42 //! Retrieves identifier of specified subsong; this identifier is meant to be used in playable_location as well as a parameter for input_info_reader::get_info().
43 //! @param p_index Index of subsong to query. Must be >=0 and < get_subsong_count().
44 virtual t_uint32 get_subsong(t_uint32 p_index) = 0;
45
46 //! Retrieves information about specified subsong.
47 //! @param p_subsong Identifier of the subsong to query. See: input_info_reader::get_subsong(), playable_location.
48 //! @param p_info file_info object to fill. Must be empty on entry.
49 //! @param p_abort abort_callback object signaling user aborting the operation.
50 virtual void get_info(t_uint32 p_subsong,file_info & p_info,abort_callback & p_abort) = 0;
51
52 //! Retrieves file stats. Equivalent to calling get_stats() on file object.
53 virtual t_filestats get_file_stats(abort_callback & p_abort) = 0;
54
55 t_filestats2 get_stats2_(const char* fallbackPath, uint32_t f, abort_callback& a);
56 };
57
58 class NOVTABLE input_info_reader_v2 : public input_info_reader {
59 FB2K_MAKE_SERVICE_INTERFACE(input_info_reader_v2, input_info_reader);
60 public:
61 virtual t_filestats2 get_stats2(uint32_t f, abort_callback& a) = 0;
62
63 t_filestats get_file_stats(abort_callback& a) override;
64 };
65
66 //! Class providing interface for retrieval of PCM audio data from files.\n
67 //! Instantiating: see input_entry.\n
68 //! Implementing: see input_impl.
69
70 class NOVTABLE input_decoder : public input_info_reader
71 {
72 public:
73 //! Prepares to decode specified subsong; resets playback position to the beginning of specified subsong. This must be called first, before any other input_decoder methods (other than those inherited from input_info_reader). \n
74 //! It is legal to set initialize() more than once, with same or different subsong, to play either the same subsong again or another subsong from same file without full reopen.\n
75 //! Warning: this interface inherits from input_info_reader, it is legal to call any input_info_reader methods even during decoding! Call order is not defined, other than initialize() requirement before calling other input_decoder methods.\n
76 //! @param p_subsong Subsong to decode. Should always be 0 for non-multi-subsong-enabled inputs.
77 //! @param p_flags Specifies additional hints for decoding process. It can be null, or a combination of one or more following constants: \n
78 //! input_flag_no_seeking - Indicates that seek() will never be called. Can be used to avoid building potentially expensive seektables when only sequential reading is needed.\n
79 //! input_flag_no_looping - Certain input implementations can be configured to utilize looping info from file formats they process and keep playing single file forever, or keep repeating it specified number of times. This flag indicates that such features should be disabled, for e.g. ReplayGain scan or conversion.\n
80 //! input_flag_playback - Indicates that decoding process will be used for realtime playback rather than conversion. This can be used to reconfigure features that are relevant only for conversion and take a lot of resources, such as very slow secure CDDA reading. \n
81 //! input_flag_testing_integrity - Indicates that we're testing integrity of the file. Any recoverable problems where decoding would normally continue should cause decoder to fail with exception_io_data.
82 //! @param p_abort abort_callback object signaling user aborting the operation.
83 virtual void initialize(t_uint32 p_subsong,unsigned p_flags,abort_callback & p_abort) = 0;
84
85 //! Reads/decodes one chunk of audio data. Use false return value to signal end of file (no more data to return). Before calling run(), decoding must be initialized by initialize() call.
86 //! @param p_chunk audio_chunk object receiving decoded data. Contents are valid only the method returns true.
87 //! @param p_abort abort_callback object signaling user aborting the operation.
88 //! @returns true on success (new data decoded), false on EOF.
89 virtual bool run(audio_chunk & p_chunk,abort_callback & p_abort) = 0;
90
91 //! Seeks to specified time offset. Before seeking or other decoding calls, decoding must be initialized with initialize() call.
92 //! @param p_seconds Time to seek to, in seconds. If p_seconds exceeds length of the object being decoded, succeed, and then return false from next run() call.
93 //! @param p_abort abort_callback object signaling user aborting the operation.
94 virtual void seek(double p_seconds,abort_callback & p_abort) = 0;
95
96 //! Queries whether resource being read/decoded is seekable. If p_value is set to false, all seek() calls will fail. Before calling can_seek() or other decoding calls, decoding must be initialized with initialize() call.
97 virtual bool can_seek() = 0;
98
99 //! This function is used to signal dynamic VBR bitrate, etc. Called after each run() (or not called at all if caller doesn't care about dynamic info).
100 //! @param p_out Initially contains currently displayed info (either last get_dynamic_info result or current cached info), use this object to return changed info.
101 //! @param p_timestamp_delta Indicates when returned info should be displayed (in seconds, relative to first sample of last decoded chunk), initially set to 0.
102 //! @returns false to keep old info, or true to indicate that changes have been made to p_info and those should be displayed.
103 virtual bool get_dynamic_info(file_info & p_out, double & p_timestamp_delta) = 0;
104
105 //! This function is used to signal dynamic live stream song titles etc. Called after each run() (or not called at all if caller doesn't care about dynamic info). The difference between this and get_dynamic_info() is frequency and relevance of dynamic info changes - get_dynamic_info_track() returns new info only on track change in the stream, returning new titles etc.
106 //! @param p_out Initially contains currently displayed info (either last get_dynamic_info_track result or current cached info), use this object to return changed info.
107 //! @param p_timestamp_delta Indicates when returned info should be displayed (in seconds, relative to first sample of last decoded chunk), initially set to 0.
108 //! @returns false to keep old info, or true to indicate that changes have been made to p_info and those should be displayed.
109 virtual bool get_dynamic_info_track(file_info & p_out, double & p_timestamp_delta) = 0;
110
111 //! Obsolete, do not use, do not rely on.
112 virtual void on_idle(abort_callback & p_abort) = 0;
113
114
115 FB2K_MAKE_SERVICE_INTERFACE(input_decoder,input_info_reader);
116 };
117
118
119 class NOVTABLE input_decoder_v2 : public input_decoder {
120 FB2K_MAKE_SERVICE_INTERFACE(input_decoder_v2, input_decoder)
121 public:
122
123 //! OPTIONAL, throws pfc::exception_not_implemented() when not supported by this implementation.
124 //! Special version of run(). Returns an audio_chunk object as well as a raw data block containing original PCM stream. This is mainly used for MD5 checks on lossless formats. \n
125 //! If you set a "MD5" tech info entry in get_info(), you should make sure that run_raw() returns data stream that can be used to verify it. \n
126 //! Returned raw data should be possible to cut into individual samples; size in bytes should be divisible by audio_chunk's sample count for splitting in case partial output is needed (with cuesheets etc).
127 virtual bool run_raw(audio_chunk & out, mem_block_container & outRaw, abort_callback & abort) = 0;
128
129 //! OBSOLETE since 1.5 \n
130 //! Specify logger when opening to reliably get info generated during input open operation.
131 virtual void set_logger(event_logger::ptr ptr) = 0;
132 };
133
134 class NOVTABLE input_decoder_v3 : public input_decoder_v2 {
135 FB2K_MAKE_SERVICE_INTERFACE(input_decoder_v3, input_decoder_v2);
136 public:
137 //! OBSOLETE, functionality implemented by core.
138 virtual void set_pause(bool paused) = 0;
139 //! OPTIONAL, should return false in most cases; return true to force playback buffer flush on unpause. Valid only after initialize() with input_flag_playback.
140 virtual bool flush_on_pause() = 0;
141 };
142
143 class NOVTABLE input_decoder_v4 : public input_decoder_v3 {
144 FB2K_MAKE_SERVICE_INTERFACE( input_decoder_v4, input_decoder_v3 );
145 public:
146 //! OPTIONAL, return 0 if not implemented. \n
147 //! Provides means for communication of context specific data with the decoder. The decoder should do nothing and return 0 if it does not recognize the passed arguments.
148 virtual size_t extended_param( const GUID & type, size_t arg1, void * arg2, size_t arg2size) = 0;
149 };
150
151 //! Parameter GUIDs for input_decoder_v3::extended_param().
152 class input_params {
153 public:
154 //! Signals whether unnecessary seeking should be avoided with this decoder for performance reasons. \n
155 //! Arguments disregarded, return value 1 or 0.
156 static const GUID seeking_expensive;
157
158 //! Tells the decoder to output at this sample rate if the decoder's sample rate is adjustable. \n
159 //! Sample rate signaled in arg1.
160 static const GUID set_preferred_sample_rate;
161
162 //! Retrieves logical decode position from the decoder. Implemented only in some rare cases where logical position does not match duration of returned data so far.
163 //! arg2 points to double position in seconds.
164 //! Return 1 if position was written to arg2, 0 if n/a.
165 static const GUID query_position;
166
167 //! Asks whether it is OK to externally rewrite tags on this file without closing and reopening the decoder. \n
168 //! Return 1 if the decoder reads all relevant content in open() without leaving the file open afterwards, 0 otherwise (the default).
169 static const GUID is_tag_write_safe;
170 };
171
172 //! Class providing interface for writing metadata and replaygain info to files. Also see: file_info. \n
173 //! Instantiating: see input_entry.\n
174 //! Implementing: see input_impl.
175 class NOVTABLE input_info_writer : public input_info_reader
176 {
177 public:
178 //! Tells the service to update file tags with new info for specified subsong.
179 //! @param p_subsong Subsong to update. Should be always 0 for non-multisubsong-enabled inputs.
180 //! @param p_info New info to write. Sometimes not all contents of p_info can be written. Caller will typically read info back after successful write, so e.g. tech infos that change with retag are properly maintained.
181 //! @param p_abort abort_callback object signaling user aborting the operation. WARNING: abort_callback object is provided for consistency; if writing tags actually gets aborted, user will be likely left with corrupted file. Anything calling this should make sure that aborting is either impossible, or gives appropriate warning to the user first.
182 virtual void set_info(t_uint32 p_subsong,const file_info & p_info,abort_callback & p_abort) = 0;
183
184 //! Commits pending updates. In case of multisubsong inputs, set_info should queue the update and perform actual file access in commit(). Otherwise, actual writing can be done in set_info() and then commit() can just do nothing and always succeed.
185 //! @param p_abort abort_callback object signaling user aborting the operation. WARNING: abort_callback object is provided for consistency; if writing tags actually gets aborted, user will be likely left with corrupted file. Anything calling this should make sure that aborting is either impossible, or gives appropriate warning to the user first.
186 virtual void commit(abort_callback & p_abort) = 0;
187
188 //! Helper for writers not implementing input_info_writer_v2::remove_tags().
189 void remove_tags_fallback(abort_callback & abort);
190
191 FB2K_MAKE_SERVICE_INTERFACE(input_info_writer,input_info_reader);
192 };
193
194 //! Extended input_info_writer. Not every input implements it. \n
195 //! Provides an explicit remove_tags(), which erases all supported tags from the file.
196 class NOVTABLE input_info_writer_v2 : public input_info_writer {
197 public:
198 //! Removes all tags from this file. Cancels any set_info() requests on this object. Does not require a commit() afterwards.
199 //! If no input_info_writer_v2 is provided, similar affect can be achieved by set_info()+commit() with blank file_info, but may not be as thorough; will typically result in blank tags rather than total removal fo tags.
200 virtual void remove_tags(abort_callback & abort) = 0;
201
202 FB2K_MAKE_SERVICE_INTERFACE(input_info_writer_v2, input_info_writer);
203 };
204
205 class NOVTABLE input_entry : public service_base {
206 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(input_entry);
207 public:
208 //! Determines whether specified content type can be handled by this input.
209 //! @param p_type Content type string to test.
210 virtual bool is_our_content_type(const char * p_type)=0;
211
212 //! Determines whether specified file type can be handled by this input. This must not use any kind of file access; the result should be only based on file path / extension.
213 //! @param p_full_path Full URL of file being tested.
214 //! @param p_extension Extension of file being tested, provided by caller for performance reasons.
215 virtual bool is_our_path(const char * p_full_path,const char * p_extension)=0;
216
217 //! Opens specified resource for decoding.
218 //! @param p_instance Receives new input_decoder instance if successful.
219 //! @param p_filehint Optional; passes file object to use for the operation; if set to null, the service will handle opening file by itself. Note that not all inputs operate on physical files that can be reached through filesystem API, some of them require this parameter to be set to null (tone and silence generators for an example).
220 //! @param p_path URL of resource being opened.
221 //! @param p_abort abort_callback object signaling user aborting the operation.
222 virtual void open_for_decoding(service_ptr_t<input_decoder> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort) = 0;
223
224 //! Opens specified file for reading info.
225 //! @param p_instance Receives new input_info_reader instance if successful.
226 //! @param p_filehint Optional; passes file object to use for the operation; if set to null, the service will handle opening file by itself. Note that not all inputs operate on physical files that can be reached through filesystem API, some of them require this parameter to be set to null (tone and silence generators for an example).
227 //! @param p_path URL of resource being opened.
228 //! @param p_abort abort_callback object signaling user aborting the operation.
229 virtual void open_for_info_read(service_ptr_t<input_info_reader> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort) = 0;
230
231 //! Opens specified file for writing info.
232 //! @param p_instance Receives new input_info_writer instance if successful.
233 //! @param p_filehint Optional; passes file object to use for the operation; if set to null, the service will handle opening file by itself. Note that not all inputs operate on physical files that can be reached through filesystem API, some of them require this parameter to be set to null (tone and silence generators for an example).
234 //! @param p_path URL of resource being opened.
235 //! @param p_abort abort_callback object signaling user aborting the operation.
236 virtual void open_for_info_write(service_ptr_t<input_info_writer> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort) = 0;
237
238 //! Reserved for future use. Do nothing and return until specifications are finalized.
239 virtual void get_extended_data(service_ptr_t<file> p_filehint,const playable_location & p_location,const GUID & p_guid,mem_block_container & p_out,abort_callback & p_abort) = 0;
240
241 enum {
242 //! Indicates that this service implements some kind of redirector that opens another input for decoding, used to avoid circular call possibility.
243 flag_redirect = 1,
244 //! Indicates that multi-CPU optimizations should not be used.
245 flag_parallel_reads_slow = 2,
246 };
247 //! See flag_* enums.
248 virtual unsigned get_flags() = 0;
249
250 inline bool is_redirect() {return (get_flags() & flag_redirect) != 0;}
251 inline bool are_parallel_reads_slow() {return (get_flags() & flag_parallel_reads_slow) != 0;}
252
253 static bool g_find_service_by_path(service_ptr_t<input_entry> & p_out,const char * p_path);
254 static bool g_find_service_by_path(service_ptr_t<input_entry> & p_out,const char * p_path, const char * p_ext);
255 static bool g_find_service_by_content_type(service_ptr_t<input_entry> & p_out,const char * p_content_type);
256 static void g_open_for_decoding(service_ptr_t<input_decoder> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort,bool p_from_redirect = false);
257 static void g_open_for_info_read(service_ptr_t<input_info_reader> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort,bool p_from_redirect = false);
258 static void g_open_for_info_write(service_ptr_t<input_info_writer> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort,bool p_from_redirect = false);
259 static void g_open_for_info_write_timeout(service_ptr_t<input_info_writer> & p_instance,service_ptr_t<file> p_filehint,const char * p_path,abort_callback & p_abort,double p_timeout,bool p_from_redirect = false);
260 static bool g_is_supported_path(const char * p_path);
261 typedef std::function<bool ( input_entry::ptr ) > input_filter_t;
262 static bool g_find_inputs_by_content_type(pfc::list_base_t<service_ptr_t<input_entry> > & p_out, const char * p_content_type, bool p_from_redirect);
263 static bool g_find_inputs_by_path(pfc::list_base_t<service_ptr_t<input_entry> > & p_out, const char * p_path, bool p_from_redirect );
264 static bool g_find_inputs_by_content_type_ex(pfc::list_base_t<service_ptr_t<input_entry> > & p_out, const char * p_content_type, input_filter_t filter );
265 static bool g_find_inputs_by_path_ex(pfc::list_base_t<service_ptr_t<input_entry> > & p_out, const char * p_path, input_filter_t filter );
266 static service_ptr g_open(const GUID & whatFor, file::ptr hint, const char * path, event_logger::ptr logger, abort_callback & aborter, bool fromRedirect = false);
267
268 void open(service_ptr_t<input_decoder> & p_instance,service_ptr_t<file> const & p_filehint,const char * p_path,abort_callback & p_abort) {open_for_decoding(p_instance,p_filehint,p_path,p_abort);}
269 void open(service_ptr_t<input_info_reader> & p_instance,service_ptr_t<file> const & p_filehint,const char * p_path,abort_callback & p_abort) {open_for_info_read(p_instance,p_filehint,p_path,p_abort);}
270 void open(service_ptr_t<input_info_writer> & p_instance,service_ptr_t<file> const & p_filehint,const char * p_path,abort_callback & p_abort) {open_for_info_write(p_instance,p_filehint,p_path,p_abort);}
271 service_ptr open(const GUID & whatFor, file::ptr hint, const char * path, event_logger::ptr logger, abort_callback & aborter);
272
273 typedef pfc::list_base_const_t< input_entry::ptr > input_entry_list_t;
274
275 static service_ptr g_open_from_list(input_entry_list_t const & list, const GUID & whatFor, file::ptr hint, const char * path, event_logger::ptr logger, abort_callback & aborter, GUID * outGUID = nullptr);
276 static bool g_are_parallel_reads_slow( const char * path );
277
278 static uint32_t g_flags_for_path( const char * pathFor, uint32_t mask = UINT32_MAX );
279 static uint32_t g_flags_for_content_type( const char * ct, uint32_t mask = UINT32_MAX );
280
281 GUID get_guid_();
282 const char * get_name_();
283 static input_entry::ptr g_find_by_guid( const GUID & );
284 };
285
286 //! \since 1.4
287 //! Extended input_entry methods provided by decoders. \n
288 //! Can be implemented by 1.3-compatible components but will not be called in fb2k versions prior to 1.4.
289 class input_entry_v2 : public input_entry {
290 FB2K_MAKE_SERVICE_INTERFACE(input_entry_v2, input_entry);
291 public:
292 //! @returns GUID used to identify us among other decoders in the decoder priority table.
293 virtual GUID get_guid() = 0;
294 //! @returns Name to present to the user in the decoder priority table.
295 virtual const char * get_name() = 0;
296 //! @returns GUID of this decoder's preferences page (optional), null guid if there's no page to present
297 virtual GUID get_preferences_guid() = 0;
298 //! @returns true if the decoder should be put at the end of the list when it's first sighted, false otherwise (will be put at the beginning of the list).
299 virtual bool is_low_merit() = 0;
300 };
301
302 //! \since 1.5
303 class input_entry_v3 : public input_entry_v2 {
304 FB2K_MAKE_SERVICE_INTERFACE(input_entry_v3, input_entry_v2);
305 public:
306 //! New unified open() function for all supported interfaces. Supports any future interfaces via alternate GUIDs, as well as allows the event logger to be set prior to the open() call.
307 //! @param whatFor The class GUID of the service we want. \n
308 //! Currently allowed are: input_decoder::class_guid, input_info_reader::class_guid, input_info_writer::class_guid. \n
309 //! This method must throw pfc::exception_not_implemented for any GUIDs it does not recognize.
310 virtual service_ptr open_v3( const GUID & whatFor, file::ptr hint, const char * path, event_logger::ptr logger, abort_callback & aborter ) = 0;
311
312
313 void open_for_decoding(service_ptr_t<input_decoder> & p_instance, service_ptr_t<file> p_filehint, const char * p_path, abort_callback & p_abort) ;
314 void open_for_info_read(service_ptr_t<input_info_reader> & p_instance, service_ptr_t<file> p_filehint, const char * p_path, abort_callback & p_abort);
315 void open_for_info_write(service_ptr_t<input_info_writer> & p_instance, service_ptr_t<file> p_filehint, const char * p_path, abort_callback & p_abort);
316 };
317
318 #ifdef FOOBAR2000_DESKTOP
319 //! \since 1.4
320 //! Core API to perform input open operations respecting user settings for decoder priority. \n
321 //! Unavailable prior to 1.4.
322 class input_manager : public service_base {
323 FB2K_MAKE_SERVICE_COREAPI(input_manager);
324 public:
325 virtual service_ptr open(const GUID & whatFor, file::ptr hint, const char * path, bool fromRedirect, abort_callback & aborter, GUID * outUsedEntry = nullptr) = 0;
326
327 //! input_manager_v2 wrapper.
328 service_ptr open_v2(const GUID & whatFor, file::ptr hint, const char * path, bool fromRedirect, event_logger::ptr logger, abort_callback & aborter, GUID * outUsedEntry = nullptr);
329 };
330
331 //! \since 1.5
332 //! Extension of input_manager. \n
333 //! Extended open_v2() supports album_art_extractor and album_art_editor. It reliably throws pfc::exception_not_implemented() for unsupported GUIDs (old version would bugcheck). \n
334 //! It also allows event_logger to be specified in advance so open() implementation can already use it.
335 class input_manager_v2 : public input_manager {
336 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(input_manager_v2, input_manager)
337 public:
338 virtual service_ptr open_v2(const GUID & whatFor, file::ptr hint, const char * path, bool fromRedirect, event_logger::ptr logger, abort_callback & aborter, GUID * outUsedEntry = nullptr) = 0;
339 };
340
341 //! \since 1.5
342 class input_manager_v3 : public input_manager_v2 {
343 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(input_manager_v3, input_manager_v2);
344 public:
345 //! Retrieves list of enabled inputs, in user-specified order. \n
346 //! This is rarely needed. If you need this function, consider redesigning your code to call input_manager open methods instead.
347 virtual void get_enabled_inputs( pfc::list_base_t<input_entry::ptr> & out ) = 0;
348 //! Returns input_entry get_flags() values for this path, as returned by enabled inputs.
349 virtual uint32_t flags_for_path( const char * pathFor, uint32_t mask = UINT32_MAX ) = 0;
350 //! Returns input_entry get_flags() values for this content type, as returned by enabled inputs.
351 virtual uint32_t flags_for_content_type( const char * ct, uint32_t mask = UINT32_MAX ) = 0;
352
353
354 enum {
355 flagFromRedirect = 1 << 0,
356 flagSuppressFilters = 1 << 1,
357 };
358
359 virtual service_ptr open_v3(const GUID & whatFor, file::ptr hint, const char * path, uint32_t flags, event_logger::ptr logger, abort_callback & aborter, GUID * outUsedEntry = nullptr) = 0;
360 };
361
362 //! \since 1.4
363 //! Core API for determining which audio stream to decode, in a multi-stream enabled input. \n
364 //! Unavailable prior to 1.4 - decode the default stream if input_stream_selector isn't present. \n
365 //! In foobar2000 v1.4 and up, this API allows decoders to determine which stream the user opted to decode for a specific file. \n
366 //! Use input_stream_selector::tryGet() to safely instantiate.
367 class input_stream_selector : public service_base {
368 FB2K_MAKE_SERVICE_COREAPI(input_stream_selector);
369 public:
370 //! Returns index of stream that should be presented for this file. \n
371 //! If not set by user, 0xFFFFFFFF will be returned and the default stream should be presented. \n
372 //! @param guid GUID of the input asking for the stream.
373 virtual uint32_t select_stream( const GUID & guid, const char * path ) = 0;
374 };
375
376 //! \since 2.0
377 class input_stream_selector_v2 : public input_stream_selector {
378 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(input_stream_selector_v2, input_stream_selector);
379 public:
380 //! Allows components to present their own user interface to alter stream preference settings.
381 //! Parameters same as select_stream() and its return value.
382 virtual void set_user_preference(const GUID& guid, const char* path, uint32_t index) = 0;
383 };
384
385 //! \since 1.4
386 //! Interface provided by multi-stream enabled inputs to let the stream picker dialog show available streams. \n
387 //! Can be implemented by 1.3-compatible components but will not be called in fb2k versions prior to 1.4.
388 class input_stream_info_reader : public service_base {
389 FB2K_MAKE_SERVICE_INTERFACE(input_stream_info_reader, service_base);
390 public:
391 //! @returns Number of audio streams found.
392 virtual uint32_t get_stream_count() = 0;
393 //! Retrieves information about the specified stream; most importantly the codec name and bitrate.
394 virtual void get_stream_info(uint32_t index, file_info & out, abort_callback & aborter) = 0;
395 //! @returns Index of default stream to decode if there is no user preference.
396 virtual uint32_t get_default_stream() = 0;
397 };
398
399 //! \since 1.4
400 //! Entrypoint interface for spawning input_stream_info_reader. \n
401 //! Can be implemented by 1.3-compatible components but will not be called in fb2k versions prior to 1.4.
402 class input_stream_info_reader_entry : public service_base {
403 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(input_stream_info_reader_entry);
404 public:
405 //! Open file for reading stream infos.
406 virtual input_stream_info_reader::ptr open( const char * path, file::ptr fileHint, abort_callback & abort ) = 0;
407
408 //! Return GUID of the matching input_entry.
409 virtual GUID get_guid() = 0;
410
411 };
412
413 //! \since 1.4
414 //! Callback for input_stream_manipulator \n
415 //! Used for applying ReplayGain to encoded audio streams.
416 class input_stream_manipulator_callback : public service_base {
417 FB2K_MAKE_SERVICE_INTERFACE(input_stream_manipulator_callback, service_base);
418 public:
419 //! Called first before other methods. Throw an exception if the file cannot be processed. \n
420 //! The arguments are the same as packet_decoder open() arguments.
421 virtual void set_decode_info(const GUID & p_owner, t_size p_param1, const void * p_param2, t_size p_param2size ) = 0;
422
423 virtual void first_frame( const void * data, size_t bytes ) = 0;
424 //! Called with progress value, in 0..1 range.
425 virtual void on_progress( float progress ) = 0;
426 //! @returns true if the frame has been altered and should be written back, false otherwise.
427 virtual bool process_frame( void * data, size_t size ) = 0;
428 };
429
430 //! \since 1.4
431 //! Manipulate audio stream payload in files. \n
432 //! Used for applying ReplayGain to encoded audio streams.
433 class input_stream_manipulator : public service_base {
434 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(input_stream_manipulator);
435 public:
436 enum op_t {
437 //! Probe the file for codec information; calls set_decode_info() + first_frame() only.
438 op_probe = 0,
439 //! Read the entire stream - same as op_probe but then calls on_progress() + process_frame() with the entire file payload. \n
440 //! No writing to the file is performed - process_frame() results are disregarded.
441 op_read,
442 //! Rewrite the stream. Similar to op_read, but frames altered by process_frame() are written back to the file.
443 op_rewrite
444 };
445 //! @param path Path of file to process.
446 //! @param fileHint optional file object, must be opened for read+write if bWalk is true.
447 //! @param callback Callback object for this operation.
448 //! @param opType Operation to perform, see op_t enum for details.
449 //! @param abort abort_callback object for this operating. Aborting with bWalk set to true will leave the file partially altered, use with caution!
450 virtual void process( const char * path, file::ptr fileHint, input_stream_manipulator_callback::ptr callback, op_t opType, abort_callback & abort ) = 0;
451 //! Return GUID of the matching input_entry.
452 virtual GUID get_guid() = 0;
453 };
454
455 //! \since 1.5
456 //! An input_info_filter lets you hook into all performed tag read & write operations. \n
457 //! Your tag manipulations will be transparent to all fb2k components, as if the tags were read/written by relevant inputs. \n
458 //! Your input_info_filter needs to be enabled in Preferences in order to become active. Newly added ones are inactive by default.
459 class input_info_filter : public service_base {
460 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT( input_info_filter );
461 public:
462 //! Tags are being read from a file.
463 virtual void filter_info_read( const playable_location & loc,file_info & info,abort_callback & abort ) = 0;
464 //! Tags are being written to a file. \n
465 //! Return true to continue, false to suppress writing of tags.
466 virtual bool filter_info_write( const playable_location & loc, file_info & info, abort_callback & abort ) = 0;
467 //! Tags are being removed from a file.
468 virtual void on_info_remove( const char * path, abort_callback & abort ) = 0;
469 //! Return GUID of your filter.
470 virtual GUID get_guid() = 0;
471 //! Return preferences page or advconfig branch GUID of your filter.
472 virtual GUID get_preferences_guid() = 0;
473 //! Return user-friendly name of your filter to be shown in preferences.
474 virtual const char * get_name() = 0;
475 //! Optional backwards compatibility method. \n
476 //! If you also provide input services for old foobar2000 versions which don't recognize input_info_filter, report their GUIDs here so they can be ignored. \n
477 //! @param outGUIDs empty on entry, contains GUIDs of ignored inputs (if any) on return.
478 virtual void get_suppressed_inputs( pfc::list_base_t<GUID> & outGUIDs ) {outGUIDs.remove_all();}
479 //! write_fallback() supported or not? \n
480 //! Used if your filter can store tags for untaggable files.
481 virtual bool supports_fallback() = 0;
482 //! Optional; called when user attempted to tag an untaggable/readonly file. \n
483 //! Used if your filter can store tags for untaggable files.
484 virtual bool write_fallback( const playable_location & loc, file_info const & info, abort_callback & abort ) = 0;
485 //! Optional; called when user attempted to remove tags from an untaggable/readonly file.\ n
486 //! Used if your filter can store tags for untaggable files.
487 virtual void remove_tags_fallback( const char * path, abort_callback & abort ) = 0;
488 };
489
490 //! \since 1.5
491 class input_stream_info_filter : public service_base {
492 FB2K_MAKE_SERVICE_INTERFACE( input_stream_info_filter, service_base );
493 public:
494 virtual void filter_dynamic_info( file_info & info ) = 0;
495 virtual void filter_dynamic_info_track( file_info & info ) = 0;
496 };
497
498 //! \since 1.5
499 //! Extended input_info_filter.
500 class input_info_filter_v2 : public input_info_filter {
501 FB2K_MAKE_SERVICE_INTERFACE( input_info_filter_v2, input_info_filter );
502 public:
503 //! Creates an object which then can work with dynamic track titles etc of a decoded track. \n
504 //! Returning null to filter the info is allowed.
505 virtual input_stream_info_filter::ptr open_stream(playable_location const & loc, abort_callback & abort) = 0;
506
507
508 typedef service_ptr_t<album_art_data> aaptr_t;
509
510 //! Album art is being read from the file. \n
511 //! info may be null if file had no such picture. \n
512 //! Return passed info, altered info or null.
513 virtual aaptr_t filter_album_art_read( const char * path, const GUID & type, aaptr_t info, abort_callback & aborter ) = 0;
514 //! Album art is being written to the file. \n
515 //! Return passed info, altered info or null to suppress writing.
516 virtual aaptr_t filter_album_art_write( const char * path, const GUID & type, aaptr_t info, abort_callback & aborter ) = 0;
517 //! Specific album art is being removed from the file. \n
518 //! Return true to go on, false to suppress file update.
519 virtual bool filter_album_art_remove( const char * path, const GUID & type, abort_callback & aborter ) = 0;
520 //! All album art is being removed from the file. \n
521 //! Return true to go on, false to suppress file update.
522 virtual bool filter_album_art_remove_all( const char * path, abort_callback & aborter ) = 0;
523
524 //! Valid with supports_fallback() = true \n
525 //! Album art is being written to an untaggable file.
526 virtual void write_album_art_fallback( const char * path, const GUID & type, aaptr_t info, abort_callback & aborter ) = 0;
527 //! Valid with supports_fallback() = true \n
528 //! Specific album art is being removed from an untaggable file.
529 virtual void remove_album_art_fallback( const char * path, const GUID & type, abort_callback & aborter ) = 0;
530 //! Valid with supports_fallback() = true \n
531 //! All album art is being removed from an untaggable file.
532 virtual void remove_all_album_art_fallback( const char * path, abort_callback & aborter ) = 0;
533 };
534
535 class dsp_preset;
536
537 //! \since 1.5
538 //! An input_playback_shim adds additional functionality to a DSP, allowing full control of the decoder. \n
539 //! Currently, input_playback_shim can only exist alongside a DSP, must have the same GUID as a DSP. \n
540 //! It will only be used in supported scenarios when the user has put your DSP in the chain. \n
541 //! Your DSP will be deactivated in such case when your input_playback_shim is active. \n
542 //! input_playback_shim is specifically intended to be instantiated for playback. Do not call this service from your component. \n/
543 //! Implement this service ONLY IF NECESSARY. Very few tasks really need it, primarily DSPs that manipulate logical playback time & seeking.
544 class input_playback_shim : public service_base {
545 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT( input_playback_shim );
546 public:
547 //! Same GUID as your DSP.
548 virtual GUID get_guid() = 0;
549 //! Preferences page / advconfig branch GUID of your shim, pfc::guid_null if none. \n
550 //! This is currently unused / reserved for future use.
551 virtual GUID get_preferences_guid() = 0;
552 //! Same as your DSP. \n
553 //! This is currently unused / reserved for future use.
554 virtual const char * get_name() = 0;
555 //! Instantiates your shim on top of existing input_decoder. \n
556 //! If you don't want to do anything with this specific decoder, just return the passed decoder.
557 virtual input_decoder::ptr shim( input_decoder::ptr dec, const char * path, dsp_preset const & preset, abort_callback & aborter ) = 0;
558 //! Optional backwards compatibility method. \n
559 //! If you also provide input services for old versions of foobar2000 which don't recognize input_playback_shim, report their GUIDs here so they can be ignored. \n
560 //! @param outGUIDs empty on entry, contains GUIDs of ignored inputs (if any) on return.
561 virtual void get_suppressed_inputs( pfc::list_base_t<GUID> & outGUIDs ) {outGUIDs.remove_all();}
562 };
563
564 #endif // #ifdef FOOBAR2000_DESKTOP
565
566
567 typedef input_info_writer_v2 input_info_writer_vhighest;
568 typedef input_decoder_v4 input_decoder_vhighest;
569 typedef input_info_reader_v2 input_info_reader_vhighest;
570
571 typedef input_info_writer input_info_writer_vrequired;
572 typedef input_decoder input_decoder_vrequired;
573 typedef input_info_reader_v2 input_info_reader_vrequired;
574
575 //! \since 2.0
576 class input_entry_v4 : public input_entry_v3 {
577 FB2K_MAKE_SERVICE_INTERFACE(input_entry_v4, input_entry_v3)
578 public:
579 //! Fallback method for detecting renamed files. \n
580 //! This gets called after normal means of opening this file failed.
581 virtual bool fallback_is_our_payload(const void* bytes, size_t bytesAvail, t_filesize bytesWhole) = 0;
582 };