1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a unix video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdio.h>
26 
27 #include <X11/Xlib.h>
28 #include <X11/Xutil.h>
29 #include <X11/keysym.h>
30 
31 #include "common.h"
32 
33 #define VFREE(vfp) do {memset (vfp, 0x55, sizeof (*(vfp))); free (vfp); } while (0)
34 
35 #undef TRACE_REWIRE
36 
37 #define DEFAULT_DEINTERLACER "tvtime:method=LinearBlend,cheap_mode=1,pulldown=0,use_progressive_frame_flag=1"
38 
39 #define WINDOW_WIDTH        530
40 #define WINDOW_HEIGHT       503
41 
42 #define FRAME_WIDTH         (WINDOW_WIDTH - 50)
43 #define FRAME_HEIGHT        80
44 
45 #define HELP_WINDOW_WIDTH   400
46 #define HELP_WINDOW_HEIGHT  402
47 
48 #define MAX_DISPLAY_FILTERS 5
49 /* It hardly makes any sense to use infinitely many filters. */
50 #define MAX_USED_FILTERS    32
51 
52 #define MAX_DISP_ENTRIES    15
53 #define BROWSER_LINE_WIDTH  55
54 
55 #define DISABLE_ME(widget)                                                                      \
56     do {                                                                                        \
57       if(widget)                                                                                \
58         xitk_disable_and_hide_widget(widget);                                                   \
59     } while(0)
60 
61 #define ENABLE_ME(widget)                                                                       \
62     do {                                                                                        \
63       if(widget)                                                                                \
64         xitk_enable_and_show_widget(widget);                                                    \
65     } while(0)
66 
67 typedef struct {
68   xine_post_t                 *post;
69   const xine_post_api_t             *api;
70   const xine_post_api_descr_t       *descr;
71   const xine_post_api_parameter_t   *param;
72   char                        *param_data;
73 
74   int                          x;
75   int                          y;
76 
77   xitk_widget_t               *frame;
78   xitk_widget_t               *plugins;
79   xitk_widget_t               *properties;
80   xitk_widget_t               *value;
81   xitk_widget_t               *comment;
82 
83   xitk_widget_t               *up;
84   xitk_widget_t               *down;
85 
86   xitk_widget_t               *help;
87 
88   int                          readonly;
89 
90   char                       **properties_names;
91 } post_object_t;
92 
93 typedef struct {
94   xitk_window_t              *xwin;
95 
96   xitk_widget_list_t         *widget_list;
97 
98   xitk_widget_t              *slider;
99 
100   char                      **plugin_names;
101 
102   post_object_t              *post_objects[MAX_USED_FILTERS];
103   int                         first_displayed;
104   int                         object_num;
105 
106   xitk_widget_t              *enable;
107 
108   int                         x, y;
109 
110   int                         running;
111   int                         visible;
112   xitk_register_key_t         widget_key;
113 
114   /* help window stuff */
115   xitk_window_t              *helpwin;
116   xitk_widget_list_t         *help_widget_list;
117   char                      **help_text;
118   xitk_register_key_t         help_widget_key;
119   int                         help_running;
120   xitk_widget_t              *help_browser;
121 } _pplugin_t;
122 
123 typedef struct {
124   _pplugin_t                 *pplugin;
125 } _pp_wrapper_t;
126 
127 static _pp_wrapper_t vpp_wrapper = { NULL };
128 static _pp_wrapper_t app_wrapper = { NULL };
129 static char        **post_audio_plugins;
130 
131 /* Some functions prototype */
132 static void _vpplugin_unwire(void);
133 static void _applugin_unwire(void);
134 static void _pplugin_unwire(_pp_wrapper_t *pp_wrapper);
135 static post_element_t **pplugin_parse_and_load(_pp_wrapper_t *pp_wrapper, const char *, int *);
136 static void _vpplugin_rewire(void);
137 static void _applugin_rewire(void);
138 static void _pplugin_rewire(_pp_wrapper_t *pp_wrapper);
139 static void _pplugin_rewire_from_post_elements(_pp_wrapper_t *pp_wrapper, post_element_t **, int);
140 static post_element_t **_pplugin_join_deinterlace_and_post_elements(int *);
141 static post_element_t **_pplugin_join_visualization_and_post_elements(int *);
142 static void _pplugin_save_chain(_pp_wrapper_t *pp_wrapper);
143 static void _vpplugin_close_help(xitk_widget_t *, void *);
144 static void _applugin_close_help(xitk_widget_t *, void *);
145 static void _pplugin_close_help(_pp_wrapper_t *pp_wrapper, xitk_widget_t *, void *);
146 
post_deinterlace_plugin_cb(void * data,xine_cfg_entry_t * cfg)147 static void post_deinterlace_plugin_cb(void *data, xine_cfg_entry_t *cfg) {
148   gGui_t *gui = data;
149   post_element_t **posts = NULL;
150   int              num, i;
151 
152   gui->deinterlace_plugin = cfg->str_value;
153 
154   if(gui->deinterlace_enable)
155     _vpplugin_unwire();
156 
157   for(i = 0; i < gui->deinterlace_elements_num; i++) {
158     xine_post_dispose(__xineui_global_xine_instance, gui->deinterlace_elements[i]->post);
159     free(gui->deinterlace_elements[i]->name);
160     VFREE(gui->deinterlace_elements[i]);
161   }
162 
163   SAFE_FREE(gui->deinterlace_elements);
164   gui->deinterlace_elements_num = 0;
165 
166   if((posts = pplugin_parse_and_load(&vpp_wrapper, gui->deinterlace_plugin, &num))) {
167     gui->deinterlace_elements     = posts;
168     gui->deinterlace_elements_num = num;
169   }
170 
171   if(gui->deinterlace_enable)
172     _vpplugin_rewire();
173 }
174 
post_audio_plugin_cb(void * data,xine_cfg_entry_t * cfg)175 static void post_audio_plugin_cb(void *data, xine_cfg_entry_t *cfg) {
176   gGui_t *gui = data;
177   gui->visual_anim.post_plugin_num = cfg->num_value;
178   post_rewire_visual_anim();
179 }
180 
post_get_audio_plugins_names(void)181 const char **post_get_audio_plugins_names(void) {
182   return (const char **) post_audio_plugins;
183 }
184 
post_init(void)185 void post_init(void) {
186   gGui_t *gui = gGui;
187 
188   memset(&gui->visual_anim.post_output_element, 0, sizeof (gui->visual_anim.post_output_element));
189 
190   gui->visual_anim.post_plugin_num = -1;
191   gui->visual_anim.post_changed = 0;
192 
193   if(gui->ao_port) {
194     const char *const *pol = xine_list_post_plugins_typed(__xineui_global_xine_instance,
195 							  XINE_POST_TYPE_AUDIO_VISUALIZATION);
196 
197     if(pol) {
198       int  num_plug = 0;
199 
200       while(pol[num_plug]) {
201 
202 	post_audio_plugins = (char **) realloc(post_audio_plugins, sizeof(char *) * (num_plug + 2));
203 
204 	post_audio_plugins[num_plug]     = strdup(pol[num_plug]);
205 	post_audio_plugins[num_plug + 1] = NULL;
206 	num_plug++;
207       }
208 
209       if(num_plug) {
210 
211 	gui->visual_anim.post_plugin_num =
212 	  xine_config_register_enum(__xineui_global_xine_instance, "gui.post_audio_plugin",
213 				    0, post_audio_plugins,
214 				    _("Audio visualization plugin"),
215 				    _("Post audio plugin to used when playing streams without video"),
216 				    CONFIG_LEVEL_BEG,
217 				    post_audio_plugin_cb,
218 				    gGui);
219 
220 	gui->visual_anim.post_output_element.post =
221 	  xine_post_init(__xineui_global_xine_instance,
222 			 post_audio_plugins[gui->visual_anim.post_plugin_num], 0,
223 			 &gui->ao_port, &gui->vo_port);
224 
225       }
226     }
227   }
228 }
229 
post_rewire_visual_anim(void)230 void post_rewire_visual_anim(void) {
231   gGui_t *gui = gGui;
232 
233   if(gui->visual_anim.post_output_element.post) {
234     (void) post_rewire_audio_port_to_stream(gui->stream);
235 
236     xine_post_dispose(__xineui_global_xine_instance, gui->visual_anim.post_output_element.post);
237   }
238 
239   gui->visual_anim.post_output_element.post =
240     xine_post_init(__xineui_global_xine_instance,
241 		   post_audio_plugins[gui->visual_anim.post_plugin_num], 0,
242 		   &gui->ao_port, &gui->vo_port);
243 
244   if(gui->visual_anim.post_output_element.post &&
245      (gui->visual_anim.enabled == 1) && (gui->visual_anim.running == 1)) {
246 
247     (void) post_rewire_audio_post_to_stream(gui->stream);
248 
249   }
250 }
251 
252 static int ignore_visual_anim = 1;
253 
post_rewire_audio_port_to_stream(xine_stream_t * stream)254 int post_rewire_audio_port_to_stream(xine_stream_t *stream) {
255 
256   _applugin_unwire();
257   ignore_visual_anim = 1;
258   _applugin_rewire();
259 /*
260   gGui_t *gui = gGui;
261   xine_post_out_t * audio_source;
262 
263   audio_source = xine_get_audio_source(stream);
264   return xine_post_wire_audio_port(audio_source, gui->ao_port);
265 */
266   return 1;
267 }
268 
post_rewire_audio_post_to_stream(xine_stream_t * stream)269 int post_rewire_audio_post_to_stream(xine_stream_t *stream) {
270 
271   _applugin_unwire();
272   ignore_visual_anim = 0;
273   _applugin_rewire();
274 /*
275   xine_post_out_t * audio_source;
276   gGui_t *gui = gGui;
277 
278   audio_source = xine_get_audio_source(stream);
279   return xine_post_wire_audio_port(audio_source, gui->visual_anim.post_output->audio_input[0]);
280 */
281   return 1;
282 }
283 
284 /* ================================================================ */
285 
_vpplugin_unwire(void)286 static void _vpplugin_unwire(void) {
287   gGui_t *gui = gGui;
288   xine_post_out_t  *vo_source;
289 
290   if (gui->stream) {
291     vo_source = xine_get_video_source(gui->stream);
292 
293     if (gui->vo_port)
294       (void) xine_post_wire_video_port(vo_source, gui->vo_port);
295   }
296 }
297 
_applugin_unwire(void)298 static void _applugin_unwire(void) {
299   gGui_t *gui = gGui;
300   xine_post_out_t  *ao_source;
301 
302   if (gui->stream) {
303     ao_source = xine_get_audio_source(gui->stream);
304 
305     if (gui->ao_port)
306       (void) xine_post_wire_audio_port(ao_source, gui->ao_port);
307   }
308 }
309 
_pplugin_unwire(_pp_wrapper_t * pp_wrapper)310 static void _pplugin_unwire(_pp_wrapper_t *pp_wrapper) {
311   if (pp_wrapper == &vpp_wrapper)
312     _vpplugin_unwire();
313   else
314     _applugin_unwire();
315 }
316 
_vpplugin_rewire(void)317 static void _vpplugin_rewire(void) {
318   static post_element_t **post_elements;
319   int post_elements_num;
320   _pp_wrapper_t *pp_wrapper = &vpp_wrapper;
321 
322   _pplugin_save_chain(pp_wrapper);
323 
324   post_elements = _pplugin_join_deinterlace_and_post_elements(&post_elements_num);
325 
326   if( post_elements ) {
327     _pplugin_rewire_from_post_elements(pp_wrapper, post_elements, post_elements_num);
328 
329     free(post_elements);
330   }
331 
332 #if 0
333   gGui_t *gui = gGui;
334   if(pplugin && (gui->post_enable && !gui->deinterlace_enable)) {
335     xine_post_out_t  *vo_source;
336     int               post_num = pplugin->object_num;
337     int               i = 0;
338 
339     if(!xitk_combo_get_current_selected(pplugin->post_objects[post_num - 1]->plugins))
340       post_num--;
341 
342     if(post_num) {
343       int paused = 0;
344 
345       if((paused = (xine_get_param(gui->stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE)))
346 	xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_SLOW_4);
347 
348       for(i = (post_num - 1); i >= 0; i--) {
349 	const char *const *outs = xine_post_list_outputs(pplugin->post_objects[i]->post);
350 	const xine_post_out_t *vo_out = xine_post_output(pplugin->post_objects[i]->post, (char *) *outs);
351 	if(i == (post_num - 1)) {
352 #ifdef TRACE_REWIRE
353 	  printf("  VIDEO_OUT .. OUT<-[PLUGIN %d]\n", i);
354 #endif
355 	  xine_post_wire_video_port((xine_post_out_t *) vo_out, gui->vo_port);
356 	}
357 	else {
358 	  const xine_post_in_t *vo_in = xine_post_input(pplugin->post_objects[i+1]->post, "video");
359 	  int                   err;
360 
361 #ifdef TRACE_REWIRE
362 	  printf("  [PLUGIN %d]->IN ... OUT<-[PLUGIN %d]", i+1, i);
363 #endif
364 	  err = xine_post_wire((xine_post_out_t *) vo_out, (xine_post_in_t *) vo_in);
365 #ifdef TRACE_REWIRE
366 	  printf(" (RESULT: %d)\n", err);
367 #endif
368 	}
369       }
370 
371 #ifdef TRACE_REWIRE
372       printf("  [PLUGIN %d]->IN .. STREAM\n", 0);
373 #endif
374 
375       vo_source = xine_get_video_source(gui->stream);
376       xine_post_wire_video_port(vo_source, pplugin->post_objects[0]->post->video_input[0]);
377 
378       if(paused)
379 	xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
380 
381     }
382   }
383 #endif
384 }
385 
_applugin_rewire(void)386 static void _applugin_rewire(void) {
387   static post_element_t **post_elements;
388   int post_elements_num;
389   _pp_wrapper_t *pp_wrapper = &app_wrapper;
390 
391   _pplugin_save_chain(pp_wrapper);
392 
393   post_elements = _pplugin_join_visualization_and_post_elements(&post_elements_num);
394 
395   if( post_elements ) {
396     _pplugin_rewire_from_post_elements(pp_wrapper, post_elements, post_elements_num);
397 
398     free(post_elements);
399   }
400 }
401 
_pplugin_rewire(_pp_wrapper_t * pp_wrapper)402 static void _pplugin_rewire(_pp_wrapper_t *pp_wrapper) {
403   if (pp_wrapper == &vpp_wrapper)
404     _vpplugin_rewire();
405   else
406     _applugin_rewire();
407 }
408 
_pplugin_get_object_offset(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)409 static int _pplugin_get_object_offset(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
410   int i;
411 
412   for(i = 0; i < pp_wrapper->pplugin->object_num; i++) {
413     if(pp_wrapper->pplugin->post_objects[i] == pobj)
414       return i;
415   }
416 
417   return 0;
418 }
419 
_pplugin_is_first_filter(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)420 static int _pplugin_is_first_filter(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
421   if(pp_wrapper->pplugin)
422     return (pobj == *pp_wrapper->pplugin->post_objects);
423 
424   return 0;
425 }
426 
_pplugin_is_last_filter(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)427 static int _pplugin_is_last_filter(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
428 
429   if(pp_wrapper->pplugin) {
430     post_object_t **po = pp_wrapper->pplugin->post_objects;
431 
432     while(*po && (*po != pobj))
433       po++;
434 
435     if(*(po + 1) == NULL)
436       return 1;
437   }
438 
439   return 0;
440 }
441 
_pplugin_hide_obj(post_object_t * pobj)442 static void _pplugin_hide_obj(post_object_t *pobj) {
443   if(pobj) {
444     DISABLE_ME(pobj->frame);
445     DISABLE_ME(pobj->plugins);
446     DISABLE_ME(pobj->properties);
447     DISABLE_ME(pobj->value);
448     DISABLE_ME(pobj->comment);
449     DISABLE_ME(pobj->up);
450     DISABLE_ME(pobj->down);
451     DISABLE_ME(pobj->help);
452   }
453 }
454 
_pplugin_show_obj(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)455 static void _pplugin_show_obj(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
456 
457   if(pobj) {
458 
459     if(pobj->frame)
460       xitk_set_widget_pos(pobj->frame, pobj->x, pobj->y);
461 
462     if(pobj->plugins)
463       xitk_set_widget_pos(pobj->plugins, pobj->x + 26 + 6, pobj->y + 5 + (20 - xitk_get_widget_height(pobj->plugins)) / 2);
464 
465     if(pobj->properties)
466       xitk_set_widget_pos(pobj->properties, pobj->x + 26 + 196, pobj->y + 5 + (20 - xitk_get_widget_height(pobj->properties)) / 2);
467 
468     if(pobj->help)
469       xitk_set_widget_pos(pobj->help, pobj->x + 26 + 386, pobj->y + 5);
470 
471     if(pobj->comment)
472       xitk_set_widget_pos(pobj->comment, pobj->x + 26 + 6, pobj->y + 28 + 4);
473 
474     if(pobj->value)
475       xitk_set_widget_pos(pobj->value, pobj->x + 26 + 6, pobj->y + (FRAME_HEIGHT - 5 + 1) - (20 + xitk_get_widget_height(pobj->value)) / 2);
476 
477     if(pobj->up)
478       xitk_set_widget_pos(pobj->up, pobj->x + 5, pobj->y + 5);
479 
480     if(pobj->down)
481       xitk_set_widget_pos(pobj->down, pobj->x + 5, pobj->y + (FRAME_HEIGHT - 16 - 5));
482 
483     ENABLE_ME(pobj->frame);
484     ENABLE_ME(pobj->plugins);
485     ENABLE_ME(pobj->properties);
486     ENABLE_ME(pobj->value);
487     ENABLE_ME(pobj->comment);
488     ENABLE_ME(pobj->help);
489 
490     if((!_pplugin_is_first_filter(pp_wrapper, pobj)) && (xitk_combo_get_current_selected(pobj->plugins)))
491       ENABLE_ME(pobj->up);
492 
493     if((!_pplugin_is_last_filter(pp_wrapper, pobj) && (xitk_combo_get_current_selected(pobj->plugins))) &&
494        (_pplugin_is_last_filter(pp_wrapper, pobj)
495 	|| (!_pplugin_is_last_filter(pp_wrapper, pobj)
496 	    && pp_wrapper->pplugin->post_objects[_pplugin_get_object_offset(pp_wrapper, pobj) + 1]
497 	    && xitk_combo_get_current_selected(pp_wrapper->pplugin->post_objects[_pplugin_get_object_offset(pp_wrapper, pobj) + 1]->plugins))))
498       ENABLE_ME(pobj->down);
499 
500   }
501 }
502 
_pplugin_paint_widgets(_pp_wrapper_t * pp_wrapper)503 static void _pplugin_paint_widgets(_pp_wrapper_t *pp_wrapper) {
504   if(pp_wrapper->pplugin) {
505     int   i, x, y;
506     int   last;
507     int   slidmax, slidpos;
508 
509     last = pp_wrapper->pplugin->object_num <= (pp_wrapper->pplugin->first_displayed + MAX_DISPLAY_FILTERS)
510       ? pp_wrapper->pplugin->object_num : (pp_wrapper->pplugin->first_displayed + MAX_DISPLAY_FILTERS);
511 
512     for(i = 0; i < pp_wrapper->pplugin->object_num; i++)
513       _pplugin_hide_obj(pp_wrapper->pplugin->post_objects[i]);
514 
515     x = 15;
516     y = 34 - (FRAME_HEIGHT + 4);
517 
518     for(i = pp_wrapper->pplugin->first_displayed; i < last; i++) {
519       y += FRAME_HEIGHT + 4;
520       pp_wrapper->pplugin->post_objects[i]->x = x;
521       pp_wrapper->pplugin->post_objects[i]->y = y;
522       _pplugin_show_obj(pp_wrapper, pp_wrapper->pplugin->post_objects[i]);
523     }
524 
525     if(pp_wrapper->pplugin->object_num > MAX_DISPLAY_FILTERS) {
526       slidmax = pp_wrapper->pplugin->object_num - MAX_DISPLAY_FILTERS;
527       slidpos = slidmax - pp_wrapper->pplugin->first_displayed;
528       xitk_enable_and_show_widget(pp_wrapper->pplugin->slider);
529     }
530     else {
531       slidmax = 1;
532       slidpos = slidmax;
533 
534       if(!pp_wrapper->pplugin->first_displayed)
535 	xitk_disable_and_hide_widget(pp_wrapper->pplugin->slider);
536     }
537 
538     xitk_slider_set_max(pp_wrapper->pplugin->slider, slidmax);
539     xitk_slider_set_pos(pp_wrapper->pplugin->slider, slidpos);
540   }
541 }
542 
_pplugin_send_expose(_pp_wrapper_t * pp_wrapper)543 static void _pplugin_send_expose(_pp_wrapper_t *pp_wrapper) {
544   gGui_t *gui = gGui;
545   if(pp_wrapper->pplugin) {
546     gui->x_lock_display (gui->display);
547     XClearWindow(gui->display, (XITK_WIDGET_LIST_WINDOW(pp_wrapper->pplugin->widget_list)));
548     gui->x_unlock_display (gui->display);
549   }
550 }
551 
_pplugin_destroy_widget(xitk_widget_t ** w)552 static void _pplugin_destroy_widget (xitk_widget_t **w) {
553   xitk_destroy_widget (*w);
554   *w = NULL;
555 }
556 
_pplugin_update_parameter(post_object_t * pobj)557 static void _pplugin_update_parameter(post_object_t *pobj) {
558   pobj->api->set_parameters(pobj->post, pobj->param_data);
559   pobj->api->get_parameters(pobj->post, pobj->param_data);
560 }
561 
_pplugin_set_param_int(xitk_widget_t * w,void * data,int value)562 static void _pplugin_set_param_int(xitk_widget_t *w, void *data, int value) {
563   post_object_t *pobj = (post_object_t *) data;
564 
565   if(pobj->readonly)
566     return;
567 
568   //can be int[]:
569   //int num_of_int = pobj->param->size / sizeof(char);
570 
571   if(pobj->param->range_min && pobj->param->range_max &&
572      (value < (int)pobj->param->range_min || value > (int)pobj->param->range_max)) {
573     xine_error(_("Entered value is out of bounds (%d>%d<%d)."),
574 	       (int)pobj->param->range_min, value, (int)pobj->param->range_max);
575   }
576   else {
577     *(int *)(pobj->param_data + pobj->param->offset) = value;
578 
579     _pplugin_update_parameter(pobj);
580 
581     if(xitk_get_widget_type(w) & WIDGET_GROUP_COMBO)
582       xitk_combo_set_select(pobj->value, *(int *)(pobj->param_data + pobj->param->offset));
583     else
584       xitk_intbox_set_value(pobj->value, *(int *)(pobj->param_data + pobj->param->offset));
585   }
586 }
587 
_pplugin_set_param_double(xitk_widget_t * w,void * data,double value)588 static void _pplugin_set_param_double(xitk_widget_t *w, void *data, double value) {
589   post_object_t *pobj = (post_object_t *) data;
590 
591   if(pobj->readonly)
592     return;
593 
594   if(pobj->param->range_min && pobj->param->range_max &&
595      (value < pobj->param->range_min || value > pobj->param->range_max)) {
596     xine_error(_("Entered value is out of bounds (%e>%e<%e)."),
597 	       pobj->param->range_min, value, pobj->param->range_max);
598   }
599   else {
600     *(double *)(pobj->param_data + pobj->param->offset) = value;
601 
602     _pplugin_update_parameter(pobj);
603 
604     xitk_doublebox_set_value(pobj->value, *(double *)(pobj->param_data + pobj->param->offset));
605   }
606 }
607 
_pplugin_set_param_char(xitk_widget_t * w,void * data,const char * text)608 static void _pplugin_set_param_char(xitk_widget_t *w, void *data, const char *text) {
609   post_object_t *pobj = (post_object_t *) data;
610 
611   if(pobj->readonly)
612     return;
613 
614   // SUPPORT CHAR but no STRING yet
615   if(pobj->param->type == POST_PARAM_TYPE_CHAR) {
616     int maxlen = pobj->param->size / sizeof(char);
617 
618     strlcpy((char *)(pobj->param_data + pobj->param->offset), text, maxlen);
619     _pplugin_update_parameter(pobj);
620     xitk_inputtext_change_text(pobj->value, (char *)(pobj->param_data + pobj->param->offset));
621   }
622   else
623     xine_error(_("parameter type POST_PARAM_TYPE_STRING not supported yet.\n"));
624 
625 }
626 
_pplugin_set_param_stringlist(xitk_widget_t * w,void * data,int value)627 static void _pplugin_set_param_stringlist(xitk_widget_t *w, void *data, int value) {
628   post_object_t *pobj = (post_object_t *) data;
629 
630   if(pobj->readonly)
631     return;
632 
633   xine_error(_("parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n"));
634 }
635 
_pplugin_set_param_bool(xitk_widget_t * w,void * data,int state)636 static void _pplugin_set_param_bool(xitk_widget_t *w, void *data, int state) {
637   post_object_t *pobj = (post_object_t *) data;
638 
639   if(pobj->readonly)
640     return;
641 
642   *(int *)(pobj->param_data + pobj->param->offset) = state;
643   _pplugin_update_parameter(pobj);
644   xitk_checkbox_set_state(pobj->value,
645 			  (*(int *)(pobj->param_data + pobj->param->offset)));
646 }
647 
_pplugin_add_parameter_widget(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)648 static void _pplugin_add_parameter_widget(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
649   gGui_t *gui = gGui;
650 
651   if(pobj) {
652     xitk_label_widget_t   lb;
653     char                  buffer[2048];
654 
655     snprintf(buffer, sizeof(buffer), "%s:", (pobj->param->description)
656 	     ? pobj->param->description : _("No description available"));
657 
658     XITK_WIDGET_INIT(&lb, gui->imlib_data);
659     lb.window              = xitk_window_get_window(pp_wrapper->pplugin->xwin);
660     lb.gc                  = (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->widget_list));
661     lb.skin_element_name   = NULL;
662     lb.label               = buffer;
663     lb.callback            = NULL;
664     lb.userdata            = NULL;
665     pobj->comment =  xitk_noskin_label_create (pp_wrapper->pplugin->widget_list, &lb,
666       0, 0, FRAME_WIDTH - (26 + 6 + 6), 20, hboldfontname);
667     xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->comment);
668 
669     switch(pobj->param->type) {
670     case POST_PARAM_TYPE_INT:
671       {
672 	if(pobj->param->enum_values) {
673 	  xitk_combo_widget_t         cmb;
674 
675 	  XITK_WIDGET_INIT(&cmb, gui->imlib_data);
676 	  cmb.skin_element_name = NULL;
677 	  cmb.layer_above       = (is_layer_above());
678 	  cmb.parent_wlist      = pp_wrapper->pplugin->widget_list;
679 	  cmb.entries           = (const char **)pobj->param->enum_values;
680 	  cmb.parent_wkey       = &pp_wrapper->pplugin->widget_key;
681 	  cmb.callback          = _pplugin_set_param_int;
682 	  cmb.userdata          = pobj;
683           pobj->value = xitk_noskin_combo_create (pp_wrapper->pplugin->widget_list, &cmb,
684             0, 0, 365, NULL, NULL);
685           xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
686 	  xitk_combo_set_select(pobj->value, *(int *)(pobj->param_data + pobj->param->offset));
687 	}
688 	else {
689 	  xitk_intbox_widget_t      ib;
690 
691 	  XITK_WIDGET_INIT(&ib, gui->imlib_data);
692 	  ib.skin_element_name = NULL;
693 	  ib.value             = *(int *)(pobj->param_data + pobj->param->offset);
694 	  ib.step              = 1;
695 	  ib.parent_wlist      = pp_wrapper->pplugin->widget_list;
696 	  ib.callback          = _pplugin_set_param_int;
697 	  ib.userdata          = pobj;
698           pobj->value =  xitk_noskin_intbox_create (pp_wrapper->pplugin->widget_list, &ib,
699             0, 0, 50, 20, NULL, NULL, NULL);
700           xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
701 	}
702       }
703       break;
704 
705     case POST_PARAM_TYPE_DOUBLE:
706       {
707 	xitk_doublebox_widget_t      ib;
708 
709 	XITK_WIDGET_INIT(&ib, gui->imlib_data);
710 	ib.skin_element_name = NULL;
711 	ib.value             = *(double *)(pobj->param_data + pobj->param->offset);
712 	ib.step              = .5;
713 	ib.parent_wlist      = pp_wrapper->pplugin->widget_list;
714 	ib.callback          = _pplugin_set_param_double;
715 	ib.userdata          = pobj;
716         pobj->value =  xitk_noskin_doublebox_create (pp_wrapper->pplugin->widget_list, &ib,
717           0, 0, 100, 20, NULL, NULL, NULL);
718         xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
719       }
720       break;
721 
722     case POST_PARAM_TYPE_CHAR:
723     case POST_PARAM_TYPE_STRING:
724       {
725 	xitk_inputtext_widget_t  inp;
726 
727 	XITK_WIDGET_INIT(&inp, gui->imlib_data);
728 	inp.skin_element_name = NULL;
729 	inp.text              = (char *)(pobj->param_data + pobj->param->offset);
730 	inp.max_length        = 256;
731 	inp.callback          = _pplugin_set_param_char;
732 	inp.userdata          = pobj;
733         pobj->value =  xitk_noskin_inputtext_create (pp_wrapper->pplugin->widget_list, &inp,
734           0, 0, 365, 20, "Black", "Black", fontname);
735         xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
736       }
737       break;
738 
739     case POST_PARAM_TYPE_STRINGLIST:
740       {
741 	xitk_combo_widget_t         cmb;
742 
743 	XITK_WIDGET_INIT(&cmb, gui->imlib_data);
744 	cmb.skin_element_name = NULL;
745 	cmb.layer_above       = (is_layer_above());
746 	cmb.parent_wlist      = pp_wrapper->pplugin->widget_list;
747 	cmb.entries           = (const char **)(pobj->param_data + pobj->param->offset);
748 	cmb.parent_wkey       = &pp_wrapper->pplugin->widget_key;
749 	cmb.callback          = _pplugin_set_param_stringlist;
750 	cmb.userdata          = pobj;
751         pobj->value = xitk_noskin_combo_create (pp_wrapper->pplugin->widget_list, &cmb,
752           0, 0, 365, NULL, NULL);
753         xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
754 	xitk_combo_set_select(pobj->value, *(int *)(pobj->param_data + pobj->param->offset));
755       }
756       break;
757 
758     case POST_PARAM_TYPE_BOOL:
759       {
760 	xitk_checkbox_widget_t    cb;
761 
762 	XITK_WIDGET_INIT(&cb, gui->imlib_data);
763 	cb.skin_element_name = NULL;
764 	cb.callback          = _pplugin_set_param_bool;
765 	cb.userdata          = pobj;
766         pobj->value =  xitk_noskin_checkbox_create (pp_wrapper->pplugin->widget_list, &cb, 0, 0, 12, 12);
767         xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->value);
768 	xitk_checkbox_set_state(pobj->value,
769 				(*(int *)(pobj->param_data + pobj->param->offset)));
770       }
771       break;
772     }
773   }
774 }
775 
_pplugin_change_parameter(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data,int select)776 static void _pplugin_change_parameter(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data, int select) {
777   post_object_t *pobj = (post_object_t *) data;
778 
779   if(pobj) {
780 
781     _pplugin_destroy_widget (&pobj->value);
782     _pplugin_destroy_widget (&pobj->comment);
783 
784     if(pobj->descr) {
785       pobj->param    = pobj->descr->parameter;
786       pobj->param    += select;
787       pobj->readonly = pobj->param->readonly;
788       _pplugin_add_parameter_widget(pp_wrapper, pobj);
789     }
790 
791     _pplugin_paint_widgets(pp_wrapper);
792   }
793 }
794 
_vpplugin_change_parameter(xitk_widget_t * w,void * data,int select)795 static void _vpplugin_change_parameter(xitk_widget_t *w, void *data, int select) {
796   return _pplugin_change_parameter(&vpp_wrapper, w, data, select);
797 }
798 
_applugin_change_parameter(xitk_widget_t * w,void * data,int select)799 static void _applugin_change_parameter(xitk_widget_t *w, void *data, int select) {
800   return _pplugin_change_parameter(&app_wrapper, w, data, select);
801 }
802 
_pplugin_get_plugins(_pp_wrapper_t * pp_wrapper)803 static void _pplugin_get_plugins(_pp_wrapper_t *pp_wrapper) {
804   int plugin_type = (pp_wrapper == &vpp_wrapper) ? XINE_POST_TYPE_VIDEO_FILTER : XINE_POST_TYPE_AUDIO_FILTER;
805   const char *const *pol = xine_list_post_plugins_typed(__xineui_global_xine_instance, plugin_type);
806 
807   if(pol) {
808     int  i = 0;
809 
810     pp_wrapper->pplugin->plugin_names    = (char **) malloc(sizeof(char *) * 2);
811     pp_wrapper->pplugin->plugin_names[i] = strdup(_("No Filter"));
812     while(pol[i]) {
813       pp_wrapper->pplugin->plugin_names = (char **) realloc(pp_wrapper->pplugin->plugin_names, sizeof(char *) * (i + 1 + 2));
814 
815       pp_wrapper->pplugin->plugin_names[i + 1] = strdup(pol[i]);
816       i++;
817     }
818     pp_wrapper->pplugin->plugin_names[i + 1] = NULL;
819   }
820 }
821 
_pplugin_destroy_only_obj(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)822 static void _pplugin_destroy_only_obj(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
823   if(pobj) {
824 
825     if(pobj->properties) {
826 
827       _pplugin_destroy_widget (&pobj->properties);
828 
829       VFREE(pobj->param_data);
830       pobj->param_data = NULL;
831 
832       if(pobj->properties_names) {
833 	int pnum = 0;
834 
835 	while(pobj->properties_names[pnum]) {
836 	  free(pobj->properties_names[pnum]);
837 	  pnum++;
838 	}
839 
840 	free(pobj->properties_names);
841 	pobj->properties_names = NULL;
842       }
843     }
844 
845     _pplugin_destroy_widget (&pobj->comment);
846     _pplugin_destroy_widget (&pobj->value);
847 
848     if(pobj->api && pobj->help) {
849       if(pp_wrapper->pplugin->help_running)
850 	_pplugin_close_help(pp_wrapper, NULL,NULL);
851       _pplugin_destroy_widget (&pobj->help);
852     }
853 
854   }
855 }
856 
__pplugin_retrieve_parameters(post_object_t * pobj)857 static int __pplugin_retrieve_parameters(post_object_t *pobj) {
858   xine_post_in_t             *input_api;
859 
860   if((input_api = (xine_post_in_t *) xine_post_input(pobj->post, "parameters"))) {
861     const xine_post_api_t            *post_api;
862     const xine_post_api_descr_t      *api_descr;
863     const xine_post_api_parameter_t  *parm;
864     int                         pnum = 0;
865 
866     post_api = (const xine_post_api_t *) input_api->data;
867 
868     api_descr = post_api->get_param_descr();
869 
870     parm = api_descr->parameter;
871     pobj->param_data = malloc(api_descr->struct_size);
872     post_api->get_parameters(pobj->post, pobj->param_data);
873 
874     while(parm->type != POST_PARAM_TYPE_LAST) {
875 
876       pobj->properties_names = (char **) realloc(pobj->properties_names, sizeof(char *) * (pnum + 2));
877 
878       pobj->properties_names[pnum]     = strdup(parm->name);
879       pobj->properties_names[pnum + 1] = NULL;
880       pnum++;
881       parm++;
882     }
883 
884     pobj->api      = post_api;
885     pobj->descr    = api_descr;
886     pobj->param    = api_descr->parameter;
887 
888     return 1;
889   }
890 
891   return 0;
892 }
893 
_pplugin_close_help(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)894 static void _pplugin_close_help(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
895   gGui_t *gui = gGui;
896 
897   pp_wrapper->pplugin->help_running = 0;
898 
899   xitk_unregister_event_handler(&pp_wrapper->pplugin->help_widget_key);
900 
901   xitk_destroy_widgets(pp_wrapper->pplugin->help_widget_list);
902   xitk_window_destroy_window(gui->imlib_data, pp_wrapper->pplugin->helpwin);
903 
904   pp_wrapper->pplugin->helpwin = NULL;
905   /* xitk_dlist_init (&pp_wrapper->pplugin->help_widget_list->list); */
906 
907   gui->x_lock_display (gui->display);
908   XFreeGC(gui->display, (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->help_widget_list)));
909   gui->x_unlock_display (gui->display);
910 
911   XITK_WIDGET_LIST_FREE(pp_wrapper->pplugin->help_widget_list);
912 }
913 
_vpplugin_close_help(xitk_widget_t * w,void * data)914 static void _vpplugin_close_help(xitk_widget_t *w, void *data) {
915   _pplugin_close_help(&vpp_wrapper, w, data);
916 }
917 
_applugin_close_help(xitk_widget_t * w,void * data)918 static void _applugin_close_help(xitk_widget_t *w, void *data) {
919   _pplugin_close_help(&app_wrapper, w, data);
920 }
921 
_pplugin_help_handle_event(_pp_wrapper_t * pp_wrapper,XEvent * event,void * data)922 static void _pplugin_help_handle_event(_pp_wrapper_t *pp_wrapper, XEvent *event, void *data) {
923 
924   if(event->type == KeyPress) {
925     if(xitk_get_key_pressed(event) == XK_Escape)
926       _pplugin_close_help(pp_wrapper, NULL, NULL);
927     else
928       gui_handle_event (event, gGui);
929   }
930 }
931 
_vpplugin_help_handle_event(XEvent * event,void * data)932 static void _vpplugin_help_handle_event(XEvent *event, void *data) {
933   _pplugin_help_handle_event(&vpp_wrapper, event, data);
934 }
935 
_applugin_help_handle_event(XEvent * event,void * data)936 static void _applugin_help_handle_event(XEvent *event, void *data) {
937   _pplugin_help_handle_event(&app_wrapper, event, data);
938 }
939 
__line_wrap(char * s,int pos,int line_size)940 static int __line_wrap(char *s, int pos, int line_size)
941 {
942   int word_size = 0;
943 
944   while( *s && *s != '\t' && *s != ' ' && *s != '\n' ) {
945     s++;
946     word_size++;
947   }
948 
949   if( word_size >= line_size )
950     return pos > line_size;
951 
952   return word_size + pos > line_size;
953 }
954 
_pplugin_show_help(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)955 static void _pplugin_show_help(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
956   gGui_t *gui = gGui;
957   post_object_t *pobj = (post_object_t *) data;
958   GC                          gc;
959   xitk_pixmap_t              *bg = NULL;
960   int                         x, y, width, height;
961   xitk_labelbutton_widget_t   lb;
962   xitk_browser_widget_t       br;
963 
964   if(!pobj->api) {
965     if(pp_wrapper->pplugin->help_running)
966       _pplugin_close_help(pp_wrapper, NULL, NULL);
967     return;
968   }
969 
970   /* create help window if needed */
971 
972   if( !pp_wrapper->pplugin->help_running ) {
973     x = y = 80;
974     pp_wrapper->pplugin->helpwin = xitk_window_create_dialog_window(gui->imlib_data,
975                                                                     _("Plugin Help"), x, y,
976                                                                     HELP_WINDOW_WIDTH, HELP_WINDOW_HEIGHT);
977 
978     set_window_states_start((xitk_window_get_window(pp_wrapper->pplugin->helpwin)));
979 
980     gui->x_lock_display (gui->display);
981     gc = XCreateGC(gui->display,
982   		 (xitk_window_get_window(pp_wrapper->pplugin->helpwin)), None, None);
983     gui->x_unlock_display (gui->display);
984 
985     pp_wrapper->pplugin->help_widget_list = xitk_widget_list_new();
986     xitk_widget_list_set(pp_wrapper->pplugin->help_widget_list,
987                          WIDGET_LIST_WINDOW, (void *) (xitk_window_get_window(pp_wrapper->pplugin->helpwin)));
988     xitk_widget_list_set(pp_wrapper->pplugin->help_widget_list, WIDGET_LIST_GC, gc);
989 
990     xitk_window_get_window_size(pp_wrapper->pplugin->helpwin, &width, &height);
991     bg = xitk_image_create_xitk_pixmap(gui->imlib_data, width, height);
992 
993     gui->x_lock_display (gui->display);
994     XCopyArea(gui->display, (xitk_window_get_background(pp_wrapper->pplugin->helpwin)), bg->pixmap,
995   	    bg->gc, 0, 0, width, height, 0, 0);
996     gui->x_unlock_display (gui->display);
997 
998     XITK_WIDGET_INIT(&lb, gui->imlib_data);
999     lb.button_type       = CLICK_BUTTON;
1000     lb.label             = _("Close");
1001     lb.align             = ALIGN_CENTER;
1002     lb.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_close_help : _applugin_close_help;
1003     lb.state_callback    = NULL;
1004     lb.userdata          = NULL;
1005     lb.skin_element_name = NULL;
1006     w =  xitk_noskin_labelbutton_create (pp_wrapper->pplugin->help_widget_list,
1007       &lb, HELP_WINDOW_WIDTH - (100 + 15), HELP_WINDOW_HEIGHT - (23 + 15), 100, 23,
1008       "Black", "Black", "White", btnfontname);
1009     xitk_add_widget (pp_wrapper->pplugin->help_widget_list, w);
1010     xitk_enable_and_show_widget(w);
1011 
1012 
1013     XITK_WIDGET_INIT(&br, gui->imlib_data);
1014     br.arrow_up.skin_element_name    = NULL;
1015     br.slider.skin_element_name      = NULL;
1016     br.arrow_dn.skin_element_name    = NULL;
1017     br.browser.skin_element_name     = NULL;
1018     br.browser.max_displayed_entries = MAX_DISP_ENTRIES;
1019     br.browser.num_entries           = 0;
1020     br.browser.entries               = NULL;
1021     br.callback                      = NULL;
1022     br.dbl_click_callback            = NULL;
1023     br.parent_wlist                  = pp_wrapper->pplugin->help_widget_list;
1024     br.userdata                      = NULL;
1025     pp_wrapper->pplugin->help_browser = xitk_noskin_browser_create (pp_wrapper->pplugin->help_widget_list,
1026       &br, (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->help_widget_list)), 15, 34,
1027       HELP_WINDOW_WIDTH - (30 + 16), 20, 16, br_fontname);
1028     xitk_add_widget (pp_wrapper->pplugin->help_widget_list, pp_wrapper->pplugin->help_browser);
1029   }
1030 
1031   /* load text to the browser widget */
1032   {
1033     char  *p, **hbuf = NULL;
1034     int    lines = 0, i;
1035 
1036     p = pobj->api->get_help();
1037 
1038     do {
1039       char c, *old_p = p, *new_p;
1040       int w;
1041 
1042       for(w = 0; !__line_wrap(p,w,BROWSER_LINE_WIDTH) && (c = *p++) != 0 && c != '\n'; w++)
1043 	if (c == '\t') {
1044 	  w = (w + 1) | 7; /* allow for loop increment */
1045 	  if (w >= BROWSER_LINE_WIDTH)
1046 	    w = BROWSER_LINE_WIDTH - 1;
1047         }
1048 
1049       hbuf  = (char **) realloc(hbuf, sizeof(char *) * (lines + 2));
1050       hbuf[lines]    = malloc(w + 2);
1051       hbuf[lines+1]  = NULL;
1052 
1053       new_p = p;
1054       p = old_p;
1055       for(i = 0; i < w; i++)
1056         switch (c = *p++) {
1057         case '\0':
1058         case '\n':
1059           hbuf[lines][i] = '\0';
1060           i = w;
1061           break;
1062         case '\t':
1063 	  do {
1064 	    hbuf[lines][i] = ' ';
1065 	  } while (++i & 7 && i < BROWSER_LINE_WIDTH);
1066 	  --i; /* allow for loop increment */
1067 	  break;
1068         default:
1069 	  hbuf[lines][i] = c;
1070         }
1071       hbuf[lines][i] = '\0';
1072       p = new_p;
1073 
1074       lines++;
1075     } while( *p );
1076 
1077     if(lines) {
1078       char **ohbuf = pp_wrapper->pplugin->help_text;
1079       int    i = 0;
1080 
1081       pp_wrapper->pplugin->help_text = hbuf;
1082       xitk_browser_update_list(pp_wrapper->pplugin->help_browser, (const char **)pp_wrapper->pplugin->help_text,
1083                                NULL, lines, 0);
1084 
1085       if(ohbuf) {
1086 	while(ohbuf[i++])
1087 	  free(ohbuf[i]);
1088 	free(ohbuf);
1089       }
1090     }
1091   }
1092 
1093   if( !pp_wrapper->pplugin->help_running ) {
1094 
1095     xitk_enable_and_show_widget(pp_wrapper->pplugin->help_browser);
1096     xitk_browser_set_alignment(pp_wrapper->pplugin->help_browser, ALIGN_LEFT);
1097 
1098 
1099     xitk_window_change_background(gui->imlib_data, pp_wrapper->pplugin->helpwin, bg->pixmap, width, height);
1100     xitk_image_destroy_xitk_pixmap(bg);
1101 
1102     pp_wrapper->pplugin->help_widget_key = xitk_register_event_handler((pp_wrapper == &vpp_wrapper) ? "vpplugin_help" : "applugin_help",
1103                                                                        (xitk_window_get_window(pp_wrapper->pplugin->helpwin)),
1104 								       (pp_wrapper == &vpp_wrapper) ? _vpplugin_help_handle_event : _applugin_help_handle_event,
1105                                                                        NULL,
1106                                                                        NULL,
1107                                                                        pp_wrapper->pplugin->help_widget_list,
1108                                                                        NULL);
1109 
1110     pp_wrapper->pplugin->help_running = 1;
1111   }
1112 
1113   raise_window(xitk_window_get_window(pp_wrapper->pplugin->helpwin), 1, pp_wrapper->pplugin->help_running);
1114 
1115   try_to_set_input_focus(xitk_window_get_window(pp_wrapper->pplugin->helpwin));
1116 }
1117 
_vpplugin_show_help(xitk_widget_t * w,void * data)1118 static void _vpplugin_show_help(xitk_widget_t *w, void *data) {
1119   _pplugin_show_help(&vpp_wrapper, w, data);
1120 }
1121 
_applugin_show_help(xitk_widget_t * w,void * data)1122 static void _applugin_show_help(xitk_widget_t *w, void *data) {
1123   _pplugin_show_help(&app_wrapper, w, data);
1124 }
1125 
_pplugin_retrieve_parameters(_pp_wrapper_t * pp_wrapper,post_object_t * pobj)1126 static void _pplugin_retrieve_parameters(_pp_wrapper_t *pp_wrapper, post_object_t *pobj) {
1127   gGui_t *gui = gGui;
1128   xitk_combo_widget_t         cmb;
1129   xitk_labelbutton_widget_t   lb;
1130 
1131   if(__pplugin_retrieve_parameters(pobj)) {
1132 
1133     XITK_WIDGET_INIT(&cmb, gui->imlib_data);
1134     cmb.skin_element_name = NULL;
1135     cmb.layer_above       = (is_layer_above());
1136     cmb.parent_wlist      = pp_wrapper->pplugin->widget_list;
1137     cmb.entries           = (const char **)pobj->properties_names;
1138     cmb.parent_wkey       = &pp_wrapper->pplugin->widget_key;
1139     cmb.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_change_parameter : _applugin_change_parameter;
1140     cmb.userdata          = pobj;
1141     pobj->properties = xitk_noskin_combo_create (pp_wrapper->pplugin->widget_list,
1142       &cmb, 0, 0, 175, NULL, NULL);
1143     xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->properties);
1144     xitk_combo_set_select(pobj->properties, 0);
1145     xitk_combo_callback_exec(pobj->properties);
1146 
1147     if(pobj->api && pobj->api->get_help) {
1148 
1149       XITK_WIDGET_INIT(&lb, gui->imlib_data);
1150       lb.button_type       = CLICK_BUTTON;
1151       lb.label             = _("Help");
1152       lb.align             = ALIGN_CENTER;
1153       lb.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_show_help : _applugin_show_help;
1154       lb.state_callback    = NULL;
1155       lb.userdata          = pobj;
1156       lb.skin_element_name = NULL;
1157       pobj->help =  xitk_noskin_labelbutton_create (pp_wrapper->pplugin->widget_list,
1158         &lb, 0, 0, 63, 20, "Black", "Black", "White", btnfontname);
1159       xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->help);
1160     }
1161   }
1162   else {
1163     xitk_label_widget_t   lb;
1164 
1165     XITK_WIDGET_INIT(&lb, gui->imlib_data);
1166     lb.window              = xitk_window_get_window(pp_wrapper->pplugin->xwin);
1167     lb.gc                  = (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->widget_list));
1168     lb.skin_element_name   = NULL;
1169     lb.label               = _("There is no parameter available for this plugin.");
1170     lb.callback            = NULL;
1171     lb.userdata            = NULL;
1172     pobj->comment =  xitk_noskin_label_create (pp_wrapper->pplugin->widget_list, &lb,
1173       0, 0, FRAME_WIDTH - (26 + 6 + 6), 20, hboldfontname);
1174     xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->comment);
1175     pobj->properties = NULL;
1176   }
1177 }
1178 
1179 static post_object_t *_pplugin_create_filter_object (_pp_wrapper_t *pp_wrapper);
1180 
_pplugin_select_filter(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data,int select)1181 static void _pplugin_select_filter(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data, int select) {
1182   gGui_t *gui = gGui;
1183   post_object_t *pobj = (post_object_t *) data;
1184   post_object_t **p = pp_wrapper->pplugin->post_objects;
1185   int n;
1186 
1187   _pplugin_unwire(pp_wrapper);
1188 
1189   for (n = 0; p[n] && (p[n] != pobj); n++) ;
1190   if (!select) {
1191     /* User selected first line which is "No filter". Reset this one, and kill everything thereafter. */
1192     if (p[n]) {
1193       _pplugin_destroy_only_obj (pp_wrapper, pobj);
1194       if (pobj->post) {
1195         xine_post_dispose (__xineui_global_xine_instance, pobj->post);
1196         pobj->post = NULL;
1197       }
1198       n++;
1199       pp_wrapper->pplugin->object_num = n;
1200       while (p[n]) {
1201         _pplugin_destroy_only_obj (pp_wrapper, p[n]);
1202         if (p[n]->post) {
1203           xine_post_dispose (__xineui_global_xine_instance, p[n]->post);
1204           p[n]->post = NULL;
1205         }
1206         _pplugin_destroy_widget (&p[n]->plugins);
1207         _pplugin_destroy_widget (&p[n]->frame);
1208         _pplugin_destroy_widget (&p[n]->up);
1209         _pplugin_destroy_widget (&p[n]->down);
1210         VFREE (p[n]);
1211         p[n] = NULL;
1212         n++;
1213       }
1214       _pplugin_send_expose (pp_wrapper);
1215     }
1216     if(pp_wrapper->pplugin->object_num <= MAX_DISPLAY_FILTERS)
1217       pp_wrapper->pplugin->first_displayed = 0;
1218     else if((pp_wrapper->pplugin->object_num - pp_wrapper->pplugin->first_displayed) < MAX_DISPLAY_FILTERS)
1219       pp_wrapper->pplugin->first_displayed = pp_wrapper->pplugin->object_num - MAX_DISPLAY_FILTERS;
1220   } else {
1221     /* Some filter has been selected. Kill old one and set new. */
1222     _pplugin_destroy_only_obj (pp_wrapper, pobj);
1223     if (pobj->post) {
1224       xine_post_dispose (__xineui_global_xine_instance, pobj->post);
1225       pobj->post = NULL;
1226     }
1227     pobj->post = xine_post_init (__xineui_global_xine_instance,
1228       xitk_combo_get_current_entry_selected (w), 0, &gui->ao_port, &gui->vo_port);
1229     _pplugin_retrieve_parameters (pp_wrapper, pobj);
1230     /* If this is the last filter, add a new "No filter" thereafter. */
1231     if ((n < MAX_USED_FILTERS - 1) && (n + 1 == pp_wrapper->pplugin->object_num)) {
1232       _pplugin_create_filter_object (pp_wrapper);
1233     }
1234   }
1235 
1236   if(pp_wrapper->pplugin->help_running)
1237     _pplugin_show_help(pp_wrapper, NULL, pobj);
1238 
1239   _pplugin_rewire(pp_wrapper);
1240   _pplugin_paint_widgets(pp_wrapper);
1241 }
1242 
_vpplugin_select_filter(xitk_widget_t * w,void * data,int select)1243 static void _vpplugin_select_filter(xitk_widget_t *w, void *data, int select) {
1244   _pplugin_select_filter(&vpp_wrapper, w, data, select);
1245 }
1246 
_applugin_select_filter(xitk_widget_t * w,void * data,int select)1247 static void _applugin_select_filter(xitk_widget_t *w, void *data, int select) {
1248   _pplugin_select_filter(&app_wrapper, w, data, select);
1249 }
1250 
_pplugin_move_up(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)1251 static void _pplugin_move_up(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
1252   post_object_t *pobj = (post_object_t *) data;
1253   post_object_t **ppobj = pp_wrapper->pplugin->post_objects;
1254 
1255   _pplugin_unwire(pp_wrapper);
1256 
1257   while(*ppobj != pobj)
1258     ppobj++;
1259 
1260   *ppobj       = *(ppobj - 1);
1261   *(ppobj - 1) = pobj;
1262 
1263   _pplugin_rewire(pp_wrapper);
1264   _pplugin_paint_widgets(pp_wrapper);
1265 }
1266 
_vpplugin_move_up(xitk_widget_t * w,void * data)1267 static void _vpplugin_move_up(xitk_widget_t *w, void *data) {
1268   _pplugin_move_up(&vpp_wrapper, w, data);
1269 }
1270 
_applugin_move_up(xitk_widget_t * w,void * data)1271 static void _applugin_move_up(xitk_widget_t *w, void *data) {
1272   _pplugin_move_up(&app_wrapper, w, data);
1273 }
1274 
_pplugin_move_down(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)1275 static void _pplugin_move_down(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
1276   post_object_t *pobj = (post_object_t *) data;
1277   post_object_t **ppobj = pp_wrapper->pplugin->post_objects;
1278 
1279   _pplugin_unwire(pp_wrapper);
1280 
1281   while(*ppobj != pobj)
1282     ppobj++;
1283 
1284   *ppobj       = *(ppobj + 1);
1285   *(ppobj + 1) = pobj;
1286 
1287   _pplugin_rewire(pp_wrapper);
1288   _pplugin_paint_widgets(pp_wrapper);
1289 }
1290 
_vpplugin_move_down(xitk_widget_t * w,void * data)1291 static void _vpplugin_move_down(xitk_widget_t *w, void *data) {
1292   _pplugin_move_down(&vpp_wrapper, w, data);
1293 }
1294 
_applugin_move_down(xitk_widget_t * w,void * data)1295 static void _applugin_move_down(xitk_widget_t *w, void *data) {
1296   _pplugin_move_down(&app_wrapper, w, data);
1297 }
1298 
_pplugin_create_filter_object(_pp_wrapper_t * pp_wrapper)1299 static post_object_t *_pplugin_create_filter_object (_pp_wrapper_t *pp_wrapper) {
1300   gGui_t *gui = gGui;
1301   xitk_combo_widget_t   cmb;
1302   post_object_t        *pobj;
1303   xitk_image_widget_t   im;
1304   xitk_image_t         *image;
1305   xitk_button_widget_t  b;
1306 
1307   if (pp_wrapper->pplugin->object_num >= MAX_USED_FILTERS - 1)
1308     return NULL;
1309   pobj = calloc (1, sizeof (post_object_t));
1310   if (!pobj)
1311     return NULL;
1312 
1313   pp_wrapper->pplugin->x = 15;
1314   pp_wrapper->pplugin->y += FRAME_HEIGHT + 4;
1315 
1316   pp_wrapper->pplugin->post_objects[pp_wrapper->pplugin->object_num] = pobj;
1317   pobj->x = pp_wrapper->pplugin->x;
1318   pobj->y = pp_wrapper->pplugin->y;
1319   pp_wrapper->pplugin->object_num++;
1320 
1321   image = xitk_image_create_image(gui->imlib_data, FRAME_WIDTH + 1, FRAME_HEIGHT + 1);
1322 
1323   gui->x_lock_display (gui->display);
1324   XSetForeground(gui->display, (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->widget_list)),
1325 		 xitk_get_pixel_color_gray(gui->imlib_data));
1326   XFillRectangle(gui->display, image->image->pixmap,
1327 		 (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->widget_list)),
1328 		 0, 0, image->width, image->height);
1329   gui->x_unlock_display (gui->display);
1330 
1331   /* Some decorations */
1332   draw_outter_frame(gui->imlib_data, image->image, NULL, NULL,
1333 		    0, 0, FRAME_WIDTH, FRAME_HEIGHT);
1334   draw_rectangular_outter_box_light(gui->imlib_data, image->image,
1335 		    27, 28, FRAME_WIDTH - 27 - 5, 1);
1336   draw_rectangular_outter_box_light(gui->imlib_data, image->image,
1337 		    26, 5, 1, FRAME_HEIGHT - 10);
1338   draw_inner_frame(gui->imlib_data, image->image, NULL, NULL,
1339 		    5, 5, 16, 16);
1340   draw_rectangular_inner_box_light(gui->imlib_data, image->image,
1341 		    5, 24, 1, FRAME_HEIGHT - 48);
1342   draw_rectangular_inner_box_light(gui->imlib_data, image->image,
1343 		    10, 24, 1, FRAME_HEIGHT - 48);
1344   draw_rectangular_inner_box_light(gui->imlib_data, image->image,
1345 		    15, 24, 1, FRAME_HEIGHT - 48);
1346   draw_rectangular_inner_box_light(gui->imlib_data, image->image,
1347 		    20, 24, 1, FRAME_HEIGHT - 48);
1348   draw_inner_frame(gui->imlib_data, image->image, NULL, NULL,
1349 		    5, FRAME_HEIGHT - 16 - 5, 16, 16);
1350 
1351   XITK_WIDGET_INIT(&im, gui->imlib_data);
1352   im.skin_element_name = NULL;
1353   pobj->frame =  xitk_noskin_image_create (pp_wrapper->pplugin->widget_list, &im, image, pobj->x - 5, pobj->y - 5);
1354   xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->frame);
1355 
1356   DISABLE_ME(pobj->frame);
1357 
1358   XITK_WIDGET_INIT(&cmb, gui->imlib_data);
1359   cmb.skin_element_name = NULL;
1360   cmb.layer_above       = (is_layer_above());
1361   cmb.parent_wlist      = pp_wrapper->pplugin->widget_list;
1362   cmb.entries           = (const char **)pp_wrapper->pplugin->plugin_names;
1363   cmb.parent_wkey       = &pp_wrapper->pplugin->widget_key;
1364   cmb.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_select_filter : _applugin_select_filter;
1365   cmb.userdata          = pobj;
1366   pobj->plugins = xitk_noskin_combo_create (pp_wrapper->pplugin->widget_list,
1367     &cmb, 0, 0, 175, NULL, NULL);
1368   xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->plugins);
1369   DISABLE_ME(pobj->plugins);
1370   xitk_combo_set_select(pobj->plugins, 0);
1371 
1372   {
1373     xitk_image_t *bimage;
1374 
1375     XITK_WIDGET_INIT(&b, gui->imlib_data);
1376     b.skin_element_name = NULL;
1377     b.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_move_up : _applugin_move_up;
1378     b.userdata          = pobj;
1379     pobj->up = xitk_noskin_button_create (pp_wrapper->pplugin->widget_list, &b, 0, 0, 17, 17);
1380     xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->up);
1381     DISABLE_ME(pobj->up);
1382 
1383     if((bimage = xitk_get_widget_foreground_skin(pobj->up)) != NULL)
1384       draw_arrow_up(gui->imlib_data, bimage);
1385 
1386     b.skin_element_name = NULL;
1387     b.callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_move_down : _applugin_move_down;
1388     b.userdata          = pobj;
1389     pobj->down = xitk_noskin_button_create (pp_wrapper->pplugin->widget_list, &b, 0, 0, 17, 17);
1390     xitk_add_widget (pp_wrapper->pplugin->widget_list, pobj->down);
1391     DISABLE_ME(pobj->down);
1392 
1393     if((bimage = xitk_get_widget_foreground_skin(pobj->down)) != NULL)
1394       draw_arrow_down(gui->imlib_data, bimage);
1395 
1396   }
1397   return pobj;
1398 }
1399 
_pplugin_rebuild_filters(_pp_wrapper_t * pp_wrapper)1400 static int _pplugin_rebuild_filters(_pp_wrapper_t *pp_wrapper) {
1401   gGui_t *gui = gGui;
1402   post_element_t  **pelem = (pp_wrapper == &vpp_wrapper) ? gui->post_video_elements : gui->post_audio_elements;
1403   int plugin_type = (pp_wrapper == &vpp_wrapper) ? XINE_POST_TYPE_VIDEO_FILTER : XINE_POST_TYPE_AUDIO_FILTER;
1404   int num_filters = 0;
1405 
1406   while(pelem && *pelem) {
1407     int i = 0;
1408 
1409     if ((*pelem)->post->type == plugin_type) {
1410       num_filters++;
1411 
1412       if (!_pplugin_create_filter_object (pp_wrapper))
1413         break;
1414       pp_wrapper->pplugin->post_objects[pp_wrapper->pplugin->object_num - 1]->post = (*pelem)->post;
1415 
1416       while(pp_wrapper->pplugin->plugin_names[i] && strcasecmp(pp_wrapper->pplugin->plugin_names[i], (*pelem)->name))
1417         i++;
1418 
1419       if(pp_wrapper->pplugin->plugin_names[i]) {
1420         xitk_combo_set_select(pp_wrapper->pplugin->post_objects[pp_wrapper->pplugin->object_num - 1]->plugins, i);
1421 
1422         _pplugin_retrieve_parameters(pp_wrapper, pp_wrapper->pplugin->post_objects[pp_wrapper->pplugin->object_num - 1]);
1423       }
1424     }
1425 
1426     pelem++;
1427   }
1428   /* Always have 1 "No filter" at the end for later extension. */
1429   _pplugin_create_filter_object (pp_wrapper);
1430 
1431   _pplugin_paint_widgets(pp_wrapper);
1432 
1433   return num_filters;
1434 }
1435 
_pplugin_join_deinterlace_and_post_elements(int * post_elements_num)1436 static post_element_t **_pplugin_join_deinterlace_and_post_elements(int *post_elements_num) {
1437   gGui_t *gui = gGui;
1438   post_element_t **post_elements;
1439   int i = 0, j = 0;
1440 
1441   *post_elements_num = 0;
1442   if( gui->post_video_enable )
1443     (*post_elements_num) += gui->post_video_elements_num;
1444   if( gui->deinterlace_enable )
1445     (*post_elements_num) += gui->deinterlace_elements_num;
1446 
1447   if( *post_elements_num == 0 )
1448     return NULL;
1449 
1450   post_elements = (post_element_t **)
1451     calloc((*post_elements_num), sizeof(post_element_t *));
1452 
1453   for( i = 0; gui->deinterlace_enable && i < gui->deinterlace_elements_num; i++ ) {
1454     post_elements[i+j] = gui->deinterlace_elements[i];
1455   }
1456 
1457   for( j = 0; gui->post_video_enable && j < gui->post_video_elements_num; j++ ) {
1458     post_elements[i+j] = gui->post_video_elements[j];
1459   }
1460 
1461   return post_elements;
1462 }
1463 
1464 
_pplugin_join_visualization_and_post_elements(int * post_elements_num)1465 static post_element_t **_pplugin_join_visualization_and_post_elements(int *post_elements_num) {
1466   gGui_t *gui = gGui;
1467   post_element_t **post_elements;
1468   int i = 0, j = 0;
1469 
1470   *post_elements_num = 0;
1471   if( gui->post_audio_enable )
1472     (*post_elements_num) += gui->post_audio_elements_num;
1473   if( !ignore_visual_anim )
1474     (*post_elements_num)++;
1475 
1476   if( *post_elements_num == 0 )
1477     return NULL;
1478 
1479   post_elements = (post_element_t **)
1480     calloc((*post_elements_num), sizeof(post_element_t *));
1481 
1482   for( j = 0; gui->post_audio_enable && j < gui->post_audio_elements_num; j++ ) {
1483     post_elements[i+j] = gui->post_audio_elements[j];
1484   }
1485 
1486   for( i = 0; !ignore_visual_anim && i < 1; i++ ) {
1487     post_elements[i+j] = &gui->visual_anim.post_output_element;
1488   }
1489 
1490   return post_elements;
1491 }
1492 
1493 
_pplugin_save_chain(_pp_wrapper_t * pp_wrapper)1494 static void _pplugin_save_chain(_pp_wrapper_t *pp_wrapper) {
1495   gGui_t *gui = gGui;
1496 
1497   if(pp_wrapper->pplugin) {
1498     post_element_t ***_post_elements = (pp_wrapper == &vpp_wrapper) ? &gui->post_video_elements : &gui->post_audio_elements;
1499     int *_post_elements_num = (pp_wrapper == &vpp_wrapper) ? &gui->post_video_elements_num : &gui->post_audio_elements_num;
1500     int i = 0;
1501     int post_num = pp_wrapper->pplugin->object_num;
1502 
1503     if(!xitk_combo_get_current_selected(pp_wrapper->pplugin->post_objects[post_num - 1]->plugins))
1504       post_num--;
1505 
1506     if(post_num) {
1507       if(!*_post_elements) {
1508 	*_post_elements = (post_element_t **)
1509 	  calloc((post_num + 1), sizeof(post_element_t *));
1510       }
1511       else {
1512 	int j;
1513 
1514 	for(j = 0; j < *_post_elements_num; j++) {
1515 	  free((*_post_elements)[j]->name);
1516 	  VFREE((*_post_elements)[j]);
1517 	}
1518 
1519 	*_post_elements = (post_element_t **) realloc(*_post_elements, sizeof(post_element_t *) * (post_num + 1));
1520 
1521       }
1522 
1523       for(i = 0; i < post_num; i++) {
1524 	(*_post_elements)[i] = (post_element_t *) calloc(1, sizeof(post_element_t));
1525 	(*_post_elements)[i]->post = pp_wrapper->pplugin->post_objects[i]->post;
1526 	(*_post_elements)[i]->name =
1527 	  strdup(xitk_combo_get_current_entry_selected(pp_wrapper->pplugin->post_objects[i]->plugins));
1528       }
1529 
1530       (*_post_elements)[post_num] = NULL;
1531       *_post_elements_num         = post_num;
1532     }
1533     else {
1534       if(*_post_elements_num) {
1535 	int j;
1536 
1537 	for(j = 0; j < *_post_elements_num; j++) {
1538 	  free((*_post_elements)[j]->name);
1539 	  VFREE((*_post_elements)[j]);
1540 	}
1541 
1542 	/* free((*_post_elements)[j]); */
1543 	free(*_post_elements);
1544 
1545 	*_post_elements_num = 0;
1546 	*_post_elements     = NULL;
1547       }
1548     }
1549   }
1550 }
1551 
_pplugin_nextprev(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data,int pos)1552 static void _pplugin_nextprev(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data, int pos) {
1553   int rpos = (xitk_slider_get_max(pp_wrapper->pplugin->slider)) - pos;
1554 
1555   if(rpos != pp_wrapper->pplugin->first_displayed) {
1556     pp_wrapper->pplugin->first_displayed = rpos;
1557     _pplugin_paint_widgets(pp_wrapper);
1558   }
1559 }
1560 
_vpplugin_nextprev(xitk_widget_t * w,void * data,int pos)1561 static void _vpplugin_nextprev(xitk_widget_t *w, void *data, int pos) {
1562   _pplugin_nextprev(&vpp_wrapper, w, data, pos);
1563 }
1564 
_applugin_nextprev(xitk_widget_t * w,void * data,int pos)1565 static void _applugin_nextprev(xitk_widget_t *w, void *data, int pos) {
1566   _pplugin_nextprev(&app_wrapper, w, data, pos);
1567 }
1568 
pplugin_exit(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)1569 static void pplugin_exit(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
1570   gGui_t *gui = gGui;
1571 
1572   if(pp_wrapper->pplugin) {
1573     window_info_t wi;
1574     int           i;
1575 
1576     if( pp_wrapper->pplugin->help_running )
1577      _pplugin_close_help(pp_wrapper, NULL,NULL);
1578 
1579     if(pp_wrapper->pplugin->help_text) {
1580       i = 0;
1581       while(pp_wrapper->pplugin->help_text[i++])
1582 	free(pp_wrapper->pplugin->help_text[i]);
1583       free(pp_wrapper->pplugin->help_text);
1584     }
1585 
1586     _pplugin_save_chain(pp_wrapper);
1587 
1588     pp_wrapper->pplugin->running = 0;
1589     pp_wrapper->pplugin->visible = 0;
1590 
1591     if((xitk_get_window_info(pp_wrapper->pplugin->widget_key, &wi))) {
1592       config_update_num ((pp_wrapper == &vpp_wrapper) ? "gui.vpplugin_x" : "gui.applugin_x", wi.x);
1593       config_update_num ((pp_wrapper == &vpp_wrapper) ? "gui.vpplugin_y" : "gui.applugin_y", wi.y);
1594       WINDOW_INFO_ZERO(&wi);
1595     }
1596 
1597     {
1598       post_object_t **p = pp_wrapper->pplugin->post_objects;
1599       while (*p) {
1600         _pplugin_destroy_only_obj (pp_wrapper, *p);
1601         _pplugin_destroy_widget (&(*p)->plugins);
1602         _pplugin_destroy_widget (&(*p)->frame);
1603         _pplugin_destroy_widget (&(*p)->up);
1604         _pplugin_destroy_widget (&(*p)->down);
1605         VFREE (*p);
1606         *p = NULL;
1607         p++;
1608       }
1609     }
1610     pp_wrapper->pplugin->object_num = 0;
1611 
1612     for(i = 0; pp_wrapper->pplugin->plugin_names[i]; i++)
1613       free(pp_wrapper->pplugin->plugin_names[i]);
1614 
1615     free(pp_wrapper->pplugin->plugin_names);
1616 
1617     xitk_unregister_event_handler(&pp_wrapper->pplugin->widget_key);
1618 
1619     xitk_destroy_widgets(pp_wrapper->pplugin->widget_list);
1620     xitk_window_destroy_window(gui->imlib_data, pp_wrapper->pplugin->xwin);
1621 
1622     pp_wrapper->pplugin->xwin = NULL;
1623     /* xitk_dlist_init (&pp_wrapper->pplugin->widget_list->list); */
1624 
1625     gui->x_lock_display (gui->display);
1626     XFreeGC(gui->display, (XITK_WIDGET_LIST_GC(pp_wrapper->pplugin->widget_list)));
1627     gui->x_unlock_display (gui->display);
1628 
1629     XITK_WIDGET_LIST_FREE(pp_wrapper->pplugin->widget_list);
1630 
1631     VFREE(pp_wrapper->pplugin);
1632     pp_wrapper->pplugin = NULL;
1633 
1634     try_to_set_input_focus(gui->video_window);
1635   }
1636 }
1637 
vpplugin_exit(xitk_widget_t * w,void * data)1638 static void vpplugin_exit(xitk_widget_t *w, void *data) {
1639   pplugin_exit(&vpp_wrapper, w, data);
1640 }
1641 
applugin_exit(xitk_widget_t * w,void * data)1642 static void applugin_exit(xitk_widget_t *w, void *data) {
1643   pplugin_exit(&app_wrapper, w, data);
1644 }
1645 
_pplugin_handle_event(_pp_wrapper_t * pp_wrapper,XEvent * event,void * data)1646 static void _pplugin_handle_event(_pp_wrapper_t *pp_wrapper, XEvent *event, void *data) {
1647 
1648   switch(event->type) {
1649 
1650   case ButtonPress:
1651     if(event->xbutton.button == Button4) {
1652       xitk_slider_make_step(pp_wrapper->pplugin->slider);
1653       xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1654     }
1655     else if(event->xbutton.button == Button5) {
1656       xitk_slider_make_backstep(pp_wrapper->pplugin->slider);
1657       xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1658     }
1659     break;
1660 
1661   case KeyPress:
1662     {
1663       KeySym         mkey;
1664       int            modifier;
1665 
1666       xitk_get_key_modifier(event, &modifier);
1667       mkey = xitk_get_key_pressed(event);
1668 
1669       switch(mkey) {
1670 
1671       case XK_Up:
1672 	if(xitk_is_widget_enabled(pp_wrapper->pplugin->slider) &&
1673 	   (modifier & 0xFFFFFFEF) == MODIFIER_NOMOD) {
1674 	  xitk_slider_make_step(pp_wrapper->pplugin->slider);
1675 	  xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1676 	  return;
1677 	}
1678 	break;
1679 
1680       case XK_Down:
1681 	if(xitk_is_widget_enabled(pp_wrapper->pplugin->slider) &&
1682 	   (modifier & 0xFFFFFFEF) == MODIFIER_NOMOD) {
1683 	  xitk_slider_make_backstep(pp_wrapper->pplugin->slider);
1684 	  xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1685 	  return;
1686 	}
1687 	break;
1688 
1689       case XK_Next:
1690 	if(xitk_is_widget_enabled(pp_wrapper->pplugin->slider)) {
1691 	  int pos, max = xitk_slider_get_max(pp_wrapper->pplugin->slider);
1692 
1693 	  pos = max - (pp_wrapper->pplugin->first_displayed + MAX_DISPLAY_FILTERS);
1694 	  xitk_slider_set_pos(pp_wrapper->pplugin->slider, (pos >= 0) ? pos : 0);
1695 	  xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1696 	  return;
1697 	}
1698 	break;
1699 
1700       case XK_Prior:
1701 	if(xitk_is_widget_enabled(pp_wrapper->pplugin->slider)) {
1702 	  int pos, max = xitk_slider_get_max(pp_wrapper->pplugin->slider);
1703 
1704 	  pos = max - (pp_wrapper->pplugin->first_displayed - MAX_DISPLAY_FILTERS);
1705 	  xitk_slider_set_pos(pp_wrapper->pplugin->slider, (pos <= max) ? pos : max);
1706 	  xitk_slider_callback_exec(pp_wrapper->pplugin->slider);
1707 	  return;
1708 	}
1709 	break;
1710 
1711       case XK_Escape:
1712 	pplugin_exit(pp_wrapper, NULL, NULL);
1713 	return;
1714       }
1715       gui_handle_event (event, gGui);
1716     }
1717     break;
1718   }
1719 }
1720 
_vpplugin_handle_event(XEvent * event,void * data)1721 static void _vpplugin_handle_event(XEvent *event, void *data) {
1722   _pplugin_handle_event(&vpp_wrapper, event, data);
1723 }
1724 
_applugin_handle_event(XEvent * event,void * data)1725 static void _applugin_handle_event(XEvent *event, void *data) {
1726   _pplugin_handle_event(&app_wrapper, event, data);
1727 }
1728 
_pplugin_enability(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data,int state)1729 static void _pplugin_enability(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data, int state) {
1730   gGui_t *gui = gGui;
1731   if (pp_wrapper == &vpp_wrapper)
1732     gui->post_video_enable = state;
1733   else
1734     gui->post_audio_enable = state;
1735 
1736   _pplugin_unwire(pp_wrapper);
1737   _pplugin_rewire(pp_wrapper);
1738 }
1739 
_vpplugin_enability(xitk_widget_t * w,void * data,int state)1740 static void _vpplugin_enability(xitk_widget_t *w, void *data, int state) {
1741   _pplugin_enability(&vpp_wrapper, w, data, state);
1742 }
1743 
_applugin_enability(xitk_widget_t * w,void * data,int state)1744 static void _applugin_enability(xitk_widget_t *w, void *data, int state) {
1745   _pplugin_enability(&app_wrapper, w, data, state);
1746 }
1747 
pplugin_is_post_selected(_pp_wrapper_t * pp_wrapper)1748 static int pplugin_is_post_selected(_pp_wrapper_t *pp_wrapper) {
1749   gGui_t *gui = gGui;
1750 
1751   if(pp_wrapper->pplugin) {
1752     int post_num = pp_wrapper->pplugin->object_num;
1753 
1754     if(!xitk_combo_get_current_selected(pp_wrapper->pplugin->post_objects[post_num - 1]->plugins))
1755       post_num--;
1756 
1757     return (post_num > 0);
1758   }
1759 
1760   return (pp_wrapper == &vpp_wrapper) ? gui->post_video_elements_num : gui->post_audio_elements_num;
1761 }
1762 
pplugin_rewire_from_posts_window(_pp_wrapper_t * pp_wrapper)1763 static void pplugin_rewire_from_posts_window(_pp_wrapper_t *pp_wrapper) {
1764   if(pp_wrapper->pplugin) {
1765     _pplugin_unwire(pp_wrapper);
1766     _pplugin_rewire(pp_wrapper);
1767   }
1768 }
1769 
_vpplugin_rewire_from_post_elements(post_element_t ** post_elements,int post_elements_num)1770 static void _vpplugin_rewire_from_post_elements(post_element_t **post_elements, int post_elements_num) {
1771   gGui_t *gui = gGui;
1772 
1773   if(post_elements_num) {
1774     xine_post_out_t   *vo_source;
1775     int                i = 0;
1776 
1777     for(i = (post_elements_num - 1); i >= 0; i--) {
1778       /* use the first output from plugin */
1779       const char *const *outs = xine_post_list_outputs(post_elements[i]->post);
1780       const xine_post_out_t *vo_out = xine_post_output(post_elements[i]->post, (char *) *outs);
1781       if(i == (post_elements_num - 1)) {
1782 	xine_post_wire_video_port((xine_post_out_t *) vo_out, gui->vo_port);
1783       }
1784       else {
1785 	const xine_post_in_t *vo_in;
1786 
1787 	/* look for standard input names */
1788 	vo_in = xine_post_input(post_elements[i + 1]->post, "video");
1789 	if( !vo_in )
1790 	  vo_in = xine_post_input(post_elements[i + 1]->post, "video in");
1791 
1792 	xine_post_wire((xine_post_out_t *) vo_out, (xine_post_in_t *) vo_in);
1793       }
1794     }
1795 
1796     vo_source = xine_get_video_source(gui->stream);
1797     xine_post_wire_video_port(vo_source, post_elements[0]->post->video_input[0]);
1798   }
1799 }
1800 
_applugin_rewire_from_post_elements(post_element_t ** post_elements,int post_elements_num)1801 static void _applugin_rewire_from_post_elements(post_element_t **post_elements, int post_elements_num) {
1802   gGui_t *gui = gGui;
1803 
1804   if(post_elements_num) {
1805     xine_post_out_t   *ao_source;
1806     int                i = 0;
1807 
1808     for(i = (post_elements_num - 1); i >= 0; i--) {
1809       /* use the first output from plugin */
1810       const char *const *outs = xine_post_list_outputs(post_elements[i]->post);
1811       const xine_post_out_t *ao_out = xine_post_output(post_elements[i]->post, (char *) *outs);
1812       if(i == (post_elements_num - 1)) {
1813 	xine_post_wire_audio_port((xine_post_out_t *) ao_out, gui->ao_port);
1814       }
1815       else {
1816 	const xine_post_in_t *ao_in;
1817 
1818 	/* look for standard input names */
1819 	ao_in = xine_post_input(post_elements[i + 1]->post, "audio");
1820 	if( !ao_in )
1821 	  ao_in = xine_post_input(post_elements[i + 1]->post, "audio in");
1822 
1823 	xine_post_wire((xine_post_out_t *) ao_out, (xine_post_in_t *) ao_in);
1824       }
1825     }
1826 
1827     ao_source = xine_get_audio_source(gui->stream);
1828     xine_post_wire_audio_port(ao_source, post_elements[0]->post->audio_input[0]);
1829   }
1830 }
1831 
_pplugin_rewire_from_post_elements(_pp_wrapper_t * pp_wrapper,post_element_t ** post_elements,int post_elements_num)1832 static void _pplugin_rewire_from_post_elements(_pp_wrapper_t *pp_wrapper, post_element_t **post_elements, int post_elements_num) {
1833   if (pp_wrapper == &vpp_wrapper)
1834     _vpplugin_rewire_from_post_elements(post_elements, post_elements_num);
1835   else
1836     _applugin_rewire_from_post_elements(post_elements, post_elements_num);
1837 }
1838 
pplugin_rewire_posts(_pp_wrapper_t * pp_wrapper)1839 static void pplugin_rewire_posts(_pp_wrapper_t *pp_wrapper) {
1840   _pplugin_unwire(pp_wrapper);
1841   _pplugin_rewire(pp_wrapper);
1842 
1843 #if 0
1844   gGui_t *gui = gGui;
1845   if(gui->post_enable && !gui->deinterlace_enable)
1846     _pplugin_rewire_from_post_elements(gui->post_elements, gui->post_elements_num);
1847 #endif
1848 }
1849 
pplugin_end(_pp_wrapper_t * pp_wrapper)1850 static void pplugin_end(_pp_wrapper_t *pp_wrapper) {
1851   pplugin_exit(pp_wrapper, NULL, NULL);
1852 }
1853 
pplugin_is_visible(_pp_wrapper_t * pp_wrapper)1854 static int pplugin_is_visible(_pp_wrapper_t *pp_wrapper) {
1855   gGui_t *gui = gGui;
1856 
1857   if(pp_wrapper->pplugin) {
1858     if(gui->use_root_window)
1859       return xitk_is_window_visible(gui->display, xitk_window_get_window(pp_wrapper->pplugin->xwin));
1860     else
1861       return pp_wrapper->pplugin->visible && xitk_is_window_visible(gui->display, xitk_window_get_window(pp_wrapper->pplugin->xwin));
1862   }
1863 
1864   return 0;
1865 }
1866 
pplugin_is_running(_pp_wrapper_t * pp_wrapper)1867 static int pplugin_is_running(_pp_wrapper_t *pp_wrapper) {
1868 
1869   if(pp_wrapper->pplugin)
1870     return pp_wrapper->pplugin->running;
1871 
1872   return 0;
1873 }
1874 
pplugin_raise_window(_pp_wrapper_t * pp_wrapper)1875 static void pplugin_raise_window(_pp_wrapper_t *pp_wrapper) {
1876   if(pp_wrapper->pplugin != NULL)
1877     raise_window(xitk_window_get_window(pp_wrapper->pplugin->xwin), pp_wrapper->pplugin->visible, pp_wrapper->pplugin->running);
1878 }
1879 
1880 
pplugin_toggle_visibility(_pp_wrapper_t * pp_wrapper,xitk_widget_t * w,void * data)1881 static void pplugin_toggle_visibility(_pp_wrapper_t *pp_wrapper, xitk_widget_t *w, void *data) {
1882   if(pp_wrapper->pplugin != NULL)
1883     toggle_window(xitk_window_get_window(pp_wrapper->pplugin->xwin), pp_wrapper->pplugin->widget_list,
1884 		  &pp_wrapper->pplugin->visible, pp_wrapper->pplugin->running);
1885 }
1886 
pplugin_update_enable_button(_pp_wrapper_t * pp_wrapper)1887 static void pplugin_update_enable_button(_pp_wrapper_t *pp_wrapper) {
1888   gGui_t *gui = gGui;
1889   if(pp_wrapper->pplugin)
1890     xitk_labelbutton_set_state(pp_wrapper->pplugin->enable, (pp_wrapper == &vpp_wrapper) ? gui->post_video_enable : gui->post_audio_enable);
1891 }
1892 
pplugin_reparent(_pp_wrapper_t * pp_wrapper)1893 static void pplugin_reparent(_pp_wrapper_t *pp_wrapper) {
1894   if(pp_wrapper->pplugin)
1895     reparent_window((xitk_window_get_window(pp_wrapper->pplugin->xwin)));
1896 }
1897 
pplugin_panel(_pp_wrapper_t * pp_wrapper)1898 static void pplugin_panel(_pp_wrapper_t *pp_wrapper) {
1899   gGui_t *gui = gGui;
1900   GC                          gc;
1901   xitk_labelbutton_widget_t   lb;
1902   xitk_label_widget_t         lbl;
1903   xitk_checkbox_widget_t      cb;
1904   xitk_pixmap_t              *bg;
1905   int                         x, y, width, height;
1906   xitk_slider_widget_t        sl;
1907   xitk_widget_t              *w;
1908 
1909   pp_wrapper->pplugin = (_pplugin_t *) calloc(1, sizeof(_pplugin_t));
1910   pp_wrapper->pplugin->first_displayed = 0;
1911   pp_wrapper->pplugin->help_text       = NULL;
1912 
1913   x = xine_config_register_num (__xineui_global_xine_instance, (pp_wrapper == &vpp_wrapper) ? "gui.vpplugin_x" : "gui.applugin_x",
1914 				80,
1915 				CONFIG_NO_DESC,
1916 				CONFIG_NO_HELP,
1917 				CONFIG_LEVEL_DEB,
1918 				CONFIG_NO_CB,
1919 				CONFIG_NO_DATA);
1920   y = xine_config_register_num (__xineui_global_xine_instance, (pp_wrapper == &vpp_wrapper) ? "gui.vpplugin_y" : "gui.applugin_y",
1921 				80,
1922 				CONFIG_NO_DESC,
1923 				CONFIG_NO_HELP,
1924 				CONFIG_LEVEL_DEB,
1925 				CONFIG_NO_CB,
1926 				CONFIG_NO_DATA);
1927 
1928   pp_wrapper->pplugin->xwin = xitk_window_create_dialog_window(gui->imlib_data,
1929 						   (pp_wrapper == &vpp_wrapper) ? _("Video Chain Reaction") : _("Audio Chain Reaction"),
1930                                                    x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
1931 
1932   set_window_states_start((xitk_window_get_window(pp_wrapper->pplugin->xwin)));
1933 
1934   gui->x_lock_display (gui->display);
1935   gc = XCreateGC(gui->display,
1936 		 (xitk_window_get_window(pp_wrapper->pplugin->xwin)), None, None);
1937   gui->x_unlock_display (gui->display);
1938 
1939   pp_wrapper->pplugin->widget_list = xitk_widget_list_new();
1940   xitk_widget_list_set(pp_wrapper->pplugin->widget_list,
1941 		       WIDGET_LIST_WINDOW, (void *) (xitk_window_get_window(pp_wrapper->pplugin->xwin)));
1942   xitk_widget_list_set(pp_wrapper->pplugin->widget_list, WIDGET_LIST_GC, gc);
1943 
1944   XITK_WIDGET_INIT(&lb, gui->imlib_data);
1945   XITK_WIDGET_INIT(&lbl, gui->imlib_data);
1946   XITK_WIDGET_INIT(&cb, gui->imlib_data);
1947 
1948   xitk_window_get_window_size(pp_wrapper->pplugin->xwin, &width, &height);
1949   bg = xitk_image_create_xitk_pixmap(gui->imlib_data, width, height);
1950 
1951   gui->x_lock_display (gui->display);
1952   XCopyArea(gui->display, (xitk_window_get_background(pp_wrapper->pplugin->xwin)), bg->pixmap,
1953 	    bg->gc, 0, 0, width, height, 0, 0);
1954   gui->x_unlock_display (gui->display);
1955 
1956   XITK_WIDGET_INIT(&sl, gui->imlib_data);
1957 
1958   sl.min                      = 0;
1959   sl.max                      = 1;
1960   sl.step                     = 1;
1961   sl.skin_element_name        = NULL;
1962   sl.callback                 = NULL;
1963   sl.userdata                 = NULL;
1964   sl.motion_callback          = (pp_wrapper == &vpp_wrapper) ? _vpplugin_nextprev : _applugin_nextprev;
1965   sl.motion_userdata          = NULL;
1966   pp_wrapper->pplugin->slider =  xitk_noskin_slider_create (pp_wrapper->pplugin->widget_list, &sl,
1967     (WINDOW_WIDTH - (16 + 15)), 34, 16, (MAX_DISPLAY_FILTERS * (FRAME_HEIGHT + 4) - 4), XITK_VSLIDER);
1968   xitk_add_widget (pp_wrapper->pplugin->widget_list, pp_wrapper->pplugin->slider);
1969 
1970   y = WINDOW_HEIGHT - (23 + 15);
1971   x = 15;
1972 
1973   lb.button_type       = RADIO_BUTTON;
1974   lb.label             = _("Enable");
1975   lb.align             = ALIGN_CENTER;
1976   lb.callback          = NULL;
1977   lb.state_callback    = (pp_wrapper == &vpp_wrapper) ? _vpplugin_enability : _applugin_enability;
1978   lb.userdata          = NULL;
1979   lb.skin_element_name = NULL;
1980   pp_wrapper->pplugin->enable =  xitk_noskin_labelbutton_create (pp_wrapper->pplugin->widget_list,
1981     &lb, x, y, 100, 23, "Black", "Black", "White", btnfontname);
1982   xitk_add_widget (pp_wrapper->pplugin->widget_list, pp_wrapper->pplugin->enable);
1983 
1984   xitk_labelbutton_set_state(pp_wrapper->pplugin->enable, (pp_wrapper == &vpp_wrapper) ? gui->post_video_enable : gui->post_audio_enable);
1985   xitk_enable_and_show_widget(pp_wrapper->pplugin->enable);
1986 
1987   /* IMPLEMENT ME
1988   x += (100 + 15);
1989 
1990   lb.button_type       = CLICK_BUTTON;
1991   lb.label             = _("Save");
1992   lb.align             = ALIGN_CENTER;
1993   lb.callback          = NULL;
1994   lb.state_callback    = NULL;
1995   lb.userdata          = NULL;
1996   lb.skin_element_name = NULL;
1997   w =  xitk_noskin_labelbutton_create (pp_wrapper->pplugin->widget_list,
1998     &lb, x, y, 100, 23, "Black", "Black", "White", btnfontname);
1999   xitk_add_widget (pp_wrapper->pplugin->widget_list, w);
2000   xitk_enable_and_show_widget(w);
2001   */
2002 
2003   x = WINDOW_WIDTH - (100 + 15);
2004 
2005   lb.button_type       = CLICK_BUTTON;
2006   lb.label             = _("OK");
2007   lb.align             = ALIGN_CENTER;
2008   lb.callback          = (pp_wrapper == &vpp_wrapper) ? vpplugin_exit : applugin_exit;
2009   lb.state_callback    = NULL;
2010   lb.userdata          = NULL;
2011   lb.skin_element_name = NULL;
2012   w =  xitk_noskin_labelbutton_create (pp_wrapper->pplugin->widget_list,
2013     &lb, x, y, 100, 23, "Black", "Black", "White", btnfontname);
2014   xitk_add_widget (pp_wrapper->pplugin->widget_list, w);
2015   xitk_enable_and_show_widget(w);
2016 
2017   _pplugin_get_plugins(pp_wrapper);
2018 
2019   pp_wrapper->pplugin->x = 15;
2020   pp_wrapper->pplugin->y = 34 - (FRAME_HEIGHT + 4);
2021 
2022   _pplugin_rebuild_filters (pp_wrapper);
2023 
2024   xitk_window_change_background(gui->imlib_data, pp_wrapper->pplugin->xwin, bg->pixmap, width, height);
2025   xitk_image_destroy_xitk_pixmap(bg);
2026 
2027   pp_wrapper->pplugin->widget_key = xitk_register_event_handler((pp_wrapper == &vpp_wrapper) ? "vpplugin" : "applugin",
2028 						    (xitk_window_get_window(pp_wrapper->pplugin->xwin)),
2029 						    (pp_wrapper == &vpp_wrapper) ? _vpplugin_handle_event : _applugin_handle_event,
2030 						    NULL,
2031 						    NULL,
2032 						    pp_wrapper->pplugin->widget_list,
2033 						    NULL);
2034 
2035   pp_wrapper->pplugin->visible = 1;
2036   pp_wrapper->pplugin->running = 1;
2037 
2038   _pplugin_paint_widgets(pp_wrapper);
2039 
2040   pplugin_raise_window(pp_wrapper);
2041 
2042   try_to_set_input_focus(xitk_window_get_window(pp_wrapper->pplugin->xwin));
2043 }
2044 
2045 /* pchain: "<post1>:option1=value1,option2=value2..;<post2>:...." */
pplugin_parse_and_load(_pp_wrapper_t * pp_wrapper,const char * pchain,int * post_elements_num)2046 static post_element_t **pplugin_parse_and_load(_pp_wrapper_t *pp_wrapper, const char *pchain, int *post_elements_num) {
2047   gGui_t *gui = gGui;
2048   int plugin_type = (pp_wrapper == &vpp_wrapper) ? XINE_POST_TYPE_VIDEO_FILTER : XINE_POST_TYPE_AUDIO_FILTER;
2049   post_element_t **post_elements = NULL;
2050 
2051   *post_elements_num = 0;
2052 
2053   if(pchain && strlen(pchain)) {
2054     char *p, *post_chain, *ppost_chain;
2055 
2056     post_chain = strdup(pchain);
2057 
2058     ppost_chain = post_chain;
2059     while((p = xine_strsep(&ppost_chain, ";"))) {
2060 
2061       if(strlen(p)) {
2062 	char          *plugin, *args = NULL;
2063 	xine_post_t   *post;
2064 
2065 	while(*p == ' ')
2066 	  p++;
2067 
2068 	plugin = strdup(p);
2069 
2070 	if((p = strchr(plugin, ':')))
2071 	  *p++ = '\0';
2072 
2073 	if(p && (strlen(p) > 1))
2074 	  args = p;
2075 
2076 	post = xine_post_init(__xineui_global_xine_instance, plugin, 0, &gui->ao_port, &gui->vo_port);
2077 
2078         if (post && pp_wrapper) {
2079           if (post->type != plugin_type) {
2080             xine_post_dispose(__xineui_global_xine_instance, post);
2081             post = NULL;
2082           }
2083         }
2084 
2085 	if(post) {
2086 	  post_object_t  pobj;
2087 
2088 	  post_elements = (post_element_t **) realloc(post_elements, sizeof(post_element_t *) * ((*post_elements_num) + 2));
2089 
2090 	  post_elements[(*post_elements_num)] = (post_element_t *)
2091 	    calloc(1, sizeof(post_element_t));
2092 	  post_elements[(*post_elements_num)]->post = post;
2093 	  post_elements[(*post_elements_num)]->name = strdup(plugin);
2094 	  (*post_elements_num)++;
2095 	  post_elements[(*post_elements_num)] = NULL;
2096 
2097 	  memset(&pobj, 0, sizeof(post_object_t));
2098 	  pobj.post = post;
2099 
2100 	  if(__pplugin_retrieve_parameters(&pobj)) {
2101 	    int   i;
2102 
2103 	    if(pobj.properties_names && args) {
2104 	      char *param;
2105 
2106 	      while((param = xine_strsep(&args, ",")) != NULL) {
2107 
2108 		p = param;
2109 
2110 		while((*p != '\0') && (*p != '='))
2111 		  p++;
2112 
2113 		if(strlen(p)) {
2114 		  int param_num = 0;
2115 
2116 		  *p++ = '\0';
2117 
2118 		  while(pobj.properties_names[param_num]
2119 			&& strcasecmp(pobj.properties_names[param_num], param))
2120 		    param_num++;
2121 
2122 		  if(pobj.properties_names[param_num]) {
2123 
2124 		    pobj.param    = pobj.descr->parameter;
2125 		    pobj.param    += param_num;
2126 		    pobj.readonly = pobj.param->readonly;
2127 
2128 		    switch(pobj.param->type) {
2129 		    case POST_PARAM_TYPE_INT:
2130 		      if(!pobj.readonly) {
2131 			if(pobj.param->enum_values) {
2132 			  char **values = pobj.param->enum_values;
2133 			  int    i = 0;
2134 
2135 			  while(values[i]) {
2136 			    if(!strcasecmp(values[i], p)) {
2137 			      *(int *)(pobj.param_data + pobj.param->offset) = i;
2138 			      break;
2139 			    }
2140 			    i++;
2141 			  }
2142 
2143 			  if( !values[i] )
2144 			    *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
2145 			} else {
2146 			  *(int *)(pobj.param_data + pobj.param->offset) = (int) strtol(p, &p, 10);
2147 			}
2148 			_pplugin_update_parameter(&pobj);
2149 		      }
2150 		      break;
2151 
2152 		    case POST_PARAM_TYPE_DOUBLE:
2153 		      if(!pobj.readonly) {
2154 			*(double *)(pobj.param_data + pobj.param->offset) = strtod(p, &p);
2155 			_pplugin_update_parameter(&pobj);
2156 		      }
2157 		      break;
2158 
2159 		    case POST_PARAM_TYPE_CHAR:
2160 		    case POST_PARAM_TYPE_STRING:
2161 		      if(!pobj.readonly) {
2162 			if(pobj.param->type == POST_PARAM_TYPE_CHAR) {
2163 			  int maxlen = pobj.param->size / sizeof(char);
2164 
2165 			  strlcpy((char *)(pobj.param_data + pobj.param->offset), p, maxlen);
2166 			  _pplugin_update_parameter(&pobj);
2167 			}
2168 			else
2169 			  fprintf(stderr, "parameter type POST_PARAM_TYPE_STRING not supported yet.\n");
2170 		      }
2171 		      break;
2172 
2173 		    case POST_PARAM_TYPE_STRINGLIST: /* unsupported */
2174 		      if(!pobj.readonly)
2175 			fprintf(stderr, "parameter type POST_PARAM_TYPE_STRINGLIST not supported yet.\n");
2176 		      break;
2177 
2178 		    case POST_PARAM_TYPE_BOOL:
2179 		      if(!pobj.readonly) {
2180 			*(int *)(pobj.param_data + pobj.param->offset) = ((int) strtol(p, &p, 10)) ? 1 : 0;
2181 			_pplugin_update_parameter(&pobj);
2182 		      }
2183 		      break;
2184 		    }
2185 		  }
2186 		}
2187 	      }
2188 
2189 	      i = 0;
2190 
2191 	      while(pobj.properties_names[i]) {
2192 		free(pobj.properties_names[i]);
2193 		i++;
2194 	      }
2195 
2196 	      free(pobj.properties_names);
2197 	    }
2198 
2199 	    VFREE(pobj.param_data);
2200 	  }
2201 	}
2202 
2203 	VFREE(plugin);
2204       }
2205     }
2206     free(post_chain);
2207   }
2208 
2209   return post_elements;
2210 }
2211 
pplugin_parse_and_store_post(_pp_wrapper_t * pp_wrapper,const char * post_chain)2212 static void pplugin_parse_and_store_post(_pp_wrapper_t *pp_wrapper, const char *post_chain) {
2213   gGui_t *gui = gGui;
2214   post_element_t ***_post_elements = (pp_wrapper == &vpp_wrapper) ? &gui->post_video_elements : &gui->post_audio_elements;
2215   int *_post_elements_num = (pp_wrapper == &vpp_wrapper) ? &gui->post_video_elements_num : &gui->post_audio_elements_num;
2216   post_element_t **posts = NULL;
2217   int              num;
2218 
2219   if((posts = pplugin_parse_and_load(pp_wrapper, post_chain, &num))) {
2220     if(*_post_elements_num) {
2221       int i;
2222       int ptot = *_post_elements_num + num;
2223 
2224       *_post_elements = (post_element_t **) realloc(*_post_elements, sizeof(post_element_t *) * (ptot + 1));
2225       for(i = *_post_elements_num; i <  ptot; i++)
2226 	(*_post_elements)[i] = posts[i - *_post_elements_num];
2227 
2228       (*_post_elements)[i]   = NULL;
2229       (*_post_elements_num) += num;
2230 
2231       free(posts);
2232     }
2233     else {
2234       *_post_elements     = posts;
2235       *_post_elements_num = num;
2236     }
2237   }
2238 }
2239 
post_deinit(void)2240 void post_deinit (void) {
2241   gGui_t *gui = gGui;
2242   int i;
2243 
2244   if (gui->post_video_enable)
2245     _vpplugin_unwire ();
2246 
2247   for (i = 0; i < gui->post_video_elements_num; i++) {
2248     xine_post_dispose (__xineui_global_xine_instance, gui->post_video_elements[i]->post);
2249     free (gui->post_video_elements[i]->name);
2250     VFREE (gui->post_video_elements[i]);
2251   }
2252   SAFE_FREE (gui->post_video_elements);
2253   gui->post_video_elements_num = 0;
2254 
2255 
2256   if (gui->post_audio_enable)
2257     _applugin_unwire ();
2258 
2259   for (i = 0; i < gui->post_audio_elements_num; i++) {
2260     xine_post_dispose (__xineui_global_xine_instance, gui->post_audio_elements[i]->post);
2261     free (gui->post_audio_elements[i]->name);
2262     VFREE (gui->post_audio_elements[i]);
2263   }
2264   SAFE_FREE (gui->post_audio_elements);
2265   gui->post_audio_elements_num = 0;
2266 }
2267 
_pplugin_get_default_deinterlacer(void)2268 static char *_pplugin_get_default_deinterlacer(void) {
2269   return DEFAULT_DEINTERLACER;
2270 }
2271 
post_deinterlace_init(const char * deinterlace_post)2272 void post_deinterlace_init(const char *deinterlace_post) {
2273   gGui_t *gui = gGui;
2274   post_element_t **posts = NULL;
2275   int              num;
2276   char            *deinterlace_default;
2277 
2278   deinterlace_default = _pplugin_get_default_deinterlacer();
2279 
2280   gui->deinterlace_plugin =
2281     (char *) xine_config_register_string (__xineui_global_xine_instance, "gui.deinterlace_plugin",
2282 					  deinterlace_default,
2283 					  _("Deinterlace plugin."),
2284 					  _("Plugin (with optional parameters) to use "
2285 					    "when deinterlace is used (plugin separator is ';')."),
2286 					  CONFIG_LEVEL_ADV,
2287 					  post_deinterlace_plugin_cb,
2288 					  gGui);
2289   if((posts = pplugin_parse_and_load(0, (deinterlace_post && strlen(deinterlace_post)) ?
2290 				     deinterlace_post : gui->deinterlace_plugin, &num))) {
2291     gui->deinterlace_elements     = posts;
2292     gui->deinterlace_elements_num = num;
2293   }
2294 
2295 }
2296 
post_deinterlace_deinit(void)2297 void post_deinterlace_deinit (void) {
2298   gGui_t *gui = gGui;
2299   int i;
2300 #if 0
2301   /* requires <xine/xine_internal.h> */
2302   __xineui_global_xine_instance->config->unregister_callback (__xineui_global_xine_instance, "gui.deinterlace_plugin");
2303 #endif
2304 
2305   if (gui->deinterlace_enable)
2306     _vpplugin_unwire ();
2307 
2308   for (i = 0; i < gui->deinterlace_elements_num; i++) {
2309     xine_post_dispose (__xineui_global_xine_instance, gui->deinterlace_elements[i]->post);
2310     free (gui->deinterlace_elements[i]->name);
2311     VFREE (gui->deinterlace_elements[i]);
2312   }
2313 
2314   SAFE_FREE (gui->deinterlace_elements);
2315   gui->deinterlace_elements_num = 0;
2316 }
2317 
post_deinterlace(void)2318 void post_deinterlace(void) {
2319   gGui_t *gui = gGui;
2320 
2321   if( !gui->deinterlace_elements_num ) {
2322     /* fallback to the old method */
2323     xine_set_param(gui->stream, XINE_PARAM_VO_DEINTERLACE,
2324                    gui->deinterlace_enable);
2325   }
2326   else {
2327     _pplugin_unwire(&vpp_wrapper);
2328     _pplugin_rewire(&vpp_wrapper);
2329   }
2330 
2331 #if 0
2332   if(gui->deinterlace_enable) {
2333     if(gui->post_enable)
2334       _pplugin_unwire();
2335 
2336     _pplugin_rewire_from_post_elements(gui->deinterlace_elements, gui->deinterlace_elements_num);
2337   }
2338   else {
2339     _pplugin_unwire();
2340 
2341     if(gui->post_enable) {
2342       if(pplugin_is_visible() && pplugin)
2343 	_pplugin_rewire();
2344       else
2345 	_pplugin_rewire_from_post_elements(gui->post_elements, gui->post_elements_num);
2346     }
2347   }
2348 #endif
2349 }
2350 
vpplugin_end(void)2351 void vpplugin_end(void)
2352 {
2353   pplugin_end(&vpp_wrapper);
2354 }
2355 
vpplugin_is_visible(void)2356 int vpplugin_is_visible(void)
2357 {
2358   return pplugin_is_visible(&vpp_wrapper);
2359 }
2360 
vpplugin_is_running(void)2361 int vpplugin_is_running(void)
2362 {
2363   return pplugin_is_running(&vpp_wrapper);
2364 }
2365 
vpplugin_toggle_visibility(xitk_widget_t * w,void * data)2366 void vpplugin_toggle_visibility(xitk_widget_t *w, void *data)
2367 {
2368   pplugin_toggle_visibility(&vpp_wrapper, w, data);
2369 }
2370 
vpplugin_raise_window(void)2371 void vpplugin_raise_window(void)
2372 {
2373   pplugin_raise_window(&vpp_wrapper);
2374 }
2375 
vpplugin_update_enable_button(void)2376 void vpplugin_update_enable_button(void)
2377 {
2378   pplugin_update_enable_button(&vpp_wrapper);
2379 }
2380 
vpplugin_panel(void)2381 void vpplugin_panel(void)
2382 {
2383   pplugin_panel(&vpp_wrapper);
2384 }
2385 
vpplugin_parse_and_store_post(const char * post)2386 void vpplugin_parse_and_store_post(const char *post)
2387 {
2388   pplugin_parse_and_store_post(&vpp_wrapper, post);
2389 }
2390 
vpplugin_rewire_from_posts_window(void)2391 void vpplugin_rewire_from_posts_window(void)
2392 {
2393   pplugin_rewire_from_posts_window(&vpp_wrapper);
2394 }
2395 
vpplugin_rewire_posts(void)2396 void vpplugin_rewire_posts(void)
2397 {
2398   pplugin_rewire_posts(&vpp_wrapper);
2399 }
2400 
vpplugin_is_post_selected(void)2401 int vpplugin_is_post_selected(void)
2402 {
2403   return pplugin_is_post_selected(&vpp_wrapper);
2404 }
2405 
vpplugin_reparent(void)2406 void vpplugin_reparent(void)
2407 {
2408   pplugin_reparent(&vpp_wrapper);
2409 }
2410 
applugin_end(void)2411 void applugin_end(void)
2412 {
2413   pplugin_end(&app_wrapper);
2414 }
2415 
applugin_is_visible(void)2416 int applugin_is_visible(void)
2417 {
2418   return pplugin_is_visible(&app_wrapper);
2419 }
2420 
applugin_is_running(void)2421 int applugin_is_running(void)
2422 {
2423   return pplugin_is_running(&app_wrapper);
2424 }
2425 
applugin_toggle_visibility(xitk_widget_t * w,void * data)2426 void applugin_toggle_visibility(xitk_widget_t *w, void *data)
2427 {
2428   pplugin_toggle_visibility(&app_wrapper, w, data);
2429 }
2430 
applugin_raise_window(void)2431 void applugin_raise_window(void)
2432 {
2433   pplugin_raise_window(&app_wrapper);
2434 }
2435 
applugin_update_enable_button(void)2436 void applugin_update_enable_button(void)
2437 {
2438   pplugin_update_enable_button(&app_wrapper);
2439 }
2440 
applugin_panel(void)2441 void applugin_panel(void)
2442 {
2443   pplugin_panel(&app_wrapper);
2444 }
2445 
applugin_parse_and_store_post(const char * post)2446 void applugin_parse_and_store_post(const char *post)
2447 {
2448   pplugin_parse_and_store_post(&app_wrapper, post);
2449 }
2450 
applugin_rewire_from_posts_window(void)2451 void applugin_rewire_from_posts_window(void)
2452 {
2453   pplugin_rewire_from_posts_window(&app_wrapper);
2454 }
2455 
applugin_rewire_posts(void)2456 void applugin_rewire_posts(void)
2457 {
2458   pplugin_rewire_posts(&app_wrapper);
2459 }
2460 
applugin_is_post_selected(void)2461 int applugin_is_post_selected(void)
2462 {
2463   return pplugin_is_post_selected(&app_wrapper);
2464 }
2465 
applugin_reparent(void)2466 void applugin_reparent(void)
2467 {
2468   pplugin_reparent(&app_wrapper);
2469 }
2470