1 // plugins.h
2 // LiVES
3 // (c) G. Finch 2003-2020 <salsaman+lives@gmail.com>
4 // released under the GNU GPL 3 or later
5 // see file ../COPYING or www.gnu.org for licensing details
6 
7 #ifndef HAS_LIVES_PLUGINS_H
8 #define HAS_LIVES_PLUGINS_H
9 
10 #ifdef GUI_GTK
11 #include <gmodule.h>
12 #endif
13 
14 #include <unistd.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <stdlib.h>
18 
19 // generic plugins
20 
21 #define PLUGIN_SUBTYPE_DLL 		"dll"
22 #define PLUGIN_SUBTYPE_BINARY 		"exe"
23 #define PLUGIN_SUBTYPE_SCRIPT 		"script"
24 
25 #define PLUGIN_TYPE_DECODER			"decoder"
26 #define PLUGIN_TYPE_ENCODER			"encoder"
27 #define PLUGIN_TYPE_FILTER			"filter"
28 #define PLUGIN_TYPE_SOURCE			"source"
29 #define PLUGIN_TYPE_PLAYER 			"player"
30 
31 #define PLUGIN_CHANNEL_NONE	0ul
32 #define PLUGIN_CHANNEL_VIDEO	(1<<0)ul
33 #define PLUGIN_CHANNEL_AUDIO	(1<<1)ul
34 #define PLUGIN_CHANNEL_TEXT	(1<<2)ul
35 
36 #define PLUGIN_CHANNEL_DATA    		(1<<32)ul
37 #define PLUGIN_CHANNEL_STREAM    	(1<<33)ul
38 #define PLUGIN_CHANNEL_TTY    		(1<<34)ul
39 #define PLUGIN_CHANNEL_FILE    		(1<<35)ul
40 
41 typedef enum {
42   LIVES_INTENTION_UNKNOWN,
43 
44   // video players
45   LIVES_INTENTION_PLAY,
46   LIVES_INTENTION_STREAM,
47   LIVES_INTENTION_TRANSCODE,  // encode / data in
48   LIVES_INTENTION_RENDER,
49 
50   //LIVES_INTENTION_ENCODE, // encode / file in
51   LIVES_INTENTION_BACKUP,
52   LIVES_INTENTION_RESTORE,
53   LIVES_INTENTION_DOWNLOAD,
54   LIVES_INTENTION_UPLOAD,
55   LIVES_INTENTION_EFFECT,
56   LIVES_INTENTION_EFFECT_REALTIME, // or make cap ?
57   LIVES_INTENTION_ANALYSE,
58   LIVES_INTENTION_CONVERT,
59   LIVES_INTENTION_MIX,
60   LIVES_INTENTION_SPLIT,
61   LIVES_INTENTION_DUPLICATE,
62   LIVES_INTENTION_OTHER = 65536
63 } lives_intention_t;
64 
65 /// type sepcific caps
66 // vpp
67 #define VPP_CAN_RESIZE    (1<<0)
68 #define VPP_CAN_RETURN    (1<<1)
69 #define VPP_LOCAL_DISPLAY (1<<2)
70 #define VPP_LINEAR_GAMMA  (1<<3)
71 #define VPP_CAN_RESIZE_WINDOW          		(1<<4)   /// can resize the image to fit the play window
72 #define VPP_CAN_LETTERBOX                  	(1<<5)
73 #define VPP_CAN_CHANGE_PALETTE			(1<<6)
74 
75 typedef struct {
76   uint64_t intent;
77   uint64_t in_chan_types; ///< channel types accepted
78   uint64_t out_chan_types; ///< channel types produced
79   uint64_t intents; ///<
80   uint64_t capabilities; ///< type specific capabilities
81 } lives_intentcaps_t;
82 
83 typedef struct {
84   char type[16];  ///< e.g. "decoder"
85   char subtype[16];  ///< e.g. "dll"
86   int api_version_major; ///< version of interface API
87   int api_version_minor;
88   char name[64];  ///< e.g. "mkv_decoder"
89   int pl_version_major; ///< version of plugin
90   int pl_version_minor;
91   lives_intentcaps_t *capabilities;  ///< for future use
92 } lives_plugin_id_t;
93 
94 LiVESList *get_plugin_list(const char *plugin_type, boolean allow_nonex,
95                            const char *plugdir, const char *filter_ext);
96 
97 // directory locations
98 #define PLUGIN_ENCODERS "encoders"
99 #define PLUGIN_DECODERS "decoders"
100 #define PLUGIN_VID_PLAYBACK "playback/video"
101 #define PLUGIN_AUDIO_STREAM "playback/audiostream"
102 
103 #define AUDIO_STREAMER_NAME "audiostreamer.pl"
104 
105 /// smogrify handles the directory differently for themes
106 #define PLUGIN_THEMES "themes"
107 #define PLUGIN_THEMES_CUSTOM "custom/themes"
108 
109 /// uses WEED_PLUGIN_PATH
110 #define PLUGIN_EFFECTS_WEED "weed"
111 #define PLUGIN_WEED_FX_BUILTIN "effects/realtime/weed"
112 
113 LiVESList *get_plugin_result(const char *command, const char *delim, boolean allow_blanks, boolean strip);
114 LiVESList *plugin_request(const char *plugin_type, const char *plugin_name, const char *request);
115 LiVESList *plugin_request_with_blanks(const char *plugin_type, const char *plugin_name, const char *request);
116 LiVESList *plugin_request_by_line(const char *plugin_type, const char *plugin_name, const char *request);
117 LiVESList *plugin_request_by_space(const char *plugin_type, const char *plugin_name, const char *request);
118 LiVESList *plugin_request_common(const char *plugin_type, const char *plugin_name, const char *request, const char *delim,
119                                  boolean allow_blanks);
120 
121 #define VPP_DEFS_FILE "vpp_defaults"
122 
123 typedef struct {
124   // playback
125   char name[64];
126   void *handle;
127 
128   // mandatory
129   const char *(*module_check_init)(void);
130   const char *(*version)(void);
131   const char *(*get_description)(void);
132 
133   int *(*get_palette_list)(void);
134   boolean(*set_palette)(int palette);
135   uint64_t (*get_capabilities)(int palette);
136 
137   boolean(*render_frame)(int hsize, int vsize, ticks_t timecode, void **pixel_data, void **return_data,
138                          weed_plant_t **play_params);
139 
140   boolean(*play_frame)(weed_layer_t *frame, ticks_t tc, weed_layer_t *ret);
141 
142   // optional
143   weed_plant_t *(*weed_setup)(weed_bootstrap_f);
144   boolean(*init_screen)(int width, int height, boolean fullscreen,
145                         uint64_t window_id, int argc, char **argv);
146   void (*exit_screen)(uint16_t mouse_x, uint16_t mouse_y);
147   void (*module_unload)(void);
148   const char *(*get_fps_list)(int palette);
149   boolean(*set_fps)(double fps);
150 
151   const char *(*get_init_rfx)(int intention);
152 
153 #ifdef __WEED_EFFECTS_H__
154   ///< optional (but should return a weed plantptr array of paramtmpl and chantmpl, NULL terminated)
155   const weed_plant_t **(*get_play_params)(weed_bootstrap_f f);
156 #endif
157 
158   // optional for YUV palettes
159   int *(*get_yuv_palette_sampling)(int palette);
160   int *(*get_yuv_palette_clamping)(int palette);
161   int *(*get_yuv_palette_subspace)(int palette);
162   int (*set_yuv_palette_sampling)(int sampling_type);
163   int (*set_yuv_palette_clamping)(int clamping_type);
164   int (*set_yuv_palette_subspace)(int subspace_type);
165 
166   // audio streaming (deprecated, use init_audio(), render_audio_frame())
167   int *(*get_audio_fmts)(void);
168 
169   uint32_t audio_codec; //(deprecated, use init_audio(), render_audio_frame())
170   // must match with the "acodec" LiVESList in interface.c
171   // and bitmaps in the encder plugins
172 
173   // optional audio packeting
174   boolean(*init_audio)(int in_sample_rate, int in_nchans, int argc, char **argv);
175   boolean(*render_audio_frame_float)(float **audio, int nsamps);
176 
177   uint64_t capabilities;
178 
179   int fwidth, fheight; /// width in pixels, but converted to macropixels for the player
180 
181   int palette;
182   int YUV_sampling;
183   int YUV_clamping;
184   int YUV_subspace;
185 
186   int fixed_fps_numer;
187   int fixed_fps_denom;
188   double fixed_fpsd;
189 
190   int extra_argc;
191   char **extra_argv;
192 
193   const weed_plant_t **play_paramtmpls;
194   weed_plant_t **play_params;
195   weed_plant_t **alpha_chans;
196   int num_play_params;
197   int num_alpha_chans;
198 } _vid_playback_plugin;
199 
200 _vid_playback_plugin *open_vid_playback_plugin(const char *name, boolean in_use);
201 void vid_playback_plugin_exit(void);
202 void close_vid_playback_plugin(_vid_playback_plugin *);
203 int64_t get_best_audio(_vid_playback_plugin *);
204 void save_vpp_defaults(_vid_playback_plugin *, char *file);
205 void load_vpp_defaults(_vid_playback_plugin *, char *file);
206 
207 boolean vpp_try_match_palette(_vid_playback_plugin *vpp, weed_layer_t *layer);
208 
209 #define DEFAULT_VPP "openGL"
210 
211 #define DEF_VPP_HSIZE DEF_FRAME_HSIZE_UNSCALED
212 #define DEF_VPP_VSIZE DEF_FRAME_VSIZE_UNSCALED
213 
214 const weed_plant_t *pp_get_param(weed_plant_t **pparams, int idx);
215 const weed_plant_t *pp_get_chan(weed_plant_t **pparams, int idx);
216 
217 // encoder plugins
218 
219 #define FFMPEG_ENCODER_NAME "ffmpeg_encoder"
220 
221 #define MULTI_ENCODER_NAME "multi_encoder"
222 #define MULTI_ENCODER3_NAME "multi_encoder3"
223 
224 #define HI_THEORA_FORMAT "hi-theora"
225 #define HI_MPEG_FORMAT "hi-mpg"
226 #define HI_H_MKV_FORMAT "hi_h-mkv"
227 #define HI_H_AVI_FORMAT "hi_h-avi"
228 
229 void do_plugin_encoder_error(const char *plugin_name_or_null);
230 
231 LiVESList *filter_encoders_by_img_ext(LiVESList *encoders, const char *img_ext);
232 
233 typedef struct {
234   char name[64];
235   uint32_t audio_codec;
236   // match with bitmaps in the encoder plugins
237   // and also anames array in plugins.c (see below)
238 
239 #define AUDIO_CODEC_MP3 0
240 #define AUDIO_CODEC_PCM 1
241 #define AUDIO_CODEC_MP2 2
242 #define AUDIO_CODEC_VORBIS 3
243 #define AUDIO_CODEC_AC3 4
244 #define AUDIO_CODEC_AAC 5
245 #define AUDIO_CODEC_AMR_NB 6
246 #define AUDIO_CODEC_RAW 7       // reserved
247 #define AUDIO_CODEC_WMA2 8
248 #define AUDIO_CODEC_OPUS 9
249 
250 #define AUDIO_CODEC_MAX 31
251   //
252 #define AUDIO_CODEC_NONE 32
253 #define AUDIO_CODEC_UNKNOWN 33
254 
255   uint32_t capabilities;
256 
257 #define HAS_RFX (1<<0)
258 
259 #define CAN_ENCODE_PNG (1<<2)
260 #define ENCODER_NON_NATIVE (1<<3)
261 
262   // current output format
263   char of_name[64];
264   char of_desc[128];
265   int of_allowed_acodecs;
266   char of_restrict[1024];
267   char of_def_ext[16];
268   char ptext[512];
269 }
270 _encoder;
271 
272 typedef struct {
273   /// a ctiming_ratio of 0. indicates that none of the other values are set.
274   // a value > 0. indicates some values are set. Unset values may be left as 0., or
275   /// A value < 0. means that the value is known to be non-zero, but cannot be accurately measured.
276   /// In this case, calculations involving this quantity should be avoided, as the result cannot be determined.
277 
278   double ctiming_ratio; // dynamic multiplier for timing info, depends on machine load and other factors.
279   double idecode_time; /// avg time to decode inter frame
280   double kdecode_time; /// avg time to decode keyframe
281   double buffer_flush_time; /// time to flush buffers after a seek
282   double kframe_nseek_time; /// avg time to seek to following keyframe (const)
283   double kframe_delay_time; /// avg extra time per iframe to arrive at following kframe
284 
285   double kframe_kframe_time; /// avg time to seek from keyframe to keyframe (const) :: default == 0. (use kframe_nseek_time)
286   double kframe_inter_time; /// extra time to seek from kframe to kframe per iframe between them :: default == kframe_delay_time
287   double kframe_extra_time; /// extra time to seek from kframe to kframe per kframe between them :: default == kframe_inter_time
288 
289   // examples:
290   // iframe to next kframe with decode: kframe_nseek_time + n * kframe_delay_time + buffer_flush_tome + kdecode_time
291   // where n is the number of iframes skipped over
292 
293   // seek from iframe to another iframe, passing over several kframes, decoding frames from final kframe to target
294 
295   /// kframe_nseek_time + A * kframe_delay_time + kframe_kframe_time + B * kframe_inter_time * C * kframe_extra_time +
296   /// kdecode_time + D * idecode_time
297   /// where A == nframes between origin and next kframe, B == iframes between kframse, C == kframes between kframes,
298   /// D = iframes after target kframe
299   /// this can approximated as: kframe_nseek_time + (A + B + C) * kframe_delay_time + kdecode_time + D * idecode_time
300 
301   double xvals[64];  /// extra values which may be
302 } adv_timing_t;
303 
304 // defined in plugins.c for the whole app
305 extern const char *const anames[AUDIO_CODEC_MAX];
306 
307 // decoder plugins
308 
309 // seek_flags is a bitmap
310 
311 /// good
312 #define LIVES_SEEK_FAST (1<<0)
313 #define LIVES_SEEK_FAST_REV (1<<1)
314 
315 /// not so good
316 #define LIVES_SEEK_NEEDS_CALCULATION (1<<2)
317 #define LIVES_SEEK_QUALITY_LOSS (1<<3)
318 
319 typedef struct _lives_clip_data {
320   // fixed part
321   lives_struct_def_t lsd;
322   lives_plugin_id_t plugin_id;
323 
324   malloc_f  *ext_malloc;
325   free_f    *ext_free;
326   memcpy_f  *ext_memcpy;
327   memset_f  *ext_memset;
328   memmove_f *ext_memmove;
329   realloc_f *ext_realloc;
330   calloc_f  *ext_calloc;
331 
332   void *priv;
333 
334   char *URI; ///< the URI of this cdata
335 
336   int nclips; ///< number of clips (titles) in container
337   char container_name[512]; ///< name of container, e.g. "ogg" or NULL
338 
339   char title[1024];
340   char author[1024];
341   char comment[1024];
342 
343   /// plugin should init this to 0 if URI changes
344   int current_clip; ///< current clip number in container (starts at 0, MUST be <= nclips) [rw host]
345 
346   // video data
347   int width;
348   int height;
349   int64_t nframes;
350   lives_interlace_t interlace;
351   int *rec_rowstrides; ///< if non-NULL, plugin can set recommended vals, pointer to single value set by host
352 
353   /// x and y offsets of picture within frame
354   /// for primary pixel plane
355   int offs_x;
356   int offs_y;
357   int frame_width;  ///< frame is the surrounding part, including any black border (>=width)
358   int frame_height;
359 
360   float par; ///< pixel aspect ratio (sample width / sample height)
361 
362   float video_start_time;
363 
364   float fps;
365 
366   /// optional info ////////////////
367   float max_decode_fps; ///< theoretical value with no memcpy
368   int64_t fwd_seek_time;
369   int64_t jump_limit; ///< for internal use
370 
371   int64_t kframe_start; /// frame number of first keyframe (usually 0)
372   int64_t kframe_dist; /// number forames from one keyframe to the next, 0 if unknown
373   //////////////////////////////////
374 
375   int *palettes; ///< list of palettes which the format supports, terminated with WEED_PALETTE_END
376 
377   /// plugin should init this to palettes[0] if URI changes
378   int current_palette;  ///< current palette [rw host]; must be contained in palettes
379 
380   /// plugin can change per frame
381   int YUV_sampling;
382   int YUV_clamping;
383   int YUV_subspace;
384   int frame_gamma; ///< values WEED_GAMMA_UNKNOWN (0), WEED_GAMMA_SRGB (1), WEED_GAMMA_LINEAR (2)
385 
386   char video_name[512]; ///< name of video codec, e.g. "theora" or NULL
387 
388   /* audio data */
389   int arate;
390   int achans;
391   int asamps;
392   boolean asigned;
393   boolean ainterleaf;
394   char audio_name[512]; ///< name of audio codec, e.g. "vorbis" or NULL
395 
396   /// plugin can change per frame
397   int seek_flag; ///< bitmap of seek properties
398 
399 #define SYNC_HINT_AUDIO_TRIM_START (1<<0)
400 #define SYNC_HINT_AUDIO_PAD_START (1<<1)
401 #define SYNC_HINT_AUDIO_TRIM_END (1<<2)
402 #define SYNC_HINT_AUDIO_PAD_END (1<<3)
403 
404 #define SYNC_HINT_VIDEO_PAD_START (1<<4)
405 #define SYNC_HINT_VIDEO_PAD_END (1<<5)
406 
407   int sync_hint;
408 
409 } lives_clip_data_t;
410 
411 
412 typedef struct {
413   // playback
414   const char *name; ///< plugin name
415   void *handle; ///< may be shared between several instances
416 
417   // mandatory
418   const char *(*version)(void);
419 
420   /// call first time with NULL cdata
421   /// subsequent calls should re-use cdata
422   /// set cdata->current_clip > 0 to get data for clip n (0 <= n < cdata->nclips)
423   /// we can also set cdata->current_palette (must be in list cdata->palettes[])
424   ///
425   /// if URI changes, current_clip and current_palette are reset by plugin
426   ///
427   /// to get a clone of cdata, pass in NULL URI and cdata
428   ///
429   lives_clip_data_t *(*get_clip_data)(char *URI, const lives_clip_data_t *cdata);
430 
431   /// frame starts at 0 in these functions; height is height of primary plane
432   boolean(*get_frame)(const lives_clip_data_t *, int64_t frame, int *rowstrides, int height, void **pixel_data);
433 
434   /// free buffers when we arent playing sequentially / on standby
435   boolean(*chill_out)(const lives_clip_data_t *);
436 
437   /// call this for each cdata before unloading the module
438   void (*clip_data_free)(lives_clip_data_t *);
439 
440   // optional
441   const char *(*module_check_init)(void);
442   boolean(*set_palette)(lives_clip_data_t *);
443   int64_t (*rip_audio)(const lives_clip_data_t *, const char *fname, int64_t stframe, int64_t nframes,
444                        unsigned char **abuff);
445   void (*rip_audio_cleanup)(const lives_clip_data_t *cdata);
446   void (*module_unload)(void);
447 } lives_decoder_sys_t;
448 
449 typedef struct {
450   const lives_decoder_sys_t *decoder;
451   lives_clip_data_t *cdata;
452   int refs;
453 } lives_decoder_t;
454 
455 LiVESList *load_decoders(void);
456 boolean chill_decoder_plugin(int fileno);
457 boolean decoder_plugin_move_to_first(const char *name);
458 const lives_clip_data_t *get_decoder_cdata(int fileno, LiVESList *disabled, const lives_clip_data_t *fake_cdata);
459 void close_decoder_plugin(lives_decoder_t *);
460 void close_clip_decoder(int clipno);
461 lives_decoder_sys_t *open_decoder_plugin(const char *plname);
462 void get_mime_type(char *text, int maxlen, const lives_clip_data_t *);
463 void unload_decoder_plugins(void);
464 lives_decoder_t *clone_decoder(int fileno);
465 
466 // RFX plugins
467 
468 /// external rendered fx plugins (RFX plugins)
469 #define PLUGIN_RENDERED_EFFECTS_BUILTIN "effects/rendered/"
470 
471 /// in the config directory
472 #define PLUGIN_RENDERED_EFFECTS_CUSTOM "plugins/effects/rendered/custom/"
473 #define PLUGIN_RENDERED_EFFECTS_TEST "plugins/effects/rendered/test/"
474 
475 /// rfx scripts for the SDK
476 #define PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS "effects/RFXscripts/"
477 
478 /// in the config directory
479 #define PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS "plugins/effects/RFXscripts/custom/"
480 #define PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS "plugins/effects/RFXscripts/test/"
481 
482 /// scraps are passed between programs to generate param windows
483 #define PLUGIN_RFX_SCRAP ""
484 
485 /// max number of display widgets per parameter (currently 7 for transition param with mergealign -
486 /// spin + label + knob + scale + in + out + dummy
487 // TODO : use enum for widget type
488 #define MAX_PARAM_WIDGETS 128
489 
490 #define RFX_MAX_NORM_WIDGETS 16
491 
492 /// special widgets
493 #define WIDGET_RB_IN 			16
494 #define WIDGET_RB_OUT	 		17
495 #define WIDGET_RB_DUMMY 		18
496 
497 /// length of max string (not including terminating NULL) for LiVES-perl
498 #define RFX_MAXSTRINGLEN (PATH_MAX - 1)
499 
500 typedef enum {
501   LIVES_PARAM_UNKNOWN = 0,
502   LIVES_PARAM_NUM,
503   LIVES_PARAM_BOOL,
504   LIVES_PARAM_COLRGB24,
505   LIVES_PARAM_STRING,
506   LIVES_PARAM_STRING_LIST,
507   LIVES_PARAM_COLRGBA32,
508 
509   LIVES_PARAM_UNDISPLAYABLE = 65536
510 } lives_param_type_t;
511 
512 typedef enum {
513   LIVES_RFX_SOURCE_RFX = 0,
514   LIVES_RFX_SOURCE_WEED,
515   LIVES_RFX_SOURCE_NEWCLIP
516 } lives_rfx_source_t;
517 
518 typedef enum {
519   LIVES_PARAM_SPECIAL_TYPE_NONE = 0, // normal parameter type
520 
521   // framedraw types
522   LIVES_PARAM_SPECIAL_TYPE_RECT_DEMASK,  ///< type may be used in framedraw
523   LIVES_PARAM_SPECIAL_TYPE_RECT_MULTIRECT,  ///< type may be used in framedraw
524   LIVES_PARAM_SPECIAL_TYPE_SINGLEPOINT,  ///< type may be used in framedraw
525   LIVES_PARAM_SPECIAL_TYPE_SCALEDPOINT,  ///< type may be used in framedraw
526 
527   // text widget types
528   LIVES_PARAM_SPECIAL_TYPE_FILEREAD,
529   LIVES_PARAM_SPECIAL_TYPE_FILEWRITE,
530   LIVES_PARAM_SPECIAL_TYPE_PASSWORD,
531   LIVES_PARAM_SPECIAL_TYPE_FONT_CHOOSER,
532 
533   // misc types
534   LIVES_PARAM_SPECIAL_TYPE_MERGEALIGN,
535   LIVES_PARAM_SPECIAL_TYPE_ASPECT_RATIO
536 } lives_param_special_t;
537 
538 typedef struct {
539   // weed style part
540   char *name;
541   char *desc;
542 
543   char *label;
544   int flags;
545   boolean use_mnemonic;
546   uint32_t hidden;
547 
548   // reason(s) for hiding [bitmap]
549   /// structural (permanent)
550 #define HIDDEN_UNDISPLAYABLE		(1 << 0)
551 #define HIDDEN_GUI_PERM			(1 << 1)
552 #define HIDDEN_MULTI			(1 << 2)
553 
554 #define HIDDEN_STRUCTURAL (0x00FF)
555 
556   /// non-structural (temporary)
557 #define HIDDEN_NEEDS_REINIT 		(1 << 16)
558 #define HIDDEN_GUI_TEMP			(1 << 17)
559 
560 #define HIDDEN_TEMPORARY (0xFF00)
561 
562   double step_size;
563   //int copy_to;
564   boolean transition;
565 
566 #define REINIT_FUNCTIONAL 	1
567 #define REINIT_VISUAL 		2
568 
569   int reinit;
570 
571   boolean wrap;
572   int group;
573   lives_param_type_t type;
574 
575   int dp;  ///<decimals, 0 for int and bool
576   void *value;  ///< current value(s)
577 
578   double min;
579   double max; ///< for string this is max characters
580 
581   void *def; ///< default values
582   LiVESList *list; ///< for string list (choices)
583 
584   /// multivalue type - single value, multi value, or per channel
585   short multi;
586 #define PVAL_MULTI_NONE 0
587 #define PVAL_MULTI_ANY 1
588 #define PVAL_MULTI_PER_CHANNEL 2
589 
590   //--------------------------------------------------
591   // extras for LiVES
592 
593   /// TODO - change to LiVESWidget **widgets, terminated with a NULL
594   LiVESWidget *widgets[MAX_PARAM_WIDGETS]; ///< widgets which hold value/RGBA settings
595   boolean onchange; ///< is there a trigger ?
596 
597   boolean changed;
598   boolean edited;
599 
600   boolean change_blocked;
601 
602   void *source;
603 
604   lives_rfx_source_t source_type;
605 
606   // this may change
607   lives_param_special_t special_type; // the visual modification type (see paramspecial.h)
608   int special_type_index; // index within special_type (e.g for DEMASK, 0==left, 1==top, 2==width, 3==height)
609 } lives_param_t;
610 
611 typedef enum {
612   RFX_STATUS_BUILTIN = 0, ///< factory presets
613   RFX_STATUS_CUSTOM = 1, ///< custom effects in the custom menu
614   RFX_STATUS_TEST = 2, ///< test effects in the advanced menu
615   RFX_STATUS_ANY = 3, ///< indicates free choice of statuses
616   RFX_STATUS_WEED = 4, ///< indicates an internal RFX, created from a weed instance
617   RFX_STATUS_SCRAP = 5, ///< used for parsing RFX scraps from external apps
618   RFX_STATUS_INTERNAL = 6, ///< used for parsing RFX scraps generated internally (will possiblky replace SCRAP)
619 
620   // these are only used when prompting for a name
621   RFX_STATUS_COPY = 128, ///< indicates a copy operation to test
622   RFX_STATUS_RENAME = 129 ///< indicates a copy operation to test
623 } lives_rfx_status_t;
624 
625 typedef struct {
626   char *name;  ///< the name of the executable (so we can run it !)
627   char *menu_text; ///< for Weed, this is the filter_class "name"
628   char *action_desc; ///< for Weed "Applying $s"
629   int min_frames; ///< for Weed, 1
630   int num_in_channels;
631   lives_rfx_status_t status;
632 
633   uint32_t props;
634 #define RFX_PROPS_SLOW        0x0001  ///< hint to GUI
635 #define RFX_PROPS_MAY_RESIZE  0x0002 ///< is a tool
636 #define RFX_PROPS_BATCHG      0x0004 ///< is a batch generator
637 
638 #define RFX_PROPS_RESERVED1   0x1000
639 #define RFX_PROPS_RESERVED2   0x2000
640 #define RFX_PROPS_RESERVED3   0x4000
641 #define RFX_PROPS_AUTO_BUILT  0x8000
642 
643   LiVESWidget *menuitem;  ///< the menu item which activates this effect
644   int num_params;
645   uint32_t flags; /// internal use
646 #define RFX_FLAGS_NO_SLIDERS 	0x0001
647 #define RFX_FLAGS_NO_RESET 	0x0002
648 
649   lives_param_t *params;
650   lives_rfx_source_t source_type;
651   void *source;  ///< points to the source (e.g. a weed_plant_t)
652   char delim[2];
653   char rfx_version[64];
654   LiVESList *gui_strings;  ///< rfxscript for constructing the params, param window and onchange triggers
655   LiVESList *onchange_strings;  ///< rfxscript for constructing the params, param window and onchange triggers
656   boolean is_template;
657   int needs_reinit;
658 } lives_rfx_t;
659 
660 boolean check_rfx_for_lives(lives_rfx_t *);
661 
662 void do_rfx_cleanup(lives_rfx_t *);
663 
664 void render_fx_get_params(lives_rfx_t *, const char *plugin_name, short status);
665 
666 void sort_rfx_array(lives_rfx_t *in_array, int num_elements);
667 
668 int find_rfx_plugin_by_name(const char *name, short status);
669 
670 void rfx_copy(lives_rfx_t *dest, lives_rfx_t *src, boolean full);
671 
672 void rfx_params_free(lives_rfx_t *);
673 
674 void rfx_free(lives_rfx_t *);
675 
676 void rfx_free_all(void);
677 
678 void param_copy(lives_param_t *dest, lives_param_t *src, boolean full);
679 
680 lives_param_t *find_rfx_param_by_name(lives_rfx_t *, const char *name);
681 
682 boolean set_rfx_param_by_name_string(lives_rfx_t *, const char *name, const char *value, boolean update_visual);
683 
684 boolean get_rfx_param_by_name_string(lives_rfx_t *rfx, const char *name, char **return_value);
685 
686 typedef struct {
687   LiVESList *list; ///< list of filter_idx from which user can delegate
688   int delegate; ///< offset in list of current delegate
689   ulong func; ///< menuitem activation function for current delegate
690   lives_rfx_t *rfx; ///< pointer to rfx for current delegate (or NULL)
691 } lives_fx_candidate_t;
692 
693 // filter types which can have candidates
694 #define FX_CANDIDATE_AUDIO_VOL 0
695 #define FX_CANDIDATE_RESIZER 1
696 #define FX_CANDIDATE_DEINTERLACE 2
697 
698 #define MAX_FX_CANDIDATE_TYPES 3
699 
700 boolean get_bool_param(void *value);
701 int get_int_param(void *value);
702 double get_double_param(void *value);
703 void get_colRGB24_param(void *value, lives_colRGB48_t *rgb);
704 void get_colRGBA32_param(void *value, lives_colRGBA64_t *rgba);
705 
706 void set_bool_param(void *value, boolean);
707 void set_int_param(void *value, int);
708 void set_double_param(void *value, double);
709 void set_colRGB24_param(void *value, short red, short green, short blue);
710 void set_colRGBA32_param(void *value, short red, short green, short blue, short alpha);
711 
712 /// return an array of parameter values
713 void **store_rfx_params(lives_rfx_t *);
714 void set_rfx_params_from_store(lives_rfx_t *rfx, void **store);
715 void rfx_params_store_free(lives_rfx_t *, void **store);
716 
717 LiVESList *array_to_string_list(char **array, int offset, int len);
718 
719 lives_rfx_t *weed_to_rfx(weed_plant_t *plant, boolean show_reinits);
720 lives_param_t *weed_params_to_rfx(int npar, weed_plant_t *instance, boolean show_reinits);
721 
722 void rfx_clean_exe(lives_rfx_t *rfx);
723 
724 char *plugin_run_param_window(const char *scrap_text, LiVESVBox *vbox, lives_rfx_t **ret_rfx);
725 
726 //////////////////////////////////////////////////////////////////////////////////////////
727 /// video playback plugin window - fixed part
728 
729 typedef struct {
730   _vid_playback_plugin *plugin;
731   LiVESWidget *dialog;
732   LiVESWidget *spinbuttonh;
733   LiVESWidget *spinbuttonw;
734   LiVESWidget *apply_fx;
735   LiVESWidget *fps_entry;
736   LiVESWidget *pal_entry;
737   lives_rfx_t *rfx;
738   boolean keep_rfx;
739   int intention;
740 } _vppaw;
741 
742 _vppaw *on_vpp_advanced_clicked(LiVESButton *, livespointer);
743 
744 void on_decplug_advanced_clicked(LiVESButton *button, livespointer user_data);
745 
746 LiVESList *get_external_window_hints(lives_rfx_t *rfx);
747 boolean check_encoder_restrictions(boolean get_extension, boolean user_audio, boolean save_all);
748 
749 /// for realtime effects, see effects-weed.h
750 
751 #endif
752