1 /*
2   deadbeef.d -- plugin API of the DeaDBeeF audio player
3   http://deadbeef.sourceforge.net
4 
5   Copyright (C) 2009-2013 Alexey Yakovenko
6 
7   This software is provided 'as-is', without any express or implied
8   warranty.  In no event will the authors be held liable for any damages
9   arising from the use of this software.
10 
11   Permission is granted to anyone to use this software for any purpose,
12   including commercial applications, and to alter it and redistribute it
13   freely, subject to the following restrictions:
14 
15   1. The origin of this software must not be misrepresented; you must not
16      claim that you wrote the original software. If you use this software
17      in a product, an acknowledgment in the product documentation would be
18      appreciated but is not required.
19   2. Altered source versions must be plainly marked as such, and must not be
20      misrepresented as being the original software.
21   3. This notice may not be removed or altered from any source distribution.
22 */
23 module deadbeef.deadbeef;
24 
25 import core.stdc.time: time_t;
26 import core.stdc.stdint: uintptr_t, intptr_t;
27 import core.stdc.stdio: FILE;
28 import core.sys.posix.dirent: dirent;
29 
30 extern (C):
31 @trusted:
32 @nogc:
33 nothrow:
34 
35 
36 // every plugin must define the following entry-point:
37 // extern "C" DB_plugin_t* $MODULENAME_load (DB_functions_t *api);
38 // where $MODULENAME is a name of module
39 // e.g. if your plugin is called "myplugin.so", $MODULENAME is "myplugin"
40 // this function should return pointer to DB_plugin_t structure
41 // that is enough for both static and dynamic modules
42 
43 // backwards compatibility is supported since API version 1.0
44 // that means that the plugins which use the API 1.0 will work without recompiling until API 2.0.
45 //
46 // increments in the major version number mean that there are API breaks, and
47 // plugins must be recompiled to be compatible.
48 //
49 // add DDB_REQUIRE_API_VERSION(x,y) macro when you define the plugin structure
50 // like this:
51 // static DB_decoder_t plugin = {
52 //   DDB_REQUIRE_API_VERSION(1,0)
53 //  ............
54 // }
55 // this is required for versioning
56 // if you don't do it -- no version checking will be done (useful for debugging/development)
57 //
58 // please DON'T release plugins without version requirement
59 //
60 // to ensure compatibility, use the following before including deadbeef.h:
61 // #define DDB_API_LEVEL x
62 // where x is the minor API version number.
63 // that way, you'll get errors or warnings when using incompatible stuff.
64 //
65 // if you also want to get the deprecation warnings, use the following:
66 // #define DDB_WARN_DEPRECATED 1
67 //
68 // NOTE: deprecation doesn't mean the API is going to be removed, it just means
69 // that there's a better replacement in the newer deadbeef versions.
70 
71 // api version history:
72 // 1.9 -- deadbeef-0.7.2
73 // 1.8 -- deadbeef-0.7.0
74 // 1.7 -- deadbeef-0.6.2
75 // 1.6 -- deadbeef-0.6.1
76 // 1.5 -- deadbeef-0.6
77 // 1.4 -- deadbeef-0.5.5
78 // 1.3 -- deadbeef-0.5.3
79 // 1.2 -- deadbeef-0.5.2
80 // 1.1 -- deadbeef-0.5.1
81 //   adds pass_through method to dsp plugins for optimization purposes
82 // 1.0 -- deadbeef-0.5.0
83 // 0.10 -- deadbeef-0.4.4-portable-r1 (note: 0.4.4 uses api v0.9)
84 // 0.9 -- deadbeef-0.4.3-portable-build3
85 // 0.8 -- deadbeef-0.4.2
86 // 0.7 -- deabdeef-0.4.0
87 // 0.6 -- deadbeef-0.3.3
88 // 0.5 -- deadbeef-0.3.2
89 // 0.4 -- deadbeef-0.3.0
90 // 0.3 -- deadbeef-0.2.3.2
91 // 0.2 -- deadbeef-0.2.3
92 // 0.1 -- deadbeef-0.2.0
93 
94 enum DB_API_VERSION_MAJOR = 1;
95 enum DB_API_VERSION_MINOR = 9;
96 
97 enum DDB_API_LEVEL = DB_API_VERSION_MINOR;
98 /+ … +/
99 
100 ////////////////////////////
101 // default values for some common config variables should go here
102 
103 // network.ctmapping : content-type to plugin mapping
104 enum DDB_DEFAULT_CTMAPPING = "audio/mpeg {stdmpg ffmpeg} audio/x-mpeg {stdmpg ffmpeg} application/ogg {stdogg ffmpeg} audio/ogg {stdogg ffmpeg} audio/aac {aac ffmpeg} audio/aacp {aac ffmpeg} audio/x-m4a {aac ffmpeg} audio/wma {wma ffmpeg}";
105 
106 enum {
107 	DDB_IS_SUBTRACK = (1<<0), // file is not single-track, might have metainfo in external file
108 	DDB_IS_READONLY = (1<<1), // check this flag to block tag writing (e.g. in iso.wv)
109 	DDB_HAS_EMBEDDED_CUESHEET = (1<<2),
110 
111 	DDB_TAG_ID3V1 = (1<<8),
112 	DDB_TAG_ID3V22 = (1<<9),
113 	DDB_TAG_ID3V23 = (1<<10),
114 	DDB_TAG_ID3V24 = (1<<11),
115 	DDB_TAG_APEV2 = (1<<12),
116 	DDB_TAG_VORBISCOMMENTS = (1<<13),
117 	DDB_TAG_CUESHEET = (1<<14),
118 	DDB_TAG_ICY = (1<<15),
119 	DDB_TAG_ITUNES = (1<<16),
120 
121 	DDB_TAG_MASK = 0x000fff00
122 }
123 
124 // playlist item
125 // these are "public" fields, available to plugins
126 struct DB_playItem_s {
127 	int startsample; // start sample of track, or -1 for auto
128 	int endsample; // end sample of track, or -1 for auto
129 	int shufflerating; // sort order for shuffle mode
130 }
131 alias ddb_playItem_t = DB_playItem_s;
132 alias DB_playItem_t = ddb_playItem_t;
133 
134 struct ddb_playlist_t {
135 }
136 
137 struct DB_metaInfo_s {
138 	DB_metaInfo_s *next;
139 	immutable char *key;
140 	immutable char *value;
141 }
142 alias DB_metaInfo_t = DB_metaInfo_s;
143 
144 // FIXME: that needs to be in separate plugin
145 
146 enum JUNK_STRIP_ID3V2 = 1;
147 enum JUNK_STRIP_APEV2 = 2;
148 enum JUNK_STRIP_ID3V1 = 4;
149 enum JUNK_WRITE_ID3V2 = 8;
150 enum JUNK_WRITE_APEV2 = 16;
151 enum JUNK_WRITE_ID3V1 = 32;
152 
153 struct DB_id3v2_frame_s {
154 	DB_id3v2_frame_s *next;
155 	char[5] id;
156 	uint size;
157 	ubyte[2] flags;
158 	ubyte[0] data;
159 }
160 alias DB_id3v2_frame_t = DB_id3v2_frame_s;
161 
162 struct DB_id3v2_tag_s {
163 	ubyte[2] ver;
164 	ubyte flags;
165 	DB_id3v2_frame_t *frames;
166 }
167 alias DB_id3v2_tag_t = DB_id3v2_tag_s;
168 
169 struct DB_apev2_frame_s {
170 	DB_apev2_frame_s *next;
171 	uint flags;
172 	char[256] key;
173 	uint size; // size of data
174 	ubyte *data; /+uint8_t data[0]; — don't know how to implement it in D+/
175 }
176 alias DB_apev2_frame_t = DB_apev2_frame_s;
177 
178 struct DB_apev2_tag_s {
179 	uint ver;
180 	uint flags;
181 	DB_apev2_frame_t *frames;
182 }
183 alias DB_apev2_tag_t = DB_apev2_tag_s;
184 
185 // plugin types
186 enum {
187 	DB_PLUGIN_DECODER = 1,
188 	DB_PLUGIN_OUTPUT  = 2,
189 	DB_PLUGIN_DSP     = 3,
190 	DB_PLUGIN_MISC    = 4,
191 	DB_PLUGIN_VFS     = 5,
192 	DB_PLUGIN_PLAYLIST = 6,
193 	DB_PLUGIN_GUI = 7,
194 }
195 
196 // output plugin states
197 enum output_state_t {
198 	OUTPUT_STATE_STOPPED = 0,
199 	OUTPUT_STATE_PLAYING = 1,
200 	OUTPUT_STATE_PAUSED = 2,
201 }
202 
203 // playback order
204 enum playback_order_t {
205 	PLAYBACK_ORDER_LINEAR = 0,
206 	PLAYBACK_ORDER_SHUFFLE_TRACKS = 1,
207 	PLAYBACK_ORDER_RANDOM = 2,
208 	PLAYBACK_ORDER_SHUFFLE_ALBUMS = 3,
209 }
210 
211 // playback modes
212 enum playback_mode_t {
213 	PLAYBACK_MODE_LOOP_ALL = 0, // loop playlist
214 	PLAYBACK_MODE_NOLOOP = 1, // don't loop
215 	PLAYBACK_MODE_LOOP_SINGLE = 2, // loop single track
216 }
217 
218 static if (DDB_API_LEVEL >= 8) {
219 	// playlist change info, used in the DB_EV_PLAYLISTCHANGED p1 argument
220 	enum ddb_playlist_change_t {
221 		DDB_PLAYLIST_CHANGE_CONTENT, // this is the most generic one, will work for the cases when p1 was omitted (0)
222 		DDB_PLAYLIST_CHANGE_CREATED,
223 		DDB_PLAYLIST_CHANGE_DELETED,
224 		DDB_PLAYLIST_CHANGE_POSITION,
225 		DDB_PLAYLIST_CHANGE_TITLE,
226 		DDB_PLAYLIST_CHANGE_SELECTION,
227 		DDB_PLAYLIST_CHANGE_SEARCHRESULT,
228 		DDB_PLAYLIST_CHANGE_PLAYQUEUE,
229 	}
230 }
231 
232 struct ddb_event_t {
233 	int event;
234 	int size;
235 }
236 
237 struct ddb_event_track_t {
238 	ddb_event_t ev;
239 	DB_playItem_t *track;
240 	float playtime; // for SONGFINISHED event -- for how many seconds track was playing
241 	time_t started_timestamp; // time when "track" started playing
242 }
243 
244 struct ddb_event_trackchange_t {
245 	ddb_event_t ev;
246 	DB_playItem_t *from;
247 	DB_playItem_t *to;
248 	float playtime; // for SONGCHANGED event -- for how many seconds prev track was playing
249 	time_t started_timestamp; // time when "from" started playing
250 }
251 
252 struct ddb_event_state_t {
253 	ddb_event_t ev;
254 	int state;
255 }
256 
257 struct ddb_event_playpos_t {
258 	ddb_event_t ev;
259 	DB_playItem_t *track;
260 	float playpos;
261 }
262 
263 struct DB_conf_item_s {
264 	char *key;
265 	char *value;
266 	DB_conf_item_s *next;
267 }
268 alias DB_conf_item_t = DB_conf_item_s;
269 
270 // event callback type
271 alias DB_callback_t = int function(ddb_event_t *, uintptr_t data);
272 
273 // events
274 enum {
275 	DB_EV_NEXT = 1, // switch to next track
276 	DB_EV_PREV = 2, // switch to prev track
277 	DB_EV_PLAY_CURRENT = 3, // play current track (will start/unpause if stopped or paused)
278 	DB_EV_PLAY_NUM = 4, // play track nr. p1
279 	DB_EV_STOP = 5, // stop current track
280 	DB_EV_PAUSE = 6, // pause playback
281 	DB_EV_PLAY_RANDOM = 7, // play random track
282 	DB_EV_TERMINATE = 8, // must be sent to player thread to terminate
283 	DB_EV_PLAYLIST_REFRESH = 9, // [DEPRECATED IN API LEVEL 8, use DB_EV_PLAYLISTCHANGED instead] save and redraw current playlist
284 	DB_EV_REINIT_SOUND = 10, // reinitialize sound output with current output_plugin config value
285 	DB_EV_CONFIGCHANGED = 11, // one or more config options were changed
286 	DB_EV_TOGGLE_PAUSE = 12,
287 	DB_EV_ACTIVATED = 13, // will be fired every time player is activated
288 	DB_EV_PAUSED = 14, // player was paused or unpaused
289 
290 	DB_EV_PLAYLISTCHANGED = 15, // playlist contents were changed (e.g. metadata in any track)
291 	// DB_EV_PLAYLISTCHANGED NOTE: it's usually sent on LARGE changes,
292 	// when multiple tracks are affected, while for single tracks
293 	// the DB_EV_TRACKINFOCHANGED is preferred
294 	// added in API level 8:
295 	// p1 is one of ddb_playlist_change_t enum values, detailing what exactly has been changed.
296 
297 	DB_EV_VOLUMECHANGED = 16, // volume was changed
298 	DB_EV_OUTPUTCHANGED = 17, // sound output plugin changed
299 	DB_EV_PLAYLISTSWITCHED = 18, // playlist switch occured
300 	DB_EV_SEEK = 19, // seek current track to position p1 (ms)
301 	DB_EV_ACTIONSCHANGED = 20, // plugin actions were changed, e.g. for reinitializing gui
302 	DB_EV_DSPCHAINCHANGED = 21, // emitted when any parameter of the main dsp chain has been changed
303 }
304 
305 	// since 1.5
306 static if (DDB_API_LEVEL >= 5) {
307 	enum {
308 		DB_EV_SELCHANGED = 22, // selection changed in playlist p1 iter p2, ctx should be a pointer to playlist viewer instance, which caused the change, or NULL
309 		DB_EV_PLUGINSLOADED = 23, // after all plugins have been loaded and connected
310 	}
311 }
312 
313 static if (DDB_API_LEVEL >= 8) {
314 	enum {
315 		DB_EV_FOCUS_SELECTION = 24, // tell playlist viewer to focus on selection
316 	}
317 }
318 
319 enum {
320 	// -----------------
321 	// structured events
322 
323 	DB_EV_FIRST = 1000,
324 	DB_EV_SONGCHANGED = 1000, // current song changed from one to another, ctx=ddb_event_trackchange_t
325 	DB_EV_SONGSTARTED = 1001, // song started playing, ctx=ddb_event_track_t
326 	DB_EV_SONGFINISHED = 1002, // song finished playing, ctx=ddb_event_track_t
327 
328 	DB_EV_TRACKINFOCHANGED = 1004, // trackinfo was changed (included medatata, playback status, playqueue state, etc), ctx=ddb_event_track_t
329 	// DB_EV_TRACKINFOCHANGED NOTE: when multiple tracks change, DB_EV_PLAYLISTCHANGED may be sent instead,
330 	// for speed reasons, so always handle both events.
331 
332 	DB_EV_SEEKED = 1005, // seek happened, ctx=ddb_event_playpos_t
333 }
334 
335 // since 1.5
336 static if (DDB_API_LEVEL >= 5) {
337 	enum {
338 		// NOTE: this is not a structured event, but too late to fix, needs to stay here for backwards compat
339 		DB_EV_TRACKFOCUSCURRENT = 1006, // user wants to highlight/find the current playing track
340 	}
341 }
342 
343 enum {
344 	DB_EV_MAX = 1007
345 }
346 
347 // preset columns, working using IDs
348 // DON'T add new ids in range 2-7, they are reserved for backwards compatibility
349 enum pl_column_t {
350 	DB_COLUMN_FILENUMBER = 0,
351 	DB_COLUMN_PLAYING = 1,
352 	DB_COLUMN_ALBUM_ART = 8,
353 };
354 
355 // replaygain constants
356 enum {
357 	DDB_REPLAYGAIN_ALBUMGAIN,
358 	DDB_REPLAYGAIN_ALBUMPEAK,
359 	DDB_REPLAYGAIN_TRACKGAIN,
360 	DDB_REPLAYGAIN_TRACKPEAK,
361 }
362 
363 // sort order constants
364 enum {
365 	DDB_SORT_DESCENDING = 0,
366 	DDB_SORT_ASCENDING = 1,
367 }
368 
369 // since 1.3
370 static if (DDB_API_LEVEL >= 3) {
371 	enum DDB_SORT_RANDOM = 2;
372 }
373 
374 enum ddb_sys_directory_t {
375 	DDB_SYS_DIR_CONFIG = 1,
376 	DDB_SYS_DIR_PREFIX = 2,
377 	DDB_SYS_DIR_DOC = 3,
378 	DDB_SYS_DIR_PLUGIN = 4,
379 	DDB_SYS_DIR_PIXMAP = 5,
380 	DDB_SYS_DIR_CACHE = 6,
381 }
382 
383 /+ do we really need it in D?
384 // typecasting macros
385 #define DB_PLUGIN(x) ((DB_plugin_t *)(x))
386 #define DB_CALLBACK(x) ((DB_callback_t)(x))
387 #define DB_EVENT(x) ((ddb_event_t *)(x))
388 #define DB_PLAYITEM(x) ((DB_playItem_t *)(x))
389 +/
390 
391 // FILE object wrapper for vfs access
392 struct DB_FILE {
393 	DB_vfs_s *vfs;
394 };
395 
396 // md5 calc control structure (see md5/md5.h)
397 struct DB_md5_s {
398 	char[88] data;
399 }
400 alias DB_md5_t = DB_md5_s;
401 
402 struct ddb_waveformat_t {
403 	int bps;
404 	int channels;
405 	int samplerate;
406 	uint channelmask;
407 	int is_float; // bps must be 32 if this is true
408 	int is_bigendian;
409 }
410 
411 // since 1.5
412 static if (DDB_API_LEVEL >= 5) {
413 	enum DDB_FREQ_BANDS = 256;
414 	enum DDB_FREQ_MAX_CHANNELS = 9;
415 	struct ddb_audio_data_s {
416 		immutable ddb_waveformat_t *fmt;
417 		immutable float *data;
418 		int nframes;
419 	}
420 	alias ddb_audio_data_t = ddb_audio_data_s;
421 
422 	struct ddb_fileadd_data_s {
423 		int visibility;
424 		ddb_playlist_t *plt;
425 		ddb_playItem_t *track;
426 	}
427 	alias ddb_fileadd_data_t = ddb_fileadd_data_s;
428 }
429 
430 // since 1.8
431 static if (DDB_API_LEVEL >= 8) {
432 	enum {
433 		DDB_TF_CONTEXT_HAS_INDEX = 1,
434 		DDB_TF_CONTEXT_HAS_ID = 2,
435 		DDB_TF_CONTEXT_NO_DYNAMIC = 4, // skip dynamic fields (%playback_time%)
436 	}
437 	static if (DDB_API_LEVEL >= 9) {
438 		// Don't convert linebreaks to semicolons
439 		enum DDB_TF_CONTEXT_MULTILINE = 8;
440 	}
441 
442 	// context for title formatting interpreter
443 	struct ddb_tf_context_t {
444 		int _size; // must be set to sizeof(tf_context_t)
445 		uint flags; // DDB_TF_CONTEXT_ flags
446 		ddb_playItem_t *it; // track to get information from, or NULL
447 		ddb_playlist_t *plt; // playlist in which the track resides, or NULL
448 
449 		// NOTE: when plt is NULL, it means that the track is not in any playlist,
450 		// that is -- playlist will never be automatically guessed, for performance
451 		// reasons.
452 
453 		// index of the track in playlist the track belongs to
454 		// if present, DDB_TF_CONTEXT_HAS_INDEX flag must be set
455 		int idx;
456 
457 		// predefined column id, one of the DB_COLUMN_
458 		// if present, DDB_TF_CONTEXT_HAS_ID flag must be set
459 		int id;
460 
461 		int iter; // playlist iteration (PL_MAIN, PL_SEARCH)
462 
463 		// update is a returned value
464 		// meaning:
465 		// 0: no automatic updates
466 		// <0: updates on every call
467 		// >0: number of milliseconds between updates / until next update
468 		int update;
469 	}
470 }
471 
472 // player api definition
473 struct DB_functions_t {
474 	// versioning
475 	int vmajor;
476 	int vminor;
477 
478 	// md5sum calc
479 	void function(ubyte[16] sig, in char *input, int len) nothrow @nogc md5;
480 	void function(char *str, in ubyte[16] sig) nothrow @nogc md5_to_str;
481 	void function(DB_md5_t *s) nothrow @nogc md5_init;
482 	void function(DB_md5_t *s, in ubyte *data, int nbytes) nothrow @nogc md5_append;
483 	void function(DB_md5_t *s, ubyte[16] digest) nothrow @nogc md5_finish;
484 
485 	// playback control
486 	DB_output_s* function() nothrow @nogc get_output;
487 	float function() nothrow @nogc playback_get_pos; // [0..100]
488 	void function(float pos) nothrow @nogc playback_set_pos; // [0..100]
489 
490 	// streamer access
491 	DB_playItem_t *function() nothrow @nogc streamer_get_playing_track;
492 	DB_playItem_t *function() nothrow @nogc streamer_get_streaming_track;
493 	float function() nothrow @nogc streamer_get_playpos;
494 	int function(int len) nothrow @nogc streamer_ok_to_read;
495 	void function(int full) nothrow @nogc streamer_reset;
496 	int function(char *bytes, int size) nothrow @nogc streamer_read;
497 	void function(int bitrate) nothrow @nogc streamer_set_bitrate;
498 	int function() nothrow @nogc streamer_get_apx_bitrate;
499 	DB_fileinfo_s *function() nothrow @nogc streamer_get_current_fileinfo;
500 	int function() nothrow @nogc streamer_get_current_playlist;
501 	ddb_dsp_context_s * function() nothrow @nogc streamer_get_dsp_chain;
502 	void function(ddb_dsp_context_s *chain) nothrow @nogc streamer_set_dsp_chain;
503 	void function() nothrow @nogc streamer_dsp_refresh; // call after changing parameters
504 
505 	// system folders
506 	// normally functions will return standard folders derived from --prefix
507 	// portable version will return pathes specified in comments below
508 	/+static if (DDB_API_LEVEL < 8) {+/
509 		immutable char* function() nothrow @nogc get_config_dir; // installdir/config | $XDG_CONFIG_HOME/.config/deadbeef
510 		immutable char* function() nothrow @nogc get_prefix; // installdir | PREFIX
511 		immutable char* function() nothrow @nogc get_doc_dir; // installdir/doc | DOCDIR
512 		immutable char* function() nothrow @nogc get_plugin_dir; // installdir/plugins | LIBDIR/deadbeef
513 		immutable char* function() nothrow @nogc get_pixmap_dir; // installdir/pixmaps | PREFIX "/share/deadbeef/pixmaps"
514 	/+}+/
515 
516 	// process control
517 	void function() quit;
518 
519 	// threading
520 	intptr_t function(void function(void *ctx) fn, void *ctx) nothrow @nogc thread_start;
521 	intptr_t function(void function(void *ctx) fn, void *ctx) nothrow @nogc thread_start_low_priority;
522 	int function(intptr_t tid) nothrow @nogc thread_join;
523 	int function(intptr_t tid) nothrow @nogc thread_detach;
524 	void function(void *retval) nothrow @nogc thread_exit;
525 	uintptr_t function() nothrow @nogc mutex_create;
526 	uintptr_t function() nothrow @nogc mutex_create_nonrecursive;
527 	void function(uintptr_t mtx) nothrow @nogc mutex_free;
528 	int function(uintptr_t mtx) nothrow @nogc mutex_lock;
529 	int function(uintptr_t mtx) nothrow @nogc mutex_unlock;
530 	uintptr_t function() nothrow @nogc cond_create;
531 	void function(uintptr_t cond) nothrow @nogc cond_free;
532 	int function(uintptr_t cond, uintptr_t mutex) nothrow @nogc cond_wait;
533 	int function(uintptr_t cond) nothrow @nogc cond_signal;
534 	int function(uintptr_t cond) nothrow @nogc cond_broadcast;
535 
536 	/////// playlist management //////
537 	void function(ddb_playlist_t *plt) nothrow @nogc plt_ref;
538 	void function(ddb_playlist_t *plt) nothrow @nogc plt_unref;
539 
540 	// total number of playlists
541 	int function() nothrow @nogc plt_get_count;
542 
543 
544 	// 1st item in playlist nr. 'plt'
545 	DB_playItem_t * function(int plt) nothrow @nogc plt_get_head;
546 
547 	// nr. of selected items in playlist nr. 'plt'
548 	int function(int plt) nothrow @nogc plt_get_sel_count;
549 
550 	// add new playlist into position before nr. 'before', with title='title'
551 	// returns index of new playlist
552 	int function(int before, in char *title) nothrow @nogc plt_add;
553 
554 	// remove playlist nr. plt
555 	void function(int plt) nothrow @nogc plt_remove;
556 
557 	// clear playlist
558 	void function(ddb_playlist_t *plt) nothrow @nogc plt_clear;
559 	void function() nothrow @nogc pl_clear;
560 
561 	// set current playlist
562 	void function(ddb_playlist_t *plt) nothrow @nogc plt_set_curr;
563 	void function(int plt) nothrow @nogc plt_set_curr_idx;
564 
565 	// get current playlist
566 	// note: caller is responsible to call plt_unref after using pointer
567 	// returned by plt_get_curr
568 	ddb_playlist_t* function() nothrow @nogc plt_get_curr;
569 	int function() nothrow @nogc plt_get_curr_idx;
570 
571 	// move playlist nr. 'from' into position before nr. 'before', where
572 	// before=-1 means last position
573 	void function(int from, int before) nothrow @nogc plt_move;
574 
575 	// playlist saving and loading
576 	/+static if (DDB_API_LEVEL < 5) {+/
577 		DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, in char *fname, int *pabort, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_load;
578 	/+}+/
579 	int function(ddb_playlist_t *plt, DB_playItem_t *first, DB_playItem_t *last, in char *fname, int *pabort, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_save;
580 
581 	ddb_playlist_t* function(int idx) nothrow @nogc plt_get_for_idx;
582 	int function(ddb_playlist_t *plt, char *buffer, int bufsize) nothrow @nogc plt_get_title;
583 	int function(ddb_playlist_t *plt, in char *title) nothrow @nogc plt_set_title;
584 
585 	// increments modification index
586 	void function(ddb_playlist_t *handle) nothrow @nogc plt_modified;
587 
588 	// returns modication index
589 	// the index is incremented by 1 every time playlist changes
590 	int function(ddb_playlist_t *handle) nothrow @nogc plt_get_modification_idx;
591 
592 	// return index of an item in specified playlist, or -1 if not found
593 	int function(ddb_playlist_t *plt, DB_playItem_t *it, int iter) nothrow @nogc plt_get_item_idx;
594 
595 	// playlist metadata
596 	// this kind of metadata is stored in playlist (dbpl) files
597 	// that is, this is the properties of playlist itself,
598 	// not of the tracks in the playlist.
599 	// for example, playlist tab color can be stored there, etc
600 
601 	// add meta if it doesn't exist yet
602 	void function(ddb_playlist_t *handle, in char *key, in char *value) nothrow @nogc plt_add_meta;
603 
604 	// replace (or add) existing meta
605 	void function(ddb_playlist_t *handle, in char *key, in char *value) nothrow @nogc plt_replace_meta;
606 
607 	// append meta to existing one, or add if doesn't exist
608 	void function(ddb_playlist_t *handle, in char *key, in char *value) nothrow @nogc plt_append_meta;
609 
610 	// set integer meta (works same as replace)
611 	void function(ddb_playlist_t *handle, in char *key, int value) nothrow @nogc plt_set_meta_int;
612 
613 	// set float meta (works same as replace)
614 	void function(ddb_playlist_t *handle, in char *key, float value) nothrow @nogc plt_set_meta_float;
615 
616 	// plt_find_meta must always be used in the pl_lock/unlock block
617 	immutable char* function(ddb_playlist_t *handle, in char *key) nothrow @nogc plt_find_meta;
618 
619 	// returns head of metadata linked list, for direct access
620 	// remember pl_lock/unlock
621 	DB_metaInfo_t* function(ddb_playlist_t *handle) nothrow @nogc plt_get_metadata_head;
622 
623 	// delete meta item from list
624 	void function(ddb_playlist_t *handle, DB_metaInfo_t *meta) nothrow @nogc plt_delete_metadata;
625 
626 	// returns integer value of requested meta, def is the default value if not found
627 	int function(ddb_playlist_t *handle, in char *key, int def) nothrow @nogc plt_find_meta_int;
628 
629 	// returns float value of requested meta, def is the default value if not found
630 	float function(ddb_playlist_t *handle, in char *key, float def) nothrow @nogc plt_find_meta_float;
631 
632 	// delete all metadata
633 	void function(ddb_playlist_t *handle) nothrow @nogc plt_delete_all_meta;
634 
635 	// operating on playlist items
636 	DB_playItem_t* function(ddb_playlist_t *playlist, DB_playItem_t *after, DB_playItem_t *it) nothrow @nogc plt_insert_item;
637 	/+static if (DDB_API_LEVEL < 5) {+/
638 		DB_playItem_t* function(ddb_playlist_t *playlist, DB_playItem_t *after, in char *fname, int *pabort, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_insert_file;
639 		DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, in char *dirname, int *pabort, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_insert_dir;
640 	/+}+/
641 	void function(ddb_playlist_t *plt, DB_playItem_t *it, float duration) nothrow @nogc plt_set_item_duration;
642 	int function(ddb_playlist_t *playlist, DB_playItem_t *it) nothrow @nogc plt_remove_item;
643 	int function(ddb_playlist_t *playlist) nothrow @nogc plt_getselcount;
644 	float function(ddb_playlist_t *plt) nothrow @nogc plt_get_totaltime;
645 	int function(ddb_playlist_t *plt, int iter) nothrow @nogc plt_get_item_count;
646 	int function(ddb_playlist_t *plt) nothrow @nogc plt_delete_selected;
647 	void function(ddb_playlist_t *plt, int iter, int cursor) nothrow @nogc plt_set_cursor;
648 	int function(ddb_playlist_t *plt, int iter) nothrow @nogc plt_get_cursor;
649 	void function(ddb_playlist_t *plt) nothrow @nogc plt_select_all;
650 	void function(ddb_playlist_t *plt) nothrow @nogc plt_crop_selected;
651 	DB_playItem_t* function(ddb_playlist_t *plt, int iter) nothrow @nogc plt_get_first;
652 	DB_playItem_t* function(ddb_playlist_t *plt, int iter) nothrow @nogc plt_get_last;
653 	DB_playItem_t* function(ddb_playlist_t *playlist, int idx, int iter) nothrow @nogc plt_get_item_for_idx;
654 	void function(ddb_playlist_t *to, int iter, ddb_playlist_t *from, DB_playItem_t *drop_before, uint *indexes, int count) nothrow @nogc plt_move_items;
655 	void function(ddb_playlist_t *to, int iter, ddb_playlist_t * from, DB_playItem_t *before, uint *indices, int cnt) nothrow @nogc plt_copy_items;
656 	void function(ddb_playlist_t *plt) nothrow @nogc plt_search_reset;
657 	void function(ddb_playlist_t *plt, in char *text) nothrow @nogc plt_search_process;
658 
659 	// sort using the title formatting v1 (deprecated)
660 	/+static if (DDB_API_LEVEL < 8) {+/
661 		void function(ddb_playlist_t *plt, int iter, int id, in char *format, int order) nothrow @nogc plt_sort;
662 	/+}+/
663 
664 	/+static if (DDB_API_LEVEL < 5) {+/
665 		// add files and folders to current playlist
666 		int function(ddb_playlist_t *plt, in char *fname, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_add_file;
667 		int function(ddb_playlist_t *plt, in char *dirname, int function(DB_playItem_t *it, void *data) cb, void *user_data) nothrow @nogc plt_add_dir;
668 	/+}+/
669 
670 	// cuesheet support
671 	DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, DB_playItem_t *origin, in ubyte *buffer, int buffersize, int numsamples, int samplerate) nothrow @nogc plt_insert_cue_from_buffer;
672 	DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, DB_playItem_t *origin, int numsamples, int samplerate) nothrow @nogc plt_insert_cue;
673 
674 	// playlist locking
675 	void function() nothrow @nogc pl_lock;
676 	void function() nothrow @nogc pl_unlock;
677 
678 	// playlist tracks access
679 	DB_playItem_t* function() nothrow @nogc pl_item_alloc;
680 	DB_playItem_t* function(in char *fname, in char *decoder_id) nothrow @nogc pl_item_alloc_init;
681 	void function(DB_playItem_t *it) nothrow @nogc pl_item_ref;
682 	void function(DB_playItem_t *it) nothrow @nogc pl_item_unref;
683 	void function(DB_playItem_t *output, DB_playItem_t *input) nothrow @nogc pl_item_copy;
684 
685 	// request lock for adding files to playlist
686 	// this function may return -1 if it is not possible to add files right now.
687 	// caller must cancel operation in this case,
688 	// or wait until previous operation finishes
689 	/+static if (DDB_API_LEVEL < 5) {+/
690 		int function(ddb_playlist_t *plt) nothrow @nogc pl_add_files_begin;
691 
692 		// release the lock for adding files to playlist
693 		// end must be called when add files operation is finished
694 		void function() nothrow @nogc pl_add_files_end;
695 	/+}+/
696 
697 	// most of this functions are self explanatory
698 	// if you don't get what they do -- look in the code
699 
700 	// --- the following functions work with current playlist ---
701 
702 	// get index of the track in MAIN
703 	int function(DB_playItem_t *it) nothrow @nogc pl_get_idx_of;
704 
705 	// get index of the track in MAIN or SEARCH
706 	int function(DB_playItem_t *it, int iter) nothrow @nogc pl_get_idx_of_iter;
707 
708 	// get track for index in MAIN
709 	DB_playItem_t* function(int idx) nothrow @nogc pl_get_for_idx;
710 
711 	// get track for index in MAIN or SEARCH
712 	DB_playItem_t* function(int idx, int iter) nothrow @nogc pl_get_for_idx_and_iter;
713 
714 	// get total play time of all tracks in MAIN
715 	float function() nothrow @nogc pl_get_totaltime;
716 
717 	// get number of tracks in MAIN or SEARCH
718 	int function(int iter) nothrow @nogc pl_getcount;
719 
720 	// delete selected tracks
721 	int function() nothrow @nogc pl_delete_selected;
722 
723 	// set cursor position in MAIN or SEARCH
724 	void function(int iter, int cursor) nothrow @nogc pl_set_cursor;
725 
726 	// get cursor position in MAIN
727 	int function(int iter) nothrow @nogc pl_get_cursor;
728 
729 	// remove all except selected tracks
730 	void function() nothrow @nogc pl_crop_selected;
731 
732 	// get number of selected tracks
733 	int function() nothrow @nogc pl_getselcount;
734 
735 	// get first track in MAIN or SEARCH
736 	DB_playItem_t* function(int iter) nothrow @nogc pl_get_first;
737 
738 	// get last track in MAIN or SEARCH
739 	DB_playItem_t* function(int iter) nothrow @nogc pl_get_last;
740 
741 	// --- misc functions ---
742 
743 	// mark the track as selected or unselected (1 or 0 respectively)
744 	void function(DB_playItem_t *it, int sel) nothrow @nogc pl_set_selected;
745 
746 	// test whether the track is selected
747 	int function(DB_playItem_t *it) nothrow @nogc pl_is_selected;
748 
749 	// save current playlist
750 	int function() nothrow @nogc pl_save_current;
751 
752 	// save all playlists
753 	int function() nothrow @nogc pl_save_all;
754 
755 	// select all tracks in current playlist
756 	void function() nothrow @nogc pl_select_all;
757 
758 	// get next track
759 	DB_playItem_t* function(DB_playItem_t *it, int iter) nothrow @nogc pl_get_next;
760 
761     // get previous track
762 	DB_playItem_t* function(DB_playItem_t *it, int iter) nothrow @nogc pl_get_prev;
763 
764 	/*
765 		pl_format_title formats the line for display in playlist
766 		@it pointer to playlist item
767 		@idx number of that item in playlist (or -1)
768 		@s output buffer
769 		@size size of output buffer
770 		@id one of IDs defined in pl_column_id_t enum, can be -1
771 		@fmt format string, used if id is -1
772 		format is printf-alike. specification:
773 		%a artist
774 		%t title
775 		%b album
776 		%B band / album artist
777 		%n track
778 		%l length (duration)
779 		%y year
780 		%g genre
781 		%c comment
782 		%r copyright
783 		%T tags
784 		%f filename without path
785 		%F full pathname/uri
786 		%d directory without path (e.g. /home/user/file.mp3 -> user)
787 		%D directory name with full path (e.g. /home/user/file.mp3 -> /home/user)
788 		more to come
789 	*/
790 	/+static if (DDB_API_LEVEL < 8) {+/
791 		int function(DB_playItem_t *it, int idx, char *s, int size, int id, in char *fmt) nothrow @nogc pl_format_title;
792 
793 		// _escaped version wraps all conversions with '' and replaces every ' in conversions with \'
794 		int function(DB_playItem_t *it, int idx, char *s, int size, int id, in char *fmt) nothrow @nogc pl_format_title_escaped;
795 	/+}+/
796 	// format duration 't' (fractional seconds) into string, for display in playlist
797 	void function(float t, char *dur, int size) nothrow @nogc pl_format_time;
798 
799 	// find which playlist the specified item belongs to, returns NULL if none
800 	ddb_playlist_t* function(DB_playItem_t *it) nothrow @nogc pl_get_playlist;
801 
802 	// direct access to metadata structures
803 	// not thread-safe, make sure to wrap with pl_lock/pl_unlock
804 	DB_metaInfo_t* function(DB_playItem_t *it) nothrow @nogc pl_get_metadata_head; // returns head of metadata linked list
805 	void function(DB_playItem_t *it, DB_metaInfo_t *meta) nothrow @nogc pl_delete_metadata;
806 
807 	// high-level access to metadata
808 	void function(DB_playItem_t *it, in char *key, in char *value) nothrow @nogc pl_add_meta;
809 	void function(DB_playItem_t *it, in char *key, in char *value) nothrow @nogc pl_append_meta;
810 	void function(DB_playItem_t *it, in char *key, int value) nothrow @nogc pl_set_meta_int;
811 	void function(DB_playItem_t *it, in char *key, float value) nothrow @nogc pl_set_meta_float;
812 	void function(DB_playItem_t *it, in char *key) nothrow @nogc pl_delete_meta;
813 
814 	// this function is not thread-safe
815 	// make sure to wrap it with pl_lock/pl_unlock block
816 	immutable char* function(DB_playItem_t *it, in char *key) nothrow @nogc pl_find_meta;
817 
818 	// following functions are thread-safe
819 	int function(DB_playItem_t *it, in char *key, int def) nothrow @nogc pl_find_meta_int;
820 	float function(DB_playItem_t *it, in char *key, float def) nothrow @nogc pl_find_meta_float;
821 	void function(DB_playItem_t *it, in char *key, in char *value) nothrow @nogc pl_replace_meta;
822 	void function(DB_playItem_t *it) nothrow @nogc pl_delete_all_meta;
823 	float function(DB_playItem_t *it) nothrow @nogc pl_get_item_duration;
824 	uint function(DB_playItem_t *it) nothrow @nogc pl_get_item_flags;
825 	void function(DB_playItem_t *it, uint flags) nothrow @nogc pl_set_item_flags;
826 	void function(DB_playItem_t *from, DB_playItem_t *first, DB_playItem_t *last) nothrow @nogc pl_items_copy_junk;
827 	// idx is one of DDB_REPLAYGAIN_* constants
828 	void function(DB_playItem_t *it, int idx, float value) nothrow @nogc pl_set_item_replaygain;
829 	float function(DB_playItem_t *it, int idx) nothrow @nogc pl_get_item_replaygain;
830 
831 	// playqueue support (obsolete since API 1.8)
832 	/+static if (DDB_API_LEVEL < 8) {+/
833 		int function(DB_playItem_t *it) nothrow @nogc pl_playqueue_push;
834 		void function() nothrow @nogc pl_playqueue_clear;
835 		void function() nothrow @nogc pl_playqueue_pop;
836 		void function(DB_playItem_t *it) nothrow @nogc pl_playqueue_remove;
837 		int function(DB_playItem_t *it) nothrow @nogc pl_playqueue_test;
838 	/+}+/
839 
840 	// volume control
841 	void function(float dB) nothrow @nogc volume_set_db;
842 	float function() nothrow @nogc volume_get_db;
843 	void function(float amp) nothrow @nogc volume_set_amp;
844 	float function() nothrow @nogc volume_get_amp;
845 	float function() nothrow @nogc volume_get_min_db;
846 
847 	// junk reading/writing
848 	int function(DB_playItem_t *it, DB_FILE *fp) nothrow @nogc junk_id3v1_read;
849 	int function(DB_FILE *fp) nothrow @nogc junk_id3v1_find;
850 	int function(FILE *fp, DB_playItem_t *it, in char *enc) nothrow @nogc junk_id3v1_write;
851 	int function(DB_FILE *fp, int *psize) nothrow @nogc junk_id3v2_find;
852 	int function(DB_playItem_t *it, DB_FILE *fp) nothrow @nogc junk_id3v2_read;
853 	int function(DB_playItem_t *it, DB_id3v2_tag_t *tag, DB_FILE *fp) nothrow @nogc junk_id3v2_read_full;
854 	int function(DB_id3v2_tag_t *tag24, DB_id3v2_tag_t *tag23) nothrow @nogc junk_id3v2_convert_24_to_23;
855 	int function(DB_id3v2_tag_t *tag23, DB_id3v2_tag_t *tag24) nothrow @nogc junk_id3v2_convert_23_to_24;
856 	int function(DB_id3v2_tag_t *tag22, DB_id3v2_tag_t *tag24) nothrow @nogc junk_id3v2_convert_22_to_24;
857 	void function(DB_id3v2_tag_t *tag) nothrow @nogc junk_id3v2_free;
858 	int function(FILE *file, DB_id3v2_tag_t *tag) nothrow @nogc junk_id3v2_write;
859 	DB_id3v2_frame_t* function(DB_id3v2_tag_t *tag, in char *frame_id, in char *value) nothrow @nogc junk_id3v2_add_text_frame;
860 	int function(DB_id3v2_tag_t *tag, in char *frame_id) nothrow @nogc junk_id3v2_remove_frames;
861 	int function(DB_playItem_t *it, DB_FILE *fp) nothrow @nogc junk_apev2_read;
862 	int function(DB_playItem_t *it, char *mem, int size) nothrow @nogc junk_apev2_read_mem;
863 	int function(DB_playItem_t *it, DB_apev2_tag_t *tag_store, DB_FILE *fp) nothrow @nogc junk_apev2_read_full;
864 	int function(DB_playItem_t *it, DB_apev2_tag_t *tag_store, char *mem, int memsize) nothrow @nogc junk_apev2_read_full_mem;
865 	int function(DB_FILE *fp, int *psize, uint *pflags, uint *pnumitems) nothrow @nogc junk_apev2_find;
866 	int function(DB_apev2_tag_t *tag, in char *frame_id) nothrow @nogc junk_apev2_remove_frames;
867 	DB_apev2_frame_t* function(DB_apev2_tag_t *tag, in char *frame_id, in char *value) nothrow @nogc junk_apev2_add_text_frame;
868 	void function(DB_apev2_tag_t *tag) nothrow @nogc junk_apev2_free;
869 	int function(FILE *fp, DB_apev2_tag_t *tag, int write_header, int write_footer) nothrow @nogc junk_apev2_write;
870 	int function(DB_FILE *fp) nothrow @nogc junk_get_leading_size;
871 	int function(FILE *fp) nothrow @nogc junk_get_leading_size_stdio;
872 	void function(DB_playItem_t *from, DB_playItem_t *first, DB_playItem_t *last) nothrow @nogc junk_copy;
873 	immutable char * function(in char *s) nothrow @nogc junk_detect_charset;
874 	int function(in char *input, int inlen, char *output, int outlen, in char *cs) nothrow @nogc junk_recode;
875 	int function(in char *input, int inlen, char *output, int outlen, in char *cs_in, in char *cs_out) nothrow @nogc junk_iconv;
876 	int function(DB_playItem_t *it, uint flags, int id3v2_version, in char *id3v1_encoding) nothrow @nogc junk_rewrite_tags;
877 
878 	// vfs
879 	DB_FILE* function(in char *fname) nothrow @nogc fopen;
880 	void function(DB_FILE *f) nothrow @nogc fclose;
881 	size_t function(void *ptr, size_t size, size_t nmemb, DB_FILE *stream) nothrow @nogc fread;
882 	int function(DB_FILE *stream, long offset, int whence) nothrow @nogc fseek;
883 	long function(DB_FILE *stream) nothrow @nogc ftell;
884 	void function(DB_FILE *stream) nothrow @nogc rewind;
885 	long function(DB_FILE *stream) nothrow @nogc fgetlength;
886 	immutable char * function(DB_FILE *stream) nothrow @nogc fget_content_type;
887 	void function(DB_FILE *stream, DB_playItem_t *it) nothrow @nogc fset_track;
888 	void function(DB_FILE *stream) nothrow @nogc fabort;
889 
890 	// message passing
891 	int function(uint id, uintptr_t ctx, uint p1, uint p2) nothrow @nogc sendmessage;
892 
893 	// convenience functions to send events, uses sendmessage internally
894 	ddb_event_t * function(uint id) nothrow @nogc event_alloc;
895 	void function(ddb_event_t *ev) nothrow @nogc event_free;
896 	int function(ddb_event_t *ev, uint p1, uint p2) nothrow @nogc event_send;
897 
898 	// configuration access
899 	//
900 	// conf_get_str_fast is not thread-safe, and
901 	// must only be used from within conf_lock/conf_unlock block
902 	// it should be preferred for fast non-blocking lookups
903 	//
904 	// all the other config access functions are thread safe
905 	void function() nothrow @nogc conf_lock;
906 	void function() nothrow @nogc conf_unlock;
907 	immutable char * function(in char *key, in char *def) nothrow @nogc conf_get_str_fast;
908 	void function(in char *key, in char *def, char *buffer, int buffer_size) nothrow @nogc conf_get_str;
909 	float function(in char *key, float def) nothrow @nogc conf_get_float;
910 	int function(in char *key, int def) nothrow @nogc conf_get_int;
911 	long function(in char *key, long def) nothrow @nogc conf_get_int64;
912 	void function(in char *key, in char *val) nothrow @nogc conf_set_str;
913 	void function(in char *key, int val) nothrow @nogc conf_set_int;
914 	void function(in char *key, long val) nothrow @nogc conf_set_int64;
915 	void function(in char *key, float val) nothrow @nogc conf_set_float;
916 	DB_conf_item_t* function(in char *group, DB_conf_item_t *prev) nothrow @nogc conf_find;
917 	void function(in char *key) nothrow @nogc conf_remove_items;
918 	int function() nothrow @nogc conf_save;
919 
920 	// plugin communication
921 	DB_decoder_s** function() nothrow @nogc plug_get_decoder_list;
922 	DB_vfs_s** function() nothrow @nogc plug_get_vfs_list;
923 	DB_output_s** function() nothrow @nogc plug_get_output_list;
924 	DB_dsp_s** function() nothrow @nogc plug_get_dsp_list;
925 	DB_playlist_s** function() nothrow @nogc plug_get_playlist_list;
926 	DB_plugin_s** function() nothrow @nogc plug_get_list;
927 	immutable char** function() nothrow @nogc plug_get_gui_names;
928 	immutable char * function(in char *id) nothrow @nogc plug_get_decoder_id;
929 	void function(in char *id) nothrow @nogc plug_remove_decoder_id;
930 	DB_plugin_s* function(in char *id) nothrow @nogc plug_get_for_id;
931 
932 	// misc utilities
933 	// returns 1 if the track is represented as a local file
934 	// returns 0 if it's a remote file, e.g. a network stream
935 	// since API 1.5 it also returns 1 for vfs tracks, e.g. from ZIP files
936 	int function(in char *fname) nothrow @nogc is_local_file;
937 
938 	// pcm utilities
939 	int function(in ddb_waveformat_t * inputfmt, in char *input, in ddb_waveformat_t *outputfmt, char *output, int inputsize) nothrow @nogc pcm_convert;
940 
941 	// dsp preset management
942 	int function(in char *fname, ddb_dsp_context_s **head) nothrow @nogc dsp_preset_load;
943 	int function(in char *fname, ddb_dsp_context_s *head) nothrow @nogc dsp_preset_save;
944 	void function(ddb_dsp_context_s *head) nothrow @nogc dsp_preset_free;
945 
946 	// since 1.2
947 	static if (DDB_API_LEVEL >= 2) {
948 		ddb_playlist_t* function(in char *title) nothrow @nogc plt_alloc;
949 		void function(ddb_playlist_t *plt) nothrow @nogc plt_free;
950 
951 		void function(ddb_playlist_t *plt, int fast) nothrow @nogc plt_set_fast_mode;
952 		int function(ddb_playlist_t *plt) nothrow @nogc plt_is_fast_mode;
953 
954 		immutable char * function(in char *str) nothrow @nogc metacache_add_string;
955 		void function(in char *str) nothrow @nogc metacache_remove_string;
956 		void function(in char *str) nothrow @nogc metacache_ref;
957 		void function(in char *str) nothrow @nogc metacache_unref;
958 
959 		// this function must return original un-overriden value (ignoring the keys prefixed with '!')
960 		// it's not thread-safe, and must be used under the same conditions as the
961 		// pl_find_meta
962 		immutable char * function(DB_playItem_t *it, in char *key) nothrow @nogc pl_find_meta_raw;
963 	}
964 
965 	// since 1.3
966 	static if (DDB_API_LEVEL >= 3) {
967 		int function() nothrow @nogc streamer_dsp_chain_save;
968 	}
969 
970 	// since 1.4
971 	static if (DDB_API_LEVEL >= 4) {
972 		int function(DB_playItem_t *it, in char *key, char *val, int size) nothrow @nogc pl_get_meta;
973 		int function(DB_playItem_t *it, in char *key, char *val, int size) nothrow @nogc pl_get_meta_raw;
974 		int function(ddb_playlist_t *handle, in char *key, char *val, int size) nothrow @nogc plt_get_meta;
975 
976 		// fast way to test if a field exists in playitem
977 		int function(DB_playItem_t *it, in char *key) nothrow @nogc pl_meta_exists;
978 	}
979 
980 	// since 1.5
981 	static if (DDB_API_LEVEL >= 5) {
982 		// register/unregister for getting continuous wave data
983 		// mainly for visualization
984 		// ctx must be unique
985 		// the waveform data can be arbitrary size
986 		// the samples are interleaved
987 		void function(void *ctx, void function(void *ctx, ddb_audio_data_t *data) callback) nothrow @nogc vis_waveform_listen;
988 		void function(void *ctx) nothrow @nogc vis_waveform_unlisten;
989 
990 		// register/unregister for getting continuous spectrum (frequency domain) data
991 		// mainly for visualization
992 		// ctx must be unique
993 		// the data always contains DDB_FREQ_BANDS frames
994 		// max number of channels is DDB_FREQ_MAX_CHANNELS
995 		// the samples are non-interleaved
996 		void function(void *ctx, void function(void *ctx, ddb_audio_data_t *data) callback) nothrow @nogc vis_spectrum_listen;
997 		void function(void *ctx) nothrow @nogc vis_spectrum_unlisten;
998 
999 		// this is useful to mute/unmute audio, and query the muted status, from
1000 		// plugins, without touching the volume control
1001 		void function(int mute) nothrow @nogc audio_set_mute;
1002 		int function() nothrow @nogc audio_is_mute;
1003 
1004 		// this is useful for prompting a user when he attempts to quit the player
1005 		// while something is working in background, e.g. the Converter,
1006 		// and let him finish or cancel the background jobs.
1007 		void function() nothrow @nogc background_job_increment;
1008 		void function() nothrow @nogc background_job_decrement;
1009 		int function() nothrow @nogc have_background_jobs;
1010 
1011 		// utility function to get plt idx from handle
1012 		int function(ddb_playlist_t *plt) nothrow @nogc plt_get_idx;
1013 
1014 		// save referenced playlist in config
1015 		// same as pl_save_current, but for index
1016 		int function(int n) nothrow @nogc plt_save_n;
1017 
1018 		// same as pl_save_current, but for playlist pointer
1019 		int function(ddb_playlist_t *plt) nothrow @nogc plt_save_config;
1020 
1021 		// register file added callback
1022 		// the callback will be called for each file
1023 		// the visibility is taken from plt_add_* arguments
1024 		// the callback must return 0 to continue, or -1 to abort the operation.
1025 		// returns ID
1026 		int function(int function(ddb_fileadd_data_t *data, void *user_data) callback, void *user_data) nothrow @nogc listen_file_added;
1027 		void function(int id) nothrow @nogc unlisten_file_added;
1028 
1029 		int function(void function(ddb_fileadd_data_t *data, void *user_data) callback_begin, void function(ddb_fileadd_data_t *data, void *user_data) callback_end, void *user_data) nothrow @nogc listen_file_add_beginend;
1030 		void function(int id) nothrow @nogc unlisten_file_add_beginend;
1031 
1032 		// visibility is a number, which tells listeners about the caller.
1033 		// the value DDB_FILEADD_VISIBILITY_GUI (or 0) is reserved for callers which
1034 		// want the GUI to intercept the calls and show visual updates.
1035 		//
1036 		// this is the default value passed from plt_load, plt_add_dir, plt_add_file.
1037 		//
1038 		// the values up to 10 are registered for deadbeef itself, so please avoid
1039 		// using them in your plugins, unless you really know what you're doing.
1040 		// any values above 10 are free for any use.
1041 		//
1042 		// the "callback", if not NULL, will be called with the passed "user_data",
1043 		// for each track.
1044 		//
1045 		// the registered listeners will be called too, the ddb_fileadd_data_t
1046 		// has the visibility
1047 		DB_playItem_t* function(int visibility, ddb_playlist_t *plt, ddb_playItem_t *after, in char *fname, int *pabort, int function(DB_playItem_t *it, void *user_data) callback, void *user_data) nothrow @nogc plt_load2;
1048 		int function(int visibility, ddb_playlist_t *plt, in char *fname, int function(DB_playItem_t *it, void *user_data) callback, void *user_data) nothrow @nogc plt_add_file2;
1049 		int function(int visibility, ddb_playlist_t *plt, in char *dirname, int function(DB_playItem_t *it, void *user_data) callback, void *user_data) nothrow @nogc plt_add_dir2;
1050 		ddb_playItem_t* function(int visibility, ddb_playlist_t *playlist, ddb_playItem_t *after, in char *fname, int *pabort, int function(DB_playItem_t *it, void *user_data) callback, void *user_data) nothrow @nogc plt_insert_file2;
1051 		ddb_playItem_t* function(int visibility, ddb_playlist_t *plt, ddb_playItem_t *after, in char *dirname, int *pabort, int function(DB_playItem_t *it, void *user_data) callback, void *user_data) nothrow @nogc plt_insert_dir2;
1052 
1053 		// request lock for adding files to playlist
1054 		// returns 0 on success
1055 		// this function may return -1 if it is not possible to add files right now.
1056 		// caller must cancel operation in this case,
1057 		// or wait until previous operation finishes
1058 		// NOTE: it's not guaranteed that all deadbeef versions support
1059 		// adding the files to different playlists in parallel.
1060 		int function(ddb_playlist_t *plt, int visibility) nothrow @nogc plt_add_files_begin;
1061 
1062 		// release the lock for adding files to playlist
1063 		// end must be called when add files operation is finished
1064 		void function(ddb_playlist_t *plt, int visibility) nothrow @nogc plt_add_files_end;
1065 
1066 		// deselect all tracks in playlist
1067 		void function(ddb_playlist_t *plt) nothrow @nogc plt_deselect_all;
1068 	}
1069 	// since 1.6
1070 	static if (DDB_API_LEVEL >= 6) {
1071 		void function(ddb_playlist_t *plt, int scroll) nothrow @nogc plt_set_scroll;
1072 		int function(ddb_playlist_t *plt) nothrow @nogc plt_get_scroll;
1073 	}
1074 
1075 	// since 1.8
1076 	static if (DDB_API_LEVEL >= 8) {
1077 		// **** title formatting v2 ****
1078 
1079 		// compile the input title formatting string into bytecode
1080 		// script: freeform string with title formatting special characters in it
1081 		// returns the pointer to compiled bytecode, which must be tf_free'd by the caller.
1082 		char * function(in char *script) nothrow @nogc tf_compile;
1083 
1084 		// free the code returned by tf_compile
1085 		void function(char *code) nothrow @nogc tf_free;
1086 
1087 		// evaluate the titleformatting script in a given context
1088 		// ctx: a pointer to ddb_tf_context_t structure initialized by the caller
1089 		// code: the bytecode data created by tf_compile
1090 		// out: buffer allocated by the caller, must be big enough to fit the output string
1091 		// outlen: the size of out buffer
1092 		// returns -1 on fail, output size on success
1093 		int function(ddb_tf_context_t *ctx, in char *code, char *output, int outlen) nothrow @nogc tf_eval;
1094 
1095 		// sort using title formatting v2
1096 		void function(ddb_playlist_t *plt, int iter, int id, in char *format, int order) nothrow @nogc plt_sort_v2;
1097 
1098 		// playqueue APIs
1099 		int function(DB_playItem_t *it) nothrow @nogc playqueue_push;
1100 		void function() nothrow @nogc playqueue_pop;
1101 		void function(DB_playItem_t *it) nothrow @nogc playqueue_remove;
1102 		void function() nothrow @nogc playqueue_clear;
1103 		int function(DB_playItem_t *it) nothrow @nogc playqueue_test;
1104 		int function() nothrow @nogc playqueue_get_count;
1105 		DB_playItem_t* function(int n) nothrow @nogc playqueue_get_item;
1106 		int function(int n) nothrow @nogc playqueue_remove_nth;
1107 		void function(int n, DB_playItem_t *it) nothrow @nogc playqueue_insert_at;
1108 
1109 		// system directory API, returns path by id from ddb_sys_directory_t enum
1110 		immutable char * function(int dir_id) nothrow @nogc get_system_dir;
1111 
1112 		// set the selected playlist for the ongoing plugin action.
1113 		// the "set" function is expected to be called by the UI plugin,
1114 		// while the "get" is expected to be called by the action code.
1115 		void function(ddb_playlist_t *plt) nothrow @nogc action_set_playlist;
1116 
1117 		// returns one of:
1118 		// selected playlist for context menu for the DDB_ACTION_CTX_PLAYLIST,
1119 		// or the current active playlist for any other context.
1120 		// returned value cannot be NULL
1121 		// returned value is refcounted, so remember to call plt_unref.
1122 		ddb_playlist_t* function() nothrow @nogc action_get_playlist;
1123 
1124 		// convert legacy title formatting to the new format, usable with tf_compile
1125 		void function(in char *fmt, char *output, int outsize) nothrow @nogc tf_import_legacy;
1126 	}
1127 }
1128 
1129 // NOTE: an item placement must be selected like this
1130 // if (flags & DB_ACTION_COMMON)  -> main menu, or nowhere, or where GUI plugin wants
1131 //    basically, to put it into main menu, prefix the item title with the menu name
1132 //    e.g. title = "File/MyItem" --> this will add the item under File menu
1133 //
1134 // if (flags & PLAYLIST)  -> playlist (tab) context menu
1135 //
1136 // if (none of the above)  -> track context menu
1137 
1138 enum {
1139 	/* Action in main menu (or whereever ui prefers) */
1140 	DB_ACTION_COMMON = 1 << 0,
1141 
1142 	/* Can handle single track */
1143 	DB_ACTION_SINGLE_TRACK = 1 << 1,
1144 
1145 	/* Can handle multiple tracks */
1146 	DB_ACTION_MULTIPLE_TRACKS = 1 << 2,
1147 
1148 	/* DEPRECATED in API 1.5 */
1149 	DB_ACTION_ALLOW_MULTIPLE_TRACKS = 1 << 2,
1150 
1151 	/* DEPRECATED in API 1.5, ignored in callback2 */
1152 	/* Action can (and prefer) traverse multiple tracks by itself */
1153 	DB_ACTION_CAN_MULTIPLE_TRACKS = 1 << 3,
1154 
1155 	/* Action is inactive */
1156 	DB_ACTION_DISABLED = 1 << 4,
1157 
1158 	/* DEPRECATED in API 1.5, ignored in callback2 */
1159 	/* since 1.2 */
1160 	/* Action for the playlist (tab) */
1161 	DB_ACTION_PLAYLIST = 1 << 5,
1162 
1163 	/* add item to menu(s), if contains slash symbol(s) */
1164 	DB_ACTION_ADD_MENU = 1 << 6
1165 };
1166 
1167 // action contexts
1168 // since 1.5
1169 static if (DDB_API_LEVEL >= 5) {
1170 	enum {
1171 		DDB_ACTION_CTX_MAIN,
1172 		DDB_ACTION_CTX_SELECTION,
1173 		// NOTE: starting with API 1.8, plugins should be using the
1174 		// action_get_playlist function for getting the playlist pointer.
1175 		DDB_ACTION_CTX_PLAYLIST,
1176 		DDB_ACTION_CTX_NOWPLAYING,
1177 		DDB_ACTION_CTX_COUNT
1178 	};
1179 }
1180 
1181 alias DB_plugin_action_callback_t = int function(DB_plugin_action_s *action, void *userdata);
1182 static if (DDB_API_LEVEL >= 5) {
1183 	alias DB_plugin_action_callback2_t = int function(DB_plugin_action_s *action, int ctx);
1184 }
1185 
1186 struct DB_plugin_action_s {
1187 	const char *title;
1188 	const char *name;
1189 	uint flags;
1190 	// the use of "callback" is deprecated,
1191 	// only use it if the code must be compatible with API 1.4
1192 	// otherwise switch to callback2
1193 	DB_plugin_action_callback_t callback;
1194 	DB_plugin_action_s *next;
1195 	static if (DDB_API_LEVEL >= 5) {
1196 		DB_plugin_action_callback2_t callback2;
1197 	}
1198 }
1199 alias DB_plugin_action_t = DB_plugin_action_s;
1200 
1201 // base plugin interface
1202 struct DB_plugin_s {
1203 	// type must be one of DB_PLUGIN_ types
1204 	int type;
1205 	// api version
1206 	short api_vmajor;
1207 	short api_vminor;
1208 	// plugin version
1209 	short version_major;
1210 	short version_minor;
1211 
1212 	uint flags; // currently unused
1213 	uint reserved1;
1214 	uint reserved2;
1215 	uint reserved3;
1216 
1217 	// any of those can be left NULL
1218 	// though it's much better to fill them with something useful
1219 	immutable char *id; // id used for serialization and runtime binding
1220 	immutable char *name; // short name
1221 	immutable char *descr; // short description (what the plugin is doing)
1222 	immutable char *copyright; // copyright notice(s), list of developers, links to original works, etc
1223 	immutable char *website; // plugin website
1224 
1225 	// plugin-specific command interface; can be NULL
1226 	int function(int cmd, ...) command;
1227 
1228 	// start is called to start plugin; can be NULL
1229 	int function() start;
1230 
1231 	// stop is called to deinit plugin; can be NULL
1232 	int function() stop;
1233 
1234 	// connect is called to setup connections between different plugins
1235 	// it is called after all plugin's start method was executed
1236 	// can be NULL
1237 	// NOTE for GUI plugin developers: don't initialize your widgets/windows in
1238 	// the connect method. look for up-to-date information on wiki:
1239 	// http://github.com/Alexey-Yakovenko/deadbeef/wiki/Porting-GUI-plugins-to-deadbeef-from-0.5.x-to-0.6.0
1240 	int function() connect;
1241 
1242 	// opposite of connect, will be called before stop, while all plugins are still
1243 	// in "started" state
1244 	int function() disconnect;
1245 
1246 	// exec_cmdline may be called at any moment when user sends commandline to player
1247 	// can be NULL if plugin doesn't support commandline processing
1248 	// cmdline is 0-separated list of strings, guaranteed to have 0 at the end
1249 	// cmdline_size is number of bytes pointed by cmdline
1250 	int function(in char *cmdline, int cmdline_size) exec_cmdline;
1251 
1252 	// @returns linked list of actions for the specified track
1253 	// when it is NULL -- the plugin must return list of all actions
1254 	DB_plugin_action_t* function(DB_playItem_t *it) get_actions;
1255 
1256 	// mainloop will call this function for every plugin
1257 	// so that plugins may handle all events;
1258 	// can be NULL
1259 	int function(uint id, uintptr_t ctx, uint p1, uint p2) message;
1260 
1261 	// plugin configuration dialog is constructed from this data
1262 	// can be NULL
1263 	immutable char *configdialog;
1264 }
1265 alias DB_plugin_t = DB_plugin_s;
1266 
1267 // file format stuff
1268 
1269 // channel mask - combine following flags to tell streamer which channels are
1270 // present in input/output streams
1271 enum {
1272 	DDB_SPEAKER_FRONT_LEFT = 0x1,
1273 	DDB_SPEAKER_FRONT_RIGHT = 0x2,
1274 	DDB_SPEAKER_FRONT_CENTER = 0x4,
1275 	DDB_SPEAKER_LOW_FREQUENCY = 0x8,
1276 	DDB_SPEAKER_BACK_LEFT = 0x10,
1277 	DDB_SPEAKER_BACK_RIGHT = 0x20,
1278 	DDB_SPEAKER_FRONT_LEFT_OF_CENTER = 0x40,
1279 	DDB_SPEAKER_FRONT_RIGHT_OF_CENTER = 0x80,
1280 	DDB_SPEAKER_BACK_CENTER = 0x100,
1281 	DDB_SPEAKER_SIDE_LEFT = 0x200,
1282 	DDB_SPEAKER_SIDE_RIGHT = 0x400,
1283 	DDB_SPEAKER_TOP_CENTER = 0x800,
1284 	DDB_SPEAKER_TOP_FRONT_LEFT = 0x1000,
1285 	DDB_SPEAKER_TOP_FRONT_CENTER = 0x2000,
1286 	DDB_SPEAKER_TOP_FRONT_RIGHT = 0x4000,
1287 	DDB_SPEAKER_TOP_BACK_LEFT = 0x8000,
1288 	DDB_SPEAKER_TOP_BACK_CENTER = 0x10000,
1289 	DDB_SPEAKER_TOP_BACK_RIGHT = 0x20000
1290 }
1291 
1292 struct DB_fileinfo_s {
1293 	DB_decoder_s *plugin;
1294 
1295 	// these parameters should be set in decoder->open
1296 	ddb_waveformat_t fmt;
1297 
1298 	// readpos should be updated to current decoder time (in seconds)
1299 	float readpos;
1300 
1301 	// this is the (optional) file handle, that can be used by streamer to
1302 	// request interruption of current read operation
1303 	DB_FILE *file;
1304 }
1305 alias DB_fileinfo_t = DB_fileinfo_s;
1306 
1307 // Decoders should try to output 16 bit stream when this flag is set, for
1308 // performance reasons.
1309 enum DDB_DECODER_HINT_16BIT = 0x1;
1310 static if (DDB_API_LEVEL >= 8) {
1311 	enum {
1312 		// Decoders should only call the streamer_set_bitrate from plugin.read function,
1313 		// and only when this flag is set.
1314 		DDB_DECODER_HINT_NEED_BITRATE = 0x2,
1315 		// Decoders can do their own infinite looping when this flag is set, in the
1316 		// "Loop Single" looping mode.
1317 		DDB_DECODER_HINT_CAN_LOOP = 0x4,
1318 	}
1319 }
1320 
1321 // decoder plugin
1322 struct DB_decoder_s {
1323 	DB_plugin_t plugin;
1324 
1325 	DB_fileinfo_t* function(uint hints) open;
1326 
1327 	// init is called to prepare song to be started
1328 	int function(DB_fileinfo_t *info, DB_playItem_t *it) init;
1329 
1330 	// free is called after decoding is finished
1331 	void function(DB_fileinfo_t *info) free;
1332 
1333 	// read is called by streamer to decode specified number of bytes
1334 	// must return number of bytes that were successfully decoded (sample aligned)
1335 	int function(DB_fileinfo_t *info, char *buffer, int nbytes) read;
1336 
1337 	int function(DB_fileinfo_t *info, float seconds) seek;
1338 
1339 	// perform seeking in samples (if possible)
1340 	// return -1 if failed, or 0 on success
1341 	// if -1 is returned, that will mean that streamer must skip that song
1342 	int function(DB_fileinfo_t *info, int sample) seek_sample;
1343 
1344 	// 'insert' is called to insert new item to playlist
1345 	// decoder is responsible to calculate duration, split it into subsongs, load cuesheet, etc
1346 	// after==NULL means "prepend before 1st item in playlist"
1347 	DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, in char *fname) insert;
1348 
1349 	int function(DB_fileinfo_t *info) numvoices;
1350 	void function(DB_fileinfo_t *info, int voice, int mute) mutevoice;
1351 
1352 	int function(DB_playItem_t *it) read_metadata;
1353 	int function(DB_playItem_t *it) write_metadata;
1354 
1355 	// NULL terminated array of all supported extensions
1356 	// examples:
1357 	// { "aac", "wma", "tak", NULL } -- supports 3 file extensions
1358 	// since API 1.9: { "*", NULL } -- supports any file extensions
1359 	immutable char **exts;
1360 
1361 	// NULL terminated array of all supported prefixes (UADE support needs that)
1362 	// e.g. "mod.song_title"
1363 	immutable char **prefixes;
1364 
1365 	static if (DDB_API_LEVEL >= 7) {
1366 		// This function's purpose is to open the file, so that the file handle is
1367 		// immediately accessible via DB_fileinfo_t, and can be used with fabort.
1368 		// If a plugin is using open2, it should not reopen the file from init.
1369 		// Plugins _must_ implement open even if open2 is present,
1370 		// because existing code may rely on it.
1371 		DB_fileinfo_t* function(uint hints, DB_playItem_t *it) open2;
1372 	}
1373 }
1374 alias DB_decoder_t = DB_decoder_s;
1375 
1376 // output plugin
1377 struct DB_output_s {
1378 	DB_plugin_t plugin;
1379 	// init is called once at plugin activation
1380 	int function() init;
1381 	// free is called if output plugin was changed to another, or unload is about to happen
1382 	int function() free;
1383 	// reconfigure output to another format
1384 	int function(ddb_waveformat_t *fmt) setformat;
1385 	// play, stop, pause, unpause are called by deadbeef in response to user
1386 	// events, or as part of streaming process
1387 	int function() play;
1388 	int function() stop;
1389 	int function() pause;
1390 	int function() unpause;
1391 	// one of output_state_t enum values
1392 	int function() state;
1393 	// soundcard enumeration (can be NULL)
1394 	void function(void function(in char *name, in char *desc, void*) callback, void *userdata) enum_soundcards;
1395 
1396 	// parameters of current output
1397 	ddb_waveformat_t fmt;
1398 
1399 	// set to 1 if volume control is done internally by plugin
1400 	int has_volume;
1401 }
1402 alias DB_output_t = DB_output_s;
1403 
1404 /+
1405 // dsp plugin
1406 // see also: examples/dsp_template.c in git
1407 #define DDB_INIT_DSP_CONTEXT(var,type,plug) {\
1408     memset(var,0,sizeof(type));\
1409     var->ctx.plugin=plug;\
1410     var->ctx.enabled=1;\
1411 }
1412 +/
1413 
1414 struct ddb_dsp_context_s {
1415 	// pointer to DSP plugin which created this context
1416 	DB_dsp_s *plugin;
1417 
1418 	// pointer to the next DSP plugin context in the chain
1419 	ddb_dsp_context_s *next;
1420 
1421 	/+ wut? +/
1422 	// read only flag; set by DB_dsp_t::enable
1423 	//unsigned enabled : 1;
1424 }
1425 alias ddb_dsp_context_t = ddb_dsp_context_s;
1426 
1427 struct DB_dsp_s {
1428 	DB_plugin_t plugin;
1429 
1430 	ddb_dsp_context_t* function() open;
1431 
1432 	void function(ddb_dsp_context_t *ctx) close;
1433 
1434 	// samples are always interleaved floating point
1435 	// returned value is number of output frames (multichannel samples)
1436 	// plugins are allowed to modify channels, samplerate, channelmask in the fmt structure
1437 	// buffer size can fit up to maxframes frames
1438 	// by default ratio=1, and plugins don't need to touch it unless they have to
1439 	int function(ddb_dsp_context_t *ctx, float *samples, int frames, int maxframes, ddb_waveformat_t *fmt, float *ratio) process;
1440 
1441 	void function(ddb_dsp_context_t *ctx) reset;
1442 
1443 	// num_params can be NULL, to indicate that plugin doesn't expose any params
1444 	//
1445 	// if num_params is non-NULL -- get_param_name, set_param and get_param must
1446 	// all be implemented
1447 	//
1448 	// param names are for display-only, and are allowed to contain spaces
1449 	int function() num_params;
1450 	immutable char * function(int p) get_param_name;
1451 	void function(ddb_dsp_context_t *ctx, int p, in char *val) set_param;
1452 	void function(ddb_dsp_context_t *ctx, int p, char *str, int len) get_param;
1453 
1454 	// config dialog implementation uses set/get param, so they must be
1455 	// implemented if this is nonzero
1456 	immutable char *configdialog;
1457 
1458 	// since 1.1
1459 	static if (DDB_API_LEVEL >= 1) {
1460 		// can be NULL
1461 		// should return 1 if the DSP plugin will not touch data with the current parameters;
1462 		// 0 otherwise
1463 		int function(ddb_dsp_context_t *ctx, ddb_waveformat_t *fmt) can_bypass;
1464 	}
1465 }
1466 alias DB_dsp_t = DB_dsp_s;
1467 
1468 // misc plugin
1469 // purpose is to provide extra services
1470 // e.g. scrobbling, converting, tagging, custom gui, etc.
1471 // misc plugins should be mostly event driven, so no special entry points in them
1472 struct DB_misc_t {
1473 	DB_plugin_t plugin;
1474 } ;
1475 
1476 // vfs plugin
1477 // provides means for reading, seeking, etc
1478 // api is based on stdio
1479 struct DB_vfs_s {
1480 	DB_plugin_t plugin;
1481 
1482 	// capabilities
1483 	immutable char ** function() get_schemes; // NULL-terminated list of supported schemes, e.g. {"http://", "ftp://", NULL}; can be NULL
1484 
1485 	int function() is_streaming; // return 1 if the plugin streaming data over slow connection, e.g. http; plugins will avoid scanning entire files if this is the case
1486 
1487 	int function(in char *fname) is_container; // should return 1 if this plugin can parse specified file
1488 
1489 	// this allows interruption of hanging network streams
1490 	void function(DB_FILE *stream) abort;
1491 
1492 	// file access, follows stdio API with few extension
1493 	DB_FILE* function(in char *fname) open;
1494 	void function(DB_FILE *f) close;
1495 	size_t function(void *ptr, size_t size, size_t nmemb, DB_FILE *stream) read;
1496 	int function(DB_FILE *stream, long offset, int whence) seek;
1497 	long function(DB_FILE *stream) tell;
1498 	void function(DB_FILE *stream) rewind;
1499 	long function(DB_FILE *stream) getlength;
1500 
1501 	// should return mime-type of a stream, if known; can be NULL
1502 	immutable char * function(DB_FILE *stream) get_content_type;
1503 
1504 	// associates stream with a track, to allow dynamic metadata updating, like
1505 	// in icy protocol
1506 	void function(DB_FILE *f, DB_playItem_t *it) set_track;
1507 
1508 	// folder access, follows dirent API, and uses dirent data structures
1509 	int function(in char *dir, dirent ***namelist, int function(in dirent *) selector, int function(in dirent **, in dirent **) cmp) scandir;
1510 
1511 	static if (DDB_API_LEVEL >= 6) {
1512 		// returns URI scheme for a given file name, e.g. "zip://"
1513 		// can be NULL
1514 		// can return NULL
1515 		immutable char * function(in char *fname) get_scheme_for_name;
1516 	}
1517 }
1518 alias DB_vfs_t = DB_vfs_s;
1519 
1520 // gui plugin
1521 // only one gui plugin can be running at the same time
1522 // should provide GUI services to other plugins
1523 
1524 // this structure represents a gui dialog with callbacks to set/get params
1525 // documentation should be available here:
1526 // http://github.com/Alexey-Yakovenko/deadbeef/wiki/GUI-Script-Syntax
1527 struct ddb_dialog_t {
1528 	immutable char *title;
1529 	immutable char *layout;
1530 	void function(in char *key, in char *value) set_param;
1531 	void function(in char *key, char *value, int len, in char *def) get_param;
1532 
1533 	static if (DDB_API_LEVEL >= 4) {
1534 		void *parent;
1535 	}
1536 }
1537 
1538 enum {
1539 	ddb_button_ok,
1540 	ddb_button_cancel,
1541 	ddb_button_close,
1542 	ddb_button_apply,
1543 	ddb_button_yes,
1544 	ddb_button_no,
1545 	ddb_button_max,
1546 };
1547 
1548 struct DB_gui_s {
1549 	DB_plugin_t plugin;
1550 
1551 	// returns response code (ddb_button_*)
1552 	// buttons is a bitset, e.g. (1<<ddb_button_ok)|(1<<ddb_button_cancel)
1553 	int function(ddb_dialog_t *dlg, uint buttons, int function(int button, void *ctx) callback, void *ctx) run_dialog;
1554 }
1555 alias DB_gui_t = DB_gui_s;
1556 
1557 // playlist plugin
1558 struct DB_playlist_s {
1559 	DB_plugin_t plugin;
1560 
1561 	DB_playItem_t* function(ddb_playlist_t *plt, DB_playItem_t *after, in char *fname, int *pabort, int function(DB_playItem_t *it, void *data) cb, void *user_data) load;
1562 
1563 	// will save items from first to last (inclusive)
1564 	// format is determined by extension
1565 	// playlist is protected from changes during the call
1566 	int function(ddb_playlist_t *plt, in char *fname, DB_playItem_t *first, DB_playItem_t *last) save;
1567 
1568 	immutable char **extensions; // NULL-terminated list of supported file extensions, e.g. {"m3u", "pls", NULL}
1569 
1570 	// since 1.5
1571 	static if (DDB_API_LEVEL >= 5) {
1572 		DB_playItem_t* function(int visibility, ddb_playlist_t *plt, DB_playItem_t *after, in char *fname, int *pabort) load2;
1573 	}
1574 }
1575 alias DB_playlist_t = DB_playlist_s;