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