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  * xine panel related stuff
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <pthread.h>
31 #include <sys/time.h>
32 
33 #include "common.h"
34 #include "xine-toolkit/button_list.h"
35 
36 struct xui_panel_st {
37   gGui_t               *gui;
38 
39   xitk_widget_list_t   *widget_list;
40 
41   int                   x;
42   int                   y;
43   int                   skin_on_change;
44 
45   xitk_widget_t        *title_label;
46   xitk_widget_t        *runtime_label;
47   int                   runtime_mode;
48 
49   struct {
50     int                 enabled;
51     xitk_widget_t      *prev;
52     xitk_widget_t      *stop;
53     xitk_widget_t      *play;
54     xitk_widget_t      *pause;
55     xitk_widget_t      *next;
56     xitk_widget_t      *eject;
57     xitk_widget_t      *slider_play;
58     unsigned int        slider_play_time;
59   } playback_widgets;
60 
61   struct {
62     xitk_widget_t      *slider;
63     xitk_widget_t      *mute;
64   } mixer;
65 
66   struct {
67     int                 enable;
68     unsigned long       timeout;
69   } tips;
70 
71   int                   visible;
72   char                  runtime[20];
73   xitk_widget_t        *audiochan_label;
74   xitk_button_list_t   *autoplay_buttons;
75   xitk_widget_t        *spuid_label;
76   ImlibImage           *bg_image;
77   xitk_register_key_t   widget_key;
78   pthread_t             slider_thread;
79 
80   /* private vars to avoid useless updates */
81   unsigned int          shown_time;
82   unsigned int          shown_length;
83 
84 };
85 
panel_update_nextprev_tips(xui_panel_t * panel)86 void panel_update_nextprev_tips (xui_panel_t *panel) {
87 
88   if (panel->gui->skip_by_chapter) {
89     xitk_set_widget_tips(panel->playback_widgets.prev, _("Play previous chapter or mrl"));
90     xitk_set_widget_tips(panel->playback_widgets.next, _("Play next chapter or mrl"));
91   }
92   else {
93     xitk_set_widget_tips(panel->playback_widgets.prev, _("Play previous entry from playlist"));
94     xitk_set_widget_tips(panel->playback_widgets.next, _("Play next entry from playlist"));
95   }
96 }
97 
is_playback_widgets_enabled(xui_panel_t * panel)98 int is_playback_widgets_enabled (xui_panel_t *panel) {
99   return (panel->playback_widgets.enabled == 1);
100 }
101 
enable_playback_controls(xui_panel_t * panel,int enable)102 void enable_playback_controls (xui_panel_t *panel, int enable) {
103   void (*enability)(xitk_widget_t *) = NULL;
104 
105   panel->playback_widgets.enabled = enable;
106 
107   if(enable)
108     enability = xitk_enable_widget;
109   else
110     enability = xitk_disable_widget;
111 
112   enability(panel->playback_widgets.prev);
113   enability(panel->playback_widgets.stop);
114   enability(panel->playback_widgets.play);
115   enability(panel->playback_widgets.pause);
116   enability(panel->playback_widgets.next);
117   enability(panel->playback_widgets.slider_play);
118 }
119 
120 /*
121  *
122  */
panel_show_tips(xui_panel_t * panel)123 void panel_show_tips (xui_panel_t *panel) {
124 
125   if(panel->tips.enable)
126     xitk_set_widgets_tips_timeout(panel->widget_list, panel->tips.timeout);
127   else
128     xitk_disable_widgets_tips(panel->widget_list);
129 
130   playlist_show_tips(panel->tips.enable, panel->tips.timeout);
131   control_show_tips (panel->gui->vctrl, panel->tips.enable, panel->tips.timeout);
132   mrl_browser_show_tips (panel->gui->mrlb, panel->tips.enable, panel->tips.timeout);
133   event_sender_show_tips(panel->tips.enable, panel->tips.timeout);
134   mmk_editor_show_tips(panel->tips.enable, panel->tips.timeout);
135   setup_show_tips (panel->gui->setup, panel->tips.enable, panel->tips.timeout);
136 }
137 
138 /* Somewhat paranoia conditionals (Hans, YOU're paranoid ;-) )*/
panel_get_tips_enable(xui_panel_t * panel)139 int panel_get_tips_enable (xui_panel_t *panel) {
140   return (panel) ? panel->tips.enable : 0;
141 }
panel_get_tips_timeout(xui_panel_t * panel)142 unsigned long panel_get_tips_timeout (xui_panel_t *panel) {
143   return (panel) ? panel->tips.timeout : 0;
144 }
145 
146 /*
147  * Config callbacks.
148  */
panel_enable_tips_cb(void * data,xine_cfg_entry_t * cfg)149 static void panel_enable_tips_cb(void *data, xine_cfg_entry_t *cfg) {
150   xui_panel_t *panel = data;
151   panel->tips.enable = cfg->num_value;
152   panel_show_tips (panel);
153 }
panel_timeout_tips_cb(void * data,xine_cfg_entry_t * cfg)154 static void panel_timeout_tips_cb(void *data, xine_cfg_entry_t *cfg) {
155   xui_panel_t *panel = data;
156   panel->tips.timeout = (unsigned long) cfg->num_value;
157   panel_show_tips (panel);
158 }
159 
160 /*
161  * Toolkit event handler will call this function with new
162  * coords of panel window.
163  */
panel_store_new_position(void * data,int x,int y,int w,int h)164 static void panel_store_new_position (void *data, int x, int y, int w, int h) {
165   xui_panel_t *panel = data;
166 
167   (void)h;
168 
169   if(panel->skin_on_change == 0) {
170 
171     panel->x = x;
172     panel->y = y;
173 
174     config_update_num ("gui.panel_x", x);
175     config_update_num ("gui.panel_y", y);
176 
177     if(event_sender_is_running())
178       event_sender_move(x+w, y);
179 
180   }
181   else
182     panel->skin_on_change--;
183 
184 }
185 
panel_exit(xitk_widget_t * w,void * data)186 static void panel_exit (xitk_widget_t *w, void *data) {
187   xui_panel_t *panel = data;
188 
189   (void)w;
190 
191   if(panel) {
192     window_info_t wi;
193 
194     panel->visible = 0;
195 
196 #ifdef HAVE_XINE_CONFIG_UNREGISTER_CALLBACKS
197     xine_config_unregister_callbacks (panel->gui->xine, NULL, NULL, panel, sizeof (*panel));
198 #endif
199 
200     if((xitk_get_window_info(panel->widget_key, &wi))) {
201       config_update_num ("gui.panel_x", wi.x);
202       config_update_num ("gui.panel_y", wi.y);
203       WINDOW_INFO_ZERO(&wi);
204     }
205 
206     xitk_unregister_event_handler(&panel->widget_key);
207 
208     pthread_join(panel->slider_thread, NULL);
209 
210     panel->gui->x_lock_display (panel->gui->display);
211     XUnmapWindow (panel->gui->display, panel->gui->panel_window);
212     panel->gui->x_unlock_display (panel->gui->display);
213 
214     panel->title_label = 0;
215     xitk_destroy_widgets(panel->widget_list);
216     xitk_button_list_delete (panel->autoplay_buttons);
217 
218     panel->gui->x_lock_display (panel->gui->display);
219     XDestroyWindow (panel->gui->display, panel->gui->panel_window);
220     Imlib_destroy_image (panel->gui->imlib_data, panel->bg_image);
221     panel->gui->x_unlock_display (panel->gui->display);
222 
223     panel->gui->panel_window = None;
224     /* xitk_dlist_init (&panel->widget_list->list); */
225 
226     panel->gui->x_lock_display (panel->gui->display);
227     XFreeGC (panel->gui->display, (XITK_WIDGET_LIST_GC(panel->widget_list)));
228     panel->gui->x_unlock_display (panel->gui->display);
229 
230     XITK_WIDGET_LIST_FREE(panel->widget_list);
231 
232     panel->gui->panel = NULL;
233     free (panel);
234   }
235 }
236 
237 /*
238  * Change the current skin.
239  */
panel_change_skins(xui_panel_t * panel,int synthetic)240 void panel_change_skins (xui_panel_t *panel, int synthetic) {
241   ImlibImage   *new_img, *old_img;
242   XSizeHints    hint;
243 
244   (void)synthetic;
245 
246   panel->skin_on_change++;
247 
248   xitk_skin_lock (panel->gui->skin_config);
249   xitk_hide_widgets(panel->widget_list);
250 
251   panel->gui->x_lock_display (panel->gui->display);
252 
253   if (!(new_img = Imlib_load_image (panel->gui->imlib_data,
254     xitk_skin_get_skin_filename (panel->gui->skin_config, "BackGround")))) {
255     xine_error (_("%s(): couldn't find image for background\n"), __XINE_FUNCTION__);
256     exit(-1);
257   }
258 
259   hint.width  = new_img->rgb_width;
260   hint.height = new_img->rgb_height;
261   hint.flags  = PPosition | PSize;
262   XSetWMNormalHints (panel->gui->display, panel->gui->panel_window, &hint);
263 
264   XResizeWindow (panel->gui->display, panel->gui->panel_window,
265 		 (unsigned int)new_img->rgb_width,
266 		 (unsigned int)new_img->rgb_height);
267 
268   panel->gui->x_unlock_display (panel->gui->display);
269 
270   while (!xitk_is_window_size (panel->gui->display, panel->gui->panel_window,
271 			     new_img->rgb_width, new_img->rgb_height)) {
272     xine_usec_sleep(10000);
273   }
274 
275   old_img = panel->bg_image;
276   panel->bg_image = new_img;
277 
278   video_window_set_transient_for (panel->gui->vwin, panel->gui->panel_window);
279 
280   panel->gui->x_lock_display (panel->gui->display);
281 
282   Imlib_destroy_image (panel->gui->imlib_data, old_img);
283   Imlib_apply_image (panel->gui->imlib_data, new_img, panel->gui->panel_window);
284 
285   panel->gui->x_unlock_display (panel->gui->display);
286 
287   if (panel_is_visible (panel))
288     raise_window (panel->gui->panel_window, 1, 1);
289 
290   xitk_skin_unlock (panel->gui->skin_config);
291 
292   xitk_change_skins_widget_list (panel->widget_list, panel->gui->skin_config);
293 
294   /*
295    * Update position of dynamic buttons.
296    */
297   xitk_button_list_new_skin (panel->autoplay_buttons, panel->gui->skin_config);
298 
299   enable_playback_controls (panel, panel->playback_widgets.enabled);
300   xitk_paint_widget_list(panel->widget_list);
301 
302   event_sender_move(panel->x + hint.width, panel->y);
303 }
304 
305 /*
306  * Update runtime displayed informations.
307  */
secs2str(char * s,unsigned int secs)308 static void secs2str (char *s, unsigned int secs) {
309   /* Avoid slow snprintf (). Yes this does not support south asian */
310   /* alternative digits, but neither does the widget bitmap font.  */
311   /* But wait -- what if you modify letters.png now ?              */
312   if (secs >= 24 * 60 * 60) { /* [  dd::hh] */
313     unsigned int days;
314     secs /= 3600u;
315     days = secs / 24u;
316     secs %= 24u;
317     memcpy (s, "    ::  ", 8);
318     s[8] = 0;
319     s[7] = (secs % 10u) + '0';
320     s[6] = (secs / 10u) + '0';
321     s[3] = (days % 10u) + '0';
322     days /= 10u;
323     if (days)
324       s[2] = days + '0';
325   } else { /* [hh:mm:ss] */
326     s[8] = 0;
327     s[7] = (secs % 10u) + '0';
328     secs /= 10u;
329     s[6] = (secs % 6u) + '0';
330     secs /= 6u;
331     s[5] = ':';
332     s[4] = (secs % 10u) + '0';
333     secs /= 10u;
334     s[3] = (secs % 6u) + '0';
335     secs /= 6u;
336     s[2] = ':';
337     s[1] = (secs % 10u) + '0';
338     s[0] = (secs / 10u) + '0';
339   }
340 }
panel_update_runtime_display(xui_panel_t * panel)341 void panel_update_runtime_display (xui_panel_t *panel) {
342   int seconds, pos, length;
343   char timestr[16];
344 
345   if (!panel_is_visible (panel))
346     return;
347 
348   if (!gui_xine_get_pos_length (panel->gui->stream, &pos, &seconds, &length)) {
349 
350     if ((panel->gui->stream_length.pos || panel->gui->stream_length.time) && panel->gui->stream_length.length) {
351       pos     = panel->gui->stream_length.pos;
352       seconds = panel->gui->stream_length.time;
353       length  = panel->gui->stream_length.length;
354     }
355     else
356       return;
357 
358   }
359 
360   do {
361     unsigned int msecs = seconds, secs;
362     if (!(pos || msecs)) { /* are you sure there is something to play? */
363       panel->shown_time = ~3;
364       strcpy (timestr, "--:--:--");
365       break;
366     }
367     if (panel->runtime_mode) { /* show remaining time */
368       if (msecs > (unsigned int)length) {
369         panel->shown_time = ~3;
370         strcpy (timestr, "  :  :  ");
371         break;
372       }
373       msecs = length - msecs;
374     }
375     if (msecs == panel->shown_time) {
376       timestr[0] = 0;
377       break;
378     }
379     panel->shown_time = msecs;
380     secs   = msecs / 1000u;
381     msecs %= 1000u;
382     secs2str (timestr, secs);
383     if (xine_get_param (panel->gui->stream, XINE_PARAM_SPEED) > XINE_SPEED_NORMAL / 2)
384       break;
385     /* millisecond information is useful when editing. since we only update */
386     /* twice a second, show this in slow mode only. */
387     timestr[12] = 0;
388     timestr[11] = (msecs % 10u) + '0';
389     msecs /= 10u;
390     timestr[10] = (msecs % 10u) + '0';
391     timestr[9] = (msecs / 10u) + '0';
392     timestr[8] = '.';
393   } while (0);
394 
395   if ((unsigned int)length != panel->shown_length) {
396     char buffer[256];
397     const char *ts = _("Total time: ");
398     size_t tl = strlen (ts);
399     if (tl > sizeof (buffer) - 9)
400       tl = sizeof (buffer) - 9;
401     memcpy (buffer, ts, tl);
402     panel->shown_length = length;
403     if (length > 0)
404       secs2str (buffer + tl, length / 1000);
405     else
406       strcpy (buffer + tl, "??:??:??");
407     xitk_set_widget_tips (panel->runtime_label, buffer);
408   }
409 
410   if (timestr[0])
411     xitk_label_change_label (panel->runtime_label, timestr);
412 }
413 
414 /*
415  * Update slider thread.
416  */
slider_loop(void * data)417 static __attribute__((noreturn)) void *slider_loop (void *data) {
418   xui_panel_t *panel = data;
419   int screensaver_timer = 0;
420   int lastmsecs = -1;
421   int i = 0;
422 
423   while (panel->gui->on_quit == 0) {
424 
425     if (panel->gui->stream) {
426 
427       int status = xine_get_status (panel->gui->stream);
428       int speed  = xine_get_param (panel->gui->stream, XINE_PARAM_SPEED);
429 
430       int pos = 0, msecs = 0;
431 
432       if(status == XINE_STATUS_PLAY) {
433         int seeking;
434         pthread_mutex_lock (&panel->gui->seek_mutex);
435         seeking = panel->gui->seek_running;
436         pthread_mutex_unlock (&panel->gui->seek_mutex);
437         if (!seeking && gui_xine_get_pos_length (panel->gui->stream, &pos, &msecs, NULL)) {
438 
439           /* pthread_mutex_lock (&panel->gui->xe_mutex); */
440 
441           if (panel->gui->playlist.num && panel->gui->playlist.cur >= 0 && panel->gui->playlist.mmk &&
442             panel->gui->playlist.mmk[panel->gui->playlist.cur] && panel->gui->mmk.end != -1) {
443             if ((msecs / 1000) >= panel->gui->playlist.mmk[panel->gui->playlist.cur]->end) {
444               panel->gui->ignore_next = 0;
445               gui_playlist_start_next (panel->gui);
446               /* pthread_mutex_unlock (&panel->gui->xe_mutex); */
447 	      goto __next_iteration;
448 	    }
449 	  }
450 
451           if (panel->gui->playlist.num) {
452             if ((xine_get_stream_info (panel->gui->stream, XINE_STREAM_INFO_SEEKABLE))) {
453 	      if(!xitk_is_widget_enabled(panel->playback_widgets.slider_play))
454 		xitk_enable_widget(panel->playback_widgets.slider_play);
455 	    }
456 	    else {
457 	      if(xitk_is_widget_enabled(panel->playback_widgets.slider_play)) {
458 		xitk_slider_reset(panel->playback_widgets.slider_play);
459 		xitk_disable_widget(panel->playback_widgets.slider_play);
460 	      }
461 	    }
462 	  }
463 
464           /* pthread_mutex_unlock (&panel->gui->xe_mutex); */
465 	}
466 	else
467 	  pos = -1;
468 
469       }
470 
471       if(!(i % 2)) {
472 	osd_update();
473 
474         if (panel->gui->mrl_overrided) {
475           panel->gui->mrl_overrided--;
476           if (panel->gui->mrl_overrided == 0)
477             panel_update_mrl_display (panel);
478 	}
479       }
480 
481       if ((status == XINE_STATUS_PLAY) &&
482         ((speed != XINE_SPEED_PAUSE) || (msecs != lastmsecs))) {
483         char *ident = stream_infos_get_ident_from_stream (panel->gui->stream);
484 
485         if (!pthread_mutex_trylock (&panel->gui->mmk_mutex)) {
486           if (ident) {
487             if (panel->gui->playlist.num &&
488                 (panel->gui->playlist.cur >= 0) &&
489                 panel->gui->playlist.mmk &&
490                 panel->gui->playlist.mmk[panel->gui->playlist.cur] &&
491                 (strcmp (panel->gui->mmk.ident, ident))) {
492               free (panel->gui->mmk.ident);
493               panel->gui->mmk.ident = strdup (ident);
494               free (panel->gui->playlist.mmk[panel->gui->playlist.cur]->ident);
495               panel->gui->playlist.mmk[panel->gui->playlist.cur]->ident = strdup (ident);
496               pthread_mutex_unlock (&panel->gui->mmk_mutex);
497               video_window_set_mrl (panel->gui->vwin, ident);
498               playlist_mrlident_toggle ();
499               panel_update_mrl_display (panel);
500             } else {
501               pthread_mutex_unlock (&panel->gui->mmk_mutex);
502             }
503           } else {
504             video_window_set_mrl (panel->gui->vwin, (char *)panel->gui->mmk.mrl);
505             pthread_mutex_unlock (&panel->gui->mmk_mutex);
506           }
507         }
508         free (ident);
509 
510         {
511           int iconified;
512           video_window_lock (panel->gui->vwin, 1);
513           iconified = xitk_is_window_iconified (panel->gui->video_display, panel->gui->video_window);
514           video_window_lock (panel->gui->vwin, 0);
515           if (!iconified) {
516             if (panel->gui->ssaver_timeout) {
517               if (!(i % 2))
518                 screensaver_timer++;
519               if (screensaver_timer >= panel->gui->ssaver_timeout)
520                 screensaver_timer = video_window_reset_ssaver (panel->gui->vwin);
521             }
522           }
523         }
524 
525         if (panel->gui->logo_mode == 0) {
526 
527           if (panel_is_visible (panel)) {
528 
529             panel_update_runtime_display (panel);
530 
531 	    if(xitk_is_widget_enabled(panel->playback_widgets.slider_play)) {
532 	      if(pos >= 0)
533 		xitk_slider_set_pos(panel->playback_widgets.slider_play, pos);
534 	    }
535 
536 	    if(!(i % 20)) {
537 	      int level = 0;
538 
539               panel_update_channel_display (panel);
540 
541               if ((panel->gui->mixer.method == SOUND_CARD_MIXER) &&
542                 (panel->gui->mixer.caps & MIXER_CAP_VOL)) {
543                 level = panel->gui->mixer.volume_level =
544                   xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_VOLUME);
545 	      }
546               else if (panel->gui->mixer.method == SOFTWARE_MIXER) {
547                 level = panel->gui->mixer.amp_level =
548                   xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_AMP_LEVEL);
549 	      }
550 
551 	      xitk_slider_set_pos(panel->mixer.slider, level);
552               panel_check_mute (panel);
553 
554 	      i = 0;
555 	    }
556 
557 	  }
558 
559           if (stream_infos_is_visible() && panel->gui->stream_info_auto_update)
560 	    stream_infos_update_infos();
561 
562 	}
563       }
564       lastmsecs = msecs;
565     }
566 
567     if (panel->gui->cursor_visible) {
568       if(!(i % 2))
569 	video_window_set_cursor_timer (panel->gui->vwin, video_window_get_cursor_timer (panel->gui->vwin) + 1);
570 
571       if (video_window_get_cursor_timer (panel->gui->vwin) >= 5) {
572         panel->gui->cursor_visible = !panel->gui->cursor_visible;
573         video_window_set_cursor_visibility (panel->gui->vwin, panel->gui->cursor_visible);
574       }
575     }
576 
577     if (panel->gui->logo_has_changed)
578       video_window_update_logo (panel->gui->vwin);
579 
580   __next_iteration:
581     xine_usec_sleep(500000.0);
582     i++;
583   }
584 
585   pthread_exit(NULL);
586 }
587 
588 /*
589  * Boolean about panel visibility.
590  */
panel_is_visible(xui_panel_t * panel)591 int panel_is_visible (xui_panel_t *panel) {
592 
593   if(panel) {
594     if (panel->gui->use_root_window)
595       return xitk_is_window_visible (panel->gui->display, panel->gui->panel_window);
596     else
597       return panel->visible && xitk_is_window_visible (panel->gui->display, panel->gui->panel_window);
598   }
599 
600   return 0;
601 }
602 
603 /*
604  * Show/Hide panel window.
605  */
_panel_toggle_visibility(xitk_widget_t * w,void * data)606 static void _panel_toggle_visibility (xitk_widget_t *w, void *data) {
607   xui_panel_t *panel = data;
608   int visible = xitk_is_window_visible (panel->gui->display, panel->gui->panel_window);
609   int invisible = !panel->visible || !visible;
610   unsigned char lut[2] = {invisible, visible};
611   int v;
612 
613   (void)w;
614 
615   v = !!playlist_is_visible ();
616   if (lut[v])
617     playlist_toggle_visibility(NULL, NULL);
618 
619   v = control_status (panel->gui->vctrl) - 2;
620   if ((v >= 0) && (lut[v]))
621     control_toggle_visibility (NULL, panel->gui->vctrl);
622 
623   v = !!mrl_browser_is_visible (panel->gui->mrlb);
624   if (lut[v])
625     mrl_browser_toggle_visibility (NULL, panel->gui->mrlb);
626 
627   v = !!setup_is_visible (panel->gui->setup);
628   if (lut[v])
629     setup_toggle_visibility (NULL, panel->gui->setup);
630 
631   v = !!viewlog_is_visible ();
632   if (lut[v])
633     viewlog_toggle_visibility(NULL, NULL);
634 
635   v = !!kbedit_is_visible ();
636   if (lut[v])
637     kbedit_toggle_visibility(NULL, NULL);
638 
639   v = !!event_sender_is_visible ();
640   if (lut[v])
641     event_sender_toggle_visibility(NULL, NULL);
642 
643   v = !!stream_infos_is_visible ();
644   if (lut[v])
645     stream_infos_toggle_visibility(NULL, NULL);
646 
647   v = !!tvset_is_visible ();
648   if (lut[v])
649     tvset_toggle_visibility(NULL, NULL);
650 
651   v = !!vpplugin_is_visible ();
652   if (lut[v])
653     vpplugin_toggle_visibility(NULL, NULL);
654 
655   v = !!applugin_is_visible ();
656   if (lut[v])
657     applugin_toggle_visibility(NULL, NULL);
658 
659   v = !!help_is_visible ();
660   if (lut[v])
661     help_toggle_visibility(NULL, NULL);
662 
663   if (panel->visible && panel->gui->video_display == panel->gui->display) {
664 
665     panel->gui->x_lock_display (panel->gui->display);
666 
667     if (video_window_is_visible (panel->gui->vwin)) {
668       if (panel->gui->use_root_window) { /* Using root window */
669 	if(visible)
670           XIconifyWindow (panel->gui->display, panel->gui->panel_window, panel->gui->screen);
671 	else
672           XMapWindow (panel->gui->display, panel->gui->panel_window);
673       }
674       else {
675 	panel->visible = 0;
676         XUnmapWindow (panel->gui->display, panel->gui->panel_window);
677         XSync (panel->gui->display, False);
678         panel->gui->x_unlock_display (panel->gui->display);
679 	xitk_hide_widgets(panel->widget_list);
680         panel->gui->x_lock_display (panel->gui->display);
681       }
682     }
683     else {
684       if(visible)
685         XIconifyWindow (panel->gui->display, panel->gui->panel_window, (XDefaultScreen (panel->gui->display)));
686       else
687         XMapWindow (panel->gui->display, panel->gui->panel_window);
688     }
689 
690     panel->gui->x_unlock_display (panel->gui->display);
691 
692     {
693       Window want;
694       int t;
695       video_window_lock (panel->gui->vwin, 1);
696       want = panel->gui->video_window;
697       panel->gui->x_lock_display (panel->gui->video_display);
698       if (panel->gui->cursor_grabbed)
699         XGrabPointer (panel->gui->video_display, want,
700           1, None, GrabModeAsync, GrabModeAsync, want, None, CurrentTime);
701       if (video_window_is_visible (panel->gui->vwin)) {
702         /* Give focus to video output window */
703         XSetInputFocus (panel->gui->video_display, want, RevertToParent, CurrentTime);
704         XSync (panel->gui->video_display, False);
705         panel->gui->x_unlock_display (panel->gui->video_display);
706         video_window_lock (panel->gui->vwin, 0);
707         /* check after 5/15/30/50/75/105/140 ms */
708         for (t = 5000; t < 40000; t += 5000) {
709           Window got;
710           int revert;
711           xine_usec_sleep (t);
712           panel->gui->x_lock_display (panel->gui->video_display);
713           XGetInputFocus (panel->gui->video_display, &got, &revert);
714           panel->gui->x_unlock_display (panel->gui->video_display);
715           if (got == want)
716             break;
717         }
718       } else {
719         panel->gui->x_unlock_display (panel->gui->video_display);
720         video_window_lock (panel->gui->vwin, 0);
721       }
722     }
723 
724   }
725   else {
726 
727     panel->visible = 1;
728     panel->gui->nongui_error_msg = NULL;
729     xitk_show_widgets(panel->widget_list);
730 
731     panel->gui->x_lock_display (panel->gui->display);
732 
733     XRaiseWindow (panel->gui->display, panel->gui->panel_window);
734     XMapWindow (panel->gui->display, panel->gui->panel_window);
735     panel->gui->x_unlock_display (panel->gui->display);
736     video_window_set_transient_for (panel->gui->vwin, panel->gui->panel_window);
737 
738     wait_for_window_visible (panel->gui->display, panel->gui->panel_window);
739     layer_above_video (panel->gui->panel_window);
740 
741     if (panel->gui->cursor_grabbed) {
742       panel->gui->x_lock_display (panel->gui->display);
743       XUngrabPointer (panel->gui->display, CurrentTime);
744       panel->gui->x_unlock_display (panel->gui->display);
745     }
746 
747 #if defined(HAVE_XINERAMA) || defined(HAVE_XF86VIDMODE)
748     if(
749 #ifdef HAVE_XINERAMA
750        (((video_window_get_fullscreen_mode (panel->gui->vwin)) & (WINDOWED_MODE | FULLSCR_MODE)) &&
751 	(!((video_window_get_fullscreen_mode (panel->gui->vwin)) & FULLSCR_XI_MODE)))
752 #ifdef HAVE_XF86VIDMODE
753        ||
754 #endif
755 #endif
756 #ifdef HAVE_XF86VIDMODE
757        (panel->gui->XF86VidMode_fullscreen)
758 #endif
759        ) {
760       int x, y, w, h, desktopw, desktoph;
761 
762       xitk_get_window_position (panel->gui->display, panel->gui->panel_window, &x, &y, &w, &h);
763 
764       panel->gui->x_lock_display (panel->gui->display);
765       desktopw = DisplayWidth (panel->gui->display, panel->gui->screen);
766       desktoph = DisplayHeight (panel->gui->display, panel->gui->screen);
767       panel->gui->x_unlock_display (panel->gui->display);
768 
769       if(((x + w) <= 0) || ((y + h) <= 0) || (x >= desktopw) || (y >= desktoph)) {
770 	int newx, newy;
771 
772 	newx = (desktopw - w) >> 1;
773 	newy = (desktoph - h) >> 1;
774 
775         panel->gui->x_lock_display (panel->gui->display);
776         XMoveWindow (panel->gui->display, panel->gui->panel_window, newx, newy);
777         panel->gui->x_unlock_display (panel->gui->display);
778 
779         panel_store_new_position (panel, newx, newy, w, h);
780       }
781     }
782 #endif
783 
784     if (panel->gui->logo_mode == 0) {
785       int pos;
786 
787       if(xitk_is_widget_enabled(panel->playback_widgets.slider_play)) {
788         if (gui_xine_get_pos_length (panel->gui->stream, &pos, NULL, NULL))
789 	  xitk_slider_set_pos(panel->playback_widgets.slider_play, pos);
790         panel_update_runtime_display (panel);
791       }
792 
793       panel_update_mrl_display (panel);
794     }
795 
796   }
797 }
798 
panel_toggle_visibility(xitk_widget_t * w,void * data)799 void panel_toggle_visibility (xitk_widget_t *w, void *data) {
800   xui_panel_t *panel = data;
801   _panel_toggle_visibility(w, data);
802   config_update_num ("gui.panel_visible", panel->visible);
803 }
804 
panel_check_mute(xui_panel_t * panel)805 void panel_check_mute (xui_panel_t *panel) {
806   xitk_checkbox_set_state (panel->mixer.mute, panel->gui->mixer.mute);
807 }
808 
809 /*
810  * Check and set the correct state of pause button.
811  */
panel_check_pause(xui_panel_t * panel)812 void panel_check_pause (xui_panel_t *panel) {
813 
814   xitk_checkbox_set_state(panel->playback_widgets.pause,
815     (((xine_get_status (panel->gui->stream) == XINE_STATUS_PLAY) &&
816       (xine_get_param (panel->gui->stream, XINE_PARAM_SPEED) == XINE_SPEED_PAUSE)) ? 1 : 0));
817 }
818 
panel_reset_runtime_label(xui_panel_t * panel)819 void panel_reset_runtime_label (xui_panel_t *panel) {
820   if(panel->runtime_mode == 0)
821     xitk_label_change_label (panel->runtime_label, "00:00:00");
822   else
823     xitk_label_change_label (panel->runtime_label, "..:..:..");
824 }
825 
_panel_change_display_mode(xitk_widget_t * w,void * data)826 static void _panel_change_display_mode(xitk_widget_t *w, void *data) {
827   xui_panel_t *panel = data;
828 
829   (void)w;
830   panel->gui->is_display_mrl = !panel->gui->is_display_mrl;
831   panel_update_mrl_display (panel);
832   playlist_mrlident_toggle();
833 }
834 
_panel_change_time_label(xitk_widget_t * w,void * data)835 static void _panel_change_time_label(xitk_widget_t *w, void *data) {
836   xui_panel_t *panel = data;
837 
838   (void)w;
839   panel->runtime_mode = !panel->runtime_mode;
840   panel_update_runtime_display (panel);
841 }
842 
843 /*
844  * Reset the slider of panel window (set to 0).
845  */
panel_reset_slider(xui_panel_t * panel)846 void panel_reset_slider (xui_panel_t *panel) {
847   xitk_slider_reset(panel->playback_widgets.slider_play);
848   panel_reset_runtime_label (panel);
849 }
850 
panel_update_slider(xui_panel_t * panel,int pos)851 void panel_update_slider (xui_panel_t *panel, int pos) {
852   xitk_slider_set_pos(panel->playback_widgets.slider_play, pos);
853 }
854 
855 /*
856  * Update audio/spu channel displayed informations.
857  */
panel_update_channel_display(xui_panel_t * panel)858 void panel_update_channel_display (xui_panel_t *panel) {
859   int   channel;
860   char  buffer[XINE_LANG_MAX];
861   char *lang = NULL;
862 
863   memset(&buffer, 0, sizeof(buffer));
864   channel = xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
865   switch (channel) {
866   case -2:
867     lang = "off";
868     break;
869 
870   case -1:
871     if (!xine_get_audio_lang (panel->gui->stream, channel, &buffer[0]))
872       lang = "auto";
873     else
874       lang = buffer;
875     break;
876 
877   default:
878     if (!xine_get_audio_lang (panel->gui->stream, channel, &buffer[0]))
879       snprintf(buffer, sizeof(buffer), "%3d", channel);
880     lang = buffer;
881     break;
882   }
883   xitk_label_change_label (panel->audiochan_label, lang);
884 
885   memset(&buffer, 0, sizeof(buffer));
886   channel = xine_get_param (panel->gui->stream, XINE_PARAM_SPU_CHANNEL);
887   switch (channel) {
888   case -2:
889     lang = "off";
890     break;
891 
892   case -1:
893     if (!xine_get_spu_lang (panel->gui->stream, channel, &buffer[0]))
894       lang = "auto";
895     else
896       lang = buffer;
897     break;
898 
899   default:
900     if (!xine_get_spu_lang (panel->gui->stream, channel, &buffer[0]))
901       snprintf(buffer, sizeof(buffer), "%3d", channel);
902     lang = buffer;
903     break;
904   }
905   xitk_label_change_label (panel->spuid_label, lang);
906 }
907 
panel_audio_lang_list(xitk_widget_t * w,void * data)908 static void panel_audio_lang_list(xitk_widget_t *w, void *data) {
909   xui_panel_t *panel = data;
910   int x, y;
911   int wx, wy;
912 
913   (void)w;
914   xitk_get_window_position (panel->gui->display, panel->gui->panel_window, &wx, &wy, NULL, NULL);
915   xitk_get_widget_pos(panel->audiochan_label, &x, &y);
916   x += wx;
917   y += (wy + xitk_get_widget_height(panel->audiochan_label));
918   audio_lang_menu (panel->gui, panel->widget_list, x, y);
919 }
920 
panel_spu_lang_list(xitk_widget_t * w,void * data)921 static void panel_spu_lang_list(xitk_widget_t *w, void *data) {
922   xui_panel_t *panel = data;
923   int x, y;
924   int wx, wy;
925 
926   (void)w;
927   xitk_get_window_position (panel->gui->display, panel->gui->panel_window, &wx, &wy, NULL, NULL);
928   xitk_get_widget_pos(panel->spuid_label, &x, &y);
929   x += wx;
930   y += (wy + xitk_get_widget_height(panel->spuid_label));
931   spu_lang_menu (panel->gui, panel->widget_list, x, y);
932 }
933 
934 /*
935  * Update displayed MRL according to the current one.
936  */
panel_update_mrl_display(xui_panel_t * panel)937 void panel_update_mrl_display (xui_panel_t *panel) {
938   if (panel) {
939     pthread_mutex_lock (&panel->gui->mmk_mutex);
940     panel_set_title (panel, (panel->gui->is_display_mrl) ? panel->gui->mmk.mrl : panel->gui->mmk.ident);
941     pthread_mutex_unlock (&panel->gui->mmk_mutex);
942   }
943 }
944 
panel_update_mixer_display(xui_panel_t * panel)945 void panel_update_mixer_display (xui_panel_t *panel) {
946   if (panel) {
947     gGui_t *gui = panel->gui;
948     int max = 100, vol = 0;
949 
950     switch(gui->mixer.method) {
951     case SOUND_CARD_MIXER:
952       max = 100;
953       vol = gui->mixer.volume_level;
954       break;
955     case SOFTWARE_MIXER:
956       max = 200;
957       vol = gui->mixer.amp_level;
958       break;
959     }
960 
961     xitk_slider_set_max(panel->mixer.slider, max);
962     xitk_slider_set_pos(panel->mixer.slider, vol);
963     xitk_checkbox_set_state(panel->mixer.mute, gui->mixer.mute);
964   }
965 }
966 
967 /*
968  *
969  */
panel_toggle_audio_mute(xitk_widget_t * w,void * data,int state)970 void panel_toggle_audio_mute(xitk_widget_t *w, void *data, int state) {
971   xui_panel_t *panel = data;
972 
973   (void)w;
974   if (panel->gui->mixer.method == SOFTWARE_MIXER) {
975     panel->gui->mixer.mute = state;
976     xine_set_param (panel->gui->stream, XINE_PARAM_AUDIO_AMP_MUTE, panel->gui->mixer.mute);
977     osd_display_info(_("Amp: %s"), panel->gui->mixer.mute ? _("Muted") : _("Unmuted"));
978   }
979   else if (panel->gui->mixer.caps & MIXER_CAP_MUTE) {
980     panel->gui->mixer.mute = state;
981     xine_set_param (panel->gui->stream, XINE_PARAM_AUDIO_MUTE, panel->gui->mixer.mute);
982     osd_display_info(_("Audio: %s"), panel->gui->mixer.mute ? _("Muted") : _("Unmuted"));
983   }
984   panel_check_mute (panel);
985 }
986 
987 /*
988  *  Use internal xine-lib framegrabber function
989  *  to snapshot current frame.
990  */
panel_snapshot_error(void * data,char * message)991 static void panel_snapshot_error(void *data, char *message) {
992   xine_error("%s", message);
993 }
panel_snapshot_info(void * data,char * message)994 static void panel_snapshot_info(void *data, char *message) {
995   xine_info("%s", message);
996 }
panel_snapshot(xitk_widget_t * w,void * data)997 void panel_snapshot (xitk_widget_t *w, void *data) {
998   xui_panel_t *panel = data;
999 
1000   (void)w;
1001   pthread_mutex_lock (&panel->gui->mmk_mutex);
1002   create_snapshot (panel->gui->mmk.mrl, panel_snapshot_error, panel_snapshot_info, NULL);
1003   pthread_mutex_unlock (&panel->gui->mmk_mutex);
1004 }
1005 
1006 /*
1007  * Handle paddle moving of slider.
1008  */
panel_slider_cb(xitk_widget_t * w,void * data,int pos)1009 static void panel_slider_cb(xitk_widget_t *w, void *data, int pos) {
1010   xui_panel_t *panel = data;
1011 
1012   if(w == panel->playback_widgets.slider_play) {
1013     unsigned int stime;
1014     struct timeval tv = {0, 0};
1015 
1016     /* Update ui gfx smoothly, at most 20 times a second (~ 5 times less than before).
1017      * There is hardly a visible difference, but a lot less X action - especially
1018      * with KDE window thumbnails on. Slider thread will fix the final position. */
1019     gettimeofday (&tv, NULL);
1020     stime = tv.tv_usec / (1000000 / 20) + tv.tv_sec * 20;
1021     /* printf ("panel_slider_cb: timeslot #%u.\n", stime); */
1022     if (xitk_is_widget_enabled (panel->playback_widgets.slider_play)) {
1023       gui_set_current_position (pos);
1024       if (stime != panel->playback_widgets.slider_play_time) {
1025         panel->playback_widgets.slider_play_time = stime;
1026         if (xine_get_status (panel->gui->stream) != XINE_STATUS_PLAY) {
1027           panel_reset_slider (panel);
1028         } else {
1029           /*
1030           int pos;
1031           if (gui_xine_get_pos_length (panel->gui->stream, &pos, NULL, NULL))
1032             xitk_slider_set_pos (panel->playback_widgets.slider_play, pos); */
1033           panel_update_runtime_display (panel);
1034         }
1035       }
1036     }
1037   }
1038   else if(w == panel->mixer.slider) {
1039 
1040     if (panel->gui->mixer.method == SOUND_CARD_MIXER)
1041       change_audio_vol(pos);
1042     else if (panel->gui->mixer.method == SOFTWARE_MIXER)
1043       change_amp_vol(pos);
1044 
1045   }
1046 
1047   panel_check_pause (panel);
1048 }
1049 
1050 /*
1051  * Handle X events here.
1052  */
panel_handle_event(XEvent * event,void * data)1053 static void panel_handle_event(XEvent *event, void *data) {
1054   xui_panel_t *panel = data;
1055 
1056   switch(event->type) {
1057   case DestroyNotify:
1058     if (panel->gui->panel_window == event->xany.window)
1059       gui_exit (NULL, panel->gui);
1060     break;
1061 
1062   case ButtonPress:
1063     {
1064       XButtonEvent *bevent = (XButtonEvent *) event;
1065 
1066       if(bevent->button == Button3)
1067         video_window_menu (panel->gui, panel->widget_list);
1068     }
1069     break;
1070 
1071   case KeyPress:
1072   case ButtonRelease:
1073     gui_handle_event (event, panel->gui);
1074     break;
1075 
1076   case MappingNotify:
1077     panel->gui->x_lock_display (panel->gui->display);
1078     XRefreshKeyboardMapping((XMappingEvent *) event);
1079     panel->gui->x_unlock_display (panel->gui->display);
1080     break;
1081 
1082   case MapNotify:
1083     /* When panel becomes visible by any means,               */
1084     /* all other hidden GUI windows shall also become visible */
1085     if(!playlist_is_visible())
1086       playlist_toggle_visibility(NULL, NULL);
1087     if (control_status (panel->gui->vctrl) == 2)
1088       control_toggle_visibility (NULL, panel->gui->vctrl);
1089     if (!mrl_browser_is_visible (panel->gui->mrlb))
1090       mrl_browser_toggle_visibility (NULL, panel->gui->mrlb);
1091     if (!setup_is_visible (panel->gui->setup))
1092       setup_toggle_visibility (NULL, panel->gui->setup);
1093     if(!viewlog_is_visible())
1094       viewlog_toggle_visibility(NULL, NULL);
1095     if(!kbedit_is_visible())
1096       kbedit_toggle_visibility(NULL, NULL);
1097     if(!event_sender_is_visible())
1098       event_sender_toggle_visibility(NULL, NULL);
1099     if(!stream_infos_is_visible())
1100       stream_infos_toggle_visibility(NULL, NULL);
1101     if(!tvset_is_visible())
1102       tvset_toggle_visibility(NULL, NULL);
1103     if(!vpplugin_is_visible())
1104       vpplugin_toggle_visibility(NULL, NULL);
1105     if(!applugin_is_visible())
1106       applugin_toggle_visibility(NULL, NULL);
1107     if(!help_is_visible())
1108       help_toggle_visibility(NULL, NULL);
1109     break;
1110   }
1111 
1112 }
1113 
1114 /*
1115  * Create buttons from information if input plugins autoplay featured.
1116  * We couldn't do this into panel_init(), this function is
1117  * called before xine engine initialization.
1118  */
panel_add_autoplay_buttons(xui_panel_t * panel)1119 void panel_add_autoplay_buttons (xui_panel_t *panel) {
1120   char *tips[64];
1121   const char * const *autoplay_plugins = xine_get_autoplay_input_plugin_ids (panel->gui->xine);
1122   unsigned int i;
1123 
1124   if (!autoplay_plugins)
1125     return;
1126 
1127   for (i = 0; autoplay_plugins[i]; i++) {
1128     if (i >= sizeof (tips) / sizeof (tips[0]))
1129       break;
1130     tips[i] = (char *)xine_get_input_plugin_description (panel->gui->xine, autoplay_plugins[i]);
1131   }
1132 
1133   panel->autoplay_buttons = xitk_button_list_new (
1134     panel->gui->imlib_data, panel->widget_list,
1135     panel->gui->skin_config, "AutoPlayGUI",
1136     playlist_scan_input, NULL,
1137     (char **)autoplay_plugins,
1138     tips, panel->tips.timeout, 0);
1139 }
1140 
1141 /*
1142  * Check if there a mixer control available,
1143  */
panel_add_mixer_control(xui_panel_t * panel)1144 void panel_add_mixer_control (xui_panel_t *panel) {
1145 
1146   panel->gui->mixer.caps = MIXER_CAP_NOTHING;
1147 
1148   if (panel->gui->ao_port) {
1149     if ((xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_VOLUME)) != -1)
1150       panel->gui->mixer.caps |= MIXER_CAP_VOL;
1151     if ((xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_MUTE)) != -1)
1152       panel->gui->mixer.caps |= MIXER_CAP_MUTE;
1153   }
1154 
1155   if (((panel->gui->mixer.method == SOUND_CARD_MIXER) && panel->gui->mixer.caps & MIXER_CAP_VOL) ||
1156      (panel->gui->mixer.method == SOFTWARE_MIXER)) {
1157     int level = 0;
1158 
1159     xitk_enable_widget(panel->mixer.slider);
1160 
1161     if (panel->gui->mixer.method == SOUND_CARD_MIXER)
1162       level = panel->gui->mixer.volume_level = xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_VOLUME);
1163     else if (panel->gui->mixer.method == SOFTWARE_MIXER)
1164       level = panel->gui->mixer.amp_level = xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_AMP_LEVEL);
1165 
1166     xitk_slider_set_pos(panel->mixer.slider, level);
1167   }
1168 
1169   if (panel->gui->mixer.caps & MIXER_CAP_MUTE) {
1170     xitk_enable_widget(panel->mixer.mute);
1171     panel->gui->mixer.mute = xine_get_param (panel->gui->stream, XINE_PARAM_AUDIO_MUTE);
1172     xitk_checkbox_set_state (panel->mixer.mute, panel->gui->mixer.mute);
1173   }
1174 
1175   /* Tips should be available only if widgets are enabled */
1176   if (panel->gui->mixer.caps & MIXER_CAP_VOL)
1177     xitk_set_widget_tips_and_timeout(panel->mixer.slider, _("Volume control"), panel->tips.timeout);
1178   if (panel->gui->mixer.caps & MIXER_CAP_MUTE)
1179     xitk_set_widget_tips_and_timeout(panel->mixer.mute, _("Mute toggle"), panel->tips.timeout);
1180 
1181   if(!panel->tips.enable) {
1182     xitk_disable_widget_tips(panel->mixer.slider);
1183     xitk_disable_widget_tips(panel->mixer.mute);
1184   }
1185 
1186 }
1187 
panel_deinit(xui_panel_t * panel)1188 void panel_deinit (xui_panel_t *panel) {
1189   if (panel_is_visible (panel))
1190     _panel_toggle_visibility (NULL, panel);
1191   panel_exit (NULL, panel);
1192 }
1193 
panel_paint(xui_panel_t * panel)1194 void panel_paint (xui_panel_t *panel) {
1195   if (panel_is_visible (panel))
1196     xitk_paint_widget_list (panel->widget_list);
1197 }
1198 
panel_reparent(xui_panel_t * panel)1199 void panel_reparent (xui_panel_t *panel) {
1200   if (panel) {
1201     reparent_window (panel->gui->panel_window);
1202   }
1203 }
1204 
1205 /*
1206  * Create the panel window, and fit all widgets in.
1207  */
panel_init(gGui_t * gui)1208 xui_panel_t *panel_init (gGui_t *gui) {
1209   xui_panel_t              *panel;
1210   GC                        gc;
1211   XSizeHints                hint;
1212   XWMHints                 *wm_hint;
1213   XSetWindowAttributes      attr;
1214   char                     *title = _("xine Panel");
1215   Atom                      prop;
1216   MWMHints                  mwmhints;
1217   XClassHint               *xclasshint;
1218   xitk_button_widget_t      b;
1219   xitk_checkbox_widget_t    cb;
1220   xitk_label_widget_t       lbl;
1221   xitk_slider_widget_t      sl;
1222   xitk_widget_t            *w;
1223 
1224   if (!gui)
1225     return NULL;
1226 
1227   XITK_WIDGET_INIT(&b, gui->imlib_data);
1228   XITK_WIDGET_INIT(&cb, gui->imlib_data);
1229   XITK_WIDGET_INIT(&lbl, gui->imlib_data);
1230   XITK_WIDGET_INIT(&sl, gui->imlib_data);
1231 
1232   panel = calloc (1, sizeof (*panel));
1233   if (!panel)
1234     return NULL;
1235 
1236   panel->gui = gui;
1237 
1238   panel->shown_length = ~3;
1239   panel->shown_time = ~3;
1240 
1241   panel->playback_widgets.enabled = -1;
1242 
1243   panel->skin_on_change = 0;
1244 
1245   panel->gui->x_lock_display (panel->gui->display);
1246 
1247   /*
1248    * load bg image before opening window, so we can determine it's size
1249    */
1250   if (!(panel->bg_image = Imlib_load_image (panel->gui->imlib_data,
1251     xitk_skin_get_skin_filename (panel->gui->skin_config, "BackGround")))) {
1252     xine_error(_("panel: couldn't find image for background\n"));
1253     exit(-1);
1254   }
1255 
1256   panel->gui->x_unlock_display (panel->gui->display);
1257 
1258   /*
1259    * open the panel window
1260    */
1261 
1262   panel->x = hint.x = xine_config_register_num (panel->gui->xine, "gui.panel_x",
1263 						200,
1264 						CONFIG_NO_DESC,
1265 						CONFIG_NO_HELP,
1266 						CONFIG_LEVEL_DEB,
1267 						CONFIG_NO_CB,
1268 						CONFIG_NO_DATA);
1269   panel->y = hint.y = xine_config_register_num (panel->gui->xine, "gui.panel_y",
1270 						100,
1271 						CONFIG_NO_DESC,
1272 						CONFIG_NO_HELP,
1273 						CONFIG_LEVEL_DEB,
1274 						CONFIG_NO_CB,
1275 						CONFIG_NO_DATA);
1276 
1277   hint.width = panel->bg_image->rgb_width;
1278   hint.height = panel->bg_image->rgb_height;
1279   hint.flags = PPosition | PSize;
1280 
1281   attr.override_redirect = False;
1282   attr.background_pixel  = panel->gui->black.pixel;
1283   /*
1284    * XXX:multivis
1285    * To avoid BadMatch errors on XCreateWindow:
1286    * If the parent and the new window have different depths, we must supply either
1287    * a BorderPixmap or a BorderPixel.
1288    * If the parent and the new window use different visuals, we must supply a
1289    * Colormap
1290    */
1291   attr.border_pixel      = panel->gui->black.pixel;
1292 
1293   panel->gui->x_lock_display (panel->gui->display);
1294   attr.colormap          = Imlib_get_colormap (panel->gui->imlib_data);
1295   /*
1296       printf ("imlib_data: %d visual : %d\n",gui->imlib_data,gui->imlib_data->x.visual);
1297       printf ("w : %d h : %d\n",hint.width, hint.height);
1298   */
1299 
1300   panel->gui->panel_window = XCreateWindow (panel->gui->display, panel->gui->imlib_data->x.root,
1301     hint.x, hint.y, hint.width, hint.height, 0,
1302     panel->gui->imlib_data->x.depth, InputOutput,
1303     panel->gui->imlib_data->x.visual,
1304     CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect, &attr);
1305 
1306   {
1307     /* prevent window manager from killing us through exit() when user closes panel.
1308        That wont work with OpenGL* video out because libGL does install an exit handler
1309        that calls X functions - while video out loop still tries the same -> deadlock */
1310     Atom wm_delete_window = XInternAtom (panel->gui->display, "WM_DELETE_WINDOW", False);
1311     XSetWMProtocols (panel->gui->display, panel->gui->panel_window, &wm_delete_window, 1);
1312   }
1313 
1314   XmbSetWMProperties (panel->gui->display, panel->gui->panel_window, title, title, NULL, 0,
1315                      &hint, NULL, NULL);
1316 
1317   XSelectInput (panel->gui->display, panel->gui->panel_window, INPUT_MOTION | KeymapStateMask);
1318   panel->gui->x_unlock_display (panel->gui->display);
1319 
1320   /*
1321    * The following is more or less a hack to keep the panel window visible
1322    * with and without focus in windowed and fullscreen mode.
1323    * Different WMs and even different versions behave different.
1324    * There is no guarantee that it works with all WMs/versions.
1325    */
1326   if (!video_window_is_visible (panel->gui->vwin)) {
1327     if(!(xitk_get_wm_type() & WM_TYPE_KWIN))
1328       xitk_unset_wm_window_type (panel->gui->panel_window, WINDOW_TYPE_TOOLBAR);
1329     xitk_set_wm_window_type (panel->gui->panel_window, WINDOW_TYPE_NORMAL);
1330   } else {
1331     xitk_unset_wm_window_type (panel->gui->panel_window, WINDOW_TYPE_NORMAL);
1332     if(!(xitk_get_wm_type() & WM_TYPE_KWIN))
1333       xitk_set_wm_window_type (panel->gui->panel_window, WINDOW_TYPE_TOOLBAR);
1334   }
1335 
1336   if(is_layer_above())
1337     xitk_set_layer_above (panel->gui->panel_window);
1338 
1339   /*
1340    * wm, no border please
1341    */
1342 
1343   memset(&mwmhints, 0, sizeof(mwmhints));
1344   panel->gui->x_lock_display (panel->gui->display);
1345   prop = XInternAtom (panel->gui->display, "_MOTIF_WM_HINTS", False);
1346   mwmhints.flags = MWM_HINTS_DECORATIONS;
1347   mwmhints.decorations = 0;
1348 
1349   XChangeProperty (panel->gui->display, panel->gui->panel_window, prop, prop, 32,
1350                   PropModeReplace, (unsigned char *) &mwmhints,
1351                   PROP_MWM_HINTS_ELEMENTS);
1352 
1353   panel->gui->x_unlock_display (panel->gui->display);
1354   video_window_set_transient_for (panel->gui->vwin, panel->gui->panel_window);
1355   panel->gui->x_lock_display (panel->gui->display);
1356 
1357   /*
1358    * set wm properties
1359    */
1360 
1361   if((xclasshint = XAllocClassHint()) != NULL) {
1362     xclasshint->res_name = title;
1363     xclasshint->res_class = "xine";
1364     XSetClassHint (panel->gui->display, panel->gui->panel_window, xclasshint);
1365     XFree(xclasshint);
1366   }
1367 
1368   wm_hint = XAllocWMHints();
1369   if (wm_hint != NULL) {
1370     wm_hint->input         = True;
1371     wm_hint->initial_state = NormalState;
1372     wm_hint->icon_pixmap   = panel->gui->icon;
1373     wm_hint->flags         = InputHint | StateHint | IconPixmapHint;
1374     XSetWMHints (panel->gui->display, panel->gui->panel_window, wm_hint);
1375     XFree(wm_hint);
1376   }
1377 
1378   /*
1379    * set background image
1380    */
1381 
1382   gc = XCreateGC (panel->gui->display, panel->gui->panel_window, 0, 0);
1383 
1384   Imlib_apply_image (panel->gui->imlib_data, panel->bg_image, panel->gui->panel_window);
1385   panel->gui->x_unlock_display (panel->gui->display);
1386 
1387   /*
1388    * Widget-list
1389    */
1390 
1391   panel->widget_list = xitk_widget_list_new();
1392   xitk_widget_list_set (panel->widget_list, WIDGET_LIST_WINDOW, (void *)panel->gui->panel_window);
1393   xitk_widget_list_set(panel->widget_list, WIDGET_LIST_GC, gc);
1394 
1395   lbl.window    = (XITK_WIDGET_LIST_WINDOW(panel->widget_list));
1396   lbl.gc        = (XITK_WIDGET_LIST_GC(panel->widget_list));
1397 
1398   /* Prev button */
1399   b.skin_element_name = "Prev";
1400   b.callback          = gui_nextprev;
1401   b.userdata          = (void *)GUI_PREV;
1402   panel->playback_widgets.prev =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1403   xitk_add_widget (panel->widget_list, panel->playback_widgets.prev);
1404 
1405   /*  Stop button */
1406   b.skin_element_name = "Stop";
1407   b.callback          = gui_stop;
1408   b.userdata          = panel->gui;
1409   panel->playback_widgets.stop =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1410   xitk_add_widget (panel->widget_list, panel->playback_widgets.stop);
1411   xitk_set_widget_tips(panel->playback_widgets.stop, _("Stop playback"));
1412 
1413   /*  Play button */
1414   b.skin_element_name = "Play";
1415   b.callback          = gui_play;
1416   b.userdata          = panel->gui;
1417   panel->playback_widgets.play =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1418   xitk_add_widget (panel->widget_list, panel->playback_widgets.play);
1419   xitk_set_widget_tips(panel->playback_widgets.play, _("Play selected entry"));
1420 
1421   /*  Pause button */
1422   cb.skin_element_name = "Pause";
1423   cb.callback          = gui_pause;
1424   cb.userdata          = panel->gui;
1425   panel->playback_widgets.pause =  xitk_checkbox_create (panel->widget_list, panel->gui->skin_config, &cb);
1426   xitk_add_widget (panel->widget_list, panel->playback_widgets.pause);
1427   xitk_set_widget_tips(panel->playback_widgets.pause, _("Pause/Resume playback"));
1428 
1429   /*  Next button */
1430   b.skin_element_name = "Next";
1431   b.callback          = gui_nextprev;
1432   b.userdata          = (void *)GUI_NEXT;
1433   panel->playback_widgets.next =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1434   xitk_add_widget (panel->widget_list, panel->playback_widgets.next);
1435 
1436   /*  Eject button */
1437   b.skin_element_name = "Eject";
1438   b.callback          = gui_eject;
1439   b.userdata          = panel->gui;
1440   panel->playback_widgets.eject =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1441   xitk_add_widget (panel->widget_list, panel->playback_widgets.eject);
1442   xitk_set_widget_tips(panel->playback_widgets.eject, _("Eject current medium"));
1443 
1444   /*  Exit button */
1445   b.skin_element_name = "Exit";
1446   b.callback          = gui_exit;
1447   b.userdata          = panel->gui;
1448   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1449   xitk_add_widget (panel->widget_list, w);
1450   xitk_set_widget_tips(w, _("Quit"));
1451 
1452   /*  Setup button */
1453   b.skin_element_name = "Setup";
1454   b.callback          = gui_setup_show;
1455   b.userdata          = NULL;
1456   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1457   xitk_add_widget (panel->widget_list, w);
1458   xitk_set_widget_tips(w, _("Setup window"));
1459 
1460   /*  Event sender button */
1461   b.skin_element_name = "Nav";
1462   b.callback          = gui_event_sender_show;
1463   b.userdata          = NULL;
1464   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1465   xitk_add_widget (panel->widget_list, w);
1466   xitk_set_widget_tips(w, _("Navigator"));
1467 
1468   /*  Close button */
1469   b.skin_element_name = "Close";
1470   b.callback          = panel_toggle_visibility;
1471   b.userdata          = panel;
1472   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1473   xitk_add_widget (panel->widget_list, w);
1474   xitk_set_widget_tips(w, _("Hide GUI"));
1475 
1476   /*  Fullscreen button */
1477   b.skin_element_name = "FullScreen";
1478   b.callback          = gui_set_fullscreen_mode;
1479   b.userdata          = panel->gui;
1480    w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1481   xitk_add_widget (panel->widget_list, w);
1482   xitk_set_widget_tips(w, _("Fullscreen/Window mode"));
1483 
1484   /*  Next audio channel */
1485   b.skin_element_name = "AudioNext";
1486   b.callback          = gui_change_audio_channel;
1487   b.userdata          = (void *)GUI_NEXT;
1488   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1489   xitk_add_widget (panel->widget_list, w);
1490   xitk_set_widget_tips(w, _("Next audio channel"));
1491 
1492   /*  Prev audio channel */
1493   b.skin_element_name = "AudioPrev";
1494   b.callback          = gui_change_audio_channel;
1495   b.userdata          = (void *)GUI_PREV;
1496   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1497   xitk_add_widget (panel->widget_list, w);
1498   xitk_set_widget_tips(w, _("Previous audio channel"));
1499 
1500   /*  Prev spuid */
1501   b.skin_element_name = "SpuNext";
1502   b.callback          = gui_change_spu_channel;
1503   b.userdata          = (void *)GUI_NEXT;
1504   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1505   xitk_add_widget (panel->widget_list, w);
1506   xitk_set_widget_tips(w, _("Next SPU channel"));
1507 
1508   /*  Next spuid */
1509   b.skin_element_name = "SpuPrev";
1510   b.callback          = gui_change_spu_channel;
1511   b.userdata          = (void *)GUI_PREV;
1512   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1513   xitk_add_widget (panel->widget_list, w);
1514   xitk_set_widget_tips(w, _("Previous SPU channel"));
1515 
1516   /*  Label title */
1517   lbl.skin_element_name = "TitleLabel";
1518   lbl.label             = "";
1519   lbl.callback          = _panel_change_display_mode;
1520   lbl.userdata          = panel;
1521   panel->title_label =  xitk_label_create (panel->widget_list, panel->gui->skin_config, &lbl);
1522   xitk_add_widget (panel->widget_list, panel->title_label);
1523 
1524   /*  Runtime label */
1525   lbl.skin_element_name = "TimeLabel";
1526   lbl.label             = "00:00:00";
1527   lbl.callback          = _panel_change_time_label;
1528   lbl.userdata          = panel;
1529   panel->runtime_label =  xitk_label_create (panel->widget_list, panel->gui->skin_config, &lbl);
1530   xitk_add_widget (panel->widget_list, panel->runtime_label);
1531   xitk_set_widget_tips(panel->runtime_label, _("Total time: --:--:--"));
1532   /*
1533    * Init to default, otherwise if panel is hide
1534    * at startup, label is empty 'till it's updated
1535    */
1536   panel->runtime_mode   = 0;
1537   panel_reset_runtime_label (panel);
1538 
1539   /*  Audio channel label */
1540   lbl.skin_element_name = "AudioLabel";
1541   lbl.label             = "";
1542   lbl.callback          = panel_audio_lang_list;
1543   lbl.userdata          = panel;
1544   panel->audiochan_label =  xitk_label_create (panel->widget_list, panel->gui->skin_config, &lbl);
1545   xitk_add_widget (panel->widget_list, panel->audiochan_label);
1546 
1547   /*  Spuid label */
1548   lbl.skin_element_name = "SpuLabel";
1549   lbl.label             = "";
1550   lbl.callback          = panel_spu_lang_list;
1551   lbl.userdata          = panel;
1552   panel->spuid_label =  xitk_label_create (panel->widget_list, panel->gui->skin_config, &lbl);
1553   xitk_add_widget (panel->widget_list, panel->spuid_label);
1554 
1555   /*  slider seek */
1556   sl.skin_element_name = "SliderPlay";
1557   sl.min               = 0;
1558   sl.max               = 65535;
1559   sl.step              = 1;
1560   sl.callback          = NULL;
1561   sl.userdata          = NULL;
1562   sl.motion_callback   = panel_slider_cb;
1563   sl.motion_userdata   = panel;
1564   panel->playback_widgets.slider_play =  xitk_slider_create (panel->widget_list, panel->gui->skin_config, &sl);
1565   xitk_add_widget (panel->widget_list, panel->playback_widgets.slider_play);
1566   xitk_widget_keyable(panel->playback_widgets.slider_play, 0);
1567   xitk_set_widget_tips(panel->playback_widgets.slider_play, _("Stream playback position slider"));
1568   xitk_slider_reset(panel->playback_widgets.slider_play);
1569   if(!panel->gui->playlist.num)
1570     xitk_disable_widget(panel->playback_widgets.slider_play);
1571 
1572   /* Mixer volume slider */
1573   sl.skin_element_name = "SliderVol";
1574   sl.min               = 0;
1575   sl.max               = (panel->gui->mixer.method == SOUND_CARD_MIXER) ? 100 : 200;
1576   sl.step              = 1;
1577   sl.callback          = NULL;
1578   sl.userdata          = NULL;
1579   sl.motion_callback   = panel_slider_cb;
1580   sl.motion_userdata   = panel;
1581   panel->mixer.slider =  xitk_slider_create (panel->widget_list, panel->gui->skin_config, &sl);
1582   xitk_add_widget (panel->widget_list, panel->mixer.slider);
1583   xitk_slider_reset(panel->mixer.slider);
1584   xitk_disable_widget(panel->mixer.slider);
1585 
1586   /*  Mute toggle */
1587   cb.skin_element_name = "Mute";
1588   cb.callback          = panel_toggle_audio_mute;
1589   cb.userdata          = panel;
1590   panel->mixer.mute =  xitk_checkbox_create (panel->widget_list, panel->gui->skin_config, &cb);
1591   xitk_add_widget (panel->widget_list, panel->mixer.mute);
1592   xitk_disable_widget(panel->mixer.mute);
1593 
1594   /* Snapshot */
1595   b.skin_element_name = "Snapshot";
1596   b.callback          = panel_snapshot;
1597   b.userdata          = panel;
1598   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1599   xitk_add_widget (panel->widget_list, w);
1600   xitk_set_widget_tips(w, _("Take a snapshot"));
1601 
1602   /*  Playback speed slow */
1603   b.skin_element_name = "PlaySlow";
1604   b.callback          = gui_change_speed_playback;
1605   b.userdata          = (void *)GUI_NEXT;
1606   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1607   xitk_add_widget (panel->widget_list, w);
1608   xitk_set_widget_tips(w, _("Slow motion"));
1609 
1610   /*  Playback speed fast */
1611   b.skin_element_name = "PlayFast";
1612   b.callback          = gui_change_speed_playback;
1613   b.userdata          = (void *)GUI_PREV;
1614   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1615   xitk_add_widget (panel->widget_list, w);
1616   xitk_set_widget_tips(w, _("Fast motion"));
1617 
1618   /*  Playlist button */
1619   b.skin_element_name = "PlBtn";
1620   b.callback          = gui_playlist_show;
1621   b.userdata          = NULL;
1622   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1623   xitk_add_widget (panel->widget_list, w);
1624   xitk_set_widget_tips(w, _("Playlist"));
1625 
1626   /*  Control button */
1627   b.skin_element_name = "CtlBtn";
1628   b.callback          = gui_control_show;
1629   b.userdata          = NULL;
1630   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1631   xitk_add_widget (panel->widget_list, w);
1632   xitk_set_widget_tips(w, _("Control"));
1633 
1634   /*  Mrl button */
1635   b.skin_element_name = "MrlBtn";
1636   b.callback          = gui_mrlbrowser_show;
1637   b.userdata          = NULL;
1638   w =  xitk_button_create (panel->widget_list, panel->gui->skin_config, &b);
1639   xitk_add_widget (panel->widget_list, w);
1640   xitk_set_widget_tips(w, _("Open Location"));
1641 
1642 
1643   panel->tips.enable = xine_config_register_bool (panel->gui->xine, "gui.tips_visible",
1644 						 1,
1645 						 _("gui tips visibility"),
1646 						 _("If disabled, no tooltips are shown."),
1647 						 CONFIG_LEVEL_ADV,
1648 						 panel_enable_tips_cb,
1649 						 panel);
1650   panel->tips.timeout = (unsigned long) xine_config_register_num (panel->gui->xine, "gui.tips_timeout",
1651 								 5000,
1652 								 _("Tips timeout (ms)"),
1653 								 _("Persistence time of tooltips, in milliseconds."),
1654 								 CONFIG_LEVEL_ADV,
1655 								 panel_timeout_tips_cb,
1656 								 panel);
1657 
1658   panel_update_mrl_display (panel);
1659   panel_update_nextprev_tips (panel);
1660 
1661   /*
1662    * show panel
1663    */
1664   {
1665     int visible = xine_config_register_bool (panel->gui->xine, "gui.panel_visible",
1666 					    1,
1667 					    _("gui panel visibility"),
1668 					    CONFIG_NO_HELP,
1669 					    CONFIG_LEVEL_DEB,
1670 					    CONFIG_NO_CB,
1671 					    CONFIG_NO_DATA);
1672 
1673       panel->visible = (!panel->gui->no_gui) ? visible : 0;
1674   }
1675 
1676   /*  The user don't want panel on startup */
1677   if (panel->visible && (actions_on_start (panel->gui->actions_on_start, ACTID_TOGGLE_VISIBLITY))) {
1678     panel->visible = !panel->visible;
1679     config_update_num ("gui.panel_visible", panel->visible);
1680   }
1681 
1682   if ((panel->gui->use_root_window || panel->gui->video_display != panel->gui->display) && (!panel->visible))
1683     panel->visible = 1;
1684 
1685   if (panel->visible) {
1686     panel->gui->x_lock_display (panel->gui->display);
1687     XRaiseWindow (panel->gui->display, panel->gui->panel_window);
1688     XMapWindow (panel->gui->display, panel->gui->panel_window);
1689     panel->gui->x_unlock_display (panel->gui->display);
1690   }
1691   else
1692     xitk_hide_widgets(panel->widget_list);
1693 
1694 
1695   panel->widget_key = xitk_register_event_handler("panel",
1696 						  panel->gui->panel_window,
1697 						  panel_handle_event,
1698 						  panel_store_new_position,
1699 						  gui_dndcallback,
1700 						  panel->widget_list,
1701 						  panel);
1702 
1703   panel->gui->cursor_visible = 1;
1704   video_window_set_cursor_visibility (panel->gui->vwin, panel->gui->cursor_visible);
1705 
1706   {
1707     pthread_attr_t       pth_attrs;
1708 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
1709     struct sched_param   pth_params;
1710 #endif
1711 
1712     pthread_attr_init(&pth_attrs);
1713 
1714     /* this won't work on linux, freebsd 5.0 */
1715 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
1716     pthread_attr_getschedparam(&pth_attrs, &pth_params);
1717     pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER);
1718     pthread_attr_setschedparam(&pth_attrs, &pth_params);
1719 #endif
1720 
1721     pthread_create (&panel->slider_thread, &pth_attrs, slider_loop, panel);
1722     pthread_attr_destroy (&pth_attrs);
1723   }
1724 
1725   if (panel->visible)
1726     try_to_set_input_focus (panel->gui->panel_window);
1727 
1728   panel->gui->panel = panel;
1729   return panel;
1730 }
1731 
panel_set_title(xui_panel_t * panel,char * title)1732 void panel_set_title (xui_panel_t *panel, char *title) {
1733   if(panel && panel->title_label)
1734     xitk_label_change_label(panel->title_label, title);
1735 }
1736 
1737