LiVES 3.2.0
plugins.c
Go to the documentation of this file.
1// plugins.c
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#include <dlfcn.h>
8#include <errno.h>
9
10#include "main.h"
11#include "resample.h"
12#include "effects.h"
13#include "interface.h"
14
15#include "rfx-builder.h"
16#include "paramwindow.h"
17
18#include "lsd-tab.h"
19
20// *INDENT-OFF*
21const char *const anames[AUDIO_CODEC_MAX] = {"mp3", "pcm", "mp2", "vorbis", "AC3", "AAC", "AMR_NB",
22 "raw", "wma2", "opus", ""};
23// *INDENT-ON*
24
25static boolean list_plugins;
26
28// command-line plugins
29
30LiVESList *get_plugin_result(const char *command, const char *delim, boolean allow_blanks, boolean strip) {
31 LiVESList *list = NULL;
32 char buffer[65536];
33
34 //threaded_dialog_spin(0.);
35
36 lives_popen(command, !mainw->is_ready && !list_plugins, buffer, 65535);
37
38 if (THREADVAR(com_failed)) return NULL;
39
40 //threaded_dialog_spin(0.);
41 list = buff_to_list(buffer, delim, allow_blanks, strip);
42 //threaded_dialog_spin(0.);
43 return list;
44}
45
46
47LIVES_GLOBAL_INLINE LiVESList *plugin_request_with_blanks(const char *plugin_type, const char *plugin_name,
48 const char *request) {
49 // allow blanks in a list
50 return plugin_request_common(plugin_type, plugin_name, request, "|", TRUE);
51}
52
53
54LIVES_GLOBAL_INLINE LiVESList *plugin_request(const char *plugin_type, const char *plugin_name, const char *request) {
55 return plugin_request_common(plugin_type, plugin_name, request, "|", FALSE);
56}
57
58
59LIVES_GLOBAL_INLINE LiVESList *plugin_request_by_line(const char *plugin_type, const char *plugin_name, const char *request) {
60 return plugin_request_common(plugin_type, plugin_name, request, "\n", FALSE);
61}
62
63
64LIVES_GLOBAL_INLINE LiVESList *plugin_request_by_space(const char *plugin_type, const char *plugin_name, const char *request) {
65 return plugin_request_common(plugin_type, plugin_name, request, " ", FALSE);
66}
67
68
69LiVESList *plugin_request_common(const char *plugin_type, const char *plugin_name, const char *request,
70 const char *delim, boolean allow_blanks) {
71 // returns a LiVESList of responses to -request, or NULL on error
72
73 // NOTE: request must not be quoted here, since it contains a list of parameters
74 // instead, caller should ensure that any strings in *request are suitably escaped and quoted
75 // e.g. by calling param_marshall()
76
77 LiVESList *reslist = NULL;
78 char *com, *comfile;
79
80 if (plugin_type) {
81 if (!plugin_name || !strlen(plugin_name)) {
82 return reslist;
83 }
84
85 // some types live in the config directory...
86 if (!strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_CUSTOM) || !strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_TEST)) {
87 comfile = lives_build_filename(prefs->config_datadir, plugin_type, plugin_name, NULL);
88 } else if (!strcmp(plugin_type, PLUGIN_RFX_SCRAP)) {
89 // scraps are in the workdir
90 comfile = lives_build_filename(prefs->workdir, plugin_name, NULL);
91 } else {
92 comfile = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, plugin_type, plugin_name, NULL);
93 }
94
95 //#define DEBUG_PLUGINS
96#ifdef DEBUG_PLUGINS
97 com = lives_strdup_printf("\"%s\" %s", comfile, request);
98 lives_printerr("will run: %s\n", com);
99#else
100 com = lives_strdup_printf("\"%s\" %s 2>/dev/null", comfile, request);
101#endif
102 lives_free(comfile);
103 } else com = lives_strdup(request);
104 list_plugins = FALSE;
105 reslist = get_plugin_result(com, delim, allow_blanks, TRUE);
106 lives_free(com);
107 //threaded_dialog_spin(0.);
108 return reslist;
109}
110
111
113// get list of plugins of various types
114
115LiVESList *get_plugin_list(const char *plugin_type, boolean allow_nonex, const char *plugdir, const char *filter_ext) {
116 // returns a LiVESList * of plugins of type plugin_type
117 // returns empty list if there are no plugins of that type
118
119 // allow_nonex to allow non-executable files (e.g. libs)
120 // filter_ext can be non-NULL to filter for files ending .filter_ext
121
122 // TODO - use enum for plugin_type
123
124 // format is: allow_nonex (0 or 1) allow_subdirs (0 or 1) plugindir ext
125
126 char *com, *tmp;
127 LiVESList *pluglist;
128
129 const char *ext = (filter_ext == NULL) ? "" : filter_ext;
130
131 if (!strcmp(plugin_type, PLUGIN_THEMES)) {
132 // must not allow_nonex, otherwise we get splash image etc (just want dirs)
133 com = lives_strdup_printf("%s list_plugins 0 1 \"%s%s\" \"\"", prefs->backend_sync, prefs->prefix_dir, THEME_DIR);
134 } else if (!strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS) ||
135 !strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS) ||
136 !strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_CUSTOM) ||
137 !strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_TEST) ||
138 !strcmp(plugin_type, PLUGIN_COMPOUND_EFFECTS_CUSTOM)
139 ) {
140 // look in home
141 tmp = lives_build_path(prefs->config_datadir, plugin_type, NULL);
142 com = lives_strdup_printf("%s list_plugins %d 0 \"%s\" \"%s\"", prefs->backend_sync, allow_nonex, tmp, ext);
143 lives_free(tmp);
144 } else if (!strcmp(plugin_type, PLUGIN_THEMES_CUSTOM)) {
145 tmp = lives_build_path(prefs->config_datadir, PLUGIN_THEMES, NULL);
146 com = lives_strdup_printf("%s list_plugins 0 1 \"%s\"", prefs->backend_sync, tmp);
147 lives_free(tmp);
148 } else if (!strcmp(plugin_type, PLUGIN_EFFECTS_WEED)) {
149 com = lives_strdup_printf("%s list_plugins 1 1 \"%s\" \"%s\"", prefs->backend_sync,
150 (tmp = lives_filename_from_utf8((char *)plugdir, -1, NULL, NULL, NULL)), ext);
151 lives_free(tmp);
152 } else if (!strcmp(plugin_type, PLUGIN_DECODERS)) {
153 com = lives_strdup_printf("%s list_plugins 1 0 \"%s\" \"%s\"", prefs->backend_sync,
154 (tmp = lives_filename_from_utf8((char *)plugdir, -1, NULL, NULL, NULL)), ext);
155 lives_free(tmp);
156 } else if (!strcmp(plugin_type, PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS)) {
157 com = lives_strdup_printf("%s list_plugins %d 0 \"%s%s%s\" \"%s\"", prefs->backend_sync, allow_nonex, prefs->prefix_dir,
158 PLUGIN_SCRIPTS_DIR, plugin_type, ext);
159 } else if (!strcmp(plugin_type, PLUGIN_COMPOUND_EFFECTS_BUILTIN)) {
160 com = lives_strdup_printf("%s list_plugins %d 0 \"%s%s%s\" \"%s\"", prefs->backend_sync, allow_nonex, prefs->prefix_dir,
161 PLUGIN_COMPOUND_DIR, plugin_type, ext);
162 } else {
163 com = lives_strdup_printf("%s list_plugins %d 0 \"%s%s%s\" \"%s\"", prefs->backend_sync, allow_nonex, prefs->lib_dir,
164 PLUGIN_EXEC_DIR, plugin_type, ext);
165 }
166 list_plugins = TRUE;
167
168 //g_print("\n\n\nLIST CMD: %s\n",com);
169
170 pluglist = get_plugin_result(com, "|", FALSE, TRUE);
171 lives_free(com);
172 //threaded_dialog_spin(0.);
173 pluglist = lives_list_sort_alpha(pluglist, TRUE);
174 return pluglist;
175}
176
177
179// video plugins
180
181void save_vpp_defaults(_vid_playback_plugin *vpp, char *vpp_file) {
182 // format is:
183 // nbytes (string) : LiVES vpp defaults file version 2\n
184 // for each video playback plugin:
185 // 4 bytes (int) name length
186 // n bytes name
187 // 4 bytes (int) version length
188 // n bytes version
189 // 4 bytes (int) palette
190 // 4 bytes (int) YUV sampling
191 // 4 bytes (int) YUV clamping
192 // 4 bytes (int) YUV subspace
193 // 4 bytes (int) width
194 // 4 bytes (int) height
195 // 8 bytes (double) fps
196 // 4 bytes (int) fps_numerator [0 indicates use fps double, >0 use fps_numer/fps_denom ]
197 // 4 bytes (int) fps_denominator
198 // 4 bytes argc (count of argv, may be 0)
199 //
200 // for each argv (extra params):
201 // 4 bytes (int) length
202 // n bytes string param value
203
204 int fd;
205 int32_t len;
206 const char *version;
207 int i;
208 char *msg;
209 int intzero = 0;
210 double dblzero = 0.;
211
212 if (!vpp) {
213 lives_rm(vpp_file);
214 return;
215 }
216
217 if ((fd = lives_open3(vpp_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) == -1) {
218 msg = lives_strdup_printf(_("\n\nUnable to write video playback plugin defaults file\n%s\nError code %d\n"), vpp_file, errno);
219 LIVES_ERROR(msg);
220 lives_free(msg);
221 return;
222 }
223
224 msg = lives_strdup_printf(_("Updating video playback plugin defaults in %s\n"), vpp_file);
225 LIVES_INFO(msg);
226 lives_free(msg);
227
228 msg = lives_strdup("LiVES vpp defaults file version 2\n");
229 if (!lives_write(fd, msg, strlen(msg), FALSE)) return;
230 lives_free(msg);
231
232 len = strlen(vpp->name);
233 if (lives_write_le(fd, &len, 4, FALSE) < 4) return;
234 if (lives_write(fd, vpp->name, len, FALSE) < len) return;
235
236 version = (*vpp->version)();
237 len = strlen(version);
238 if (lives_write_le(fd, &len, 4, FALSE) < 4) return;
239 if (lives_write(fd, version, len, FALSE) < len) return;
240
241 if (lives_write_le(fd, &(vpp->palette), 4, FALSE) < 4) return;
242 if (lives_write_le(fd, &(vpp->YUV_sampling), 4, FALSE) < 4) return;
243 if (lives_write_le(fd, &(vpp->YUV_clamping), 4, FALSE) < 4) return;
244 if (lives_write_le(fd, &(vpp->YUV_subspace), 4, FALSE) < 4) return;
245
246 if (lives_write_le(fd, vpp->fwidth <= 0 ? &intzero : & (vpp->fwidth), 4, FALSE) < 4) return;
247 if (lives_write_le(fd, vpp->fheight <= 0 ? &intzero : & (vpp->fheight), 4, FALSE) < 4) return;
248
249 if (lives_write_le(fd, vpp->fixed_fpsd <= 0. ? &dblzero : & (vpp->fixed_fpsd), 8, FALSE) < 8) return;
250 if (lives_write_le(fd, vpp->fixed_fps_numer <= 0 ? &intzero : & (vpp->fixed_fps_numer), 4, FALSE) < 4) return;
251 if (lives_write_le(fd, vpp->fixed_fps_denom <= 0 ? &intzero : & (vpp->fixed_fps_denom), 4, FALSE) < 4) return;
252
253 if (lives_write_le(fd, &(vpp->extra_argc), 4, FALSE) < 4) return;
254
255 for (i = 0; i < vpp->extra_argc; i++) {
256 len = strlen(vpp->extra_argv[i]);
257 if (lives_write_le(fd, &len, 4, FALSE) < 4) return;
258 if (lives_write(fd, vpp->extra_argv[i], len, FALSE) < len) return;
259 }
260
261 close(fd);
262}
263
264
265void load_vpp_defaults(_vid_playback_plugin *vpp, char *vpp_file) {
266 ssize_t len;
267 const char *version;
268
269 char buf[512];
270
271 char *msg;
272
273 int retval;
274 int fd;
275
276 register int i;
277
278 if (!lives_file_test(vpp_file, LIVES_FILE_TEST_EXISTS)) {
279 return;
280 }
281
282 d_print(_("Loading video playback plugin defaults from %s..."), vpp_file);
283
284 do {
285 retval = 0;
286 if ((fd = lives_open2(vpp_file, O_RDONLY)) == -1) {
287 retval = do_read_failed_error_s_with_retry(vpp_file, lives_strerror(errno));
288 if (retval == LIVES_RESPONSE_CANCEL) {
289 vpp = NULL;
290 return;
291 }
292 } else {
293 do {
294 // only do this loop once, so we can use break to escape it
295
296 THREADVAR(read_failed) = FALSE;
297 msg = lives_strdup("LiVES vpp defaults file version 2\n");
298 len = lives_read(fd, buf, strlen(msg), FALSE);
299 if (len < 0) len = 0;
300 lives_memset(buf + len, 0, 1);
301
302 if (THREADVAR(read_failed)) break;
303
304 // identifier string
305 if (strcmp(msg, buf)) {
306 lives_free(msg);
308 close(fd);
309 return;
310 }
311 lives_free(msg);
312
313 // plugin name
314 lives_read_le(fd, &len, 4, FALSE);
315 if (THREADVAR(read_failed)) break;
316 lives_read(fd, buf, len, FALSE);
317 lives_memset(buf + len, 0, 1);
318
319 if (THREADVAR(read_failed)) break;
320
321 if (strcmp(buf, vpp->name)) {
323 close(fd);
324 return;
325 }
326
327 // version string
328 version = (*vpp->version)();
329 lives_read_le(fd, &len, 4, FALSE);
330 if (THREADVAR(read_failed)) break;
331 lives_read(fd, buf, len, FALSE);
332
333 if (THREADVAR(read_failed)) break;
334
335 lives_memset(buf + len, 0, 1);
336
337 if (strcmp(buf, version)) {
339 _("\nThe %s video playback plugin has been updated.\nPlease check your settings in\n"
340 "Tools|Preferences|Playback|Playback Plugins Advanced\n\n"),
341 vpp->name);
343 do_error_dialog(msg);
345 lives_free(msg);
346 lives_rm(vpp_file);
348 close(fd);
349 return;
350 }
351
352 lives_read_le(fd, &(vpp->palette), 4, FALSE);
353 lives_read_le(fd, &(vpp->YUV_sampling), 4, FALSE);
354 lives_read_le(fd, &(vpp->YUV_clamping), 4, FALSE);
355 lives_read_le(fd, &(vpp->YUV_subspace), 4, FALSE);
356 lives_read_le(fd, &(vpp->fwidth), 4, FALSE);
357 lives_read_le(fd, &(vpp->fheight), 4, FALSE);
358 lives_read_le(fd, &(vpp->fixed_fpsd), 8, FALSE);
359 lives_read_le(fd, &(vpp->fixed_fps_numer), 4, FALSE);
360 lives_read_le(fd, &(vpp->fixed_fps_denom), 4, FALSE);
361
362 if (THREADVAR(read_failed)) break;
363
364 lives_read_le(fd, &(vpp->extra_argc), 4, FALSE);
365
366 if (THREADVAR(read_failed)) break;
367
368 if (vpp->extra_argv) {
369 for (i = 0; vpp->extra_argv[i]; i++) {
370 lives_free(vpp->extra_argv[i]);
371 }
373 }
374
375 vpp->extra_argv = (char **)lives_calloc((vpp->extra_argc + 1), (sizeof(char *)));
376
377 for (i = 0; i < vpp->extra_argc; i++) {
378 lives_read_le(fd, &len, 4, FALSE);
379 if (THREADVAR(read_failed)) break;
380 vpp->extra_argv[i] = (char *)lives_malloc(len + 1);
381 lives_read(fd, vpp->extra_argv[i], len, FALSE);
382 if (THREADVAR(read_failed)) break;
383 lives_memset((vpp->extra_argv[i]) + len, 0, 1);
384 }
385
386 vpp->extra_argv[i] = NULL;
387
388 close(fd);
389 } while (FALSE);
390
391 if (THREADVAR(read_failed)) {
392 close(fd);
393 retval = do_read_failed_error_s_with_retry(vpp_file, NULL);
394 if (retval == LIVES_RESPONSE_CANCEL) {
395 THREADVAR(read_failed) = FALSE;
396 vpp = NULL;
398 return;
399 }
400 }
401 }
402 } while (retval == LIVES_RESPONSE_RETRY);
403
404 d_print_done();
405}
406
407
408void on_vppa_cancel_clicked(LiVESButton *button, livespointer user_data) {
409 _vppaw *vppw = (_vppaw *)user_data;
410 _vid_playback_plugin *vpp = vppw->plugin;
411
414 if (vpp && vpp != mainw->vpp) {
415 // close the temp current vpp
417 }
418
419 if (vppw->rfx) {
420 if (!vppw->keep_rfx) {
421 rfx_free(vppw->rfx);
422 lives_free(vppw->rfx);
423 }
424 }
425
426 lives_free(vppw);
427
428 if (prefsw) {
431 }
432}
433
434
435void on_vppa_ok_clicked(LiVESButton *button, livespointer user_data) {
436 _vppaw *vppw = (_vppaw *)user_data;
437 uint64_t xwinid = 0;
438
439 const char *fixed_fps = NULL;
440 const char *tmp;
441
442 char *cur_pal = NULL;
443
444 int *pal_list, i = 0;
445
446 boolean ext_audio = FALSE;
447
448 _vid_playback_plugin *vpp = vppw->plugin;
449
450 if (vppw->rfx && mainw->textwidget_focus) {
451 // make sure text widgets are updated if they activate the default
452 LiVESWidget *textwidget = (LiVESWidget *)lives_widget_object_get_data(LIVES_WIDGET_OBJECT(mainw->textwidget_focus),
454 after_param_text_changed(textwidget, vppw->rfx);
455 }
456
457 if (!special_cleanup(TRUE)) {
458 // check for file overwrites with special type "filewrite"
459 // if user declines, will return with LIVES_RESPONSE_RETRY
460 if (LIVES_IS_DIALOG(lives_widget_get_toplevel(LIVES_WIDGET(button))))
461 lives_dialog_response(LIVES_DIALOG(lives_widget_get_toplevel(LIVES_WIDGET(button))), LIVES_RESPONSE_RETRY);
462 return;
463 }
464
465 mainw->textwidget_focus = NULL;
466
467 if (vpp == mainw->vpp) {
468 if (vppw->spinbuttonw) mainw->vpp->fwidth
469 = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(vppw->spinbuttonw));
470 if (vppw->spinbuttonh) mainw->vpp->fheight
471 = lives_spin_button_get_value_as_int(LIVES_SPIN_BUTTON(vppw->spinbuttonh));
472 if (vppw->apply_fx) mainw->fx1_bool = lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(vppw->apply_fx));
473 if (vppw->fps_entry) fixed_fps = lives_entry_get_text(LIVES_ENTRY(vppw->fps_entry));
474 if (vppw->pal_entry) {
475 cur_pal = lives_strdup(lives_entry_get_text(LIVES_ENTRY(vppw->pal_entry)));
476
477 if (get_token_count(cur_pal, ' ') > 1) {
478 char **array = lives_strsplit(cur_pal, " ", 2);
479 char *clamping = lives_strdup(array[1] + 1);
480 lives_free(cur_pal);
481 cur_pal = lives_strdup(array[0]);
482 lives_memset(clamping + strlen(clamping) - 1, 0, 1);
483 do {
485 if (tmp && !strcmp(clamping, tmp)) {
486 vpp->YUV_clamping = i;
487 break;
488 }
489 i++;
490 } while (tmp);
491 lives_strfreev(array);
492 lives_free(clamping);
493 }
494 }
495
496 if (vppw->fps_entry) {
497 if (!strlen(fixed_fps)) {
498 mainw->vpp->fixed_fpsd = -1.;
500 } else {
501 if (get_token_count((char *)fixed_fps, ':') > 1) {
502 char **array = lives_strsplit(fixed_fps, ":", 2);
503 mainw->vpp->fixed_fps_numer = atoi(array[0]);
504 mainw->vpp->fixed_fps_denom = atoi(array[1]);
505 lives_strfreev(array);
506 mainw->vpp->fixed_fpsd = get_ratio_fps((char *)fixed_fps);
507 } else {
508 mainw->vpp->fixed_fpsd = lives_strtod(fixed_fps, NULL);
510 }
511 }
512 } else {
513 mainw->vpp->fixed_fpsd = -1.;
515 }
516
517 if (mainw->vpp->fixed_fpsd > 0. && (mainw->fixed_fpsd > 0. ||
518 (mainw->vpp->set_fps &&
519 !((*mainw->vpp->set_fps)(mainw->vpp->fixed_fpsd))))) {
521 mainw->error = TRUE;
522 mainw->vpp->fixed_fpsd = -1.;
524 }
525
526 if (vppw->pal_entry) {
527 if (vpp->get_palette_list && (pal_list = (*vpp->get_palette_list)())) {
528 for (i = 0; pal_list[i] != WEED_PALETTE_END; i++) {
529 if (!strcmp(cur_pal, weed_palette_get_name(pal_list[i]))) {
530 vpp->palette = pal_list[i];
531 if (mainw->ext_playback) {
532 pthread_mutex_lock(&mainw->vpp_stream_mutex);
534 pthread_mutex_unlock(&mainw->vpp_stream_mutex);
536 if (mainw->vpp->exit_screen) {
538 }
539
540#ifdef RT_AUDIO
542#endif
543 mainw->stream_ticks = -1;
544 mainw->vpp->palette = pal_list[i];
545 if (!(*vpp->set_palette)(vpp->palette)) {
547 mainw->error = TRUE;
548 }
549
550 if (prefs->play_monitor != 0) {
551 if (mainw->play_window) {
552 xwinid = lives_widget_get_xwinid(mainw->play_window, "Unsupported display type for playback plugin");
553 if (xwinid == -1) {
554 lives_dialog_response(LIVES_DIALOG(vppw->dialog), LIVES_RESPONSE_CANCEL);
555 return;
556 }
557 }
558 }
559
560#ifdef RT_AUDIO
562
565 }
566
567#endif
568 if (vpp->init_audio && prefs->stream_audio_out) {
569#ifdef HAVE_PULSE_AUDIO
571 if ((*vpp->init_audio)(mainw->pulsed->out_arate, mainw->pulsed->out_achans, vpp->extra_argc, vpp->extra_argv))
573 }
574#endif
575#ifdef ENABLE_JACK
577 if ((*vpp->init_audio)(mainw->jackd->sample_out_rate, mainw->jackd->num_output_channels,
578 vpp->extra_argc, vpp->extra_argv))
579 ext_audio = TRUE;
580 }
581#endif
582 }
583
584 if (vpp->init_screen) {
585 (*vpp->init_screen)(mainw->vpp->fwidth > 0 ? mainw->vpp->fwidth : mainw->pwidth,
587 TRUE, xwinid, vpp->extra_argc, vpp->extra_argv);
588 }
589 mainw->ext_audio = ext_audio; // cannot set this until after init_screen()
593 }
594 } else {
595 mainw->vpp->palette = pal_list[i];
596 if (!(*vpp->set_palette)(vpp->palette)) {
598 mainw->error = TRUE;
599 }
601 }
602 break;
603 }
604 }
605 }
606 lives_free(cur_pal);
607 }
608 if (vpp->extra_argv) {
609 for (i = 0; vpp->extra_argv[i]; i++) lives_free(vpp->extra_argv[i]);
611 vpp->extra_argv = NULL;
612 }
613 vpp->extra_argc = 0;
614 if (vppw->rfx) {
616 for (i = 0; vpp->extra_argv[i]; vpp->extra_argc = ++i);
617 }
619 } else {
620 if (vppw->spinbuttonw)
622 else future_prefs->vpp_fwidth = -1;
623 if (vppw->spinbuttonh)
625 else future_prefs->vpp_fheight = -1;
626 if (vppw->fps_entry) fixed_fps = lives_entry_get_text(LIVES_ENTRY(vppw->fps_entry));
627 if (vppw->pal_entry) {
628 cur_pal = lives_strdup(lives_entry_get_text(LIVES_ENTRY(vppw->pal_entry)));
629
630 if (get_token_count(cur_pal, ' ') > 1) {
631 char **array = lives_strsplit(cur_pal, " ", 2);
632 char *clamping = lives_strdup(array[1] + 1);
633 lives_free(cur_pal);
634 cur_pal = lives_strdup(array[0]);
635 lives_memset(clamping + strlen(clamping) - 1, 0, 1);
636 do {
638 if (tmp && !strcmp(clamping, tmp)) {
640 break;
641 }
642 i++;
643 } while (tmp);
644 lives_strfreev(array);
645 lives_free(clamping);
646 }
647 }
648
649 if (fixed_fps) {
650 if (get_token_count((char *)fixed_fps, ':') > 1) {
651 char **array = lives_strsplit(fixed_fps, ":", 2);
652 future_prefs->vpp_fixed_fps_numer = atoi(array[0]);
653 future_prefs->vpp_fixed_fps_denom = atoi(array[1]);
654 lives_strfreev(array);
655 future_prefs->vpp_fixed_fpsd = get_ratio_fps((char *)fixed_fps);
656 } else {
657 future_prefs->vpp_fixed_fpsd = lives_strtod(fixed_fps, NULL);
659 }
660 } else {
663 }
664
665 if (cur_pal) {
666 if (vpp->get_palette_list && (pal_list = (*vpp->get_palette_list)())) {
667 for (i = 0; pal_list[i] != WEED_PALETTE_END; i++) {
668 if (!strcmp(cur_pal, weed_palette_get_name(pal_list[i]))) {
669 future_prefs->vpp_palette = pal_list[i];
670 break;
671 }
672 }
673 }
674 lives_free(cur_pal);
675 } else future_prefs->vpp_palette = WEED_PALETTE_END;
676
677 if (future_prefs->vpp_argv) {
678 for (i = 0; future_prefs->vpp_argv[i]; i++) lives_free(future_prefs->vpp_argv[i]);
680 future_prefs->vpp_argv = NULL;
681 }
682
684 if (vppw->rfx) {
686 if (future_prefs->vpp_argv) {
687 for (i = 0; future_prefs->vpp_argv[i]; future_prefs->vpp_argc = ++i);
688 }
689 } else {
691 vpp->extra_argv = NULL;
692 vpp->extra_argc = 0;
693 }
694 }
695 if (button && !mainw->error) on_vppa_cancel_clicked(button, user_data);
696 else lives_dialog_response(LIVES_DIALOG(vppw->dialog), LIVES_RESPONSE_OK);
697 if (button) mainw->error = FALSE;
698}
699
700
701void on_vppa_save_clicked(LiVESButton *button, livespointer user_data) {
702 _vppaw *vppw = (_vppaw *)user_data;
703 _vid_playback_plugin *vpp = vppw->plugin;
704 char *save_file;
705
706 // apply
707 mainw->error = FALSE;
708 on_vppa_ok_clicked(NULL, user_data);
709 if (mainw->error) {
710 mainw->error = FALSE;
711 return;
712 }
713
714 // get filename
715 save_file = choose_file(NULL, NULL, NULL, LIVES_FILE_CHOOSER_ACTION_SAVE, NULL, NULL);
716 if (!save_file) return;
717
718 // save
719 d_print(_("Saving playback plugin defaults to %s..."), save_file);
721 d_print_done();
723
724}
725
726
727_vppaw *on_vpp_advanced_clicked(LiVESButton *button, livespointer user_data) {
728 LiVESWidget *dialog_vbox;
729 LiVESWidget *hbox;
730 LiVESWidget *label;
731 LiVESWidget *combo;
732 LiVESWidget *cancelbutton;
733 LiVESWidget *okbutton;
734 LiVESWidget *savebutton;
735
736 LiVESAccelGroup *accel_group;
737
738 _vppaw *vppa;
739
740 _vid_playback_plugin *tmpvpp;
741
742 int *pal_list;
743
744 double wscale = 1., hscale = 1.;
745
746 int intention = LIVES_INTENTION_PLAY;
747 int hsize, vsize;
748
749 LiVESList *fps_list_strings = NULL;
750 LiVESList *pal_list_strings = NULL;
751
752 const char *string;
753 const char *pversion;
754 const char *desc;
755 const char *fps_list;
756
757 char *title;
758 char *tmp, *tmp2;
759
760 char *ctext = NULL;
761
762 // TODO - set default values from tmpvpp
763
764 if (user_data) intention = LIVES_POINTER_TO_INT(user_data);
765
766 if (strlen(future_prefs->vpp_name)) {
767 if (!(tmpvpp = open_vid_playback_plugin(future_prefs->vpp_name, FALSE))) return NULL;
768 } else {
769 if (!mainw->vpp) return NULL;
770 tmpvpp = mainw->vpp;
771 }
772
773 vppa = (_vppaw *)(lives_calloc(1, sizeof(_vppaw)));
774
775 vppa->plugin = tmpvpp;
776 /* vppa->rfx = NULL; */
777 /* vppa->spinbuttonh = vppa->spinbuttonw = NULL; */
778 /* vppa->apply_fx = NULL; */
779 /* vppa->pal_entry = vppa->fps_entry = NULL; */
780 /* vppa->keep_rfx = FALSE; */
781
782 vppa->intention = intention;
783
784 pversion = (tmpvpp->version)();
785
786 if (intention == LIVES_INTENTION_PLAY)
787 title = lives_strdup_printf("%s", pversion);
788 else {
789 // LIVES_INTENTION_TRANSCODE
790 title = (_("Quick Transcoding"));
791 wscale = 2. * widget_opts.scale;
792 hscale = 1.5;
793 }
794
795 vppa->dialog = lives_standard_dialog_new(title, FALSE, DEF_DIALOG_WIDTH * wscale, DEF_DIALOG_HEIGHT * hscale);
796 lives_free(title);
797
798 accel_group = LIVES_ACCEL_GROUP(lives_accel_group_new());
799 lives_window_add_accel_group(LIVES_WINDOW(vppa->dialog), accel_group);
800
801 dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(vppa->dialog));
802
803 // the filling...
804 if (intention == LIVES_INTENTION_PLAY && tmpvpp->get_description) {
805 desc = (tmpvpp->get_description)();
806 if (desc) {
807 label = lives_standard_label_new(desc);
808 lives_box_pack_start(LIVES_BOX(dialog_vbox), label, FALSE, FALSE, widget_opts.packing_height);
809 }
810 }
811 if (intention == LIVES_INTENTION_TRANSCODE) {
812 tmp = lives_big_and_bold("%s", _("Quick transcode provides a rapid, high quality preview of the selected frames and audio."));
814 label = lives_standard_label_new(tmp);
816 lives_free(tmp);
817 lives_box_pack_start(LIVES_BOX(dialog_vbox), label, FALSE, FALSE, widget_opts.packing_height);
818 }
819
820 if (tmpvpp->get_fps_list && (fps_list = (*tmpvpp->get_fps_list)(tmpvpp->palette))) {
821 int nfps, i;
822 char **array = lives_strsplit(fps_list, "|", -1);
823
824 nfps = get_token_count((char *)fps_list, '|');
825 for (i = 0; i < nfps; i++) {
826 if (strlen(array[i]) && strcmp(array[i], "\n")) {
827 if (get_token_count(array[i], ':') == 0) {
828 fps_list_strings = lives_list_append(fps_list_strings, remove_trailing_zeroes(lives_strtod(array[i], NULL)));
829 } else fps_list_strings = lives_list_append(fps_list_strings, lives_strdup(array[i]));
830 }
831 }
832
833 if (intention == LIVES_INTENTION_PLAY) {
834 // fps
835 combo = lives_standard_combo_new((tmp = (_("_FPS"))), fps_list_strings,
836 LIVES_BOX(dialog_vbox), (tmp2 = (_("Fixed framerate for plugin.\n"))));
837 lives_free(tmp);
838 lives_free(tmp2);
839 vppa->fps_entry = lives_combo_get_entry(LIVES_COMBO(combo));
840 lives_entry_set_width_chars(LIVES_ENTRY(lives_combo_get_entry(LIVES_COMBO(combo))), COMBOWIDTHCHARS);
841
842 lives_list_free_all(&fps_list_strings);
843 lives_strfreev(array);
844
845 if (tmpvpp->fixed_fps_numer > 0) {
846 char *tmp = lives_strdup_printf("%d:%d", tmpvpp->fixed_fps_numer, tmpvpp->fixed_fps_denom);
847 lives_entry_set_text(LIVES_ENTRY(vppa->fps_entry), tmp);
848 lives_free(tmp);
849 } else {
850 char *tmp = remove_trailing_zeroes(tmpvpp->fixed_fpsd);
851 lives_entry_set_text(LIVES_ENTRY(vppa->fps_entry), tmp);
852 lives_free(tmp);
853 }
854 }
855 }
856
857 // frame size
858
859 if (!(tmpvpp->capabilities & VPP_LOCAL_DISPLAY)) {
860 hbox = lives_hbox_new(FALSE, 0);
861 lives_box_pack_start(LIVES_BOX(dialog_vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
862
863 add_fill_to_box(LIVES_BOX(hbox));
864
865 hsize = tmpvpp->fwidth > 0 ? tmpvpp->fwidth :
866 intention == LIVES_INTENTION_TRANSCODE ? cfile->hsize : DEF_VPP_HSIZE;
867
869 hsize,
870 4., MAX_FRAME_WIDTH, 4., 16., 0, LIVES_BOX(hbox), NULL);
871
872 add_fill_to_box(LIVES_BOX(hbox));
873
874 vsize = tmpvpp->fheight > 0 ? tmpvpp->fheight :
875 intention == LIVES_INTENTION_TRANSCODE ? cfile->vsize : DEF_VPP_VSIZE;
876
878 vsize,
879 4., MAX_FRAME_HEIGHT, 4., 16., 0, LIVES_BOX(hbox), NULL);
880
881 if (intention == LIVES_INTENTION_TRANSCODE) {
882 if (mainw->event_list) {
884 } else {
885 // add aspect ratio butto
887 /* hbox = lives_hbox_new(FALSE, 0); */
888 /* lives_box_pack_start(LIVES_BOX(dialog_vbox), hbox, FALSE, FALSE, widget_opts.packing_height); */
889 aspect = (lives_special_aspect_t *)add_aspect_ratio_button(LIVES_SPIN_BUTTON(vppa->spinbuttonw),
890 LIVES_SPIN_BUTTON(vppa->spinbuttonh), LIVES_BOX(hbox));
891 // don't reset the aspect params when we make_param_box
892 aspect->no_reset = TRUE;
893 }
894 }
895 add_fill_to_box(LIVES_BOX(hbox));
896 }
897
898 if (intention == LIVES_INTENTION_PLAY) {
899 if (tmpvpp->get_palette_list && (pal_list = (*tmpvpp->get_palette_list)())) {
900 int i;
901
902 for (i = 0; pal_list[i] != WEED_PALETTE_END; i++) {
903 int j = 0;
904 string = weed_palette_get_name(pal_list[i]);
905 if (weed_palette_is_yuv(pal_list[i]) && tmpvpp->get_yuv_palette_clamping) {
906 int *clampings = (*tmpvpp->get_yuv_palette_clamping)(pal_list[i]);
907 while (clampings[j] != -1) {
908 char *string2 = lives_strdup_printf("%s (%s)", string, weed_yuv_clamping_get_name(clampings[j]));
909 pal_list_strings = lives_list_append(pal_list_strings, string2);
910 j++;
911 }
912 }
913 if (j == 0) {
914 pal_list_strings = lives_list_append(pal_list_strings, lives_strdup(string));
915 }
916 }
917
918 combo = lives_standard_combo_new((tmp = (_("_Colourspace"))), pal_list_strings,
919 LIVES_BOX(dialog_vbox), tmp2 = (_("Colourspace input to the plugin.\n")));
920 lives_free(tmp);
921 lives_free(tmp2);
922 vppa->pal_entry = lives_combo_get_entry(LIVES_COMBO(combo));
923
924 if (tmpvpp->get_yuv_palette_clamping && weed_palette_is_yuv(tmpvpp->palette)) {
925 int *clampings = tmpvpp->get_yuv_palette_clamping(tmpvpp->palette);
926 if (clampings[0] != -1)
927 ctext = lives_strdup_printf("%s (%s)", weed_palette_get_name(tmpvpp->palette),
929 }
930 if (!ctext) ctext = lives_strdup(weed_palette_get_name(tmpvpp->palette));
931 lives_entry_set_text(LIVES_ENTRY(vppa->pal_entry), ctext);
932 lives_free(ctext);
933 lives_list_free_all(&pal_list_strings);
934 }
935 }
936 if (intention == LIVES_INTENTION_TRANSCODE) {
937 vppa->apply_fx = lives_standard_check_button_new(_("Apply current realtime effects"),
938 FALSE, LIVES_BOX(dialog_vbox), NULL);
940 }
941
942 // extra params
943 if (tmpvpp->get_init_rfx) {
944 LiVESWidget *vbox = lives_vbox_new(FALSE, 0);
945 /* LiVESWidget *scrolledwindow = lives_standard_scrolled_window_new(RFX_WINSIZE_H, RFX_WINSIZE_V / 2, vbox); */
946 lives_box_pack_start(LIVES_BOX(dialog_vbox), vbox, TRUE, TRUE, 0);
947 plugin_run_param_window((*tmpvpp->get_init_rfx)(intention), LIVES_VBOX(vbox), &(vppa->rfx));
948 if (intention != LIVES_INTENTION_TRANSCODE) {
949 char *fnamex = lives_build_filename(prefs->workdir, vppa->rfx->name, NULL);
950 if (lives_file_test(fnamex, LIVES_FILE_TEST_EXISTS))
951 lives_rm(fnamex);
952 lives_free(fnamex);
953 }
954 if (tmpvpp->extra_argv && tmpvpp->extra_argc > 0) {
955 // update with defaults
956 LiVESList *plist = argv_to_marshalled_list(vppa->rfx, tmpvpp->extra_argc, tmpvpp->extra_argv);
957 param_demarshall(vppa->rfx, plist, FALSE, FALSE); // set defaults
958 param_demarshall(vppa->rfx, plist, FALSE, TRUE); // update widgets
959 lives_list_free_all(&plist);
960 }
961 }
962
963 cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(vppa->dialog), LIVES_STOCK_CANCEL, NULL,
964 LIVES_RESPONSE_CANCEL);
965
966 lives_widget_add_accelerator(cancelbutton, LIVES_WIDGET_CLICKED_SIGNAL, accel_group,
967 LIVES_KEY_Escape, (LiVESXModifierType)0, (LiVESAccelFlags)0);
968
969 if (intention == LIVES_INTENTION_PLAY) {
970 savebutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(vppa->dialog), LIVES_STOCK_SAVE_AS, NULL,
971 LIVES_RESPONSE_BROWSE);
972
973 lives_widget_set_tooltip_text(savebutton, _("Save settings to an alternate file.\n"));
974 lives_signal_connect(LIVES_GUI_OBJECT(savebutton), LIVES_WIDGET_CLICKED_SIGNAL,
975 LIVES_GUI_CALLBACK(on_vppa_save_clicked),
976 vppa);
977 }
978
979 okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(vppa->dialog), LIVES_STOCK_OK, NULL,
980 LIVES_RESPONSE_OK);
981
983
984 lives_signal_sync_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
985 LIVES_GUI_CALLBACK(on_vppa_cancel_clicked), vppa);
986
987 lives_signal_sync_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
988 LIVES_GUI_CALLBACK(on_vppa_ok_clicked), vppa);
989
991 lives_window_present(LIVES_WINDOW(vppa->dialog));
993
994 return vppa;
995}
996
997
999 register int i;
1000
1001 if (vpp) {
1002 if (vpp == mainw->vpp) {
1004 if (mainw->ext_playback) {
1005 pthread_mutex_lock(&mainw->vpp_stream_mutex);
1008 pthread_mutex_unlock(&mainw->vpp_stream_mutex);
1009 if (mainw->vpp->exit_screen) {
1011 }
1012#ifdef RT_AUDIO
1014#endif
1016 if (mainw->play_window && prefs->play_monitor == 0)
1018 }
1019 mainw->stream_ticks = -1;
1020 mainw->vpp = NULL;
1021 }
1022 if (vpp->module_unload)(vpp->module_unload)();
1023 dlclose(vpp->handle);
1024
1025 if (vpp->extra_argv) {
1026 for (i = 0; vpp->extra_argv[i]; i++) {
1027 lives_free(vpp->extra_argv[i]);
1028 }
1029 lives_free(vpp->extra_argv);
1030 }
1031
1032 for (i = 0; i < vpp->num_play_params + vpp->num_alpha_chans; i++) {
1033 weed_plant_free(vpp->play_params[i]);
1034 }
1035
1036 lives_freep((void **)&vpp->play_params);
1037 lives_free(vpp);
1038 }
1039}
1040
1041
1042const weed_plant_t *pp_get_param(weed_plant_t **pparams, int idx) {
1043 register int i = 0;
1044 while (pparams[i]) {
1045 if (WEED_PLANT_IS_PARAMETER(pparams[i])) {
1046 if (--idx < 0) return pparams[i];
1047 }
1048 i++;
1049 }
1050 return NULL;
1051}
1052
1053
1054const weed_plant_t *pp_get_chan(weed_plant_t **pparams, int idx) {
1055 register int i = 0;
1056 while (pparams[i]) {
1057 if (WEED_PLANT_IS_CHANNEL(pparams[i])) {
1058 if (--idx < 0) return pparams[i];
1059 }
1060 i++;
1061 }
1062 return NULL;
1063}
1064
1065
1067 int *pal_list, i = 0;
1068 if (vpp->get_palette_list && (pal_list = (*vpp->get_palette_list)())) {
1069 int palette = weed_layer_get_palette(layer);
1070 for (i = 0; pal_list[i] != WEED_PALETTE_END; i++) {
1071 if (pal_list[i] == palette) break;
1072 }
1073 if (pal_list[i] == WEED_PALETTE_END) {
1074 if (!i) return FALSE;
1075 palette = best_palette_match(pal_list, i, palette);
1076 }
1077 if (palette == WEED_PALETTE_END) return FALSE;
1078 if (palette != vpp->palette) {
1079 if (!(*vpp->set_palette)(palette)) {
1080 return FALSE;
1081 }
1082 }
1083 vpp->palette = palette;
1085 int *yuv_clamping_types = (*vpp->get_yuv_palette_clamping)(vpp->palette);
1086 int lclamping = weed_layer_get_yuv_clamping(layer);
1087 for (i = 0; yuv_clamping_types[i] != -1; i++) {
1088 if (yuv_clamping_types[i] == lclamping) {
1089 if ((*vpp->set_yuv_palette_clamping)(lclamping))
1090 vpp->YUV_clamping = lclamping;
1091 break;
1092 // *INDENT-OFF*
1093 }}}}
1094 // *INDENT-ON*
1095 return FALSE;
1096}
1097
1098
1099_vid_playback_plugin *open_vid_playback_plugin(const char *name, boolean in_use) {
1100 // this is called on startup or when the user selects a new playback plugin
1101
1102 // if in_use is TRUE, it is our active vpp
1103
1104 // TODO - if in_use, get fixed_fps,fwidth,fheight,palette,argc and argv from a file
1105
1107 char **array;
1108 const char *fps_list;
1109 const char *pl_error;
1110 void *handle;
1111 int *palette_list;
1112 char *msg, *tmp;
1113 char *plugname;
1114 int dlflags = RTLD_LAZY;
1115 boolean OK = TRUE;
1116
1117 if (in_use && LIVES_IS_PLAYING && mainw->noswitch) {
1118 mainw->new_vpp = name;
1119 return NULL;
1120 }
1121
1122 tmp = lives_strdup_printf("%s.%s", name, DLL_NAME);
1123 plugname = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_VID_PLAYBACK, tmp, NULL);
1124 lives_free(tmp);
1125
1126 handle = dlopen(plugname, dlflags);
1127
1128 if (!handle) {
1129 char *msg = lives_strdup_printf(_("\n\nFailed to open playback plugin %s\nError was %s\n"
1130 "Playback plugin will be disabled,\n"
1131 "it can be re-enabled in Preferences / Playback.\n"), plugname, dlerror());
1132 if (prefs->startup_phase != 1 && prefs->startup_phase != -1) {
1134 do_error_dialog(msg);
1136 }
1137 LIVES_ERROR(msg);
1138 lives_free(msg);
1139 lives_free(plugname);
1141 set_vpp(TRUE);
1142 return NULL;
1143 }
1144
1146
1147 vpp->play_paramtmpls = NULL;
1148 vpp->get_init_rfx = NULL;
1149 vpp->play_params = NULL;
1150 vpp->alpha_chans = NULL;
1151 vpp->num_play_params = vpp->num_alpha_chans = 0;
1152 vpp->extra_argv = NULL;
1153
1154 if ((vpp->module_check_init = (const char *(*)())dlsym(handle, "module_check_init")) == NULL) {
1155 OK = FALSE;
1156 }
1157 if ((vpp->version = (const char *(*)())dlsym(handle, "version")) == NULL) {
1158 OK = FALSE;
1159 }
1160 if ((vpp->get_palette_list = (int *(*)())dlsym(handle, "get_palette_list")) == NULL) {
1161 OK = FALSE;
1162 }
1163 if ((vpp->set_palette = (boolean(*)(int))dlsym(handle, "set_palette")) == NULL) {
1164 OK = FALSE;
1165 }
1166 if ((vpp->get_capabilities = (uint64_t (*)(int))dlsym(handle, "get_capabilities")) == NULL) {
1167 OK = FALSE;
1168 }
1169 if ((vpp->render_frame = (boolean(*)(int, int, int64_t, void **, void **, weed_plant_t **))
1170 dlsym(handle, "render_frame")) == NULL) {
1171 if ((vpp->play_frame = (boolean(*)(weed_layer_t *, ticks_t, weed_layer_t *))
1172 dlsym(handle, "play_frame")) == NULL) {
1173 OK = FALSE;
1174 }
1175 }
1176 if ((vpp->get_fps_list = (const char *(*)(int))dlsym(handle, "get_fps_list"))) {
1177 if ((vpp->set_fps = (boolean(*)(double))dlsym(handle, "set_fps")) == NULL) {
1178 OK = FALSE;
1179 }
1180 }
1181
1182 if (!OK) {
1183 char *msg = lives_strdup_printf
1184 (_("\n\nPlayback module %s\nis missing a mandatory function.\nUnable to use it.\n"), plugname);
1186 do_error_dialog(msg);
1187 lives_free(msg);
1188 dlclose(handle);
1189 lives_free(vpp);
1190 vpp = NULL;
1191 lives_free(plugname);
1192 return NULL;
1193 }
1194
1195 if ((pl_error = (*vpp->module_check_init)())) {
1196 msg = lives_strdup_printf(_("Video playback plugin failed to initialise.\nError was: %s\n"), pl_error);
1197 if (prefs->startup_phase != 1 && prefs->startup_phase != -1) {
1198 do_error_dialog(msg);
1199 } else {
1200 LIVES_ERROR(msg);
1201 }
1202 lives_free(msg);
1203 dlclose(handle);
1204 lives_free(vpp);
1205 vpp = NULL;
1206 lives_free(plugname);
1207 return NULL;
1208 }
1209
1210 // now check for optional functions
1211 vpp->weed_setup = (weed_plant_t *(*)(weed_bootstrap_f))dlsym(handle, "weed_setup");
1212
1213 if (vpp->weed_setup) {
1214 weed_set_host_info_callback(host_info_cb, LIVES_INT_TO_POINTER(100));
1215 (*vpp->weed_setup)(weed_bootstrap);
1216 }
1217
1218 vpp->get_description = (const char *(*)())dlsym(handle, "get_description");
1219 vpp->get_init_rfx = (const char *(*)())dlsym(handle, "get_init_rfx");
1220
1221 vpp->get_play_params = (const weed_plant_t **(*)(weed_bootstrap_f))dlsym(handle, "get_play_params");
1222
1223 vpp->get_yuv_palette_clamping = (int *(*)(int))dlsym(handle, "get_yuv_palette_clamping");
1224 vpp->set_yuv_palette_clamping = (int (*)(int))dlsym(handle, "set_yuv_palette_clamping");
1225 vpp->get_audio_fmts = (int *(*)())dlsym(handle, "get_audio_fmts");
1226 vpp->init_screen = (boolean(*)(int, int, boolean, uint64_t, int, char **))dlsym(handle, "init_screen");
1227 vpp->init_audio = (boolean(*)(int, int, int, char **))dlsym(handle, "init_audio");
1228 vpp->render_audio_frame_float = (boolean(*)(float **, int))dlsym(handle, "render_audio_frame_float");
1229 vpp->exit_screen = (void (*)(uint16_t, uint16_t))dlsym(handle, "exit_screen");
1230 vpp->module_unload = (void (*)())dlsym(handle, "module_unload");
1231
1232 vpp->YUV_sampling = 0;
1233 vpp->YUV_subspace = 0;
1234
1235 palette_list = (*vpp->get_palette_list)();
1236
1237 if (future_prefs->vpp_argv) {
1240 } else {
1241 if (!in_use && mainw->vpp && !(strcmp(name, mainw->vpp->name))) {
1242 vpp->palette = mainw->vpp->palette;
1244 } else {
1245 vpp->palette = palette_list[0];
1246 vpp->YUV_clamping = -1;
1247 }
1248 }
1249
1251 vpp->capabilities = (*vpp->get_capabilities)(vpp->palette);
1252
1254 vpp->fwidth = vpp->fheight = -1;
1255 } else {
1256 vpp->fwidth = vpp->fheight = 0;
1257 }
1258 if (future_prefs->vpp_argv) {
1261 } else if (!in_use && mainw->vpp && !(strcmp(name, mainw->vpp->name))) {
1262 vpp->fwidth = mainw->vpp->fwidth;
1263 vpp->fheight = mainw->vpp->fheight;
1264 }
1265 if (vpp->fwidth == -1 && !(vpp->capabilities & VPP_CAN_RESIZE && vpp->capabilities & VPP_LOCAL_DISPLAY)) {
1266 vpp->fwidth = vpp->fheight = 0;
1267 }
1268
1269 vpp->fixed_fpsd = -1.;
1270 vpp->fixed_fps_numer = 0;
1271
1272 if (future_prefs->vpp_argv) {
1276 } else if (!in_use && mainw->vpp && !(strcmp(name, mainw->vpp->name))) {
1277 vpp->fixed_fpsd = mainw->vpp->fixed_fpsd;
1280 }
1281
1282 vpp->handle = handle;
1283 lives_snprintf(vpp->name, 256, "%s", name);
1284
1285 if (future_prefs->vpp_argv) {
1287 vpp->extra_argv = (char **)lives_calloc((vpp->extra_argc + 1), (sizeof(char *)));
1288 for (register int i = 0; i <= vpp->extra_argc; i++) vpp->extra_argv[i] = lives_strdup(future_prefs->vpp_argv[i]);
1289 } else {
1290 if (!in_use && mainw->vpp && !(strcmp(name, mainw->vpp->name))) {
1291 vpp->extra_argc = mainw->vpp->extra_argc;
1292 vpp->extra_argv = (char **)lives_calloc((mainw->vpp->extra_argc + 1), (sizeof(char *)));
1293 for (register int i = 0; i <= vpp->extra_argc; i++) vpp->extra_argv[i] = lives_strdup(mainw->vpp->extra_argv[i]);
1294 } else {
1295 vpp->extra_argc = 0;
1296 vpp->extra_argv = (char **)lives_malloc(sizeof(char *));
1297 vpp->extra_argv[0] = NULL;
1298 }
1299 }
1300 // see if plugin is using fixed fps
1301
1302 if (vpp->fixed_fpsd <= 0. && vpp->get_fps_list) {
1303 // fixed fps
1304
1305 if ((fps_list = (*vpp->get_fps_list)(vpp->palette))) {
1306 array = lives_strsplit(fps_list, "|", -1);
1307 if (get_token_count(array[0], ':') > 1) {
1308 char **array2 = lives_strsplit(array[0], ":", 2);
1309 vpp->fixed_fps_numer = atoi(array2[0]);
1310 vpp->fixed_fps_denom = atoi(array2[1]);
1311 lives_strfreev(array2);
1312 vpp->fixed_fpsd = get_ratio_fps(array[0]);
1313 } else {
1314 vpp->fixed_fpsd = lives_strtod(array[0], NULL);
1315 vpp->fixed_fps_numer = 0;
1316 }
1317 lives_strfreev(array);
1318 }
1319 }
1320
1321 if (vpp->YUV_clamping == -1) {
1322 vpp->YUV_clamping = WEED_YUV_CLAMPING_CLAMPED;
1323
1325 int *yuv_clamping_types = (*vpp->get_yuv_palette_clamping)(vpp->palette);
1326 if (yuv_clamping_types[0] != -1) vpp->YUV_clamping = yuv_clamping_types[0];
1327 }
1328 }
1329
1330 if (vpp->get_audio_fmts && mainw->is_ready) vpp->audio_codec = get_best_audio(vpp);
1331 if (prefsw) {
1334 }
1335
1337 if (vpp->get_play_params) {
1338 vpp->play_paramtmpls = (*vpp->get_play_params)(NULL);
1339 }
1340
1341 // create vpp->play_params
1342 if (vpp->play_paramtmpls) {
1343 register int i;
1344 weed_plant_t *ptmpl;
1345 for (i = 0; (ptmpl = (weed_plant_t *)vpp->play_paramtmpls[i]); i++) {
1346 vpp->play_params = (weed_plant_t **)lives_realloc(vpp->play_params, (i + 2) * sizeof(weed_plant_t *));
1348 // is param template, create a param
1349 vpp->play_params[i] = weed_plant_new(WEED_PLANT_PARAMETER);
1350 weed_leaf_copy(vpp->play_params[i], WEED_LEAF_VALUE, ptmpl, WEED_LEAF_DEFAULT);
1351 weed_set_plantptr_value(vpp->play_params[i], WEED_LEAF_TEMPLATE, ptmpl);
1352 vpp->num_play_params++;
1353 } else {
1354 // must be an alpha channel
1355 vpp->play_params[i] = weed_plant_new(WEED_PLANT_CHANNEL);
1356 weed_set_plantptr_value(vpp->play_params[i], WEED_LEAF_TEMPLATE, ptmpl);
1357 vpp->num_alpha_chans++;
1358 }
1359 }
1360 vpp->play_params[i] = NULL;
1361 }
1362
1363 if (!in_use) return vpp;
1364
1365 if (!mainw->is_ready) {
1366 double fixed_fpsd = vpp->fixed_fpsd;
1367 int fwidth = vpp->fwidth;
1368 int fheight = vpp->fheight;
1369
1370 mainw->vpp = vpp;
1372 if (fixed_fpsd < 0.) vpp->fixed_fpsd = fixed_fpsd;
1373 if (fwidth < 0) vpp->fwidth = fwidth;
1374 if (fheight < 0) vpp->fheight = fheight;
1375 }
1376
1377 if (!(*vpp->set_palette)(vpp->palette)) {
1380 lives_free(plugname);
1381 return NULL;
1382 }
1383
1385
1386 if (vpp->get_fps_list) {
1387 if (mainw->fixed_fpsd > 0. || (vpp->fixed_fpsd > 0. && vpp->set_fps &&
1388 !((*vpp->set_fps)(vpp->fixed_fpsd)))) {
1390 vpp->fixed_fpsd = -1.;
1391 vpp->fixed_fps_numer = 0;
1392 }
1393 }
1394
1395 cached_key = cached_mod = 0;
1396
1397 // TODO: - support other YUV subspaces
1398 d_print(_("*** Using %s plugin for fs playback, agreed to use palette type %d ( %s ). ***\n"), name,
1400 WEED_YUV_SUBSPACE_YCBCR)));
1401 lives_free(tmp);
1402
1403 lives_free(plugname);
1404
1405 if (mainw->is_ready && in_use && mainw->vpp) {
1407 }
1408
1409 return vpp;
1410}
1411
1412
1414 // external plugin
1415 if (mainw->ext_playback) {
1416 pthread_mutex_lock(&mainw->vpp_stream_mutex);
1418 pthread_mutex_unlock(&mainw->vpp_stream_mutex);
1420
1421 if (mainw->vpp->exit_screen) {
1423 }
1424#ifdef RT_AUDIO
1426#endif
1429 if (mainw->play_window && prefs->play_monitor == 0)
1431 }
1432 mainw->stream_ticks = -1;
1433
1435 if (mainw->play_window) {
1437 }
1438}
1439
1440
1442 // find best audio from video plugin list, matching with audiostream plugins
1443
1444 // i.e. cross-check video list with astreamer list
1445
1446 // only for plugins which want to stream audiom but dont provide a render_audio_frame()
1447
1448 int *fmts, *sfmts;
1449 int ret = AUDIO_CODEC_NONE;
1450 int i, j = 0, nfmts;
1451 char *astreamer, *com;
1452 char buf[1024];
1453 char **array;
1454
1455 if (vpp && vpp->get_audio_fmts) {
1456 fmts = (*vpp->get_audio_fmts)(); // const, so do not free()
1457
1458 // make audiostream plugin name
1459 astreamer = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_AUDIO_STREAM, AUDIO_STREAMER_NAME, NULL);
1460
1461 // create sfmts array and nfmts
1462
1463 com = lives_strdup_printf("\"%s\" get_formats", astreamer);
1464 lives_popen(com, FALSE, buf, 1024);
1465 lives_free(com);
1466
1467 nfmts = get_token_count(buf, '|');
1468 array = lives_strsplit(buf, "|", nfmts);
1469 sfmts = (int *)lives_calloc(nfmts, sizint);
1470
1471 for (i = 0; i < nfmts; i++) {
1472 if (array[i] && *array[i]) sfmts[j++] = atoi(array[i]);
1473 }
1474
1475 nfmts = j;
1476 lives_strfreev(array);
1477
1478 for (i = 0; fmts[i] != -1; i++) {
1479 // traverse video list and see if audiostreamer supports each one
1480 if (int_array_contains_value(sfmts, nfmts, fmts[i])) {
1481
1482 com = lives_strdup_printf("\"%s\" check %d", astreamer, fmts[i]);
1483 lives_popen(com, FALSE, buf, 1024);
1484 lives_free(com);
1485
1486 if (THREADVAR(com_failed)) {
1487 lives_free(astreamer);
1488 lives_free(com);
1489 lives_free(sfmts);
1490 return ret;
1491 }
1492
1493 if (*buf) {
1494 if (i == 0 && prefsw) {
1495 do_error_dialog(buf);
1496 d_print(_("Audio stream unable to use preferred format '%s'\n"), anames[fmts[i]]);
1497 }
1498 continue;
1499 }
1500
1501 if (i > 0 && prefsw) {
1502 d_print(_("Using format '%s' instead.\n"), anames[fmts[i]]);
1503 }
1504 ret = fmts[i];
1505 break;
1506 }
1507 }
1508
1509 if (fmts[i] == -1) {
1510 //none suitable, stick with first
1511 for (i = 0; fmts[i] != -1; i++) {
1512 // traverse video list and see if audiostreamer supports each one
1513 if (int_array_contains_value(sfmts, nfmts, fmts[i])) {
1514 ret = fmts[i];
1515 break;
1516 }
1517 }
1518 }
1519
1520 lives_free(sfmts);
1521 lives_free(astreamer);
1522 }
1523
1524 return ret;
1525}
1526
1527
1529// encoder plugins
1530
1531void do_plugin_encoder_error(const char *plugin_name) {
1532 char *msg, *tmp;
1533
1534 if (!plugin_name) {
1535 msg = lives_strdup_printf(
1536 _("LiVES was unable to find its encoder plugins. Please make sure you have the plugins installed in\n"
1537 "%s%s%s\nor change the value of <lib_dir> in %s\n"),
1539 (tmp = lives_filename_to_utf8(prefs->configfile, -1, NULL, NULL, NULL)));
1540 lives_free(tmp);
1542 do_error_dialog(msg);
1543 lives_free(msg);
1544 return;
1545 }
1546
1547 msg = lives_strdup_printf(
1548 _("LiVES did not receive a response from the encoder plugin called '%s'.\n"
1549 "Please make sure you have that plugin installed correctly in\n%s%s%s\n"
1550 "or switch to another plugin using Tools|Preferences|Encoding\n"),
1552 do_error_dialog(msg);
1553 lives_free(msg);
1554}
1555
1556
1557boolean check_encoder_restrictions(boolean get_extension, boolean user_audio, boolean save_all) {
1558 LiVESList *ofmt_all = NULL;
1559 char **checks;
1560 char **array = NULL;
1561 char **array2;
1562 char aspect_buffer[512];
1563
1564 // for auto resizing/resampling
1565 double best_fps = 0.;
1566 double fps;
1567 double best_fps_delta = 0.;
1568
1569 boolean sizer = FALSE;
1570 boolean allow_aspect_override = FALSE;
1571 boolean calc_aspect = FALSE;
1572 boolean swap_endian = FALSE;
1573
1574 int best_arate = 0;
1575 int width, owidth;
1576 int height, oheight;
1577 int best_arate_delta = 0;
1578 int hblock = 2, vblock = 2;
1579 int i, r, val;
1580 int pieces, numtok;
1581 int best_fps_num = 0, best_fps_denom = 0;
1582 int arate, achans, asampsize, asigned = 0;
1583
1584 if (!rdet) {
1585 width = owidth = cfile->hsize;
1586 height = oheight = cfile->vsize;
1587 fps = cfile->fps;
1588 } else {
1589 width = owidth = rdet->width;
1590 height = oheight = rdet->height;
1591 fps = rdet->fps;
1593 }
1594
1595 if (mainw->osc_auto) {
1596 if (mainw->osc_enc_width > 0) {
1597 width = mainw->osc_enc_width;
1598 height = mainw->osc_enc_height;
1599 }
1600 if (mainw->osc_enc_fps != 0.) fps = mainw->osc_enc_fps;
1601 }
1602
1603 // TODO - allow lists for size
1604 lives_snprintf(prefs->encoder.of_restrict, 5, "none");
1605 if ((ofmt_all = plugin_request_by_line(PLUGIN_ENCODERS, prefs->encoder.name, "get_formats"))) {
1606 // get any restrictions for the current format
1607 for (i = 0; i < lives_list_length(ofmt_all); i++) {
1608 if ((numtok = get_token_count((char *)lives_list_nth_data(ofmt_all, i), '|')) > 2) {
1609 array = lives_strsplit((char *)lives_list_nth_data(ofmt_all, i), "|", -1);
1610 if (!strcmp(array[0], prefs->encoder.of_name)) {
1611 if (numtok > 5) {
1612 lives_snprintf(prefs->encoder.ptext, 512, "%s", array[5]);
1613 } else {
1615 }
1616 if (numtok > 4) {
1617 lives_snprintf(prefs->encoder.of_def_ext, 16, "%s", array[4]);
1618 } else {
1620 }
1621 if (numtok > 3) {
1622 lives_snprintf(prefs->encoder.of_restrict, 128, "%s", array[3]);
1623 } else {
1624 lives_snprintf(prefs->encoder.of_restrict, 128, "none");
1625 }
1626 prefs->encoder.of_allowed_acodecs = atoi(array[2]);
1627 lives_list_free_all(&ofmt_all);
1628 lives_strfreev(array);
1629 break;
1630 }
1631 lives_strfreev(array);
1632 }
1633 }
1634 }
1635
1636 if (get_extension) {
1637 return TRUE; // just wanted file extension
1638 }
1639
1643 return FALSE;
1644 }
1645 }
1646
1647 if (user_audio && future_prefs->encoder.of_allowed_acodecs == 0) best_arate = -1;
1648
1649 if ((!*prefs->encoder.of_restrict || !strcmp(prefs->encoder.of_restrict, "none")) && best_arate > -1) {
1650 return TRUE;
1651 }
1652
1653 if (!rdet) {
1654 arate = cfile->arate;
1655 achans = cfile->achans;
1656 asampsize = cfile->asampsize;
1657 } else {
1658 arate = rdet->arate;
1659 achans = rdet->achans;
1660 asampsize = rdet->asamps;
1661 }
1662
1663 // audio endianness check - what should we do for big-endian machines ?
1666 && prefs->encoder.audio_codec != AUDIO_CODEC_NONE && arate != 0 && achans != 0 && asampsize != 0) {
1667 if (rdet && !rdet->is_encoding) {
1669 swap_endian = TRUE;
1670 } else {
1671 if (mainw->endian != AFORM_BIG_ENDIAN && (cfile->signed_endian & AFORM_BIG_ENDIAN)) swap_endian = TRUE;
1672 //if (mainw->endian==AFORM_BIG_ENDIAN && (cfile->signed_endian&AFORM_BIG_ENDIAN)) swap_endian=TRUE; // needs test
1673 }
1674 }
1675
1676 if (*prefs->encoder.of_restrict) {
1677 pieces = get_token_count(prefs->encoder.of_restrict, ',');
1678 checks = lives_strsplit(prefs->encoder.of_restrict, ",", pieces);
1679
1680 for (r = 0; r < pieces; r++) {
1681 // check each restriction in turn
1682
1683 if (!strncmp(checks[r], "fps=", 4)) {
1684 double allowed_fps;
1685 int mbest_num = 0, mbest_denom = 0;
1686 int numparts;
1687 char *fixer;
1688
1689 best_fps_delta = 1000000000.;
1690 array = lives_strsplit(checks[r], "=", 2);
1691 numtok = get_token_count(array[1], ';');
1692 array2 = lives_strsplit(array[1], ";", numtok);
1693 for (i = 0; i < numtok; i++) {
1694 mbest_num = mbest_denom = 0;
1695 if ((numparts = get_token_count(array2[i], ':')) > 1) {
1696 char **array3 = lives_strsplit(array2[i], ":", 2);
1697 mbest_num = atoi(array3[0]);
1698 mbest_denom = atoi(array3[1]);
1699 lives_strfreev(array3);
1700 if (mbest_denom == 0) continue;
1701 allowed_fps = (mbest_num * 1.) / (mbest_denom * 1.);
1702 } else allowed_fps = lives_strtod(array2[i], NULL);
1703
1704 // convert to 8dp
1705 fixer = lives_strdup_printf("%.8f %.8f", allowed_fps, fps);
1706 lives_free(fixer);
1707
1708 if (allowed_fps >= fps) {
1709 if (allowed_fps - fps < best_fps_delta) {
1710 best_fps_delta = allowed_fps - fps;
1711 if (mbest_denom > 0) {
1712 best_fps_num = mbest_num;
1713 best_fps_denom = mbest_denom;
1714 best_fps = 0.;
1715 if (!rdet) cfile->ratio_fps = TRUE;
1716 else rdet->ratio_fps = TRUE;
1717 } else {
1718 best_fps_num = best_fps_denom = 0;
1719 best_fps = allowed_fps;
1720 if (!rdet) cfile->ratio_fps = FALSE;
1721 else rdet->ratio_fps = FALSE;
1722 }
1723 }
1724 } else if ((best_fps_denom == 0 && allowed_fps > best_fps) || (best_fps_denom > 0
1725 && allowed_fps > (best_fps_num * 1.) /
1726 (best_fps_denom * 1.))) {
1727 best_fps_delta = fps - allowed_fps;
1728 if (mbest_denom > 0) {
1729 best_fps_num = mbest_num;
1730 best_fps_denom = mbest_denom;
1731 best_fps = 0.;
1732 if (!rdet) cfile->ratio_fps = TRUE;
1733 else rdet->ratio_fps = TRUE;
1734 } else {
1735 best_fps = allowed_fps;
1736 best_fps_num = best_fps_denom = 0;
1737 if (!rdet) cfile->ratio_fps = FALSE;
1738 else rdet->ratio_fps = FALSE;
1739 }
1740 }
1741 if (best_fps_delta <= prefs->fps_tolerance) {
1742 best_fps_delta = 0.;
1743 best_fps_denom = best_fps_num = 0;
1744 }
1745 if (best_fps_delta == 0.) break;
1746 }
1747 lives_strfreev(array);
1748 lives_strfreev(array2);
1749 continue;
1750 }
1751
1752 if (!strncmp(checks[r], "size=", 5)) {
1753 // TODO - allow list for size
1754 array = lives_strsplit(checks[r], "=", 2);
1755 array2 = lives_strsplit(array[1], "x", 2);
1756 width = atoi(array2[0]);
1757 height = atoi(array2[1]);
1758 lives_strfreev(array2);
1759 lives_strfreev(array);
1760 sizer = TRUE;
1761 continue;
1762 }
1763
1764 if (!strncmp(checks[r], "minw=", 5)) {
1765 array = lives_strsplit(checks[r], "=", 2);
1766 val = atoi(array[1]);
1767 if (width < val) width = val;
1768 lives_strfreev(array);
1769 continue;
1770 }
1771
1772 if (!strncmp(checks[r], "minh=", 5)) {
1773 array = lives_strsplit(checks[r], "=", 2);
1774 val = atoi(array[1]);
1775 if (height < val) height = val;
1776 lives_strfreev(array);
1777 continue;
1778 }
1779
1780 if (!strncmp(checks[r], "maxh=", 5)) {
1781 array = lives_strsplit(checks[r], "=", 2);
1782 val = atoi(array[1]);
1783 if (height > val) height = val;
1784 lives_strfreev(array);
1785 continue;
1786 }
1787
1788 if (!strncmp(checks[r], "maxw=", 5)) {
1789 array = lives_strsplit(checks[r], "=", 2);
1790 val = atoi(array[1]);
1791 if (width > val) width = val;
1792 lives_strfreev(array);
1793 continue;
1794 }
1795
1796 if (!strncmp(checks[r], "asigned=", 8) &&
1797 ((mainw->save_with_sound || rdet) && (!resaudw ||
1800 (LIVES_TOGGLE_BUTTON(resaudw->aud_checkbutton)))) &&
1802 && arate != 0 && achans != 0 && asampsize != 0) {
1803 array = lives_strsplit(checks[r], "=", 2);
1804 if (!strcmp(array[1], "signed")) {
1805 asigned = 1;
1806 }
1807
1808 if (!strcmp(array[1], "unsigned")) {
1809 asigned = 2;
1810 }
1811
1812 lives_strfreev(array);
1813
1814 if (asigned != 0 && !capable->has_sox_sox) {
1816 lives_strfreev(checks);
1817 return FALSE;
1818 }
1819 continue;
1820 }
1821
1822 if (!strncmp(checks[r], "arate=", 6) && ((mainw->save_with_sound || rdet) && (!resaudw ||
1825 (LIVES_TOGGLE_BUTTON
1826 (resaudw->aud_checkbutton)))) &&
1827 prefs->encoder.audio_codec != AUDIO_CODEC_NONE && arate != 0 && achans != 0 && asampsize != 0) {
1828 // we only perform this test if we are encoding with audio
1829 // find next highest allowed rate from list,
1830 // if none are higher, use the highest
1831 int allowed_arate;
1832 best_arate_delta = 1000000000;
1833
1834 array = lives_strsplit(checks[r], "=", 2);
1835 numtok = get_token_count(array[1], ';');
1836 array2 = lives_strsplit(array[1], ";", numtok);
1837 for (i = 0; i < numtok; i++) {
1838 allowed_arate = atoi(array2[i]);
1839 if (allowed_arate >= arate) {
1840 if (allowed_arate - arate < best_arate_delta) {
1841 best_arate_delta = allowed_arate - arate;
1842 best_arate = allowed_arate;
1843 }
1844 } else if (allowed_arate > best_arate) best_arate = allowed_arate;
1845 }
1846 lives_strfreev(array2);
1847 lives_strfreev(array);
1848
1849 if (!capable->has_sox_sox) {
1851 lives_strfreev(checks);
1852 return FALSE;
1853 }
1854 continue;
1855 }
1856
1857 if (!strncmp(checks[r], "hblock=", 7)) {
1858 // width must be a multiple of this
1859 array = lives_strsplit(checks[r], "=", 2);
1860 hblock = atoi(array[1]);
1861 width = (int)(width / hblock + .5) * hblock;
1862 lives_strfreev(array);
1863 continue;
1864 }
1865
1866 if (!strncmp(checks[r], "vblock=", 7)) {
1867 // height must be a multiple of this
1868 array = lives_strsplit(checks[r], "=", 2);
1869 vblock = atoi(array[1]);
1870 height = (int)(height / vblock + .5) * vblock;
1871 lives_strfreev(array);
1872 continue;
1873 }
1874
1875 if (!strncmp(checks[r], "aspect=", 7)) {
1876 // we calculate the nearest smaller frame size using aspect,
1877 // hblock and vblock
1878 calc_aspect = TRUE;
1879 array = lives_strsplit(checks[r], "=", 2);
1880 lives_snprintf(aspect_buffer, 512, "%s", array[1]);
1881 lives_strfreev(array);
1882 continue;
1883 }
1884 }
1885
1887 lives_strfreev(checks);
1888
1889 if (!mainw->osc_auto && calc_aspect && !sizer) {
1890 // we calculate this last, after getting hblock and vblock sizes
1891 char **array3;
1892 double allowed_aspect;
1893 int xwidth = width;
1894 int xheight = height;
1895
1896 width = height = 1000000;
1897
1898 numtok = get_token_count(aspect_buffer, ';');
1899 array2 = lives_strsplit(aspect_buffer, ";", numtok);
1900
1901 // see if we can get a width:height which is nearer an aspect than
1902 // current width:height
1903
1904 for (i = 0; i < numtok; i++) {
1905 array3 = lives_strsplit(array2[i], ":", 2);
1906 allowed_aspect = lives_strtod(array3[0], NULL) / lives_strtod(array3[1], NULL);
1907 lives_strfreev(array3);
1908 minimise_aspect_delta(allowed_aspect, hblock, vblock, xwidth, xheight, &width, &height);
1909 }
1910 lives_strfreev(array2);
1911
1912 // allow override if current width and height are integer multiples of blocks
1913 if (owidth % hblock == 0 && oheight % vblock == 0) allow_aspect_override = TRUE;
1914
1915 // end recheck
1916 }
1917
1918 // fps can't be altered if we have a multitrack event_list
1919 if (mainw->multitrack && mainw->multitrack->event_list) best_fps_delta = 0.;
1920
1921 if (sizer) allow_aspect_override = FALSE;
1922 }
1923
1924 // if we have min or max size, make sure we fit within that
1925
1926 if (((width != owidth || height != oheight) && width * height > 0) || (best_fps_delta > 0.) || (best_arate_delta > 0 &&
1927 best_arate > 0) ||
1928 best_arate < 0 || asigned != 0 || swap_endian) {
1929 boolean ofx1_bool = mainw->fx1_bool;
1930 mainw->fx1_bool = FALSE;
1931 if ((width != owidth || height != oheight) && width * height > 0) {
1933 if (allow_aspect_override) {
1934 width = owidth;
1935 height = oheight;
1936 }
1937 }
1938 }
1939 if (rdet && !rdet->is_encoding) {
1940 rdet->arate = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_arate)));
1941 rdet->achans = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_achans)));
1942 rdet->asamps = (int)atoi(lives_entry_get_text(LIVES_ENTRY(resaudw->entry_asamps)));
1944 lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(resaudw->rb_littleend)));
1945
1946 if (swap_endian || width != rdet->width || height != rdet->height || best_fps_delta != 0. || best_arate != rdet->arate ||
1947 ((asigned == 1 && (rdet->aendian & AFORM_UNSIGNED)) || (asigned == 2 && !(rdet->aendian & AFORM_SIGNED)))) {
1948
1949 if (rdet_suggest_values(width, height, best_fps, best_fps_num, best_fps_denom, best_arate, asigned, swap_endian,
1950 allow_aspect_override, (best_fps_delta == 0.))) {
1951 char *arate_string;
1952 rdet->width = width;
1953 rdet->height = height;
1954 if (best_arate != -1) rdet->arate = best_arate;
1955 else lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->aud_checkbutton), FALSE);
1956
1957 if (asigned == 1) lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_signed), TRUE);
1958 else if (asigned == 2) lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_unsigned), TRUE);
1959
1960 if (swap_endian) {
1961 if (!lives_toggle_button_get_active(LIVES_TOGGLE_BUTTON(resaudw->rb_bigend)))
1962 lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_bigend), TRUE);
1963 else lives_toggle_button_set_active(LIVES_TOGGLE_BUTTON(resaudw->rb_littleend), TRUE);
1964 }
1965
1966 if (best_fps_delta > 0.) {
1967 if (best_fps_denom > 0) {
1968 rdet->fps = (best_fps_num * 1.) / (best_fps_denom * 1.);
1969 } else rdet->fps = best_fps;
1971 }
1974 if (best_arate != -1) {
1975 arate_string = lives_strdup_printf("%d", best_arate);
1976 lives_entry_set_text(LIVES_ENTRY(resaudw->entry_arate), arate_string);
1977 lives_free(arate_string);
1978 }
1980 return TRUE;
1981 }
1982 }
1983 return FALSE;
1984 }
1985
1986 if (mainw->osc_auto || do_encoder_restrict_dialog(width, height, best_fps, best_fps_num, best_fps_denom, best_arate,
1987 asigned, swap_endian, allow_aspect_override, save_all)) {
1988 if (!mainw->fx1_bool && mainw->osc_enc_width == 0) {
1989 width = owidth;
1990 height = oheight;
1991 }
1992
1993 if (!auto_resample_resize(width, height, best_fps, best_fps_num, best_fps_denom, best_arate, asigned, swap_endian)) {
1994 mainw->fx1_bool = ofx1_bool;
1995 return FALSE;
1996 }
1997 } else {
1998 mainw->fx1_bool = ofx1_bool;
1999 return FALSE;
2000 }
2001 }
2002 return TRUE;
2003}
2004
2005
2006LiVESList *filter_encoders_by_img_ext(LiVESList * encoders, const char *img_ext) {
2007 LiVESList *encoder_capabilities = NULL;
2008 LiVESList *list = encoders, *listnext;
2009 int caps;
2010
2011 register int i;
2012
2013 char *blacklist[] = {
2014 NULL,
2015 NULL
2016 };
2017
2018 // something broke as of python 2.7.2, and python 3 files now just hang
2019 if (capable->python_version < 3000000) blacklist[0] = lives_strdup("multi_encoder3");
2020
2021 while (list) {
2022 boolean skip = FALSE;
2023 i = 0;
2024
2025 listnext = list->next;
2026
2027 while (blacklist[i]) {
2028 if (!strcmp((const char *)list->data, blacklist[i])) {
2029 // skip blacklisted encoders
2030 lives_free((livespointer)list->data);
2031 encoders = lives_list_delete_link(encoders, list);
2032 skip = TRUE;
2033 break;
2034 }
2035 i++;
2036 }
2037 if (skip) {
2038 list = listnext;
2039 continue;
2040 }
2041
2042 if (!strcmp(img_ext, LIVES_FILE_EXT_JPG)) {
2043 list = listnext;
2044 continue;
2045 }
2046
2047 if ((encoder_capabilities = plugin_request(PLUGIN_ENCODERS, (char *)list->data, "get_capabilities")) == NULL) {
2048 lives_free((livespointer)list->data);
2049 encoders = lives_list_delete_link(encoders, list);
2050 } else {
2051 caps = atoi((char *)lives_list_nth_data(encoder_capabilities, 0));
2052 if (!(caps & CAN_ENCODE_PNG) && !strcmp(img_ext, LIVES_FILE_EXT_PNG)) {
2053 lives_free((livespointer)list->data);
2054 encoders = lives_list_delete_link(encoders, list);
2055 }
2056
2057 lives_list_free_all(&encoder_capabilities);
2058 }
2059
2060 list = listnext;
2061 }
2062
2063 for (i = 0; blacklist[i]; i++) lives_free(blacklist[i]);
2064
2065 return encoders;
2066}
2067
2068
2070// decoder plugins
2071
2072boolean decoder_plugin_move_to_first(const char *name) {
2073 LiVESList *decoder_plugin, *last_decoder_plugin = NULL;
2074 decoder_plugin = mainw->decoder_list;
2075 while (decoder_plugin) {
2076 if (!strcmp((const char *)(decoder_plugin->data), name)) {
2077 if (last_decoder_plugin) {
2078 last_decoder_plugin->next = decoder_plugin->next;
2079 decoder_plugin->next = mainw->decoder_list;
2080 mainw->decoder_list = decoder_plugin;
2081 }
2082 return TRUE;
2083 }
2084 last_decoder_plugin = decoder_plugin;
2085 decoder_plugin = decoder_plugin->next;
2086 }
2087 return FALSE;
2088}
2089
2090
2091
2092LiVESList *load_decoders(void) {
2093 lives_decoder_sys_t *dplug;
2094 char *decplugdir = lives_strdup_printf("%s%s%s", prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_DECODERS);
2095 LiVESList *dlist = NULL;
2096 LiVESList *decoder_plugins_o = get_plugin_list(PLUGIN_DECODERS, TRUE, decplugdir, "-" DLL_NAME);
2097 LiVESList *decoder_plugins = decoder_plugins_o;
2098
2099 char *blacklist[3] = {
2100 "zyavformat_decoder",
2101 "ogg_theora_decoder",
2102 NULL
2103 };
2104
2105 const char *dplugname;
2106 boolean skip;
2107
2108 register int i;
2109
2110 while (decoder_plugins) {
2111 skip = FALSE;
2112 dplugname = (const char *)(decoder_plugins->data);
2113 for (i = 0; blacklist[i]; i++) {
2114 if (!strcmp(dplugname, blacklist[i])) {
2115 // skip blacklisted decoders
2116 skip = TRUE;
2117 break;
2118 }
2119 }
2120 if (!skip) {
2121 dplug = open_decoder_plugin((char *)decoder_plugins->data);
2122 if (dplug) dlist = lives_list_append(dlist, (livespointer)dplug);
2123 }
2124 lives_free((livespointer)decoder_plugins->data);
2125 decoder_plugins = decoder_plugins->next;
2126 }
2127
2128 lives_list_free(decoder_plugins_o);
2129
2130 if (!dlist) {
2131 char *msg = lives_strdup_printf(_("\n\nNo decoders found in %s !\n"), decplugdir);
2132 LIVES_WARN(msg);
2133 d_print(msg);
2134 lives_free(msg);
2135 }
2136
2137 lives_free(decplugdir);
2138 return dlist;
2139}
2140
2141
2142static void set_cdata_memfuncs(lives_clip_data_t *cdata) {
2143 // set specific memory functions for decoder plugins to use
2144 static malloc_f ext_malloc = (malloc_f) _ext_malloc;
2145 static free_f ext_free = (free_f) _ext_free;
2146 static memcpy_f ext_memcpy = (memcpy_f) _ext_memcpy;
2147 static memset_f ext_memset = (memset_f) _ext_memset;
2148 static memmove_f ext_memmove = (memmove_f) _ext_memmove;
2149 static realloc_f ext_realloc = (realloc_f) _ext_realloc;
2150 static calloc_f ext_calloc = (calloc_f) _ext_calloc;
2151 if (!cdata) return;
2152 cdata->ext_malloc = &ext_malloc;
2153 cdata->ext_free = &ext_free;
2154 cdata->ext_memcpy = &ext_memcpy;
2155 cdata->ext_memset = &ext_memset;
2156 cdata->ext_memmove = &ext_memmove;
2157 cdata->ext_realloc = &ext_realloc;
2158 cdata->ext_calloc = &ext_calloc;
2159}
2160
2161
2162static boolean sanity_check_cdata(lives_clip_data_t *cdata) {
2163 if (cdata->nframes <= 0 || cdata->nframes >= INT_MAX) {
2164 return FALSE;
2165 }
2166
2167 // no usable palettes found
2168 if (cdata->palettes[0] == WEED_PALETTE_END) return FALSE;
2169
2170 // all checks passed - OK
2171 return TRUE;
2172}
2173
2174
2175typedef struct {
2176 LiVESList *disabled;
2177 lives_decoder_t *dplug;
2178 lives_clip_t *sfile;
2179} tdp_data;
2180
2182 lives_decoder_t *dplug;
2183 const lives_decoder_sys_t *dpsys;
2184 lives_clip_data_t *cdata;
2185
2186 if (!mainw->files[fileno] || !mainw->files[fileno]->ext_src) return NULL;
2187
2188 cdata = ((lives_decoder_sys_t *)((lives_decoder_t *)mainw->files[fileno]->ext_src)->decoder)->get_clip_data
2189 (NULL, ((lives_decoder_t *)mainw->files[fileno]->ext_src)->cdata);
2190
2191 if (!cdata) return NULL;
2192
2193 dplug = (lives_decoder_t *)lives_calloc(1, sizeof(lives_decoder_t));
2194 dpsys = ((lives_decoder_t *)mainw->files[fileno]->ext_src)->decoder;
2195
2196 dplug->decoder = dpsys;
2197 dplug->cdata = cdata;
2198 dplug->refs = 1;
2199 set_cdata_memfuncs((lives_clip_data_t *)cdata);
2200 cdata->rec_rowstrides = NULL;
2201 return dplug;
2202}
2203
2204
2205static lives_decoder_t *try_decoder_plugins(char *file_name, LiVESList * disabled, const lives_clip_data_t *fake_cdata) {
2206 // here we test each decoder in turn to see if it can open "file_name"
2207
2208 // if we are reopening a clip, then fake cdata is a partially initialised cdata, but with only the frame count and fps set
2209 // this allows the decoder plugins to startup quicker as they don't have to seek to the last frame or calculate the fps.
2210
2211 // we pass this to each decoder in turn and check what it returns. If the values look sane then we use that decoder,
2212 // otherwise we try the next one.
2213
2214 // when reloading clips we try the decoder which last opened them first, othwerwise they could get picked up by another
2215 // decoder and the frames could come out different
2216
2218 LiVESList *decoder_plugin = mainw->decoder_list;
2219 //LiVESList *last_decoder_plugin = NULL;
2220
2221 dplug->refs = 1;
2222
2223 if (fake_cdata) {
2224 set_cdata_memfuncs((lives_clip_data_t *)fake_cdata);
2225 //if (prefs->vj_mode) {
2226 ((lives_clip_data_t *)fake_cdata)->seek_flag = LIVES_SEEK_FAST;
2227 //}
2228 }
2229
2230 while (decoder_plugin) {
2231 lives_decoder_sys_t *dpsys = (lives_decoder_sys_t *)decoder_plugin->data;
2232 if (lives_list_strcmp_index(disabled, dpsys->name, FALSE) != -1) {
2233 // check if (user) disabled this decoder
2234 decoder_plugin = decoder_plugin->next;
2235 continue;
2236 }
2237
2238 //#define DEBUG_DECPLUG
2239#ifdef DEBUG_DECPLUG
2240 g_print("trying decoder %s\n", dpsys->name);
2241#endif
2242
2243 dplug->cdata = (dpsys->get_clip_data)(file_name, fake_cdata);
2244
2245 if (dplug->cdata) {
2246 // check for sanity
2247 //g_print("Checking return data from %s\n", dpsys->name);
2249 &dplug->cdata->lsd)) {
2250 g_printerr("Error in cdata received from decoder plugin:\n%s\nAborting.", dpsys->name);
2251 abort();
2252 }
2253 if (!sanity_check_cdata(dplug->cdata)) {
2254 //last_decoder_plugin = decoder_plugin;
2255 decoder_plugin = decoder_plugin->next;
2256 continue;
2257 }
2258 set_cdata_memfuncs(dplug->cdata);
2260
2261 dplug->decoder = dpsys;
2262
2263 /* if (strncmp(dpsys->name, "zz", 2)) { */
2264 /* // if libav decoder opened us, move it to the first, since it can save time */
2265 /* if (last_decoder_plugin) { */
2266 /* last_decoder_plugin->next = decoder_plugin->next; */
2267 /* decoder_plugin->next = mainw->decoder_list; */
2268 /* mainw->decoder_list = decoder_plugin; */
2269 /* } */
2270 break;
2271 }
2272 //last_decoder_plugin = decoder_plugin;
2273 decoder_plugin = decoder_plugin->next;
2274 }
2275
2276 if (!decoder_plugin) {
2277 lives_freep((void **)&dplug);
2278 } else {
2279 dplug->cdata->rec_rowstrides = NULL;
2280 }
2281
2282 return dplug;
2283}
2284
2285
2286const lives_clip_data_t *get_decoder_cdata(int fileno, LiVESList * disabled, const lives_clip_data_t *fake_cdata) {
2287 // pass file to each decoder (demuxer) plugin in turn, until we find one that can parse
2288 // the file
2289 // NULL is returned if no decoder plugin recognises the file - then we
2290 // fall back to other methods
2291
2292 // otherwise we return data for the clip as supplied by the decoder plugin
2293
2294 // If the file does not exist, we set mainw->error=TRUE and return NULL
2295
2296 // If we find a plugin we also set sfile->ext_src to point to a newly created decoder_plugin_t
2297
2298 lives_decoder_t *dplug;
2299
2300 LiVESList *xdisabled;
2301
2302 lives_clip_t *sfile = mainw->files[fileno];
2303
2304 char decplugname[PATH_MAX];
2305
2306 mainw->error = FALSE;
2307
2308 if (!lives_file_test(sfile->file_name, LIVES_FILE_TEST_EXISTS)) {
2309 mainw->error = TRUE;
2310 return NULL;
2311 }
2312
2313 lives_memset(decplugname, 0, 1);
2314
2315 // check sfile->file_name against each decoder plugin,
2316 // until we get non-NULL cdata
2317
2318 sfile->ext_src = NULL;
2320
2322
2323 xdisabled = lives_list_copy(disabled);
2324
2325 if (fake_cdata) {
2326 get_clip_value(fileno, CLIP_DETAILS_DECODER_NAME, decplugname, PATH_MAX);
2327 if (*decplugname) {
2328 LiVESList *decoder_plugin = mainw->decoder_list;
2329 xdisabled = lives_list_remove(xdisabled, decplugname);
2330 while (decoder_plugin) {
2331 lives_decoder_sys_t *dpsys = (lives_decoder_sys_t *)decoder_plugin->data;
2332 if (!strcmp(dpsys->name, decplugname)) {
2334 break;
2335 }
2336 decoder_plugin = decoder_plugin->next;
2337 }
2338 }
2339 }
2340
2342 dplug = try_decoder_plugins(fake_cdata == NULL ? sfile->file_name : NULL, xdisabled, fake_cdata);
2343
2344 if (xdisabled) lives_list_free(xdisabled);
2345
2347
2348 if (dplug) {
2349 d_print(_(" using %s"), dplug->decoder->version());
2350 sfile->ext_src = dplug;
2352 return dplug->cdata;
2353 }
2354
2355 if (dplug) return dplug->cdata;
2356 return NULL;
2357}
2358
2359
2360// close one instance of dplug
2362 lives_clip_data_t *cdata;
2363
2364 if (!dplug) return;
2365
2366 dplug->refs--;
2367 if (dplug->refs) return;
2368
2369 cdata = dplug->cdata;
2370
2371 if (cdata) {
2372 if (cdata->rec_rowstrides) {
2373 lives_free(cdata->rec_rowstrides);
2374 cdata->rec_rowstrides = NULL;
2375 }
2376 (*dplug->decoder->clip_data_free)(cdata);
2377 }
2378 lives_free(dplug);
2379}
2380
2381
2382void close_clip_decoder(int clipno) {
2383 if (!IS_VALID_CLIP(clipno)) return;
2384 else {
2385 lives_clip_t *sfile = mainw->files[clipno];
2386 if (sfile->ext_src && sfile->ext_src_type == LIVES_EXT_SRC_DECODER) {
2387 char *cwd = lives_get_current_dir();
2388 char *ppath = lives_build_filename(prefs->workdir, sfile->handle, NULL);
2389 lives_chdir(ppath, FALSE);
2390 lives_free(ppath);
2392 sfile->ext_src = NULL;
2394 lives_chdir(cwd, FALSE);
2395 lives_free(cwd);
2396 }
2397 }
2398}
2399
2400
2401static void unload_decoder_plugin(lives_decoder_sys_t *dplug) {
2402 if (dplug->module_unload)(*dplug->module_unload)();
2403
2404 lives_freep((void **)&dplug->name);
2405
2406 dlclose(dplug->handle);
2407 lives_free(dplug);
2408}
2409
2410
2412 LiVESList *dplugs = mainw->decoder_list;
2413
2414 while (dplugs) {
2415 unload_decoder_plugin((lives_decoder_sys_t *)dplugs->data);
2416 dplugs = dplugs->next;
2417 }
2418
2419 lives_list_free(mainw->decoder_list);
2420 mainw->decoder_list = NULL;
2422}
2423
2424
2425boolean chill_decoder_plugin(int fileno) {
2426 lives_clip_t *sfile = mainw->files[fileno];
2427 if (IS_NORMAL_CLIP(fileno) && sfile->clip_type == CLIP_TYPE_FILE && sfile->ext_src) {
2428 lives_decoder_t *dplug = (lives_decoder_t *)sfile->ext_src;
2430 lives_clip_data_t *cdata = dplug->cdata;
2431 if (cdata)
2432 if (dpsys->chill_out) return (*dpsys->chill_out)(cdata);
2433 }
2434 return FALSE;
2435}
2436
2437
2439 lives_decoder_sys_t *dplug;
2440 char *plugname, *tmp;
2441 boolean OK = TRUE;
2442 const char *err;
2443 int dlflags = RTLD_NOW | RTLD_LOCAL;
2444
2446
2447 dplug->name = NULL;
2448
2449 tmp = lives_strdup_printf("%s.%s", plname, DLL_NAME);
2450 plugname = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_DECODERS, tmp, NULL);
2451 lives_free(tmp);
2452
2453#ifdef RTLD_DEEPBIND
2454 dlflags |= RTLD_DEEPBIND;
2455#endif
2456
2457 dplug->handle = dlopen(plugname, dlflags);
2458 lives_free(plugname);
2459
2460 if (!dplug->handle) {
2461 d_print(_("\n\nFailed to open decoder plugin %s\nError was %s\n"), plname, dlerror());
2462 lives_free(dplug);
2463 return NULL;
2464 }
2465
2466 if ((dplug->version = (const char *(*)())dlsym(dplug->handle, "version")) == NULL) {
2467 OK = FALSE;
2468 }
2469 if ((dplug->get_clip_data = (lives_clip_data_t *(*)(char *, const lives_clip_data_t *))
2470 dlsym(dplug->handle, "get_clip_data")) == NULL) {
2471 OK = FALSE;
2472 }
2473 if ((dplug->get_frame = (boolean(*)(const lives_clip_data_t *, int64_t, int *, int, void **))
2474 dlsym(dplug->handle, "get_frame")) == NULL) {
2475 OK = FALSE;
2476 }
2477 if ((dplug->clip_data_free = (void (*)(lives_clip_data_t *))dlsym(dplug->handle, "clip_data_free")) == NULL) {
2478 OK = FALSE;
2479 }
2480
2481 if (!OK) {
2482 d_print(_("\n\nDecoder plugin %s\nis missing a mandatory function.\nUnable to use it.\n"), plname);
2483 unload_decoder_plugin(dplug);
2484 lives_free(dplug);
2485 return NULL;
2486 }
2487
2488 // optional
2489 dplug->module_check_init = (const char *(*)())dlsym(dplug->handle, "module_check_init");
2490 dplug->chill_out = (boolean(*)(const lives_clip_data_t *))dlsym(dplug->handle, "chill_out");
2491 dplug->set_palette = (boolean(*)(lives_clip_data_t *))dlsym(dplug->handle, "set_palette");
2492 dplug->module_unload = (void (*)())dlsym(dplug->handle, "module_unload");
2493 dplug->rip_audio = (int64_t (*)(const lives_clip_data_t *, const char *, int64_t, int64_t, unsigned char **))
2494 dlsym(dplug->handle, "rip_audio");
2495 dplug->rip_audio_cleanup = (void (*)(const lives_clip_data_t *))dlsym(dplug->handle, "rip_audio_cleanup");
2496
2497 if (dplug->module_check_init) {
2498 err = (*dplug->module_check_init)();
2499
2500 if (err) {
2501 lives_snprintf(mainw->msg, MAINW_MSG_SIZE, "%s", err);
2502 unload_decoder_plugin(dplug);
2503 lives_free(dplug);
2504 return NULL;
2505 }
2506 }
2507
2508 dplug->name = lives_strdup(plname);
2509 return dplug;
2510}
2511
2512
2513void get_mime_type(char *text, int maxlen, const lives_clip_data_t *cdata) {
2514 char *audname;
2515
2516 if (!*cdata->container_name) lives_snprintf(text, maxlen, "%s", _("unknown"));
2517 else lives_snprintf(text, maxlen, "%s", cdata->container_name);
2518
2519 if (!*cdata->video_name && !*cdata->audio_name) return;
2520
2521 if (!*cdata->video_name) lives_strappend(text, maxlen, _("/unknown"));
2522 else {
2523 char *vidname = lives_strdup_printf("/%s", cdata->video_name);
2524 lives_strappend(text, maxlen, vidname);
2525 lives_free(vidname);
2526 }
2527
2528 if (!*cdata->audio_name) {
2529 if (cfile->achans == 0) return;
2530 audname = lives_strdup_printf("/%s", _("unknown"));
2531 } else
2532 audname = lives_strdup_printf("/%s", cdata->audio_name);
2533 lives_strappend(text, maxlen, audname);
2534 lives_free(audname);
2535}
2536
2537
2538static void dpa_ok_clicked(LiVESButton * button, livespointer user_data) {
2539 lives_general_button_clicked(button, NULL);
2540
2541 if (prefsw) {
2545 apply_button_set_enabled(NULL, NULL);
2546 }
2547
2549
2551}
2552
2553
2554static void dpa_cancel_clicked(LiVESButton * button, livespointer user_data) {
2555 lives_general_button_clicked(button, NULL);
2556
2557 if (prefsw) {
2560 }
2561
2563}
2564
2565
2566static void on_dpa_cb_toggled(LiVESToggleButton * button, const char *decname) {
2567 if (!lives_toggle_button_get_active(button))
2568 // unchecked is disabled
2569 future_prefs->disabled_decoders_new = lives_list_append(future_prefs->disabled_decoders_new, lives_strdup(decname));
2570 else
2572}
2573
2574
2575void on_decplug_advanced_clicked(LiVESButton * button, livespointer user_data) {
2576 LiVESList *decoder_plugin;
2577
2578 LiVESWidget *hbox;
2579 LiVESWidget *vbox;
2580 LiVESWidget *checkbutton;
2581 LiVESWidget *scrolledwindow;
2582 LiVESWidget *label;
2583 LiVESWidget *dialog;
2584 LiVESWidget *dialog_vbox;
2585 LiVESWidget *cancelbutton;
2586 LiVESWidget *okbutton;
2587
2588 char *ltext;
2589 char *decplugdir = lives_strdup_printf("%s%s%s", prefs->lib_dir, PLUGIN_EXEC_DIR, PLUGIN_DECODERS);
2590
2591 if (!mainw->decoders_loaded) {
2594 }
2595
2596 decoder_plugin = mainw->decoder_list;
2597
2598 dialog = lives_standard_dialog_new(_("Decoder Plugins"), FALSE, DEF_DIALOG_WIDTH, DEF_DIALOG_HEIGHT);
2599
2600 dialog_vbox = lives_dialog_get_content_area(LIVES_DIALOG(dialog));
2601
2602 vbox = lives_vbox_new(FALSE, 0);
2603
2605
2606 lives_container_add(LIVES_CONTAINER(dialog_vbox), scrolledwindow);
2607
2608 label = lives_standard_label_new(_("Enabled Video Decoders (uncheck to disable)"));
2609 lives_box_pack_start(LIVES_BOX(vbox), label, FALSE, FALSE, widget_opts.packing_height);
2610
2611 while (decoder_plugin) {
2612 lives_decoder_sys_t *dpsys = (lives_decoder_sys_t *)decoder_plugin->data;
2613 hbox = lives_hbox_new(FALSE, 0);
2614 lives_box_pack_start(LIVES_BOX(vbox), hbox, FALSE, FALSE, widget_opts.packing_height);
2615 ltext = lives_strdup_printf("%s (%s)", dpsys->name, (*dpsys->version)());
2616
2619 FALSE) == -1,
2620 LIVES_BOX(hbox), NULL);
2622
2623 lives_free(ltext);
2624
2625 lives_signal_sync_connect_after(LIVES_GUI_OBJECT(checkbutton), LIVES_WIDGET_TOGGLED_SIGNAL,
2626 LIVES_GUI_CALLBACK(on_dpa_cb_toggled),
2627 (livespointer)dpsys->name);
2628
2629 decoder_plugin = decoder_plugin->next;
2630 }
2631
2632 cancelbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_CANCEL, NULL,
2633 LIVES_RESPONSE_CANCEL);
2634
2635 okbutton = lives_dialog_add_button_from_stock(LIVES_DIALOG(dialog), LIVES_STOCK_OK, NULL,
2636 LIVES_RESPONSE_OK);
2637
2639
2640 lives_signal_connect(LIVES_GUI_OBJECT(cancelbutton), LIVES_WIDGET_CLICKED_SIGNAL,
2641 LIVES_GUI_CALLBACK(dpa_cancel_clicked),
2642 NULL);
2643
2644 lives_signal_connect(LIVES_GUI_OBJECT(okbutton), LIVES_WIDGET_CLICKED_SIGNAL,
2645 LIVES_GUI_CALLBACK(dpa_ok_clicked),
2646 NULL);
2647
2648 lives_widget_show_all(dialog);
2649 lives_window_present(LIVES_WINDOW(dialog));
2651
2653
2654 lives_free(decplugdir);
2655}
2656
2658// rfx plugin functions
2659
2660
2662 // check that an RFX is suitable for loading (cf. check_for_lives in effects-weed.c)
2663 if (rfx->num_in_channels == 2 && rfx->props & RFX_PROPS_MAY_RESIZE) {
2664 d_print(_("Failed to load %s, transitions may not resize.\n"), rfx->name);
2665 return FALSE;
2666 }
2667 return TRUE;
2668}
2669
2670
2672 char *com;
2673 char *dir = NULL;
2674
2676 if (rfx == &mainw->rendered_fx[0]) return;
2677
2678 switch (rfx->status) {
2679 case RFX_STATUS_BUILTIN:
2680 dir = lives_build_filename(prefs->lib_dir, PLUGIN_EXEC_DIR, NULL);
2681 com = lives_strdup_printf("%s plugin_clear \"%s\" %d %d \"%s\" \"%s\" \"%s\"", prefs->backend_sync,
2682 cfile->handle, cfile->start, cfile->end, dir,
2684 break;
2685 case RFX_STATUS_CUSTOM:
2686 com = lives_strdup_printf("%s plugin_clear \"%s\" %d %d \"%s\" \"%s\" \"%s\"", prefs->backend_sync,
2687 cfile->handle, cfile->start, cfile->end, prefs->config_datadir,
2689 break;
2690 case RFX_STATUS_TEST:
2691 com = lives_strdup_printf("%s plugin_clear \"%s\" %d %d \"%s\" \"%s\" \"%s\"", prefs->backend_sync,
2692 cfile->handle, cfile->start, cfile->end, prefs->config_datadir,
2694 break;
2695 default:
2696 return;
2697 }
2698
2699 lives_freep((void **)&dir);
2700
2701 // if the command fails we just give a warning
2702 lives_system(com, FALSE);
2703 lives_free(com);
2704}
2705
2706
2707void render_fx_get_params(lives_rfx_t *rfx, const char *plugin_name, short status) {
2708 // create lives_param_t array from plugin supplied values
2709 LiVESList *parameter_list, *list;
2710 int param_idx, i;
2711 lives_param_t *cparam;
2712 char **param_array;
2713 char *line;
2714 int len;
2715
2716 switch (status) {
2717 case RFX_STATUS_BUILTIN:
2718 parameter_list = plugin_request_by_line(PLUGIN_RENDERED_EFFECTS_BUILTIN, plugin_name, "get_parameters");
2719 break;
2720 case RFX_STATUS_CUSTOM:
2721 parameter_list = plugin_request_by_line(PLUGIN_RENDERED_EFFECTS_CUSTOM, plugin_name, "get_parameters");
2722 break;
2723 case RFX_STATUS_SCRAP:
2724 parameter_list = plugin_request_by_line(PLUGIN_RFX_SCRAP, plugin_name, "get_parameters");
2725 break;
2727 parameter_list = plugin_request_by_line(PLUGIN_RFX_SCRAP, plugin_name, "get_parameters");
2728 break;
2729 default:
2730 parameter_list = plugin_request_by_line(PLUGIN_RENDERED_EFFECTS_TEST, plugin_name, "get_parameters");
2731 break;
2732 }
2733
2734 if (!parameter_list) {
2735 rfx->num_params = 0;
2736 rfx->params = NULL;
2737 return;
2738 }
2739
2740 //threaded_dialog_spin(0.);
2741 rfx->num_params = lives_list_length(parameter_list);
2742 rfx->params = (lives_param_t *)lives_calloc(rfx->num_params, sizeof(lives_param_t));
2743 list = parameter_list;
2744
2745 for (param_idx = 0; param_idx < rfx->num_params; param_idx++) {
2746 line = (char *)list->data;
2747 list = list->next;
2748 len = get_token_count(line, (unsigned int)rfx->delim[0]);
2749
2750 if (len < 3) continue;
2751
2752 param_array = lives_strsplit(line, rfx->delim, -1);
2753
2754 cparam = &rfx->params[param_idx];
2755 cparam->name = lives_strdup(param_array[0]);
2756 cparam->label = lives_strdup(param_array[1]);
2757 cparam->desc = NULL;
2758 cparam->use_mnemonic = TRUE;
2759 cparam->hidden = 0;
2760 cparam->wrap = FALSE;
2761 cparam->transition = FALSE;
2762 cparam->step_size = 1.;
2763 cparam->group = 0;
2764 cparam->max = 0.;
2765 cparam->reinit = FALSE;
2766 cparam->changed = FALSE;
2767 cparam->edited = FALSE;
2768 cparam->change_blocked = FALSE;
2769 cparam->source = NULL;
2772 cparam->special_type_index = 0;
2773 cparam->def = NULL;
2774 cparam->value = NULL;
2775
2776#ifdef DEBUG_RENDER_FX_P
2777 lives_printerr("Got parameter %s\n", cparam->name);
2778#endif
2779 cparam->dp = 0;
2780 cparam->list = NULL;
2781
2782 cparam->type = LIVES_PARAM_UNKNOWN;
2783
2784 if (!strncmp(param_array[2], "num", 3)) {
2785 cparam->dp = atoi(param_array[2] + 3);
2786 cparam->type = LIVES_PARAM_NUM;
2787 } else if (!strncmp(param_array[2], "bool", 4)) {
2788 cparam->type = LIVES_PARAM_BOOL;
2789 } else if (!strncmp(param_array[2], "colRGB24", 8)) {
2790 cparam->type = LIVES_PARAM_COLRGB24;
2791 } else if (!strncmp(param_array[2], "string", 8)) {
2792 cparam->type = LIVES_PARAM_STRING;
2793 } else if (!strncmp(param_array[2], "string_list", 8)) {
2794 cparam->type = LIVES_PARAM_STRING_LIST;
2795 } else continue;
2796
2797 if (cparam->dp) {
2798 double val;
2799 if (len < 6) continue;
2800 val = lives_strtod(param_array[3], NULL);
2801 cparam->value = lives_malloc(sizdbl);
2802 cparam->def = lives_malloc(sizdbl);
2803 set_double_param(cparam->def, val);
2804 set_double_param(cparam->value, val);
2805 cparam->min = lives_strtod(param_array[4], NULL);
2806 cparam->max = lives_strtod(param_array[5], NULL);
2807 if (len > 6) {
2808 cparam->step_size = lives_strtod(param_array[6], NULL);
2809 if (cparam->step_size == 0.) cparam->step_size = 1. / (double)lives_10pow(cparam->dp);
2810 else if (cparam->step_size < 0.) {
2811 cparam->step_size = -cparam->step_size;
2812 cparam->wrap = TRUE;
2813 }
2814 }
2815 } else if (cparam->type == LIVES_PARAM_COLRGB24) {
2816 short red;
2817 short green;
2818 short blue;
2819 if (len < 6) continue;
2820 red = (short)atoi(param_array[3]);
2821 green = (short)atoi(param_array[4]);
2822 blue = (short)atoi(param_array[5]);
2823 cparam->value = lives_malloc(sizeof(lives_colRGB48_t));
2824 cparam->def = lives_malloc(sizeof(lives_colRGB48_t));
2825 set_colRGB24_param(cparam->def, red, green, blue);
2826 set_colRGB24_param(cparam->value, red, green, blue);
2827 } else if (cparam->type == LIVES_PARAM_STRING) {
2828 if (len < 4) continue;
2829 cparam->value = (_(param_array[3]));
2830 cparam->def = (_(param_array[3]));
2831 if (len > 4) cparam->max = (double)atoi(param_array[4]);
2832 if (cparam->max == 0. || cparam->max > RFX_MAXSTRINGLEN) cparam->max = RFX_MAXSTRINGLEN;
2833 } else if (cparam->type == LIVES_PARAM_STRING_LIST) {
2834 if (len < 4) continue;
2835 cparam->value = lives_malloc(sizint);
2836 cparam->def = lives_malloc(sizint);
2837 *(int *)cparam->def = atoi(param_array[3]);
2838 if (len > 4) {
2839 cparam->list = array_to_string_list(param_array, 3, len);
2840 } else {
2841 set_int_param(cparam->def, 0);
2842 }
2843 set_int_param(cparam->value, get_int_param(cparam->def));
2844 } else {
2845 // int or bool
2846 int val;
2847 if (len < 4) continue;
2848 val = atoi(param_array[3]);
2849 cparam->value = lives_malloc(sizint);
2850 cparam->def = lives_malloc(sizint);
2851 set_int_param(cparam->def, val);
2852 set_int_param(cparam->value, val);
2853 if (cparam->type == LIVES_PARAM_BOOL) {
2854 cparam->min = 0;
2855 cparam->max = 1;
2856 if (len > 4) cparam->group = atoi(param_array[4]);
2857 } else {
2858 if (len < 6) continue;
2859 cparam->min = (double)atoi(param_array[4]);
2860 cparam->max = (double)atoi(param_array[5]);
2861 if (len > 6) {
2862 cparam->step_size = (double)atoi(param_array[6]);
2863 if (cparam->step_size == 0.) cparam->step_size = 1.;
2864 else if (cparam->step_size < 0.) {
2865 cparam->step_size = -cparam->step_size;
2866 cparam->wrap = TRUE;
2867 }
2868 }
2869 }
2870 }
2871
2872 for (i = 0; i < MAX_PARAM_WIDGETS; i++) {
2873 cparam->widgets[i] = NULL;
2874 }
2875 cparam->onchange = FALSE;
2876 lives_strfreev(param_array);
2877 }
2878 lives_list_free_all(&parameter_list);
2879 //threaded_dialog_spin(0.);
2880}
2881
2882
2883LiVESList *array_to_string_list(char **array, int offset, int len) {
2884 // build a LiVESList from an array.
2885 int i;
2886
2887 char *string, *tmp;
2888 LiVESList *slist = NULL;
2889
2890 for (i = offset + 1; i < len; i++) {
2891 string = subst((tmp = L2U8(array[i])), "\\n", "\n");
2892 lives_free(tmp);
2893
2894 // omit a last empty string
2895 if (i < len - 1 || *string) {
2896 slist = lives_list_append(slist, string);
2897 } else lives_free(string);
2898 }
2899
2900 return slist;
2901}
2902
2903
2904static int cmp_menu_entries(livesconstpointer a, livesconstpointer b) {
2905 return lives_utf8_strcmpfunc(((lives_rfx_t *)a)->menu_text, ((lives_rfx_t *)b)->menu_text, LIVES_INT_TO_POINTER(TRUE));
2906}
2907
2908
2909void sort_rfx_array(lives_rfx_t *in, int num) {
2910 // sort rfx array into UTF-8 order by menu entry
2911 lives_rfx_t *rfx;
2912 int sorted = 1;
2913 register int i;
2914
2915 LiVESList *rfx_list = NULL, *xrfx_list;
2916 for (i = num; i > 0; i--) {
2917 rfx_list = lives_list_prepend(rfx_list, (livespointer)&in[i]);
2918 }
2919 rfx_list = lives_list_sort(rfx_list, cmp_menu_entries);
2920 rfx = mainw->rendered_fx = (lives_rfx_t *)lives_calloc((num + 1), sizeof(lives_rfx_t));
2921 rfx_copy(rfx, in, FALSE);
2922 xrfx_list = rfx_list;
2923 while (xrfx_list) {
2924 rfx_copy(&mainw->rendered_fx[sorted++], (lives_rfx_t *)(xrfx_list->data), FALSE);
2925 xrfx_list = xrfx_list->next;
2926 }
2927 lives_list_free(rfx_list);
2928}
2929
2930
2931void rfx_copy(lives_rfx_t *dest, lives_rfx_t *src, boolean full) {
2932 // Warning, does not copy all fields (full will do that)
2933 lives_memcpy(dest->delim, src->delim, 2);
2934 dest->source = src->source;
2935 if (!full) {
2936 // ref. assigned memory
2937 src->source = NULL;
2938 dest->name = src->name;
2939 src->name = NULL;
2940 dest->menu_text = src->menu_text;
2941 src->menu_text = NULL;
2942 dest->action_desc = src->action_desc;
2943 src->action_desc = NULL;
2944 dest->params = src->params;
2945 src->params = NULL;
2946 } else {
2947 // deep copy
2948 if (dest->source_type == LIVES_RFX_SOURCE_WEED && dest->source) weed_instance_ref(dest->source);
2949 dest->name = lives_strdup(src->name);
2950 dest->menu_text = lives_strdup(src->menu_text);
2951 dest->action_desc = lives_strdup(src->action_desc);
2952 // TODO - copy params
2953 }
2954
2955 lives_snprintf(dest->rfx_version, 64, "%s", src->rfx_version);
2956 dest->min_frames = src->min_frames;
2957 dest->num_in_channels = src->num_in_channels;
2958 dest->status = src->status;
2959 dest->props = src->props;
2960 dest->source_type = src->source_type;
2961 dest->num_params = src->num_params;
2962 dest->is_template = src->is_template;
2963 dest->menuitem = src->menuitem;
2964 dest->gui_strings = lives_list_copy(src->gui_strings);
2965 dest->onchange_strings = lives_list_copy(src->onchange_strings);
2966 if (!full) return;
2967
2968 // TODO
2969
2970}
2971
2972
2974 register int i;
2975 for (i = 0; i < rfx->num_params; i++) {
2976 if (rfx->params[i].type == LIVES_PARAM_UNDISPLAYABLE || rfx->params[i].type == LIVES_PARAM_UNKNOWN) continue;
2977 lives_free(rfx->params[i].name);
2978 lives_freep((void **)&rfx->params[i].def);
2979 lives_freep((void **)&rfx->params[i].value);
2980 lives_freep((void **)&rfx->params[i].label);
2981 lives_freep((void **)&rfx->params[i].desc);
2983 }
2984}
2985
2986
2988 if (!rfx) return;
2989
2990 if (mainw->vrfx_update == rfx) mainw->vrfx_update = NULL;
2991
2992 lives_freep((void **)&rfx->name);
2993 lives_freep((void **)&rfx->menu_text);
2994 lives_freep((void **)&rfx->action_desc);
2995
2996 if (rfx->params) {
2997 rfx_params_free(rfx);
2998 lives_free(rfx->params);
2999 }
3000
3003
3004 if (rfx->source_type == LIVES_RFX_SOURCE_WEED && rfx->source) {
3005 weed_instance_unref((weed_plant_t *)rfx->source); // remove the ref we held
3006 }
3007}
3008
3009
3010void rfx_free_all(void) {
3011 register int i;
3015 }
3016 lives_freep((void **)&mainw->rendered_fx);
3017}
3018
3019
3020void param_copy(lives_param_t *dest, lives_param_t *src, boolean full) {
3021 // rfxbuilder.c uses this to copy params to a temporary copy and back again
3022
3023 dest->name = lives_strdup(src->name);
3024 dest->label = lives_strdup(src->label);
3025 dest->group = src->group;
3026 dest->onchange = src->onchange;
3027 dest->type = src->type;
3028 dest->dp = src->dp;
3029 dest->min = src->min;
3030 dest->max = src->max;
3031 dest->step_size = src->step_size;
3032 dest->wrap = src->wrap;
3033 dest->source = src->source;
3034 dest->reinit = src->reinit;
3035 dest->source_type = src->source_type;
3036 dest->value = dest->def = NULL;
3037 dest->list = NULL;
3038
3039 switch (dest->type) {
3040 case LIVES_PARAM_BOOL:
3041 dest->dp = 0;
3042 case LIVES_PARAM_NUM:
3043 if (!dest->dp) {
3044 dest->def = lives_malloc(sizint);
3045 lives_memcpy(dest->def, src->def, sizint);
3046 } else {
3047 dest->def = lives_malloc(sizdbl);
3048 lives_memcpy(dest->def, src->def, sizdbl);
3049 }
3050 break;
3052 dest->def = lives_malloc(sizeof(lives_colRGB48_t));
3053 lives_memcpy(dest->def, src->def, sizeof(lives_colRGB48_t));
3054 break;
3055 case LIVES_PARAM_STRING:
3056 dest->def = lives_strdup((char *)src->def);
3057 break;
3059 dest->def = lives_malloc(sizint);
3060 set_int_param(dest->def, get_int_param(src->def));
3061 if (src->list) dest->list = lives_list_copy(src->list);
3062 break;
3063 default:
3064 break;
3065 }
3066 if (!full) return;
3067 // TODO - copy value, copy widgets
3068
3069}
3070
3071
3072boolean get_bool_param(void *value) {
3073 boolean ret;
3074 lives_memcpy(&ret, value, 4);
3075 return ret;
3076}
3077
3078
3079int get_int_param(void *value) {
3080 int ret;
3081 lives_memcpy(&ret, value, sizint);
3082 return ret;
3083}
3084
3085
3086double get_double_param(void *value) {
3087 double ret;
3088 lives_memcpy(&ret, value, sizdbl);
3089 return ret;
3090}
3091
3092
3093void get_colRGB24_param(void *value, lives_colRGB48_t *rgb) {
3094 lives_memcpy(rgb, value, sizeof(lives_colRGB48_t));
3095}
3096
3097
3098void get_colRGBA32_param(void *value, lives_colRGBA64_t *rgba) {
3099 lives_memcpy(rgba, value, sizeof(lives_colRGBA64_t));
3100}
3101
3102
3103void set_bool_param(void *value, boolean _const) {
3104 set_int_param(value, !!_const);
3105}
3106
3107
3108void set_string_param(void **value_ptr, const char *_const, size_t maxlen) {
3109 lives_freep(value_ptr);
3110 *value_ptr = lives_strndup(_const, maxlen);
3111}
3112
3113
3114void set_int_param(void *value, int _const) {
3115 lives_memcpy(value, &_const, sizint);
3116}
3117
3118
3119void set_double_param(void *value, double _const) {
3120 lives_memcpy(value, &_const, sizdbl);
3121}
3122
3123
3124boolean set_rfx_param_by_name_string(lives_rfx_t *rfx, const char *name, const char *value, boolean update_visual) {
3125 size_t len = strlen(value);
3126 lives_param_t *param = find_rfx_param_by_name(rfx, name);
3127 if (!param) return FALSE;
3128 set_string_param((void **)&param->value, value, len > RFX_MAXSTRINGLEN ? RFX_MAXSTRINGLEN : len);
3129 if (update_visual) {
3130 LiVESList *list = NULL;
3131 char *tmp, *tmp2;
3132 list = lives_list_append(list, lives_strdup_printf("\"%s\"", (tmp = U82L(tmp2 = subst(value, "\"", "\\\"")))));
3133 lives_free(tmp); lives_free(tmp2);
3134 set_param_from_list(list, param, 0, FALSE, TRUE);
3135 lives_list_free_all(&list);
3136 }
3137 return TRUE;
3138}
3139
3140
3141boolean get_rfx_param_by_name_string(lives_rfx_t *rfx, const char *name, char **return_value) {
3142 lives_param_t *param = find_rfx_param_by_name(rfx, name);
3143 if (!param) return FALSE;
3144 *return_value = lives_strndup(param->value, RFX_MAXSTRINGLEN);
3145 return TRUE;
3146}
3147
3148
3149void set_colRGB24_param(void *value, short red, short green, short blue) {
3150 lives_colRGB48_t *rgbp = (lives_colRGB48_t *)value;
3151
3152 if (red < 0) red = 0;
3153 if (red > 255) red = 255;
3154 if (green < 0) green = 0;
3155 if (green > 255) green = 255;
3156 if (blue < 0) blue = 0;
3157 if (blue > 255) blue = 255;
3158
3159 rgbp->red = red;
3160 rgbp->green = green;
3161 rgbp->blue = blue;
3162
3163}
3164
3165
3166void set_colRGBA32_param(void *value, short red, short green, short blue, short alpha) {
3167 lives_colRGBA64_t *rgbap = (lives_colRGBA64_t *)value;
3168 rgbap->red = red;
3169 rgbap->green = green;
3170 rgbap->blue = blue;
3171 rgbap->alpha = alpha;
3172}
3173
3174
3176
3177int find_rfx_plugin_by_name(const char *name, short status) {
3178 int i;
3181 if (mainw->rendered_fx[i].name && !strcmp(mainw->rendered_fx[i].name, name)
3182 && mainw->rendered_fx[i].status == status)
3183 return (int)i;
3184 }
3185 return -1;
3186}
3187
3188
3190 int i;
3191 if (!rfx) return NULL;
3192 for (i = 0; i < rfx->num_params; i++) {
3193 if (!strcmp(name, rfx->params[i].name)) {
3194 return &rfx->params[i];
3195 }
3196 }
3197 return NULL;
3198}
3199
3200
3201lives_param_t *weed_params_to_rfx(int npar, weed_plant_t *inst, boolean show_reinits) {
3202 int i, j;
3203 lives_param_t *rpar = (lives_param_t *)lives_calloc(npar, sizeof(lives_param_t));
3204 int param_type;
3205 char **list;
3206 LiVESList *gtk_list = NULL;
3207 char *string;
3208 int vali;
3209 double vald;
3210 weed_plant_t *gui = NULL;
3211 int listlen;
3212 int cspace, *cols = NULL, red_min = 0, red_max = 255, green_min = 0, green_max = 255, blue_min = 0, blue_max = 255,
3213 *maxi = NULL, *mini = NULL;
3214 double *colsd;
3215 double red_mind = 0., red_maxd = 1., green_mind = 0., green_maxd = 1., blue_mind = 0., blue_maxd = 1.,
3216 *maxd = NULL, *mind = NULL;
3217 int flags = 0;
3218 int nwpars = 0, poffset = 0;
3219 boolean col_int;
3220
3221 weed_plant_t *wtmpl;
3222 weed_plant_t **wpars = NULL, *wpar = NULL;
3223
3224 weed_plant_t *chann, *ctmpl;
3225 weed_plant_t *filter = weed_instance_get_filter(inst, TRUE);
3226
3227 wpars = weed_instance_get_in_params(inst, &nwpars);
3228
3229 for (i = 0; i < npar; i++) {
3230 if (i - poffset >= nwpars) {
3231 // handling for compound fx
3232 poffset += nwpars;
3233 if (wpars) lives_free(wpars);
3234 inst = weed_get_plantptr_value(inst, WEED_LEAF_HOST_NEXT_INSTANCE, NULL);
3235 wpars = weed_instance_get_in_params(inst, &nwpars);
3236 i--;
3237 continue;
3238 }
3239
3240 if (!wpars) {
3241 lives_free(rpar);
3242 return NULL;
3243 }
3244
3245 wpar = wpars[i - poffset];
3246 wtmpl = weed_param_get_template(wpar);
3247
3248 flags = weed_paramtmpl_get_flags(wtmpl);
3249
3250 rpar[i].flags = flags;
3251
3252 gui = weed_paramtmpl_get_gui(wtmpl, FALSE);
3253
3254 rpar[i].group = 0;
3255
3256 rpar[i].use_mnemonic = FALSE;
3257 rpar[i].hidden = 0;
3258 rpar[i].step_size = 1.;
3259 if (enabled_in_channels(filter, FALSE) == 2 && get_transition_param(filter, FALSE) == i) rpar[i].transition = TRUE;
3260 else rpar[i].transition = FALSE;
3261 rpar[i].wrap = FALSE;
3262 rpar[i].reinit = FALSE;
3263 rpar[i].change_blocked = FALSE;
3264 rpar[i].source = wtmpl;
3267 rpar[i].special_type_index = 0;
3268 rpar[i].value = NULL;
3269 rpar[i].def = NULL;
3270
3271 if (flags & WEED_PARAMETER_VARIABLE_SIZE && !(flags & WEED_PARAMETER_VALUE_PER_CHANNEL)) {
3272 rpar[i].hidden |= HIDDEN_MULTI;
3273 rpar[i].multi = PVAL_MULTI_ANY;
3274 } else if (flags & WEED_PARAMETER_VALUE_PER_CHANNEL) {
3275 rpar[i].hidden |= HIDDEN_MULTI;
3276 rpar[i].multi = PVAL_MULTI_PER_CHANNEL;
3277 } else rpar[i].multi = PVAL_MULTI_NONE;
3278
3279 chann = get_enabled_channel(inst, 0, TRUE);
3280 ctmpl = weed_get_plantptr_value(chann, WEED_LEAF_TEMPLATE, NULL);
3281
3282 if (weed_get_boolean_value(ctmpl, WEED_LEAF_IS_AUDIO, NULL) == WEED_TRUE) {
3283 // dont hide multivalued params for audio effects
3284 rpar[i].hidden = 0;
3285 }
3286
3287 rpar[i].dp = 0;
3288 rpar[i].min = 0.;
3289 rpar[i].max = 0.;
3290 rpar[i].list = NULL;
3291
3292 rpar[i].reinit = 0;
3293 if (flags & WEED_PARAMETER_REINIT_ON_VALUE_CHANGE)
3294 rpar[i].reinit = REINIT_FUNCTIONAL;
3295 if (gui && (weed_gui_get_flags(gui) & WEED_GUI_REINIT_ON_VALUE_CHANGE))
3296 rpar[i].reinit |= REINIT_VISUAL;
3297
3298 if (!show_reinits && rpar[i].reinit != 0) rpar[i].hidden |= HIDDEN_NEEDS_REINIT;
3299
3301 param_type = weed_paramtmpl_get_type(wtmpl);
3302
3303 switch (param_type) {
3304 case WEED_PARAM_SWITCH:
3305 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 1) {
3306 rpar[i].hidden |= HIDDEN_MULTI;
3307 }
3308 rpar[i].type = LIVES_PARAM_BOOL;
3309 rpar[i].value = lives_malloc(sizint);
3310 rpar[i].def = lives_malloc(sizint);
3311 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT))
3312 vali = weed_get_boolean_value(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3313 else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3314 vali = weed_get_boolean_value(wtmpl, WEED_LEAF_DEFAULT, NULL);
3315 else vali = weed_get_boolean_value(wtmpl, WEED_LEAF_NEW_DEFAULT, NULL);
3316 set_int_param(rpar[i].def, vali);
3317 vali = weed_get_boolean_value(wpar, WEED_LEAF_VALUE, NULL);
3318 set_int_param(rpar[i].value, vali);
3319 if (weed_plant_has_leaf(wtmpl, WEED_LEAF_GROUP)) rpar[i].group = weed_get_int_value(wtmpl, WEED_LEAF_GROUP, NULL);
3320 break;
3321 case WEED_PARAM_INTEGER:
3322 if (weed_plant_has_leaf(wtmpl, WEED_LEAF_DEFAULT) && weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 1) {
3323 rpar[i].hidden |= HIDDEN_MULTI;
3324 }
3325 rpar[i].type = LIVES_PARAM_NUM;
3326 rpar[i].value = lives_malloc(sizint);
3327 rpar[i].def = lives_malloc(sizint);
3328 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT)) {
3329 vali = weed_get_int_value(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3330 } else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3331 vali = weed_get_int_value(wtmpl, WEED_LEAF_DEFAULT, NULL);
3332 else vali = weed_get_int_value(wtmpl, WEED_LEAF_NEW_DEFAULT, NULL);
3333 set_int_param(rpar[i].def, vali);
3334 vali = weed_get_int_value(wpar, WEED_LEAF_VALUE, NULL);
3335 set_int_param(rpar[i].value, vali);
3336 rpar[i].min = (double)weed_get_int_value(wtmpl, WEED_LEAF_MIN, NULL);
3337 rpar[i].max = (double)weed_get_int_value(wtmpl, WEED_LEAF_MAX, NULL);
3338 if (weed_paramtmpl_does_wrap(wtmpl)) rpar[i].wrap = TRUE;
3339 if (gui) {
3340 if (weed_plant_has_leaf(gui, WEED_LEAF_CHOICES)) {
3341 listlen = weed_leaf_num_elements(gui, WEED_LEAF_CHOICES);
3342 list = weed_get_string_array(gui, WEED_LEAF_CHOICES, NULL);
3343 for (j = 0; j < listlen; j++) {
3344 gtk_list = lives_list_append(gtk_list, list[j]);
3345 }
3346 lives_free(list);
3347 rpar[i].list = lives_list_copy(gtk_list);
3348 lives_list_free(gtk_list);
3349 gtk_list = NULL;
3350 rpar[i].type = LIVES_PARAM_STRING_LIST;
3351 rpar[i].max = listlen;
3352 } else if (weed_plant_has_leaf(gui, WEED_LEAF_STEP_SIZE))
3353 rpar[i].step_size = (double)weed_get_int_value(gui, WEED_LEAF_STEP_SIZE, NULL);
3354 if (rpar[i].step_size == 0.) rpar[i].step_size = 1.;
3355 }
3356 break;
3357 case WEED_PARAM_FLOAT:
3358 if (weed_plant_has_leaf(wtmpl, WEED_LEAF_DEFAULT) && weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 1) {
3359 rpar[i].hidden |= HIDDEN_MULTI;
3360 }
3361 rpar[i].type = LIVES_PARAM_NUM;
3362 rpar[i].value = lives_malloc(sizdbl);
3363 rpar[i].def = lives_malloc(sizdbl);
3364 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT))
3365 vald = weed_get_double_value(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3366 else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3367 vald = weed_get_double_value(wtmpl, WEED_LEAF_DEFAULT, NULL);
3368 else vald = weed_get_double_value(wtmpl, WEED_LEAF_NEW_DEFAULT, NULL);
3369 set_double_param(rpar[i].def, vald);
3370 vald = weed_get_double_value(wpar, WEED_LEAF_VALUE, NULL);
3371 set_double_param(rpar[i].value, vald);
3372 rpar[i].min = weed_get_double_value(wtmpl, WEED_LEAF_MIN, NULL);
3373 rpar[i].max = weed_get_double_value(wtmpl, WEED_LEAF_MAX, NULL);
3374 if (weed_paramtmpl_does_wrap(wtmpl)) rpar[i].wrap = TRUE;
3375 rpar[i].step_size = 0.;
3376 rpar[i].dp = 2;
3377 if (gui) {
3378 if (weed_plant_has_leaf(gui, WEED_LEAF_STEP_SIZE))
3379 rpar[i].step_size = weed_get_double_value(gui, WEED_LEAF_STEP_SIZE, NULL);
3380 if (weed_plant_has_leaf(gui, WEED_LEAF_DECIMALS))
3381 rpar[i].dp = weed_get_int_value(gui, WEED_LEAF_DECIMALS, NULL);
3382 }
3383 if (rpar[i].step_size == 0.) {
3384 if (rpar[i].max - rpar[i].min > 10. && !(rpar[i].min >= -10. && rpar[i].max <= 10.))
3385 rpar[i].step_size = 1.;
3386 else if (rpar[i].max - rpar[i].min > 1. && !(rpar[i].min >= -1. && rpar[i].max <= 1.))
3387 rpar[i].step_size = .1;
3388 else rpar[i].step_size = 1. / (double)lives_10pow(rpar[i].dp);
3389 }
3390 break;
3391 case WEED_PARAM_TEXT:
3392 if (weed_plant_has_leaf(wtmpl, WEED_LEAF_DEFAULT) && weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 1) {
3393 rpar[i].hidden |= HIDDEN_MULTI;
3394 }
3395 rpar[i].type = LIVES_PARAM_STRING;
3396 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT))
3397 string = weed_get_string_value(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3398 else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3399 string = weed_get_string_value(wtmpl, WEED_LEAF_DEFAULT, NULL);
3400 else string = weed_get_string_value(wtmpl, WEED_LEAF_NEW_DEFAULT, NULL);
3401 rpar[i].def = string;
3402 string = weed_get_string_value(wpar, WEED_LEAF_VALUE, NULL);
3403 rpar[i].value = string;
3404 rpar[i].max = 0.;
3405 if (gui && weed_plant_has_leaf(gui, WEED_LEAF_MAXCHARS)) {
3406 rpar[i].max = (double)weed_get_int_value(gui, WEED_LEAF_MAXCHARS, NULL);
3407 if (rpar[i].max < 0.) rpar[i].max = 0.;
3408 }
3409 break;
3410 case WEED_PARAM_COLOR:
3411 cspace = weed_get_int_value(wtmpl, WEED_LEAF_COLORSPACE, NULL);
3412 switch (cspace) {
3413 case WEED_COLORSPACE_RGB:
3414 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 3) {
3415 rpar[i].hidden |= HIDDEN_MULTI;
3416 }
3417 rpar[i].type = LIVES_PARAM_COLRGB24;
3418 rpar[i].value = lives_malloc(3 * sizint);
3419 rpar[i].def = lives_malloc(3 * sizint);
3420
3421 if (weed_leaf_seed_type(wtmpl, WEED_LEAF_DEFAULT) == WEED_SEED_INT) {
3422 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT)) {
3423 cols = weed_get_int_array(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3424 } else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3425 cols = weed_get_int_array(wtmpl, WEED_LEAF_DEFAULT, NULL);
3426 else cols = weed_get_int_array(wtmpl, WEED_LEAF_NEW_DEFAULT, NULL);
3427 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_MAX) == 1) {
3428 red_max = green_max = blue_max = weed_get_int_value(wtmpl, WEED_LEAF_MAX, NULL);
3429 } else {
3430 maxi = weed_get_int_array(wtmpl, WEED_LEAF_MAX, NULL);
3431 red_max = maxi[0];
3432 green_max = maxi[1];
3433 blue_max = maxi[2];
3434 }
3435 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_MIN) == 1) {
3436 red_min = green_min = blue_min = weed_get_int_value(wtmpl, WEED_LEAF_MIN, NULL);
3437 } else {
3438 mini = weed_get_int_array(wtmpl, WEED_LEAF_MIN, NULL);
3439 red_min = mini[0];
3440 green_min = mini[1];
3441 blue_min = mini[2];
3442 }
3443 if (cols[0] < red_min) cols[0] = red_min;
3444 if (cols[1] < green_min) cols[1] = green_min;
3445 if (cols[2] < blue_min) cols[2] = blue_min;
3446 if (cols[0] > red_max) cols[0] = red_max;
3447 if (cols[1] > green_max) cols[1] = green_max;
3448 if (cols[2] > blue_max) cols[2] = blue_max;
3449 cols[0] = (double)(cols[0] - red_min) / (double)(red_max - red_min) * 255. + .49999;
3450 cols[1] = (double)(cols[1] - green_min) / (double)(green_max - green_min) * 255. + .49999;
3451 cols[2] = (double)(cols[2] - blue_min) / (double)(blue_max - blue_min) * 255. + .49999;
3452 col_int = TRUE;
3453 } else {
3454 if (!weed_paramtmpl_value_irrelevant(wtmpl) && weed_plant_has_leaf(wtmpl, WEED_LEAF_HOST_DEFAULT))
3455 colsd = weed_get_double_array(wtmpl, WEED_LEAF_HOST_DEFAULT, NULL);
3456 else if (weed_leaf_num_elements(wtmpl, WEED_LEAF_DEFAULT) > 0)
3457 colsd = weed_get_double_array(wtmpl, WEED_LEAF_DEFAULT, NULL);
3458 else colsd = weed_get_double_array(wtmpl, WEED_LEAF_DEFAULT, NULL);
3459 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_MAX) == 1) {
3460 red_maxd = green_maxd = blue_maxd = weed_get_double_value(wtmpl, WEED_LEAF_MAX, NULL);
3461 } else {
3462 maxd = weed_get_double_array(wtmpl, WEED_LEAF_MAX, NULL);
3463 red_maxd = maxd[0];
3464 green_maxd = maxd[1];
3465 blue_maxd = maxd[2];
3466 }
3467 if (weed_leaf_num_elements(wtmpl, WEED_LEAF_MIN) == 1) {
3468 red_mind = green_mind = blue_mind = weed_get_double_value(wtmpl, WEED_LEAF_MIN, NULL);
3469 } else {
3470 mind = weed_get_double_array(wtmpl, WEED_LEAF_MIN, NULL);
3471 red_mind = mind[0];
3472 green_mind = mind[1];
3473 blue_mind = mind[2];
3474 }
3475 if (colsd[0] < red_mind) colsd[0] = red_mind;
3476 if (colsd[1] < green_mind) colsd[1] = green_mind;
3477 if (colsd[2] < blue_mind) colsd[2] = blue_mind;
3478 if (colsd[0] > red_maxd) colsd[0] = red_maxd;
3479 if (colsd[1] > green_maxd) colsd[1] = green_maxd;
3480 if (colsd[2] > blue_maxd) colsd[2] = blue_maxd;
3481 cols = (int *)lives_malloc(3 * sizint);
3482 cols[0] = (colsd[0] - red_mind) / (red_maxd - red_mind) * 255. + .49999;
3483 cols[1] = (colsd[1] - green_mind) / (green_maxd - green_mind) * 255. + .49999;
3484 cols[2] = (colsd[2] - blue_mind) / (blue_maxd - blue_mind) * 255. + .49999;
3485 col_int = FALSE;
3486 }
3487 set_colRGB24_param(rpar[i].def, cols[0], cols[1], cols[2]);
3488
3489 if (col_int) {
3490 lives_free(cols);
3491 cols = weed_get_int_array(wpar, WEED_LEAF_VALUE, NULL);
3492 if (cols[0] < red_min) cols[0] = red_min;
3493 if (cols[1] < green_min) cols[1] = green_min;
3494 if (cols[2] < blue_min) cols[2] = blue_min;
3495 if (cols[0] > red_max) cols[0] = red_max;
3496 if (cols[1] > green_max) cols[1] = green_max;
3497 if (cols[2] > blue_max) cols[2] = blue_max;
3498 cols[0] = (double)(cols[0] - red_min) / (double)(red_max - red_min) * 255. + .49999;
3499 cols[1] = (double)(cols[1] - green_min) / (double)(green_max - green_min) * 255. + .49999;
3500 cols[2] = (double)(cols[2] - blue_min) / (double)(blue_max - blue_min) * 255. + .49999;
3501 } else {
3502 colsd = weed_get_double_array(wpar, WEED_LEAF_VALUE, NULL);
3503 if (colsd[0] < red_mind) colsd[0] = red_mind;
3504 if (colsd[1] < green_mind) colsd[1] = green_mind;
3505 if (colsd[2] < blue_mind) colsd[2] = blue_mind;
3506 if (colsd[0] > red_maxd) colsd[0] = red_maxd;
3507 if (colsd[1] > green_maxd) colsd[1] = green_maxd;
3508 if (colsd[2] > blue_maxd) colsd[2] = blue_maxd;
3509 cols[0] = (colsd[0] - red_mind) / (red_maxd - red_mind) * 255. + .49999;
3510 cols[1] = (colsd[1] - green_mind) / (green_maxd - green_mind) * 255. + .49999;
3511 cols[2] = (colsd[2] - blue_mind) / (blue_maxd - blue_mind) * 255. + .49999;
3512 }
3513 set_colRGB24_param(rpar[i].value, (short)cols[0], (short)cols[1], (short)cols[2]);
3514 lives_free(cols);
3515
3516 lives_freep((void **)&maxi);
3517 lives_freep((void **)&mini);
3518 lives_freep((void **)&maxd);
3519 lives_freep((void **)&mind);
3520 break;
3521 }
3522 break;
3523
3524 default:
3525 rpar[i].type = LIVES_PARAM_UNKNOWN; // TODO - try to get default
3526 }
3527
3528 string = weed_get_string_value(wtmpl, WEED_LEAF_NAME, NULL);
3529 rpar[i].name = string;
3530 rpar[i].label = lives_strdup(string);
3531
3532 if (weed_plant_has_leaf(wtmpl, WEED_LEAF_DESCRIPTION)) {
3533 string = weed_get_string_value(wtmpl, WEED_LEAF_DESCRIPTION, NULL);
3534 rpar[i].desc = string;
3535 } else rpar[i].desc = NULL;
3536
3537 if (is_hidden_param(inst, i)) rpar[i].hidden |= HIDDEN_GUI_PERM;
3538
3539 // gui part /////////////////////
3540
3541 if (gui) {
3542 if (weed_plant_has_leaf(gui, WEED_LEAF_LABEL)) {
3543 string = weed_get_string_value(gui, WEED_LEAF_LABEL, NULL);
3544 lives_free(rpar[i].label);
3545 rpar[i].label = string;
3546 }
3547 if (weed_plant_has_leaf(gui, WEED_LEAF_USE_MNEMONIC)) {
3548 rpar[i].use_mnemonic = weed_get_boolean_value(gui, WEED_LEAF_USE_MNEMONIC, NULL);
3549 }
3550 }
3551
3552 for (j = 0; j < MAX_PARAM_WIDGETS; j++) {
3553 rpar[i].widgets[j] = NULL;
3554 }
3555 rpar[i].onchange = FALSE;
3556 }
3557
3558 lives_free(wpars);
3559
3560 return rpar;
3561}
3562
3563
3564lives_rfx_t *weed_to_rfx(weed_plant_t *plant, boolean show_reinits) {
3565 // return an RFX for a weed effect; set rfx->source to an INSTANCE of the filter (first instance for compound fx)
3566 // instance should be refcounted
3567 weed_plant_t *filter, *inst;
3568
3569 char *string;
3570 lives_rfx_t *rfx = (lives_rfx_t *)lives_calloc(1, sizeof(lives_rfx_t));
3571 rfx->is_template = FALSE;
3572 if (weed_get_int_value(plant, WEED_LEAF_TYPE, NULL) == WEED_PLANT_FILTER_INSTANCE) {
3573 filter = weed_instance_get_filter(plant, TRUE);
3574 inst = plant;
3575 } else {
3576 filter = plant;
3577 inst = weed_instance_from_filter(filter);
3578 // init and deinit the effect to allow the plugin to hide parameters, etc.
3579 // rfx will inherit the refcount
3580 weed_reinit_effect(inst, TRUE);
3581 weed_instance_unref(inst);
3582 rfx->is_template = TRUE;
3583 }
3584
3585 string = weed_get_string_value(filter, WEED_LEAF_NAME, NULL);
3586 rfx->name = string;
3587 rfx->menu_text = lives_strdup(string);
3588 rfx->action_desc = lives_strdup("no action");
3589 rfx->min_frames = -1;
3591 rfx->status = RFX_STATUS_WEED;
3592 rfx->props = 0;
3593 rfx->menuitem = NULL;
3594 rfx->num_params = weed_leaf_num_elements(filter, WEED_LEAF_IN_PARAMETER_TEMPLATES);
3595 if (rfx->num_params > 0) rfx->params = weed_params_to_rfx(rfx->num_params, inst, show_reinits);
3596 else rfx->params = NULL;
3597 rfx->source = (void *)inst;
3599 rfx->gui_strings = NULL;
3600 rfx->onchange_strings = NULL;
3601 rfx->flags = 0;
3602 rfx->needs_reinit = FALSE;
3603 return rfx;
3604}
3605
3619 LiVESList *hints = NULL;
3620
3621 if (rfx->status == RFX_STATUS_WEED) {
3622 weed_plant_t *gui;
3623 weed_plant_t *inst = (weed_plant_t *)rfx->source;
3624 weed_plant_t *filter = weed_instance_get_filter(inst, TRUE);
3625 int *filters = NULL;
3626 char *string, **rfx_strings, *delim;
3627 int nfilters;
3628 int num_hints;
3629 int i;
3630
3631 if ((nfilters = num_compound_fx(filter)) > 1) {
3632 // handle compound fx
3633 filters = weed_get_int_array(filter, WEED_LEAF_HOST_FILTER_LIST, NULL);
3634 }
3635
3636 for (i = 0; i < nfilters; i++) {
3637 if (filters) {
3638 filter = get_weed_filter(filters[i]);
3639 }
3640
3641 if (!weed_plant_has_leaf(filter, WEED_LEAF_GUI)) continue;
3642 gui = weed_get_plantptr_value(filter, WEED_LEAF_GUI, NULL);
3643
3644 if (!weed_plant_has_leaf(gui, WEED_LEAF_LAYOUT_SCHEME)) continue;
3645
3646 string = weed_get_string_value(gui, WEED_LEAF_LAYOUT_SCHEME, NULL);
3647 if (strcmp(string, "RFX")) {
3648 lives_free(string);
3649 continue;
3650 }
3651 lives_free(string);
3652
3653 if (!weed_plant_has_leaf(gui, WEED_LEAF_RFX_DELIM)) continue;
3654 delim = weed_get_string_value(gui, WEED_LEAF_RFX_DELIM, NULL);
3655 lives_snprintf(rfx->delim, 2, "%s", delim);
3656 lives_free(delim);
3657
3658 rfx_strings = weed_get_string_array_counted(gui, WEED_LEAF_RFX_STRINGS, &num_hints);
3659 if (!num_hints) continue;
3660
3661 for (i = 0; i < num_hints; i++) {
3662 hints = lives_list_append(hints, rfx_strings[i]);
3663 }
3664 lives_free(rfx_strings);
3665
3666 if (filters) hints = lives_list_append(hints, lives_strdup("internal|nextfilter"));
3667 }
3668
3669 lives_freep((void **)&filters);
3670 }
3671
3672 return hints;
3673}
3674
3675
3677 if (rfx) {
3678 char *fnamex = lives_build_filename(prefs->workdir, rfx->name, NULL);
3679 if (lives_file_test(fnamex, LIVES_FILE_TEST_EXISTS)) lives_rm(fnamex);
3680 lives_free(fnamex);
3681 }
3682}
3683
3684
3717char *plugin_run_param_window(const char *scrap_text, LiVESVBox * vbox, lives_rfx_t **ret_rfx) {
3718 FILE *sfile;
3719
3720 lives_rfx_t *rfx = (lives_rfx_t *)lives_calloc(1, sizeof(lives_rfx_t));
3721
3722 char *string;
3723 char *rfx_scrapname, *rfx_scriptname;
3724 char *rfxfile;
3725 char *com;
3726 char *fnamex = NULL;
3727 char *res_string = NULL;
3728 char buff[32];
3729
3730 int res;
3731 int retval;
3732
3735 return NULL;
3736 }
3737
3738 rfx_scrapname = get_worktmpfile("rfx.");
3739 if (!rfx_scrapname) {
3741 return NULL;
3742 }
3743
3744 rfx_scriptname = lives_strdup_printf("%s.%s", rfx_scrapname, LIVES_FILE_EXT_RFX_SCRIPT);
3745
3746 rfxfile = lives_build_path(prefs->workdir, rfx_scriptname, NULL);
3747 lives_free(rfx_scriptname);
3748
3749 rfx->name = NULL;
3750
3751 string = lives_strdup_printf("<name>\n%s\n</name>\n", rfx_scrapname);
3752
3753 do {
3754 retval = 0;
3755 sfile = fopen(rfxfile, "w");
3756 if (!sfile) {
3757 retval = do_write_failed_error_s_with_retry(rfxfile, lives_strerror(errno));
3758 if (retval == LIVES_RESPONSE_CANCEL) {
3759 lives_free(string);
3760 return NULL;
3761 }
3762 } else {
3763 THREADVAR(write_failed) = FALSE;
3764 lives_fputs(string, sfile);
3765 if (scrap_text) {
3766 char *data = subst(scrap_text, "\\n", "\n");
3767 lives_fputs(data, sfile);
3768 lives_free(data);
3769 }
3770 fclose(sfile);
3771 lives_free(string);
3772 if (THREADVAR(write_failed)) {
3773 retval = do_write_failed_error_s_with_retry(rfxfile, NULL);
3774 if (retval == LIVES_RESPONSE_CANCEL) {
3775 return NULL;
3776 }
3777 }
3778 }
3779 } while (retval == LIVES_RESPONSE_RETRY);
3780
3781 // OK, we should now have an RFX fragment in a file, we can compile it, then build a parameter window from it
3782
3783 // call RFX_BUILDER program to compile the script, passing parameters input_filename and output_directory
3784 com = lives_strdup_printf("\"%s\" \"%s\" \"%s\" >%s", EXEC_RFX_BUILDER, rfxfile, prefs->workdir, LIVES_DEVNULL);
3785 res = lives_system(com, TRUE);
3786 lives_free(com);
3787
3788 lives_rm(rfxfile);
3789 lives_free(rfxfile);
3790
3791 if (res == 0) {
3792 // the script compiled correctly
3793
3794 // now we pop up the parameter window, get the values of our parameters, and marshall them as extra_params
3795
3796 // first create a lives_rfx_t from the scrap
3797 rfx->name = lives_strdup(rfx_scrapname);
3798 rfx->menu_text = NULL;
3799 rfx->action_desc = NULL;
3800 rfx->gui_strings = NULL;
3801 rfx->onchange_strings = NULL;
3802 lives_snprintf(rfx->rfx_version, 64, "%s", RFX_VERSION);
3803 rfx->flags = 0;
3804 rfx->status = RFX_STATUS_SCRAP;
3805
3806 rfx->num_in_channels = 0;
3807 rfx->min_frames = -1;
3808
3810
3811 fnamex = lives_build_filename(prefs->workdir, rfx_scrapname, NULL);
3812 com = lives_strdup_printf("\"%s\" get_define", fnamex);
3813 lives_free(fnamex);
3814
3815 if (!lives_popen(com, TRUE, buff, 32)) {
3816 THREADVAR(com_failed) = TRUE;
3817 }
3818 lives_free(com);
3819
3820 // command to get_define failed
3821 if (THREADVAR(com_failed)) {
3822 rfx_clean_exe(rfx);
3823 return NULL;
3824 }
3825
3826 lives_snprintf(rfx->delim, 2, "%s", buff);
3827
3828 // ok, this might need adjusting afterwards
3829 rfx->menu_text = (vbox == NULL ? lives_strdup_printf(_("%s advanced settings"), prefs->encoder.of_desc) : lives_strdup(""));
3830 rfx->is_template = FALSE;
3831
3832 rfx->source = NULL;
3834
3835#if 0
3836 render_fx_get_params(rfx, scrap_text, RFX_STATUS_INTERNAL);
3837#else
3838 render_fx_get_params(rfx, rfx_scrapname, RFX_STATUS_SCRAP);
3839#endif
3840
3842 if (!make_param_box(NULL, rfx)) {
3843 res_string = lives_strdup("");
3844 goto prpw_done;
3845 }
3846
3847 // now we build our window and get param values
3848 if (!vbox) {
3849 _fx_dialog *fxdialog = on_fx_pre_activate(rfx, TRUE, NULL);
3850 LiVESWidget *dialog = fxdialog->dialog;
3851 if (prefs->show_gui) {
3852 lives_window_set_transient_for(LIVES_WINDOW(dialog), LIVES_WINDOW(LIVES_MAIN_WINDOW_WIDGET));
3853 }
3854 lives_window_set_modal(LIVES_WINDOW(dialog), TRUE);
3855
3856 do {
3857 res = lives_dialog_run(LIVES_DIALOG(dialog));
3858 } while (res == LIVES_RESPONSE_RETRY);
3859
3860 if (res == LIVES_RESPONSE_OK) {
3861 // marshall our params for passing to the plugin
3862 res_string = param_marshall(rfx, FALSE);
3863 }
3864
3865 lives_widget_destroy(dialog);
3866
3867 if (fx_dialog[1]) {
3868 lives_freep((void **)&fx_dialog[1]);
3869 }
3870 } else {
3871 make_param_box(vbox, rfx);
3872 }
3873
3874prpw_done:
3875 if (ret_rfx) {
3876 *ret_rfx = rfx;
3877 } else {
3878 rfx_clean_exe(rfx);
3879 rfx_free(rfx);
3880 lives_free(rfx);
3881 }
3882 } else {
3883 if (ret_rfx) {
3884 *ret_rfx = NULL;
3885 } else {
3886 res_string = lives_strdup("");
3887 }
3888 if (rfx) {
3889 lives_free(rfx);
3890 }
3891 }
3892 lives_free(rfx_scrapname);
3893 return res_string;
3894}
3895
boolean start_audio_stream(void)
Definition: audio.c:3827
void stop_audio_stream(void)
Definition: audio.c:3906
LIVES_GLOBAL_INLINE boolean weed_palette_is_yuv(int pal)
Definition: colourspace.c:1457
LIVES_GLOBAL_INLINE int weed_layer_get_palette(weed_layer_t *layer)
LIVES_GLOBAL_INLINE int weed_layer_get_yuv_clamping(weed_layer_t *layer)
weed_plant_t weed_layer_t
Definition: colourspace.h:71
boolean do_encoder_restrict_dialog(int width, int height, double fps, int fps_num, int fps_denom, int arate, int asigned, boolean swap_endian, boolean anr, boolean save_all)
Definition: dialogs.c:3148
LiVESResponseType do_read_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4122
LIVES_GLOBAL_INLINE void do_encoder_sox_error(void)
Definition: dialogs.c:3039
LIVES_GLOBAL_INLINE void do_encoder_acodec_error(void)
Definition: dialogs.c:3046
LIVES_GLOBAL_INLINE void do_vpp_fps_error(void)
Definition: dialogs.c:3737
LIVES_GLOBAL_INLINE void do_program_not_found_error(const char *progname)
Definition: dialogs.c:3640
LiVESResponseType do_write_failed_error_s_with_retry(const char *fname, const char *errtext)
Definition: dialogs.c:4058
LIVES_GLOBAL_INLINE void do_vpp_palette_error(void)
Definition: dialogs.c:3727
boolean rdet_suggest_values(int width, int height, double fps, int fps_num, int fps_denom, int arate, int asigned, boolean swap_endian, boolean anr, boolean ignore_fps)
Definition: dialogs.c:3065
LIVES_GLOBAL_INLINE LiVESResponseType do_error_dialog(const char *text)
Definition: dialogs.c:749
void workdir_warning(void)
Definition: dialogs.c:3001
boolean is_hidden_param(weed_plant_t *plant, int i)
returns the permanent (structural) state c.f check_hidden_gui() which sets flag values for params lin...
weed_plant_t * weed_instance_get_filter(weed_plant_t *inst, boolean get_compound_parent)
Definition: effects-weed.c:180
int best_palette_match(int *palette_list, int num_palettes, int palette)
check palette vs.
Definition: effects-weed.c:868
int num_compound_fx(weed_plant_t *plant)
return number of filters in a compound fx (1 if it is not compound) - works for filter or inst
Definition: effects-weed.c:132
int enabled_in_channels(weed_plant_t *plant, boolean count_repeats)
LIVES_GLOBAL_INLINE int weed_instance_ref(weed_plant_t *inst)
weed_plant_t * host_info_cb(weed_plant_t *xhost_info, void *data)
LIVES_GLOBAL_INLINE int weed_instance_unref(weed_plant_t *inst)
weed_plant_t * get_weed_filter(int idx)
int get_transition_param(weed_plant_t *filter, boolean skip_internal)
weed_plant_t * get_enabled_channel(weed_plant_t *inst, int which, boolean is_in)
for FILTER_INST
Definition: effects-weed.c:536
weed_plant_t * weed_instance_from_filter(weed_plant_t *filter)
lives_filter_error_t weed_reinit_effect(weed_plant_t *inst, boolean reinit_compound)
#define WEED_LEAF_HOST_NEXT_INSTANCE
Definition: effects-weed.h:104
#define WEED_LEAF_RFX_DELIM
Definition: effects-weed.h:97
#define PLUGIN_COMPOUND_EFFECTS_CUSTOM
Definition: effects-weed.h:129
#define PLUGIN_COMPOUND_EFFECTS_BUILTIN
Definition: effects-weed.h:128
#define WEED_LEAF_RFX_STRINGS
Definition: effects-weed.h:96
#define WEED_LEAF_HOST_DEFAULT
Definition: effects-weed.h:62
#define WEED_LEAF_HOST_FILTER_LIST
Definition: effects-weed.h:77
render_details * rdet
Definition: events.h:256
void play_window_set_title(void)
Definition: gui.c:3722
char * choose_file(const char *dir, const char *fname, char **const filt, LiVESFileChooserAction act, const char *title, LiVESWidget *extra_widget)
Definition: interface.c:4080
const lives_special_aspect_t * add_aspect_ratio_button(LiVESSpinButton *sp_width, LiVESSpinButton *sp_height, LiVESBox *box)
Definition: interface.c:4963
uint16_t cached_mod
Definition: keyboard.h:11
uint16_t cached_key
Definition: keyboard.h:10
const lives_struct_def_t * get_lsd(lives_struct_type st_type)
Definition: lsd-tab.c:23
uint64_t lsd_check_match(lives_struct_def_t *lsd1, lives_struct_def_t *lsd2)
Definition: lsd-tab.c:174
@ LIVES_STRUCT_CLIP_DATA_T
Definition: lsd-tab.h:12
void * _ext_malloc(size_t n)
Definition: machinestate.c:530
char * get_worktmpfile(const char *prefix)
void * _ext_calloc(size_t nmemb, size_t msize)
Definition: machinestate.c:584
void _ext_free(void *p)
Definition: machinestate.c:556
LIVES_GLOBAL_INLINE int lives_strappend(const char *string, int len, const char *xnew)
void * _ext_memset(void *p, int i, size_t n)
Definition: machinestate.c:571
void * _ext_memcpy(void *dest, const void *src, size_t n)
Definition: machinestate.c:567
void * _ext_realloc(void *p, size_t n)
Definition: machinestate.c:575
void * _ext_memmove(void *dest, const void *src, size_t n)
Definition: machinestate.c:573
void *(* malloc_f)(size_t)
Definition: machinestate.h:18
#define lives_calloc
Definition: machinestate.h:67
void *(* memset_f)(void *, int, size_t)
Definition: machinestate.h:23
void *(* memmove_f)(void *, const void *, size_t)
Definition: machinestate.h:24
void *(* memcpy_f)(void *, const void *, size_t)
Definition: machinestate.h:21
#define THREADVAR(var)
Definition: machinestate.h:531
#define lives_free
Definition: machinestate.h:52
#define lives_memset
Definition: machinestate.h:61
#define lives_malloc
Definition: machinestate.h:46
void *(* realloc_f)(void *, size_t)
Definition: machinestate.h:25
void *(* calloc_f)(size_t, size_t)
Definition: machinestate.h:26
#define lives_memcpy
Definition: machinestate.h:55
void(* free_f)(void *)
Definition: machinestate.h:19
#define lives_realloc
Definition: machinestate.h:49
_palette * palette
interface colour settings
Definition: main.c:101
ssize_t sizdbl
Definition: main.c:102
ssize_t sizint
type sizes
Definition: main.c:102
mainwindow * mainw
Definition: main.c:103
#define LIVES_WARN(x)
Definition: main.h:1862
LiVESList * lives_list_copy_strings(LiVESList *list)
Definition: utils.c:5820
ssize_t lives_popen(const char *com, boolean allow_error, char *buff, ssize_t buflen)
Definition: utils.c:194
void lives_list_free_all(LiVESList **)
Definition: utils.c:4873
#define LIVES_EXT_SRC_DECODER
Definition: main.h:1044
LiVESList * lives_list_sort_alpha(LiVESList *list, boolean fwd)
Definition: utils.c:5474
#define MAX_FRAME_WIDTH
Definition: main.h:220
boolean get_clip_value(int which, lives_clip_details_t, void *retval, size_t maxlen)
Definition: utils.c:5039
#define MAX_FRAME_HEIGHT
Definition: main.h:221
size_t get_token_count(const char *string, int delim)
Definition: utils.c:5430
double get_ratio_fps(const char *string)
Definition: utils.c:5379
ssize_t lives_write(int fd, livesconstpointer buf, ssize_t count, boolean allow_fail)
void d_print_file_error_failed(void)
Definition: utils.c:2625
#define LIVES_GLOBAL_INLINE
Definition: main.h:239
int lives_chdir(const char *path, boolean no_error_dlg)
Definition: utils.c:1393
#define AFORM_SIGNED
Definition: main.h:783
char * subst(const char *string, const char *from, const char *to)
Definition: utils.c:5484
LiVESList * buff_to_list(const char *buffer, const char *delim, boolean allow_blanks, boolean strip)
Definition: utils.c:5755
#define LIVES_IS_PLAYING
Definition: main.h:840
#define IS_NORMAL_CLIP(clip)
Definition: main.h:833
int lives_open3(const char *pathname, int flags, mode_t mode)
Definition: utils.c:94
uint64_t lives_10pow(int pow) GNU_CONST
Definition: utils.c:1438
int lives_system(const char *com, boolean allow_error)
Definition: utils.c:145
char * get_extension(const char *filename)
Definition: utils.c:3217
#define AFORM_UNSIGNED
Definition: main.h:786
ssize_t lives_read_le(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:486
void minimise_aspect_delta(double allowed_aspect, int hblock, int vblock, int hsize, int vsize, int *width, int *height)
Definition: utils.c:3750
@ CLIP_DETAILS_DECODER_NAME
Definition: main.h:1164
#define IS_VALID_CLIP(clip)
Definition: main.h:808
#define LIVES_EXT_SRC_NONE
Definition: main.h:1043
boolean int_array_contains_value(int *array, int num_elems, int value)
Definition: utils.c:4284
int lives_rm(const char *file)
Definition: utils.c:4395
int64_t ticks_t
Definition: main.h:97
ssize_t lives_write_le(int fd, livesconstpointer buf, ssize_t count, boolean allow_fail)
void d_print_failed(void)
Definition: utils.c:2615
ssize_t lives_read(int fd, void *buf, ssize_t count, boolean allow_less)
Definition: utils.c:460
capability * capable
Definition: main.h:627
boolean string_lists_differ(LiVESList *, LiVESList *)
Definition: utils.c:5831
#define cfile
Definition: main.h:1833
int lives_open2(const char *pathname, int flags)
Definition: utils.c:99
LiVESList * lives_list_move_to_first(LiVESList *list, LiVESList *item) WARN_UNUSED
Definition: utils.c:5789
int lives_list_strcmp_index(LiVESList *list, livesconstpointer data, boolean case_sensitive)
Definition: utils.c:4678
void d_print(const char *fmt,...)
Definition: utils.c:2542
#define LIVES_ERROR(x)
Definition: main.h:1870
boolean check_for_executable(lives_checkstatus_t *cap, const char *exec)
Definition: utils.c:3434
LiVESList * lives_list_delete_string(LiVESList *, const char *string) WARN_UNUSED
Definition: utils.c:5801
#define AFORM_BIG_ENDIAN
Definition: main.h:787
uint32_t get_signed_endian(boolean is_signed, boolean little_endian)
produce bitmapped value
Definition: utils.c:5408
void d_print_done(void)
Definition: utils.c:2620
#define PATH_MAX
Definition: main.h:255
boolean lives_freep(void **ptr)
Definition: utils.c:1411
@ CLIP_TYPE_FILE
unimported video, not or partially broken in frames
Definition: main.h:765
char * remove_trailing_zeroes(double val)
Definition: utils.c:5395
int lives_fputs(const char *s, FILE *stream)
Definition: utils.c:359
#define LIVES_INFO(x)
Definition: main.h:1854
void save_file(int clip, int start, int end, const char *filename)
Definition: saveplay.c:1260
#define MAINW_MSG_SIZE
mainw->msg bytesize
Definition: mainwindow.h:702
#define DLL_NAME
Definition: mainwindow.h:530
#define PLUGIN_COMPOUND_DIR
Definition: mainwindow.h:597
#define LIVES_FILE_EXT_RFX_SCRIPT
Definition: mainwindow.h:515
#define DEF_DIALOG_HEIGHT
Definition: mainwindow.h:186
#define PLUGIN_EXEC_DIR
Definition: mainwindow.h:599
#define LIVES_MAIN_WINDOW_WIDGET
Definition: mainwindow.h:188
@ LIVES_STRING_CONSTANT_NONE
Definition: mainwindow.h:371
#define LIVES_FILE_EXT_PNG
Definition: mainwindow.h:487
#define THEME_DIR
Definition: mainwindow.h:595
#define RFX_WINSIZE_V
Definition: mainwindow.h:177
#define EXEC_MKTEMP
Definition: mainwindow.h:430
#define PLUGIN_SCRIPTS_DIR
Definition: mainwindow.h:596
#define RFX_WINSIZE_H
size of the fx dialog windows scrollwindow
Definition: mainwindow.h:175
_fx_dialog * fx_dialog[2]
Definition: mainwindow.h:1851
#define LIVES_FILE_EXT_JPG
Definition: mainwindow.h:488
#define COMBOWIDTHCHARS
char width of combo entries (default)
Definition: mainwindow.h:74
#define LIVES_DEVNULL
Definition: mainwindow.h:592
#define DEF_DIALOG_WIDTH
Definition: mainwindow.h:185
boolean special_cleanup(boolean is_ok)
Definition: paramspecial.c:641
LiVESList * argv_to_marshalled_list(lives_rfx_t *rfx, int argc, char **argv)
Definition: paramwindow.c:3031
char * param_marshall(lives_rfx_t *rfx, boolean with_min_max)
Definition: paramwindow.c:2844
int set_param_from_list(LiVESList *plist, lives_param_t *param, int pnum, boolean with_min_max, boolean upd)
update values for param using values in plist if upd is TRUE, the widgets for that param also are upd...
Definition: paramwindow.c:3065
char ** param_marshall_to_argv(lives_rfx_t *rfx)
Definition: paramwindow.c:2797
void param_demarshall(lives_rfx_t *rfx, LiVESList *plist, boolean with_min_max, boolean upd)
Definition: paramwindow.c:3013
_fx_dialog * on_fx_pre_activate(lives_rfx_t *rfx, boolean is_realtime, LiVESWidget *pbox)
Definition: paramwindow.c:687
void after_param_text_changed(LiVESWidget *textwidget, lives_rfx_t *rfx)
Definition: paramwindow.c:2635
boolean make_param_box(LiVESVBox *top_vbox, lives_rfx_t *rfx)
make a dynamic parameter window
Definition: paramwindow.c:1015
lives_param_t * weed_params_to_rfx(int npar, weed_plant_t *inst, boolean show_reinits)
Definition: plugins.c:3201
void get_mime_type(char *text, int maxlen, const lives_clip_data_t *cdata)
Definition: plugins.c:2513
void sort_rfx_array(lives_rfx_t *in, int num)
Definition: plugins.c:2909
void set_colRGBA32_param(void *value, short red, short green, short blue, short alpha)
Definition: plugins.c:3166
void unload_decoder_plugins(void)
Definition: plugins.c:2411
void vid_playback_plugin_exit(void)
Definition: plugins.c:1413
void on_vppa_cancel_clicked(LiVESButton *button, livespointer user_data)
Definition: plugins.c:408
LiVESList * get_external_window_hints(lives_rfx_t *rfx)
get the interface hints set by a Weed filter in the filter_class.
Definition: plugins.c:3618
LiVESList * filter_encoders_by_img_ext(LiVESList *encoders, const char *img_ext)
Definition: plugins.c:2006
void on_vppa_ok_clicked(LiVESButton *button, livespointer user_data)
Definition: plugins.c:435
boolean check_rfx_for_lives(lives_rfx_t *rfx)
Definition: plugins.c:2661
boolean decoder_plugin_move_to_first(const char *name)
Definition: plugins.c:2072
void do_rfx_cleanup(lives_rfx_t *rfx)
Definition: plugins.c:2671
void do_plugin_encoder_error(const char *plugin_name)
Definition: plugins.c:1531
void rfx_clean_exe(lives_rfx_t *rfx)
Definition: plugins.c:3676
LiVESList * array_to_string_list(char **array, int offset, int len)
Definition: plugins.c:2883
LiVESList * get_plugin_list(const char *plugin_type, boolean allow_nonex, const char *plugdir, const char *filter_ext)
Definition: plugins.c:115
void get_colRGBA32_param(void *value, lives_colRGBA64_t *rgba)
Definition: plugins.c:3098
void param_copy(lives_param_t *dest, lives_param_t *src, boolean full)
Definition: plugins.c:3020
boolean chill_decoder_plugin(int fileno)
Definition: plugins.c:2425
_vid_playback_plugin * open_vid_playback_plugin(const char *name, boolean in_use)
Definition: plugins.c:1099
LiVESList * load_decoders(void)
Definition: plugins.c:2092
void close_vid_playback_plugin(_vid_playback_plugin *vpp)
Definition: plugins.c:998
int64_t get_best_audio(_vid_playback_plugin *vpp)
Definition: plugins.c:1441
void get_colRGB24_param(void *value, lives_colRGB48_t *rgb)
Definition: plugins.c:3093
const char *const anames[AUDIO_CODEC_MAX]
Definition: plugins.c:21
const lives_clip_data_t * get_decoder_cdata(int fileno, LiVESList *disabled, const lives_clip_data_t *fake_cdata)
Definition: plugins.c:2286
void rfx_free(lives_rfx_t *rfx)
Definition: plugins.c:2987
boolean set_rfx_param_by_name_string(lives_rfx_t *rfx, const char *name, const char *value, boolean update_visual)
Definition: plugins.c:3124
void on_vppa_save_clicked(LiVESButton *button, livespointer user_data)
Definition: plugins.c:701
void save_vpp_defaults(_vid_playback_plugin *vpp, char *vpp_file)
Definition: plugins.c:181
void set_double_param(void *value, double _const)
Definition: plugins.c:3119
void rfx_params_free(lives_rfx_t *rfx)
Definition: plugins.c:2973
double get_double_param(void *value)
Definition: plugins.c:3086
void set_bool_param(void *value, boolean _const)
Definition: plugins.c:3103
boolean get_bool_param(void *value)
Definition: plugins.c:3072
boolean get_rfx_param_by_name_string(lives_rfx_t *rfx, const char *name, char **return_value)
Definition: plugins.c:3141
lives_decoder_sys_t * open_decoder_plugin(const char *plname)
Definition: plugins.c:2438
void on_decplug_advanced_clicked(LiVESButton *button, livespointer user_data)
Definition: plugins.c:2575
void close_decoder_plugin(lives_decoder_t *dplug)
Definition: plugins.c:2361
int find_rfx_plugin_by_name(const char *name, short status)
Definition: plugins.c:3177
LIVES_GLOBAL_INLINE LiVESList * plugin_request_by_line(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:59
boolean check_encoder_restrictions(boolean get_extension, boolean user_audio, boolean save_all)
Definition: plugins.c:1557
const weed_plant_t * pp_get_param(weed_plant_t **pparams, int idx)
Definition: plugins.c:1042
boolean vpp_try_match_palette(_vid_playback_plugin *vpp, weed_layer_t *layer)
Definition: plugins.c:1066
LIVES_GLOBAL_INLINE LiVESList * plugin_request_with_blanks(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:47
void load_vpp_defaults(_vid_playback_plugin *vpp, char *vpp_file)
Definition: plugins.c:265
void set_string_param(void **value_ptr, const char *_const, size_t maxlen)
Definition: plugins.c:3108
const weed_plant_t * pp_get_chan(weed_plant_t **pparams, int idx)
Definition: plugins.c:1054
LiVESList * plugin_request_common(const char *plugin_type, const char *plugin_name, const char *request, const char *delim, boolean allow_blanks)
Definition: plugins.c:69
int get_int_param(void *value)
Definition: plugins.c:3079
_vppaw * on_vpp_advanced_clicked(LiVESButton *button, livespointer user_data)
Definition: plugins.c:727
void close_clip_decoder(int clipno)
Definition: plugins.c:2382
LIVES_GLOBAL_INLINE LiVESList * plugin_request_by_space(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:64
void set_colRGB24_param(void *value, short red, short green, short blue)
Definition: plugins.c:3149
lives_param_t * find_rfx_param_by_name(lives_rfx_t *rfx, const char *name)
Definition: plugins.c:3189
lives_decoder_t * clone_decoder(int fileno)
Definition: plugins.c:2181
char * plugin_run_param_window(const char *scrap_text, LiVESVBox *vbox, lives_rfx_t **ret_rfx)
create an interface window for a plugin; possibly run it, and return the parameters
Definition: plugins.c:3717
lives_rfx_t * weed_to_rfx(weed_plant_t *plant, boolean show_reinits)
Definition: plugins.c:3564
void set_int_param(void *value, int _const)
Definition: plugins.c:3114
void rfx_free_all(void)
Definition: plugins.c:3010
void rfx_copy(lives_rfx_t *dest, lives_rfx_t *src, boolean full)
Definition: plugins.c:2931
LIVES_GLOBAL_INLINE LiVESList * plugin_request(const char *plugin_type, const char *plugin_name, const char *request)
Definition: plugins.c:54
void render_fx_get_params(lives_rfx_t *rfx, const char *plugin_name, short status)
Definition: plugins.c:2707
LiVESList * get_plugin_result(const char *command, const char *delim, boolean allow_blanks, boolean strip)
Definition: plugins.c:30
#define PLUGIN_RENDERED_EFFECTS_BUILTIN_SCRIPTS
rfx scripts for the SDK
Definition: plugins.h:476
#define FX_CANDIDATE_RESIZER
Definition: plugins.h:695
#define AUDIO_STREAMER_NAME
Definition: plugins.h:103
#define PLUGIN_THEMES_CUSTOM
Definition: plugins.h:107
#define PLUGIN_RENDERED_EFFECTS_CUSTOM
in the config directory
Definition: plugins.h:472
#define REINIT_FUNCTIONAL
Definition: plugins.h:566
#define MAX_PARAM_WIDGETS
max number of display widgets per parameter (currently 7 for transition param with mergealign - spin ...
Definition: plugins.h:488
#define HIDDEN_GUI_PERM
Definition: plugins.h:551
#define PLUGIN_ENCODERS
Definition: plugins.h:98
#define RFX_MAXSTRINGLEN
length of max string (not including terminating NULL) for LiVES-perl
Definition: plugins.h:498
#define AUDIO_CODEC_MAX
Definition: plugins.h:250
@ RFX_STATUS_TEST
test effects in the advanced menu
Definition: plugins.h:614
@ RFX_STATUS_CUSTOM
custom effects in the custom menu
Definition: plugins.h:613
@ RFX_STATUS_WEED
indicates an internal RFX, created from a weed instance
Definition: plugins.h:616
@ RFX_STATUS_BUILTIN
factory presets
Definition: plugins.h:612
@ RFX_STATUS_INTERNAL
used for parsing RFX scraps generated internally (will possiblky replace SCRAP)
Definition: plugins.h:618
@ RFX_STATUS_SCRAP
used for parsing RFX scraps from external apps
Definition: plugins.h:617
@ LIVES_PARAM_SPECIAL_TYPE_NONE
Definition: plugins.h:519
#define AUDIO_CODEC_NONE
Definition: plugins.h:252
#define PLUGIN_AUDIO_STREAM
Definition: plugins.h:101
#define CAN_ENCODE_PNG
Definition: plugins.h:259
#define PVAL_MULTI_PER_CHANNEL
Definition: plugins.h:588
@ LIVES_PARAM_COLRGB24
Definition: plugins.h:504
@ LIVES_PARAM_STRING
Definition: plugins.h:505
@ LIVES_PARAM_UNDISPLAYABLE
Definition: plugins.h:509
@ LIVES_PARAM_STRING_LIST
Definition: plugins.h:506
@ LIVES_PARAM_BOOL
Definition: plugins.h:503
@ LIVES_PARAM_UNKNOWN
Definition: plugins.h:501
@ LIVES_PARAM_NUM
Definition: plugins.h:502
#define PLUGIN_DECODERS
Definition: plugins.h:99
#define HIDDEN_NEEDS_REINIT
non-structural (temporary)
Definition: plugins.h:557
#define PLUGIN_RENDERED_EFFECTS_TEST_SCRIPTS
Definition: plugins.h:480
#define VPP_LOCAL_DISPLAY
Definition: plugins.h:69
#define PLUGIN_RENDERED_EFFECTS_TEST
Definition: plugins.h:473
#define DEF_VPP_HSIZE
Definition: plugins.h:211
@ LIVES_INTENTION_PLAY
Definition: plugins.h:45
@ LIVES_INTENTION_TRANSCODE
Definition: plugins.h:47
#define LIVES_SEEK_FAST
good
Definition: plugins.h:312
@ LIVES_RFX_SOURCE_WEED
Definition: plugins.h:514
@ LIVES_RFX_SOURCE_RFX
Definition: plugins.h:513
#define PLUGIN_EFFECTS_WEED
uses WEED_PLUGIN_PATH
Definition: plugins.h:110
#define PLUGIN_RFX_SCRAP
scraps are passed between programs to generate param windows
Definition: plugins.h:483
#define PVAL_MULTI_ANY
Definition: plugins.h:587
#define PLUGIN_RENDERED_EFFECTS_CUSTOM_SCRIPTS
in the config directory
Definition: plugins.h:479
#define HIDDEN_MULTI
Definition: plugins.h:552
#define PLUGIN_THEMES
smogrify handles the directory differently for themes
Definition: plugins.h:106
#define PLUGIN_VID_PLAYBACK
Definition: plugins.h:100
#define VPP_CAN_RESIZE
type sepcific caps
Definition: plugins.h:67
#define PVAL_MULTI_NONE
Definition: plugins.h:586
#define PLUGIN_RENDERED_EFFECTS_BUILTIN
external rendered fx plugins (RFX plugins)
Definition: plugins.h:469
#define REINIT_VISUAL
Definition: plugins.h:567
#define DEF_VPP_VSIZE
Definition: plugins.h:212
#define RFX_FLAGS_NO_SLIDERS
internal use
Definition: plugins.h:646
#define RFX_PROPS_MAY_RESIZE
is a tool
Definition: plugins.h:635
void apply_button_set_enabled(LiVESWidget *widget, livespointer func_data)
Definition: preferences.c:2911
int set_string_pref(const char *key, const char *value)
Definition: preferences.c:290
void prefsw_set_astream_settings(_vid_playback_plugin *vpp, _prefsw *prefsw)
Definition: preferences.c:2730
void prefsw_set_rec_after_settings(_vid_playback_plugin *vpp, _prefsw *prefsw)
Definition: preferences.c:2741
void set_vpp(boolean set_in_prefs)
Definition: preferences.c:476
_prefs * prefs
Definition: preferences.h:847
#define AUD_PLAYER_JACK
Definition: preferences.h:43
_prefsw * prefsw
Definition: preferences.h:849
_future_prefs * future_prefs
Definition: preferences.h:848
#define PREF_VID_PLAYBACK_PLUGIN
Definition: preferences.h:920
#define AUD_PLAYER_PULSE
Definition: preferences.h:44
boolean auto_resample_resize(int width, int height, double fps, int fps_num, int fps_denom, int arate, int asigned, boolean swap_endian)
Definition: resample.c:80
_resaudw * resaudw
Definition: resample.h:38
#define EXEC_RFX_BUILDER
Definition: rfx-builder.h:10
#define RFX_VERSION
must match whatever is in RFX_BUILDER
Definition: rfx-builder.h:13
char of_desc[128]
Definition: plugins.h:264
char name[64]
Definition: plugins.h:234
char ptext[512]
Definition: plugins.h:268
char of_name[64]
Definition: plugins.h:263
char of_restrict[1024]
Definition: plugins.h:266
char of_def_ext[16]
Definition: plugins.h:267
uint32_t audio_codec
Definition: plugins.h:235
int of_allowed_acodecs
Definition: plugins.h:265
LiVESList * disabled_decoders_new
Definition: preferences.h:835
int vpp_fixed_fps_numer
Definition: preferences.h:803
int vpp_YUV_clamping
Definition: preferences.h:809
int vpp_fixed_fps_denom
Definition: preferences.h:804
LiVESList * disabled_decoders
Definition: preferences.h:834
double vpp_fixed_fpsd
Definition: preferences.h:806
char ** vpp_argv
Definition: preferences.h:817
_encoder encoder
Definition: preferences.h:820
char vpp_name[64]
new video playback plugin
Definition: preferences.h:801
LiVESWidget * dialog
Definition: mainwindow.h:1839
_encoder encoder
from main.h
Definition: preferences.h:38
int play_monitor
Definition: preferences.h:306
boolean show_gui
Definition: preferences.h:290
char workdir[PATH_MAX]
kept in locale encoding
Definition: preferences.h:61
char config_datadir[PATH_MAX]
kept in locale encoding (general config files) (default ~/.local/share/lives)
Definition: preferences.h:64
char prefix_dir[PATH_MAX]
Definition: preferences.h:74
char configfile[PATH_MAX]
kept in locale encoding (config settings) [default ~/.local/config/lives)
Definition: preferences.h:63
char lib_dir[PATH_MAX]
Definition: preferences.h:75
boolean stream_audio_out
Definition: preferences.h:360
char backend_sync[PATH_MAX *4]
Definition: preferences.h:410
short startup_phase
0 = normal , -1 or 1: fresh install, 2: workdir set, 3: startup tests passed, 4: aud pl chosen,...
Definition: preferences.h:216
short audio_player
Definition: preferences.h:40
LiVESWidget * prefs_dialog
Definition: preferences.h:536
LiVESWidget * aud_checkbutton
Definition: resample.h:32
LiVESWidget * rb_signed
Definition: resample.h:23
LiVESWidget * entry_asamps
Definition: resample.h:22
LiVESWidget * rb_littleend
Definition: resample.h:26
LiVESWidget * rb_unsigned
Definition: resample.h:24
LiVESWidget * rb_bigend
Definition: resample.h:25
LiVESWidget * entry_arate
Definition: resample.h:20
LiVESWidget * entry_achans
Definition: resample.h:21
uint64_t(* get_capabilities)(int palette)
Definition: plugins.h:135
uint64_t capabilities
Definition: plugins.h:177
weed_plant_t ** alpha_chans
Definition: plugins.h:195
const char *(* get_description)(void)
Definition: plugins.h:131
boolean(* render_frame)(int hsize, int vsize, ticks_t timecode, void **pixel_data, void **return_data, weed_plant_t **play_params)
Definition: plugins.h:137
char ** extra_argv
Definition: plugins.h:191
const char *(* get_fps_list)(int palette)
Definition: plugins.h:148
int(* set_yuv_palette_clamping)(int clamping_type)
Definition: plugins.h:163
boolean(* init_audio)(int in_sample_rate, int in_nchans, int argc, char **argv)
Definition: plugins.h:174
int palette
width in pixels, but converted to macropixels for the player
Definition: plugins.h:181
boolean(* render_audio_frame_float)(float **audio, int nsamps)
Definition: plugins.h:175
uint32_t audio_codec
Definition: plugins.h:169
boolean(* set_fps)(double fps)
Definition: plugins.h:149
const char *(* get_init_rfx)(int intention)
Definition: plugins.h:151
weed_plant_t ** play_params
Definition: plugins.h:194
void(* exit_screen)(uint16_t mouse_x, uint16_t mouse_y)
Definition: plugins.h:146
boolean(* set_palette)(int palette)
Definition: plugins.h:134
int *(* get_audio_fmts)(void)
Definition: plugins.h:167
const char *(* version)(void)
Definition: plugins.h:130
weed_plant_t *(* weed_setup)(weed_bootstrap_f)
Definition: plugins.h:143
int *(* get_palette_list)(void)
Definition: plugins.h:133
boolean(* play_frame)(weed_layer_t *frame, ticks_t tc, weed_layer_t *ret)
Definition: plugins.h:140
int *(* get_yuv_palette_clamping)(int palette)
Definition: plugins.h:160
void(* module_unload)(void)
Definition: plugins.h:147
const weed_plant_t ** play_paramtmpls
Definition: plugins.h:193
boolean(* init_screen)(int width, int height, boolean fullscreen, uint64_t window_id, int argc, char **argv)
Definition: plugins.h:144
const char *(* module_check_init)(void)
Definition: plugins.h:129
video playback plugin window - fixed part
Definition: plugins.h:729
LiVESWidget * spinbuttonh
Definition: plugins.h:732
LiVESWidget * fps_entry
Definition: plugins.h:735
LiVESWidget * apply_fx
Definition: plugins.h:734
lives_rfx_t * rfx
Definition: plugins.h:737
LiVESWidget * spinbuttonw
Definition: plugins.h:733
int intention
Definition: plugins.h:739
boolean keep_rfx
Definition: plugins.h:738
_vid_playback_plugin * plugin
Definition: plugins.h:730
LiVESWidget * dialog
Definition: plugins.h:731
LiVESWidget * pal_entry
Definition: plugins.h:736
lives_checkstatus_t has_mktemp
Definition: main.h:540
lives_checkstatus_t has_sox_sox
Definition: main.h:509
uint64_t python_version
Definition: main.h:574
lives_checkstatus_t has_convert
Definition: main.h:514
malloc_f * ext_malloc
Definition: plugins.h:324
free_f * ext_free
Definition: plugins.h:325
int * palettes
number forames from one keyframe to the next, 0 if unknown
Definition: plugins.h:375
memset_f * ext_memset
Definition: plugins.h:327
memmove_f * ext_memmove
Definition: plugins.h:328
memcpy_f * ext_memcpy
Definition: plugins.h:326
int64_t nframes
Definition: plugins.h:349
char video_name[512]
name of video codec, e.g. "theora" or NULL
Definition: plugins.h:386
int * rec_rowstrides
if non-NULL, plugin can set recommended vals, pointer to single value set by host
Definition: plugins.h:351
realloc_f * ext_realloc
Definition: plugins.h:329
lives_struct_def_t lsd
Definition: plugins.h:321
char audio_name[512]
name of audio codec, e.g. "vorbis" or NULL
Definition: plugins.h:394
calloc_f * ext_calloc
Definition: plugins.h:330
char container_name[512]
name of container, e.g. "ogg" or NULL
Definition: plugins.h:337
corresponds to one clip in the GUI
Definition: main.h:877
char file_name[PATH_MAX]
input file
Definition: main.h:923
void * ext_src
points to opaque source for non-disk types
Definition: main.h:1040
lives_clip_type_t clip_type
Definition: main.h:886
int ext_src_type
Definition: main.h:1051
char handle[256]
Definition: main.h:881
uint16_t green
Definition: main.h:318
uint16_t red
Definition: main.h:317
uint16_t blue
Definition: main.h:319
uint16_t alpha
Definition: main.h:326
uint16_t blue
Definition: main.h:325
uint16_t green
Definition: main.h:324
uint16_t red
Definition: main.h:323
int64_t(* rip_audio)(const lives_clip_data_t *, const char *fname, int64_t stframe, int64_t nframes, unsigned char **abuff)
Definition: plugins.h:443
boolean(* chill_out)(const lives_clip_data_t *)
free buffers when we arent playing sequentially / on standby
Definition: plugins.h:435
const char *(* version)(void)
Definition: plugins.h:418
const char *(* module_check_init)(void)
Definition: plugins.h:441
void(* module_unload)(void)
Definition: plugins.h:446
boolean(* set_palette)(lives_clip_data_t *)
Definition: plugins.h:442
boolean(* get_frame)(const lives_clip_data_t *, int64_t frame, int *rowstrides, int height, void **pixel_data)
frame starts at 0 in these functions; height is height of primary plane
Definition: plugins.h:432
void(* rip_audio_cleanup)(const lives_clip_data_t *cdata)
Definition: plugins.h:445
const char * name
plugin name
Definition: plugins.h:414
lives_clip_data_t *(* get_clip_data)(char *URI, const lives_clip_data_t *cdata)
call first time with NULL cdata subsequent calls should re-use cdata set cdata->current_clip > 0 to g...
Definition: plugins.h:429
void(* clip_data_free)(lives_clip_data_t *)
call this for each cdata before unloading the module
Definition: plugins.h:438
void * handle
may be shared between several instances
Definition: plugins.h:415
const lives_decoder_sys_t * decoder
Definition: plugins.h:450
lives_clip_data_t * cdata
Definition: plugins.h:451
int delegate
offset in list of current delegate
Definition: plugins.h:688
lives_param_type_t type
Definition: plugins.h:573
char * name
Definition: plugins.h:540
boolean use_mnemonic
Definition: plugins.h:545
char * label
Definition: plugins.h:543
boolean changed
Definition: plugins.h:597
short multi
multivalue type - single value, multi value, or per channel
Definition: plugins.h:585
boolean onchange
is there a trigger ?
Definition: plugins.h:595
boolean wrap
Definition: plugins.h:571
void * source
Definition: plugins.h:602
int dp
decimals, 0 for int and bool
Definition: plugins.h:575
LiVESWidget * widgets[MAX_PARAM_WIDGETS]
TODO - change to LiVESWidget **widgets, terminated with a NULL.
Definition: plugins.h:594
uint32_t hidden
Definition: plugins.h:546
char * desc
Definition: plugins.h:541
boolean transition
Definition: plugins.h:564
int special_type_index
Definition: plugins.h:608
void * def
default values
Definition: plugins.h:581
double min
Definition: plugins.h:578
double step_size
Definition: plugins.h:562
lives_param_special_t special_type
Definition: plugins.h:607
lives_rfx_source_t source_type
Definition: plugins.h:604
boolean edited
Definition: plugins.h:598
void * value
current value(s)
Definition: plugins.h:576
double max
for string this is max characters
Definition: plugins.h:579
boolean change_blocked
Definition: plugins.h:600
LiVESList * list
for string list (choices)
Definition: plugins.h:582
LiVESWidget * menuitem
the menu item which activates this effect
Definition: plugins.h:643
int num_params
Definition: plugins.h:644
char rfx_version[64]
Definition: plugins.h:653
uint32_t props
Definition: plugins.h:633
char * menu_text
for Weed, this is the filter_class "name"
Definition: plugins.h:627
char delim[2]
Definition: plugins.h:652
char * action_desc
for Weed "Applying $s"
Definition: plugins.h:628
LiVESList * gui_strings
rfxscript for constructing the params, param window and onchange triggers
Definition: plugins.h:654
uint32_t flags
Definition: plugins.h:645
lives_param_t * params
Definition: plugins.h:649
LiVESList * onchange_strings
rfxscript for constructing the params, param window and onchange triggers
Definition: plugins.h:655
lives_rfx_status_t status
Definition: plugins.h:631
int num_in_channels
Definition: plugins.h:630
void * source
points to the source (e.g. a weed_plant_t)
Definition: plugins.h:651
boolean is_template
Definition: plugins.h:656
lives_rfx_source_t source_type
Definition: plugins.h:650
int needs_reinit
Definition: plugins.h:657
int min_frames
for Weed, 1
Definition: plugins.h:629
char * name
the name of the executable (so we can run it !)
Definition: plugins.h:626
112 bytes
Definition: lsd.h:241
_vid_playback_plugin * vpp
video plugin
Definition: mainwindow.h:1572
int num_rendered_effects_builtin
Definition: mainwindow.h:856
volatile lives_rfx_t * vrfx_update
single access for updating alarm list
Definition: mainwindow.h:1510
int osc_auto
bypass user choices automatically
Definition: mainwindow.h:918
char msg[MAINW_MSG_SIZE]
Definition: mainwindow.h:724
boolean fx1_bool
Definition: mainwindow.h:1053
double fixed_fpsd
<=0. means free playback
Definition: mainwindow.h:990
void * pulsed
pulseaudio player
Definition: mainwindow.h:1463
lives_clip_t * files[MAX_FILES+1]
+1 for the clipboard
Definition: mainwindow.h:729
const char * new_vpp
Definition: mainwindow.h:1573
char * string_constants[NUM_LIVES_STRING_CONSTANTS]
Definition: mainwindow.h:1539
volatile boolean ext_audio
using external video playback plugin to stream audio
Definition: mainwindow.h:774
boolean noswitch
value set automatically to prevent 'inopportune' clip switching
Definition: mainwindow.h:1019
int num_rendered_effects_test
Definition: mainwindow.h:858
boolean is_ready
Definition: mainwindow.h:787
LiVESWidget * play_window
Definition: mainwindow.h:947
int num_rendered_effects_custom
Definition: mainwindow.h:857
void * jackd
jack audio player / transport
Definition: mainwindow.h:1453
short endian
Definition: mainwindow.h:817
boolean decoders_loaded
decoders
Definition: mainwindow.h:1611
boolean fs
Definition: mainwindow.h:762
pthread_mutex_t vpp_stream_mutex
prevent from writing audio when stream is closing
Definition: mainwindow.h:1501
int pwidth
PLAYBACK.
Definition: mainwindow.h:926
LiVESWidget * textwidget_focus
Definition: mainwindow.h:1569
boolean error
Definition: mainwindow.h:801
lives_fx_candidate_t fx_candidates[MAX_FX_CANDIDATE_TYPES]
< effects which can have candidates from which a delegate is selected (current examples are: audio_vo...
Definition: mainwindow.h:1514
boolean ext_playback
using external video playback plugin
Definition: mainwindow.h:773
int pheight
playback height
Definition: mainwindow.h:927
boolean sep_win
Definition: mainwindow.h:761
LiVESList * decoder_list
Definition: mainwindow.h:1612
lives_mt * multitrack
holds a pointer to the entire multitrack environment; NULL in Clip Edit mode
Definition: mainwindow.h:1087
int osc_enc_height
Definition: mainwindow.h:921
float osc_enc_fps
Definition: mainwindow.h:922
boolean save_with_sound
Definition: mainwindow.h:784
int osc_enc_width
encode width, height and fps set externally
Definition: mainwindow.h:921
boolean write_vpp_file
video playback plugin was updated; write settings to a file on exit
Definition: mainwindow.h:1040
lives_rfx_t * rendered_fx
rendered fx
Definition: mainwindow.h:855
char vpp_defs_file[PATH_MAX]
Definition: mainwindow.h:1627
weed_event_t * event_list
current event_list, for recording
Definition: mainwindow.h:803
ticks_t stream_ticks
ticks since first frame sent to playback plugin
Definition: mainwindow.h:1011
LiVESWidget * spinbutton_height
Definition: events.h:229
double fps
Definition: events.h:218
boolean is_encoding
Definition: events.h:248
boolean ratio_fps
Definition: events.h:219
LiVESWidget * spinbutton_fps
Definition: events.h:230
LiVESWidget * spinbutton_width
Definition: events.h:228
boolean suggestion_followed
Definition: events.h:246
LiVESWidget * last_container
container which wraps last widget created + subwidgets (READONLY)
double scale
scale factor for all sizes
boolean non_modal
non-modal for dialogs
int packing_height
vertical pixels between widgets
boolean mnemonic_label
if underscore in label text should be mnemonic accelerator
boolean use_markup
whether markup should be used in labels
#define lives_strdup_printf(fmt,...)
Definition: support.c:27
#define _(String)
Definition: support.h:44
int boolean
Definition: videoplugin.h:54
const char * version(void)
#define TRUE
Definition: videoplugin.h:59
#define FALSE
Definition: videoplugin.h:60
WEED_GLOBAL_INLINE weed_plant_t * weed_paramtmpl_get_gui(weed_plant_t *paramt, int create_if_not_exists)
char * weed_palette_get_name_full(int pal, int clamping, int subspace)
WEED_GLOBAL_INLINE int weed_paramtmpl_get_flags(weed_plant_t *paramtmpl)
WEED_GLOBAL_INLINE int weed_paramtmpl_does_wrap(weed_plant_t *paramtmpl)
WEED_GLOBAL_INLINE weed_plant_t * weed_param_get_template(weed_plant_t *param)
WEED_GLOBAL_INLINE int weed_paramtmpl_value_irrelevant(weed_plant_t *paramtmpl)
WEED_GLOBAL_INLINE int weed_paramtmpl_get_type(weed_plant_t *paramtmpl)
WEED_GLOBAL_INLINE int weed_gui_get_flags(weed_plant_t *gui)
gui plants
const char * weed_palette_get_name(int pal)
const char * weed_yuv_clamping_get_name(int clamping)
WEED_GLOBAL_INLINE weed_plant_t ** weed_instance_get_in_params(weed_plant_t *instance, int *nparams)
#define WEED_PLANT_IS_PARAMETER_TEMPLATE(plant)
#define WEED_PLANT_IS_PARAMETER(plant)
#define WEED_PLANT_IS_CHANNEL(plant)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_dialog_response(LiVESDialog *dialog, int response)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_present(LiVESWindow *window)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_xwindow_raise(LiVESXWindow *xwin)
void lives_set_cursor_style(lives_cursor_t cstyle, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_spin_button_set_value(LiVESSpinButton *button, double value)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_set_tooltip_text(LiVESWidget *widget, const char *tip_text)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_vbox_new(boolean homogeneous, int spacing)
WIDGET_HELPER_GLOBAL_INLINE LiVESAccelGroup * lives_accel_group_new(void)
boolean lives_button_grab_default_special(LiVESWidget *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_get_active(LiVESToggleButton *button)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_modal(LiVESWindow *window, boolean modal)
WIDGET_HELPER_GLOBAL_INLINE LiVESResponseType lives_dialog_run(LiVESDialog *dialog)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_box_pack_start(LiVESBox *box, LiVESWidget *child, boolean expand, boolean fill, uint32_t padding)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_combo_get_entry(LiVESCombo *widget)
LiVESWidget * lives_standard_dialog_new(const char *title, boolean add_std_buttons, int width, int height)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_grab_remove(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE const char * lives_entry_get_text(LiVESEntry *entry)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_dialog_get_content_area(LiVESDialog *dialog)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_fullscreen(LiVESWindow *window)
LiVESWidget * add_fill_to_box(LiVESBox *box)
WIDGET_HELPER_GLOBAL_INLINE int lives_spin_button_get_value_as_int(LiVESSpinButton *button)
WIDGET_HELPER_GLOBAL_INLINE uint64_t lives_widget_get_xwinid(LiVESWidget *widget, const char *msg)
char * lives_big_and_bold(const char *fmt,...)
LIVES_GLOBAL_INLINE boolean lives_widget_destroy(LiVESWidget *widget)
LiVESWidget * lives_standard_scrolled_window_new(int width, int height, LiVESWidget *child)
LiVESWidget * lives_dialog_add_button_from_stock(LiVESDialog *dialog, const char *stock_id, const char *label, int response_id)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_container_add(LiVESContainer *container, LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_grab_add(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_set_no_show_all(LiVESWidget *widget, boolean set)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_toggle_button_set_active(LiVESToggleButton *button, boolean active)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_show_all(LiVESWidget *widget)
boolean lives_widget_context_update(void)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_keep_below(LiVESWindow *window, boolean set)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_hbox_new(boolean homogeneous, int spacing)
LiVESWidget * lives_standard_label_new(const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_width_chars(LiVESEntry *entry, int nchars)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_entry_set_text(LiVESEntry *entry, const char *text)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_set_transient_for(LiVESWindow *window, LiVESWindow *parent)
WIDGET_HELPER_GLOBAL_INLINE LiVESWidget * lives_widget_get_toplevel(LiVESWidget *widget)
WIDGET_HELPER_GLOBAL_INLINE LiVESXWindow * lives_widget_get_xwindow(LiVESWidget *widget)
LiVESWidget * lives_standard_check_button_new(const char *labeltext, boolean active, LiVESBox *box, const char *tooltip)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_widget_add_accelerator(LiVESWidget *widget, const char *accel_signal, LiVESAccelGroup *accel_group, uint32_t accel_key, LiVESXModifierType accel_mods, LiVESAccelFlags accel_flags)
LiVESWidget * lives_standard_spin_button_new(const char *labeltext, double val, double min, double max, double step, double page, int dp, LiVESBox *box, const char *tooltip)
LiVESWidget * lives_standard_combo_new(const char *labeltext, LiVESList *list, LiVESBox *box, const char *tooltip)
int lives_utf8_strcmpfunc(livesconstpointer a, livesconstpointer b, livespointer fwd)
void lives_general_button_clicked(LiVESButton *button, livespointer data_to_free)
WIDGET_HELPER_GLOBAL_INLINE boolean lives_window_add_accel_group(LiVESWindow *window, LiVESAccelGroup *group)
@ LIVES_CURSOR_NORMAL
must be zero
@ LIVES_CURSOR_BUSY
#define TEXTWIDGET_KEY
ulong lives_signal_connect(LiVESWidget *, const char *signal_name, ulong funcptr, livespointer data)
widget_opts_t widget_opts