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  * implementation of all the various actions for the gui (play, stop, open, pause...)
21  *
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdio.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 
33 #ifdef HAVE_ALLOCA_H
34 #include <alloca.h>
35 #endif
36 #include <X11/Xlib.h>
37 #include <xine/xineutils.h>
38 #include <pthread.h>
39 
40 #include "common.h"
41 #include "oxine/oxine.h"
42 
gui_messages_off(gGui_t * gui)43 static void gui_messages_off (gGui_t *gui) {
44   pthread_mutex_lock (&gui->no_messages.mutex);
45   ++gui->no_messages.level;
46   gui->no_messages.until.tv_sec = sizeof (gui->no_messages.until.tv_sec) > 4 ? ((~(uint64_t)0) >> 1) : 0x7fffffff;
47   pthread_mutex_unlock (&gui->no_messages.mutex);
48 }
49 
gui_messages_on(gGui_t * gui)50 static void gui_messages_on (gGui_t *gui) {
51   pthread_mutex_lock (&gui->no_messages.mutex);
52   if (--gui->no_messages.level == 0)
53     gettimeofday (&gui->no_messages.until, NULL);
54   pthread_mutex_unlock (&gui->no_messages.mutex);
55 }
56 
reparent_all_windows(void)57 void reparent_all_windows(void) {
58   gGui_t *gui = gGui;
59   int                    i;
60   static const struct {
61     int                 (*visible)(void);
62     void                (*reparent)(void);
63   } _reparent[] = {
64     { playlist_is_visible,      playlist_reparent },
65     { viewlog_is_visible,       viewlog_reparent },
66     { kbedit_is_visible,        kbedit_reparent },
67     { event_sender_is_visible,  event_sender_reparent },
68     { stream_infos_is_visible,  stream_infos_reparent },
69     { tvset_is_visible,         tvset_reparent },
70     { vpplugin_is_visible,      vpplugin_reparent },
71     { applugin_is_visible,      applugin_reparent },
72     { help_is_visible,          help_reparent },
73     { NULL,                     NULL}
74   };
75 
76   if (panel_is_visible (gui->panel))
77     panel_reparent (gui->panel);
78   if (setup_is_visible (gui->setup))
79     setup_reparent (gui->setup);
80   if (mrl_browser_is_visible (gui->mrlb))
81     mrl_browser_reparent (gui->mrlb);
82   control_reparent (gui->vctrl);
83 
84   for(i = 0; _reparent[i].visible; i++) {
85     if(_reparent[i].visible())
86       _reparent[i].reparent();
87   }
88 
89 }
90 
wait_for_window_visible(Display * display,Window window)91 void wait_for_window_visible(Display *display, Window window) {
92   int t = 0;
93 
94   while((!xitk_is_window_visible(display, window)) && (++t < 3))
95     xine_usec_sleep(5000);
96 }
97 
raise_window(Window window,int visible,int running)98 void raise_window(Window window, int visible, int running) {
99   if(window) {
100     if(visible && running) {
101       reparent_window(window);
102       layer_above_video(window);
103     }
104   }
105 }
106 
toggle_window(Window window,xitk_widget_list_t * widget_list,int * visible,int running)107 void toggle_window(Window window, xitk_widget_list_t *widget_list, int *visible, int running) {
108   gGui_t *gui = gGui;
109   if(window && (*visible) && running) {
110 
111     gui->x_lock_display (gui->display);
112     if(gui->use_root_window) {
113       if(xitk_is_window_visible(gui->display, window))
114         XIconifyWindow(gui->display, window, gui->screen);
115       else
116 	XMapWindow(gui->display, window);
117     }
118     else if(!xitk_is_window_visible(gui->display, window)) {
119       /* Obviously user has iconified the window, let it be */
120     }
121     else {
122       *visible = 0;
123       gui->x_unlock_display (gui->display);
124       xitk_hide_widgets(widget_list);
125       gui->x_lock_display (gui->display);
126       XUnmapWindow(gui->display, window);
127     }
128     gui->x_unlock_display (gui->display);
129 
130   }
131   else {
132     if(running) {
133       *visible = 1;
134       xitk_show_widgets(widget_list);
135 
136       gui->x_lock_display (gui->display);
137       XRaiseWindow(gui->display, window);
138       XMapWindow(gui->display, window);
139       gui->x_unlock_display (gui->display);
140       video_window_set_transient_for (gui->vwin, window);
141 
142       wait_for_window_visible(gui->display, window);
143       layer_above_video(window);
144     }
145   }
146 }
147 
gui_xine_get_pos_length(xine_stream_t * stream,int * ppos,int * ptime,int * plength)148 int gui_xine_get_pos_length (xine_stream_t *stream, int *ppos, int *ptime, int *plength) {
149   gGui_t *gui = gGui;
150 
151   do {
152 
153     if (!stream)
154       break;
155 
156     if (stream == gui->stream) {
157       pthread_mutex_lock (&gui->seek_mutex);
158       if (gui->seek_running) {
159         /* xine_play (), xine_get_* () etc. all grab stream frontend lock.
160          * Dont wait for seek thread, just use its values. */
161         if (ppos)
162           *ppos = gui->stream_length.pos;
163         if (ptime)
164           *ptime = gui->stream_length.time;
165         if (plength)
166           *plength = gui->stream_length.length;
167         pthread_mutex_unlock (&gui->seek_mutex);
168         return 1;
169       }
170       pthread_mutex_unlock (&gui->seek_mutex);
171     }
172 
173     if (xine_get_status (stream) == XINE_STATUS_PLAY) {
174       int lpos = 0, ltime = 0, llength = 0;
175       int ret, t = 0;
176       while (((ret = xine_get_pos_length (stream, &lpos, &ltime, &llength)) == 0) && (++t < 10) && (!gui->on_quit)) {
177         printf ("gui_xine_get_pos_length: wait 100 ms (%d).\n", t);
178         xine_usec_sleep (100000); /* wait before trying again */
179       }
180       if (ret == 0)
181         break;
182       if (stream == gui->stream) {
183         gui->stream_length.pos = lpos;
184         gui->stream_length.time = ltime;
185         gui->stream_length.length = llength;
186       }
187       if (ppos)
188         *ppos = lpos;
189       if (ptime)
190         *ptime = ltime;
191       if (plength)
192         *plength = llength;
193       return ret;
194     }
195   } while (0);
196 
197   if (ppos)
198     *ppos = 0;
199   if (ptime)
200     *ptime = 0;
201   if (plength)
202     *plength = 0;
203   return 0;
204 }
205 
206 /*
207  *
208  */
try_to_set_input_focus(Window window)209 void try_to_set_input_focus(Window window) {
210   gGui_t *gui = gGui;
211 
212   wait_for_window_visible(gui->display, window);
213 
214   if(xitk_is_window_visible(gui->display, window)) {
215     int    retry = 0;
216     Window focused_win;
217 
218     do {
219       int revert;
220 
221       gui->x_lock_display (gui->display);
222       XSetInputFocus(gui->display, window, RevertToParent, CurrentTime);
223       XSync(gui->display, False);
224       gui->x_unlock_display (gui->display);
225 
226       /* Retry until the WM was mercyful to give us the focus (but not indefinitely) */
227       xine_usec_sleep(5000);
228       gui->x_lock_display (gui->display);
229       XGetInputFocus(gui->display, &focused_win, &revert);
230       gui->x_unlock_display (gui->display);
231 
232     } while((focused_win != window) && (retry++ < 30));
233   }
234 }
235 
236 /*
237  *
238  */
gui_display_logo(void)239 void gui_display_logo(void) {
240   gGui_t *gui = gGui;
241 
242   pthread_mutex_lock(&gui->logo_mutex);
243 
244   gui->logo_mode = 2;
245 
246   if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
247     gui->ignore_next = 1;
248     xine_stop(gui->stream);
249     gui->ignore_next = 0;
250   }
251 
252   if(gui->visual_anim.running)
253     visual_anim_stop();
254 
255   xine_set_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1);
256   xine_set_param(gui->stream, XINE_PARAM_SPU_CHANNEL, -1);
257   panel_update_channel_display (gui->panel);
258 
259   if(gui->display_logo)
260     (void) gui_xine_open_and_play((char *)gui->logo_mrl, NULL, 0, 0, 0, 0, 1);
261 
262   gui->logo_mode = 1;
263 
264   panel_reset_slider (gui->panel);
265   if(stream_infos_is_visible())
266     stream_infos_update_infos();
267 
268   pthread_mutex_unlock(&gui->logo_mutex);
269 }
270 
_gui_xine_play(gGui_t * gui,xine_stream_t * stream,int start_pos,int start_ms,int update_mmk)271 static int _gui_xine_play (gGui_t *gui, xine_stream_t *stream, int start_pos, int start_ms, int update_mmk) {
272   int      ret;
273   int      has_video;
274   int      already_playing = (gui->logo_mode == 0);
275 
276   if(gui->visual_anim.post_changed && (xine_get_status(stream) == XINE_STATUS_STOP)) {
277     post_rewire_visual_anim();
278     gui->visual_anim.post_changed = 0;
279   }
280 
281   has_video = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_VIDEO);
282   if (has_video)
283     has_video = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
284 
285   if((has_video && gui->visual_anim.enabled == 1) && gui->visual_anim.running) {
286 
287     if(post_rewire_audio_port_to_stream(stream))
288       gui->visual_anim.running = 0;
289 
290   } else if (!has_video && (gui->visual_anim.enabled == 1) &&
291 	     (gui->visual_anim.running == 0) && gui->visual_anim.post_output_element.post) {
292 
293     if(post_rewire_audio_post_to_stream(stream))
294       gui->visual_anim.running = 1;
295 
296   }
297 
298   if ((ret = xine_play (stream, start_pos, start_ms)) == 0)
299     gui_handle_xine_error(stream, NULL);
300   else {
301     char *ident;
302 
303     pthread_mutex_lock(&gui->logo_mutex);
304     if(gui->logo_mode != 2)
305       gui->logo_mode = 0;
306     pthread_mutex_unlock(&gui->logo_mutex);
307 
308     if(gui->logo_mode == 0) {
309 
310       if(stream_infos_is_visible())
311 	stream_infos_update_infos();
312 
313       if(update_mmk && ((ident = stream_infos_get_ident_from_stream(stream)) != NULL)) {
314         pthread_mutex_lock (&gui->mmk_mutex);
315 	free(gui->mmk.ident);
316 	free(gui->playlist.mmk[gui->playlist.cur]->ident);
317 
318 	gui->mmk.ident = strdup(ident);
319 	gui->playlist.mmk[gui->playlist.cur]->ident = strdup(ident);
320         pthread_mutex_unlock (&gui->mmk_mutex);
321 
322         video_window_set_mrl (gui->vwin, ident);
323 	playlist_mrlident_toggle();
324 	panel_update_mrl_display (gui->panel);
325 	free(ident);
326       }
327 
328       if(has_video) {
329 
330 	if((gui->visual_anim.enabled == 2) && gui->visual_anim.running)
331 	  visual_anim_stop();
332 
333 	if(gui->auto_vo_visibility) {
334 
335           if (!video_window_is_visible (gui->vwin))
336             video_window_set_visibility (gui->vwin, 1);
337 
338 	}
339 
340         if (gui->auto_panel_visibility && video_window_is_visible (gui->vwin) &&
341           panel_is_visible (gui->panel))
342           panel_toggle_visibility (NULL, gui->panel);
343 
344       }
345       else {
346 
347 	if(gui->auto_vo_visibility) {
348 
349           if (!panel_is_visible (gui->panel))
350             panel_toggle_visibility (NULL, gui->panel);
351 
352           if (video_window_is_visible (gui->vwin))
353             video_window_set_visibility (gui->vwin, 0);
354 
355 	}
356 
357         if (gui->auto_panel_visibility && video_window_is_visible (gui->vwin) &&
358           !panel_is_visible (gui->panel))
359           panel_toggle_visibility (NULL, gui->panel);
360 
361         if (video_window_is_visible (gui->vwin)) {
362 	  if(!gui->visual_anim.running)
363 	    visual_anim_play();
364 	}
365 	else
366 	  gui->visual_anim.running = 2;
367       }
368 
369       xine_usec_sleep(100);
370       if(!already_playing)
371 	osd_update_status();
372     }
373   }
374 
375   return ret;
376 }
377 
378 typedef struct {
379   xine_stream_t *stream;
380   int            start_pos;
381   int            start_time_in_secs;
382   int            update_mmk;
383   int            running;
384 } play_data_t;
385 static play_data_t play_data;
386 
start_anyway_yesno(xitk_widget_t * w,void * data,int button)387 static void start_anyway_yesno(xitk_widget_t *w, void *data, int button) {
388   gGui_t *gui = data;
389   play_data.running = 0;
390 
391   if(button == XITK_WINDOW_ANSWER_YES)
392     _gui_xine_play (gui, play_data.stream, play_data.start_pos, play_data.start_time_in_secs * 1000, play_data.update_mmk);
393   else
394     gui_playlist_start_next (gui);
395 
396 }
397 
set_mmk(mediamark_t * mmk)398 static void set_mmk(mediamark_t *mmk) {
399   gGui_t *gui = gGui;
400 
401   pthread_mutex_lock (&gui->mmk_mutex);
402   free(gui->mmk.mrl);
403   free(gui->mmk.ident);
404   free(gui->mmk.sub);
405   if(mediamark_have_alternates(&(gui->mmk)))
406     mediamark_free_alternates(&(gui->mmk));
407 
408   if(mmk) {
409     gui->mmk.mrl           = strdup(mmk->mrl);
410     gui->mmk.ident         = strdup(((mmk->ident) ? mmk->ident : mmk->mrl));
411     gui->mmk.sub           = mmk->sub ? strdup(mmk->sub): NULL;
412     gui->mmk.start         = mmk->start;
413     gui->mmk.end           = mmk->end;
414     gui->mmk.av_offset     = mmk->av_offset;
415     gui->mmk.spu_offset    = mmk->spu_offset;
416     gui->mmk.got_alternate = mmk->got_alternate;
417     mediamark_duplicate_alternates(mmk, &(gui->mmk));
418   } else {
419     /* TRANSLATORS: only ASCII characters (skin) */
420     gui->mmk.mrl           = strdup(pgettext("skin", "There is no MRL."));
421     gui->mmk.ident         = strdup ("xine-ui version " VERSION);
422     gui->mmk.sub           = NULL;
423     gui->mmk.start         = 0;
424     gui->mmk.end           = -1;
425     gui->mmk.av_offset     = 0;
426     gui->mmk.spu_offset    = 0;
427     gui->mmk.got_alternate = 0;
428     gui->mmk.alternates    = NULL;
429     gui->mmk.cur_alt       = NULL;
430   }
431   pthread_mutex_unlock (&gui->mmk_mutex);
432 }
433 
mmk_set_update(void)434 static void mmk_set_update(void) {
435   gGui_t *gui = gGui;
436 
437   video_window_set_mrl (gui->vwin, gui->mmk.ident);
438   event_sender_update_menu_buttons();
439   panel_update_mrl_display (gui->panel);
440   playlist_update_focused_entry();
441 
442   gui->playlist.ref_append = gui->playlist.cur;
443 }
444 
gui_xine_play(gGui_t * gui,xine_stream_t * stream,int start_pos,int start_time_in_secs,int update_mmk)445 int gui_xine_play (gGui_t *gui, xine_stream_t *stream, int start_pos, int start_time_in_secs, int update_mmk) {
446   int has_video, has_audio, v_unhandled = 0, a_unhandled = 0;
447   uint32_t video_handled, audio_handled;
448 
449   if(play_data.running)
450     return 0;
451 
452   has_video     = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_VIDEO);
453   video_handled = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_HANDLED);
454   has_audio     = xine_get_stream_info(stream, XINE_STREAM_INFO_HAS_AUDIO);
455   audio_handled = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_HANDLED);
456 
457   if (has_video)
458     has_video = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_VIDEO);
459   if (has_audio)
460     has_audio = !xine_get_stream_info(stream, XINE_STREAM_INFO_IGNORE_AUDIO);
461 
462   v_unhandled = (has_video && (!video_handled));
463   a_unhandled = (has_audio && (!audio_handled));
464   if(v_unhandled || a_unhandled) {
465     char *buffer = NULL;
466     char *v_info = NULL;
467     char *a_info = NULL;
468 
469     if(v_unhandled && a_unhandled) {
470       buffer = xitk_asprintf(_("The stream '%s' isn't supported by xine:\n\n"),
471                              (stream == gui->stream) ? gui->mmk.mrl : gui->visual_anim.mrls[gui->visual_anim.current]);
472     }
473     else {
474       buffer = xitk_asprintf(_("The stream '%s' uses an unsupported codec:\n\n"),
475                              (stream == gui->stream) ? gui->mmk.mrl : gui->visual_anim.mrls[gui->visual_anim.current]);
476     }
477 
478     if(v_unhandled) {
479       const char *minfo;
480       uint32_t    vfcc;
481       char        tmp[8];
482 
483       minfo = xine_get_meta_info(stream, XINE_META_INFO_VIDEOCODEC);
484       vfcc = xine_get_stream_info(stream, XINE_STREAM_INFO_VIDEO_FOURCC);
485       v_info = xitk_asprintf(_("Video Codec: %s (%s)\n"),
486                              (minfo && strlen(minfo)) ? (char *) minfo : _("Unavailable"),
487                              (get_fourcc_string(tmp, sizeof(tmp), vfcc)));
488     }
489 
490     if(a_unhandled) {
491       const char *minfo;
492       uint32_t    afcc;
493       char        tmp[8];
494 
495       minfo = xine_get_meta_info(stream, XINE_META_INFO_AUDIOCODEC);
496       afcc = xine_get_stream_info(stream, XINE_STREAM_INFO_AUDIO_FOURCC);
497       a_info = xitk_asprintf(_("Audio Codec: %s (%s)\n"),
498                              (minfo && strlen(minfo)) ? (char *) minfo : _("Unavailable"),
499                              (get_fourcc_string(tmp, sizeof(tmp), afcc)));
500     }
501 
502 
503     if(v_unhandled && a_unhandled) {
504       xine_error("%s%s%s", buffer ? buffer : "", v_info ? v_info : "", a_info ? a_info : "");
505       free(buffer); free(v_info); free(a_info);
506       return 0;
507     }
508 
509     if(!gui->play_anyway) {
510       xitk_window_t *xw;
511 
512       play_data.stream             = stream;
513       play_data.start_pos          = start_pos;
514       play_data.start_time_in_secs = start_time_in_secs;
515       play_data.update_mmk         = update_mmk;
516       play_data.running            = 1;
517 
518       xw = xitk_window_dialog_yesno_with_width(gui->imlib_data, _("Start Playback ?"),
519 					       start_anyway_yesno, start_anyway_yesno,
520 					       gui, 400, ALIGN_CENTER,
521 					       "%s%s%s%s", buffer ? buffer : "",
522 					       v_info ? v_info : "", a_info ? a_info : "",
523 					       _("\nStart playback anyway ?\n"));
524       free(buffer); free(v_info); free(a_info);
525 
526       gui->x_lock_display (gui->display);
527       XSync(gui->display, False);
528       gui->x_unlock_display (gui->display);
529       video_window_set_transient_for (gui->vwin, xitk_window_get_window (xw));
530       layer_above_video(xitk_window_get_window(xw));
531 
532       /* Doesn't work so well yet
533 	 use play_data.running hack for a while
534 	 xitk_window_dialog_set_modal(xw);
535       */
536 
537       return 1;
538     }
539 
540     free(buffer); free(v_info); free(a_info);
541   }
542 
543   return _gui_xine_play (gui, stream, start_pos, start_time_in_secs * 1000, update_mmk);
544 }
545 
gui_xine_open_and_play(char * _mrl,char * _sub,int start_pos,int start_time,int av_offset,int spu_offset,int report_error)546 int gui_xine_open_and_play(char *_mrl, char *_sub, int start_pos,
547 			   int start_time, int av_offset, int spu_offset, int report_error) {
548   gGui_t *gui = gGui;
549   char *mrl = _mrl;
550   int ret;
551 
552   if(__xineui_global_verbosity)
553     printf("%s():\n\tmrl: '%s',\n\tsub '%s',\n\tstart_pos %d, start_time %d, av_offset %d, spu_offset %d.\n",
554 	   __func__, _mrl, (_sub) ? _sub : "NONE", start_pos, start_time, av_offset, spu_offset);
555 
556   if(!strncasecmp(mrl, "cfg:/", 5)) {
557     config_mrl(mrl);
558     gui_playlist_start_next (gui);
559     return 1;
560   }
561   else if(/*(!strncasecmp(mrl, "ftp://", 6)) ||*/ (!strncasecmp(mrl, "dload:/", 7)))  {
562     char        *url = mrl;
563     download_t   download;
564 
565     if(!strncasecmp(mrl, "dload:/", 7))
566       url = _mrl + 7;
567 
568     download.buf    = NULL;
569     download.error  = NULL;
570     download.size   = 0;
571     download.status = 0;
572 
573     if((network_download(url, &download))) {
574       char *filename;
575 
576       filename = strrchr(url, '/');
577       if(filename && filename[1]) { /* we have a filename */
578 	char  fullfilename[XITK_PATH_MAX + XITK_NAME_MAX + 2];
579 	FILE *fd;
580 
581 	filename++;
582 	snprintf(fullfilename, sizeof(fullfilename), "%s/%s", xine_get_homedir(), filename);
583 
584 	if((fd = fopen(fullfilename, "w+b")) != NULL) {
585 	  char  *sub = NULL;
586 	  int    start, end;
587 
588 	  char *newmrl = strdup(fullfilename);
589 	  char *ident = strdup(gui->playlist.mmk[gui->playlist.cur]->ident);
590 	  if(gui->playlist.mmk[gui->playlist.cur]->sub)
591 	    sub = strdup(gui->playlist.mmk[gui->playlist.cur]->sub);
592 	  start = gui->playlist.mmk[gui->playlist.cur]->start;
593 	  end = gui->playlist.mmk[gui->playlist.cur]->end;
594 
595 	  fwrite(download.buf, download.size, 1, fd);
596 	  fflush(fd);
597 	  fclose(fd);
598 
599 	  mediamark_replace_entry(&gui->playlist.mmk[gui->playlist.cur],
600 				  newmrl, ident, sub, start, end, 0, 0);
601 	  gui_set_current_mmk(mediamark_get_current_mmk());
602 	  mrl = gui->mmk.mrl;
603 
604 	  free(newmrl);
605 	  free(ident);
606 	  free(sub);
607 	}
608       }
609     }
610 
611     free(download.buf);
612     free(download.error);
613 
614   }
615 
616   if(mrl_look_like_playlist(mrl)) {
617     if(mediamark_concat_mediamarks(mrl)) {
618       gui_set_current_mmk(mediamark_get_current_mmk());
619       mrl        = gui->mmk.mrl;
620       start_pos  = 0;
621       start_time = gui->mmk.start;
622       av_offset  = gui->mmk.av_offset;
623       spu_offset = gui->mmk.spu_offset;
624       playlist_update_playlist();
625     }
626   }
627 
628   gui_messages_off (gui);
629   ret = xine_open(gui->stream, (const char *) mrl);
630   gui_messages_on (gui);
631   if (!ret) {
632 
633 #ifdef XINE_PARAM_GAPLESS_SWITCH
634     if( xine_check_version(1,1,1) )
635       xine_set_param(gui->stream, XINE_PARAM_GAPLESS_SWITCH, 0);
636 #endif
637 
638     if(!strcmp(mrl, gui->mmk.mrl))
639       gui->playlist.mmk[gui->playlist.cur]->played = 1;
640 
641     if(report_error)
642       gui_handle_xine_error(gui->stream, mrl);
643     return 0;
644   }
645 
646   if(_sub) {
647 
648     gui_messages_off (gui);
649     ret = xine_open(gui->spu_stream, _sub);
650     gui_messages_on (gui);
651     if (ret)
652       xine_stream_master_slave(gui->stream,
653 			       gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
654   }
655   else
656     xine_close (gui->spu_stream);
657 
658   xine_set_param(gui->stream, XINE_PARAM_AV_OFFSET, av_offset);
659   xine_set_param(gui->stream, XINE_PARAM_SPU_OFFSET, spu_offset);
660 
661   if (!gui_xine_play (gui, gui->stream, start_pos, start_time, 1)) {
662     if(!strcmp(mrl, gui->mmk.mrl))
663       gui->playlist.mmk[gui->playlist.cur]->played = 1;
664     return 0;
665   }
666 
667   if(!strcmp(mrl, gui->mmk.mrl))
668     gui->playlist.mmk[gui->playlist.cur]->played = 1;
669 
670   gui_xine_get_pos_length(gui->stream, NULL, NULL, NULL);
671 
672   if (gui->stdctl_enable)
673     stdctl_playing(mrl);
674 
675   return 1;
676 }
677 
gui_open_and_play_alternates(mediamark_t * mmk,const char * sub)678 int gui_open_and_play_alternates(mediamark_t *mmk, const char *sub) {
679   gGui_t *gui = gGui;
680   char *alt;
681 
682   if(!(alt = mediamark_get_current_alternate_mrl(mmk)))
683     alt = mediamark_get_first_alternate_mrl(mmk);
684 
685   do {
686 
687     if(gui_xine_open_and_play(alt, gui->mmk.sub, 0, 0, 0, 0, 0))
688       return 1;
689 
690   } while((alt = mediamark_get_next_alternate_mrl(&(gui->mmk))));
691   return 0;
692 }
693 
694 /*
695  * Callback-functions for widget-button click
696  */
gui_exit(xitk_widget_t * w,void * data)697 void gui_exit (xitk_widget_t *w, void *data) {
698   gGui_t *gui = data;
699 
700   oxine_exit();
701 
702   if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
703     gui->ignore_next = 1;
704 
705     if(gui->visual_anim.running) {
706       xine_post_out_t * audio_source;
707 
708       xine_stop(gui->visual_anim.stream);
709 
710       while(xine_get_status(gui->visual_anim.stream) == XINE_STATUS_PLAY)
711       	xine_usec_sleep(50000);
712 
713       audio_source = xine_get_audio_source(gui->stream);
714       (void) xine_post_wire_audio_port(audio_source, gui->ao_port);
715     }
716 
717     xine_stop (gui->stream);
718     while(xine_get_status(gui->stream) == XINE_STATUS_PLAY)
719       xine_usec_sleep(50000);
720 
721     gui->ignore_next = 0;
722   }
723 
724   gui->on_quit = 1;
725 
726   /* shut down event queue threads */
727   /* do it first, events access gui elements ... */
728   xine_event_dispose_queue(gui->event_queue);
729   xine_event_dispose_queue(gui->visual_anim.event_queue);
730   gui->event_queue = gui->visual_anim.event_queue = NULL;
731 
732   panel_deinit (gui->panel);
733   destroy_mrl_browser (gui->mrlb);
734   control_deinit (gui->vctrl);
735 
736   gui_deinit (gui);
737 
738   playlist_deinit();
739 
740   setup_end (gui->setup);
741   viewlog_end();
742   kbedit_end();
743   event_sender_end();
744   stream_infos_end();
745   tvset_end();
746   vpplugin_end();
747   applugin_end();
748   help_end();
749 #ifdef HAVE_TAR
750   download_skin_end();
751 #endif
752 
753   if (gui->load_stream) {
754     filebrowser_end (gui->load_stream);
755     gui->load_stream = NULL;
756   }
757   if (gui->load_sub) {
758     filebrowser_end (gui->load_sub);
759     gui->load_sub = NULL;
760   }
761 
762   if (video_window_is_visible (gui->vwin))
763     video_window_set_visibility (gui->vwin, 0);
764 
765   tvout_deinit(gui->tvout);
766 
767 #ifdef HAVE_XF86VIDMODE
768   /* just in case a different modeline than the original one is running,
769    * toggle back to window mode which automatically causes a switch back to
770    * the original modeline
771    */
772   if(gui->XF86VidMode_fullscreen)
773     video_window_set_fullscreen_mode (gui->vwin, WINDOWED_MODE);
774   //     gui_set_fullscreen_mode (NULL, gui);
775 #endif
776 
777   osd_deinit();
778 
779   config_update_num("gui.amp_level", gui->mixer.amp_level);
780   xine_config_save (gui->xine, __xineui_global_config_file);
781 
782   xine_close(gui->stream);
783   xine_close(gui->visual_anim.stream);
784   xine_close (gui->spu_stream);
785 
786   /* we are going to dispose this stream, so make sure slider_loop
787    * won't use it anymore (otherwise -> segfault on exit).
788    */
789   gui->running = 0;
790 
791   if(gui->visual_anim.post_output_element.post)
792     xine_post_dispose (gui->xine, gui->visual_anim.post_output_element.post);
793   gui->visual_anim.post_output_element.post = NULL;
794 
795   /* unwire post plugins before closing streams */
796   post_deinit ();
797   post_deinterlace_deinit ();
798 
799   xine_dispose(gui->stream);
800   xine_dispose(gui->visual_anim.stream);
801   xine_dispose (gui->spu_stream);
802   gui->stream = gui->visual_anim.stream = gui->spu_stream = NULL;
803 
804   if(gui->vo_port)
805     xine_close_video_driver (gui->xine, gui->vo_port);
806   if(gui->vo_none)
807     xine_close_video_driver (gui->xine, gui->vo_none);
808   gui->vo_port = gui->vo_none = NULL;
809 
810   if(gui->ao_port)
811     xine_close_audio_driver (gui->xine, gui->ao_port);
812   if(gui->ao_none)
813     xine_close_audio_driver (gui->xine, gui->ao_none);
814   gui->ao_port = gui->ao_none = NULL;
815 
816   video_window_exit (gui->vwin);
817 
818 #ifdef HAVE_LIRC
819   if(__xineui_global_lirc_enable)
820     lirc_stop();
821 #endif
822 
823   if(gui->stdctl_enable)
824     stdctl_stop();
825 
826   /* this will prevent a race condition that may lead to a lock:
827    * xitk_stop() makes gui_run() in event.c return from xitk_run()
828    * and do some house cleaning which includes closing displays.
829    * However, we're not done using displays and we must prevent that
830    * from happening until we're finished.
831    */
832   gui->x_lock_display (gui->video_display);
833   if( gui->video_display != gui->display )
834     gui->x_lock_display (gui->display);
835   xitk_stop();
836   /*
837    * This prevent xine waiting till the end of time for an
838    * XEvent when lirc (and futur other control ways) is used to quit .
839    */
840   if( gui->video_display == gui->display )
841     gui_send_expose_to_window(gui->video_window);
842 
843   xitk_skin_unload_config(gui->skin_config);
844   gui->x_unlock_display (gui->video_display);
845   if( gui->video_display != gui->display )
846     gui->x_unlock_display (gui->display);
847 }
848 
gui_play(xitk_widget_t * w,void * data)849 void gui_play (xitk_widget_t *w, void *data) {
850   gGui_t *gui = data;
851 
852   if((!gui->playlist.num) && (xine_get_status(gui->stream) != XINE_STATUS_PLAY))
853     return;
854 
855   video_window_reset_ssaver (gui->vwin);
856 
857   if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
858     if(gui->logo_mode != 0) {
859       gui->ignore_next = 1;
860       xine_stop(gui->stream);
861       gui->ignore_next = 0;
862     }
863   }
864 
865   if(xine_get_status(gui->stream) != XINE_STATUS_PLAY) {
866 
867     if (!strncmp(gui->mmk.ident, "xine-ui version", 15)) {
868       xine_error (_("No MRL (input stream) specified"));
869       return;
870     }
871 
872     if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
873 			       gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset,
874 			       !mediamark_have_alternates(&(gui->mmk)))) {
875 
876       if(!mediamark_have_alternates(&(gui->mmk)) ||
877 	 !gui_open_and_play_alternates(&(gui->mmk), gui->mmk.sub)) {
878 
879 	if(mediamark_all_played() && (gui->actions_on_start[0] == ACTID_QUIT)) {
880           gui_exit (NULL, gui);
881 	  return;
882 	}
883 	gui_display_logo();
884       }
885     }
886   }
887   else {
888     int oldspeed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
889 
890     xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
891     if(oldspeed != XINE_SPEED_NORMAL)
892       osd_update_status();
893   }
894 
895   panel_check_pause (gui->panel);
896 }
897 
gui_stop(xitk_widget_t * w,void * data)898 void gui_stop (xitk_widget_t *w, void *data) {
899   gGui_t *gui = data;
900 
901   gui->ignore_next = 1;
902   xine_stop (gui->stream);
903   gui->ignore_next = 0;
904 
905   if(!(gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST))
906     gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
907 
908   gui->stream_length.pos = gui->stream_length.time = gui->stream_length.length = 0;
909 
910   mediamark_reset_played_state();
911   if(gui->visual_anim.running) {
912     xine_stop(gui->visual_anim.stream);
913     if(gui->visual_anim.enabled == 2)
914       gui->visual_anim.running = 0;
915   }
916 
917   osd_hide_sinfo();
918   osd_hide_bar();
919   osd_hide_info();
920   osd_update_status();
921   panel_reset_slider (gui->panel);
922   panel_check_pause (gui->panel);
923   panel_update_runtime_display (gui->panel);
924 
925   if (is_playback_widgets_enabled (gui->panel)) {
926     if(!gui->playlist.num) {
927       gui_set_current_mmk(NULL);
928       enable_playback_controls (gui->panel, 0);
929     }
930     else if(gui->playlist.num && (strcmp((mediamark_get_current_mrl()), gui->mmk.mrl))) {
931       gui_set_current_mmk(mediamark_get_current_mmk());
932     }
933   }
934   gui_display_logo();
935 }
936 
gui_close(xitk_widget_t * w,void * data)937 void gui_close (xitk_widget_t *w, void *data) {
938   gGui_t *gui = data;
939 
940   gui->ignore_next = 1;
941   xine_stop (gui->stream);
942   gui->ignore_next = 0;
943 
944   if(!(gui->playlist.control & PLAYLIST_CONTROL_STOP_PERSIST))
945     gui->playlist.control &= ~PLAYLIST_CONTROL_STOP;
946 
947   gui->stream_length.pos = gui->stream_length.time = gui->stream_length.length = 0;
948 
949   mediamark_reset_played_state();
950   if(gui->visual_anim.running) {
951     xine_stop(gui->visual_anim.stream);
952     if(gui->visual_anim.enabled == 2)
953       gui->visual_anim.running = 0;
954   }
955 
956   osd_hide_sinfo();
957   osd_hide_bar();
958   osd_hide_info();
959   osd_update_status();
960   panel_reset_slider (gui->panel);
961   panel_check_pause (gui->panel);
962   panel_update_runtime_display (gui->panel);
963 
964   if (is_playback_widgets_enabled (gui->panel)) {
965     if(!gui->playlist.num) {
966       gui_set_current_mmk(NULL);
967       enable_playback_controls (gui->panel, 0);
968     }
969     else if(gui->playlist.num && (strcmp((mediamark_get_current_mrl()), gui->mmk.mrl))) {
970       gui_set_current_mmk(mediamark_get_current_mmk());
971     }
972   }
973   gui->ignore_next = 1;
974   xine_close (gui->stream);
975   gui->ignore_next = 0;
976 }
977 
gui_pause(xitk_widget_t * w,void * data,int state)978 void gui_pause (xitk_widget_t *w, void *data, int state) {
979   gGui_t *gui = data;
980   int speed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
981 
982   if(speed != XINE_SPEED_PAUSE) {
983     gui->last_playback_speed = speed;
984     xine_set_param(gui->stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
985     panel_update_runtime_display (gui->panel);
986   }
987   else {
988     xine_set_param (gui->stream, XINE_PARAM_SPEED, gui->last_playback_speed);
989     video_window_reset_ssaver (gui->vwin);
990   }
991 
992   panel_check_pause (gui->panel);
993   /* Give xine engine some time before updating OSD, otherwise the */
994   /* time disp may be empty when switching to XINE_SPEED_PAUSE.    */
995   xine_usec_sleep(10000);
996   osd_update_status();
997 }
998 
gui_eject(xitk_widget_t * w,void * data)999 void gui_eject (xitk_widget_t *w, void *data) {
1000   gGui_t *gui = data;
1001   int i;
1002 
1003   if(xine_get_status(gui->stream) == XINE_STATUS_PLAY)
1004     gui_stop (NULL, gui);
1005 
1006   if(xine_eject(gui->stream)) {
1007 
1008     if(gui->playlist.num) {
1009       mediamark_t **mmk = NULL;
1010       char         *mrl;
1011       size_t        tok_len = 0;
1012       int           new_num = 0;
1013 
1014       const char *const cur_mrl = mediamark_get_current_mrl();
1015       /*
1016        * If it's an mrl (____://) remove all of them in playlist
1017        */
1018       if ( (mrl = strstr((cur_mrl), ":/")) )
1019 	tok_len = (mrl - cur_mrl) + 2;
1020 
1021       if(tok_len != 0) {
1022 	/*
1023 	 * Store all of not maching entries
1024 	 */
1025 	for(i = 0; i < gui->playlist.num; i++) {
1026 	  if(strncasecmp(gui->playlist.mmk[i]->mrl, cur_mrl, tok_len)) {
1027 
1028 	    mmk = (mediamark_t **) realloc(mmk, sizeof(mediamark_t *) * (new_num + 2));
1029 
1030 	    (void) mediamark_store_mmk(&mmk[new_num],
1031 				       gui->playlist.mmk[i]->mrl,
1032 				       gui->playlist.mmk[i]->ident,
1033 				       gui->playlist.mmk[i]->sub,
1034 				       gui->playlist.mmk[i]->start,
1035 				       gui->playlist.mmk[i]->end,
1036 				       gui->playlist.mmk[i]->av_offset,
1037 				       gui->playlist.mmk[i]->spu_offset);
1038 	    new_num++;
1039 	  }
1040 	}
1041 
1042 	/*
1043 	 * flip playlists.
1044 	 */
1045 	mediamark_free_mediamarks();
1046 	if(mmk)
1047 	  gui->playlist.mmk = mmk;
1048 
1049 	if(!(gui->playlist.num = new_num))
1050 	  gui->playlist.cur = -1;
1051 	else if(new_num)
1052 	  gui->playlist.cur = 0;
1053       }
1054       else {
1055       __remove_current_mrl:
1056 	/*
1057 	 * Remove only the current MRL
1058 	 */
1059 	mediamark_free_entry(gui->playlist.cur);
1060 
1061 	for(i = gui->playlist.cur; i < gui->playlist.num; i++)
1062 	  gui->playlist.mmk[i] = gui->playlist.mmk[i + 1];
1063 
1064 	gui->playlist.mmk = (mediamark_t **) realloc(gui->playlist.mmk, sizeof(mediamark_t *) * (gui->playlist.num + 2));
1065 
1066 	gui->playlist.mmk[gui->playlist.num] = NULL;
1067 
1068 	if(gui->playlist.cur)
1069 	  gui->playlist.cur--;
1070       }
1071 
1072       if (is_playback_widgets_enabled (gui->panel) && (!gui->playlist.num))
1073         enable_playback_controls (gui->panel, 0);
1074 
1075     }
1076 
1077     gui_set_current_mmk(mediamark_get_current_mmk());
1078     playlist_update_playlist();
1079   }
1080   else {
1081     /* Remove current mrl */
1082     if(gui->playlist.num)
1083       goto __remove_current_mrl;
1084   }
1085 
1086   if(!gui->playlist.num)
1087     gui->playlist.cur = -1;
1088 
1089 }
1090 
gui_toggle_visibility(xitk_widget_t * w,void * data)1091 void gui_toggle_visibility (xitk_widget_t *w, void *data) {
1092   gGui_t *gui = data;
1093 
1094   if (panel_is_visible (gui->panel) && (!gui->use_root_window)) {
1095     int visible = !video_window_is_visible (gui->vwin);
1096 
1097     video_window_set_visibility (gui->vwin, visible);
1098 
1099 
1100     /* We need to reparent all visible windows because of redirect tweaking */
1101     if(!visible) { /* Show the panel in taskbar */
1102       int x = 0, y = 0;
1103 
1104       xitk_get_window_position(gui->display, gui->panel_window, &x, &y, NULL, NULL);
1105       gui->x_lock_display (gui->display);
1106       XReparentWindow(gui->display, gui->panel_window, gui->imlib_data->x.root, x, y);
1107       gui->x_unlock_display (gui->display);
1108     }
1109     reparent_all_windows();
1110 
1111     /* (re)start/stop visual animation */
1112     if (video_window_is_visible (gui->vwin)) {
1113       layer_above_video(gui->panel_window);
1114 
1115       if(gui->visual_anim.enabled && (gui->visual_anim.running == 2))
1116 	visual_anim_play();
1117     }
1118     else {
1119 
1120       if(gui->visual_anim.running) {
1121 	visual_anim_stop();
1122 	gui->visual_anim.running = 2;
1123       }
1124     }
1125   }
1126 }
1127 
gui_toggle_border(xitk_widget_t * w,void * data)1128 void gui_toggle_border (xitk_widget_t *w, void *data) {
1129   gGui_t *gui = data;
1130   video_window_toggle_border (gui->vwin);
1131 }
1132 
set_fullscreen_mode(int fullscreen_mode)1133 static void set_fullscreen_mode(int fullscreen_mode) {
1134   gGui_t *gui = gGui;
1135   int panel        = panel_is_visible (gui->panel);
1136   int mrl_browser  = mrl_browser_is_visible (gui->mrlb);
1137   int playlist     = playlist_is_visible();
1138   int control      = control_status (gui->vctrl) == 3;
1139   int setup        = setup_is_visible (gui->setup);
1140   int viewlog      = viewlog_is_visible();
1141   int kbedit       = kbedit_is_visible();
1142   int event_sender = event_sender_is_visible();
1143   int stream_infos = stream_infos_is_visible();
1144   int tvset        = tvset_is_visible();
1145   int vpplugin     = vpplugin_is_visible();
1146   int applugin     = applugin_is_visible();
1147   int help         = help_is_visible();
1148 
1149   if ((!(video_window_is_visible (gui->vwin))) || gui->use_root_window)
1150     return;
1151 
1152   if(panel)
1153     panel_toggle_visibility (NULL, gui->panel);
1154   else {
1155     if(mrl_browser)
1156       mrl_browser_toggle_visibility (NULL, gui->mrlb);
1157     if(playlist)
1158       playlist_toggle_visibility(NULL, NULL);
1159     if(control)
1160       control_toggle_visibility (NULL, gui->vctrl);
1161     if(setup)
1162       setup_toggle_visibility (NULL, gui->setup);
1163     if(viewlog)
1164       viewlog_toggle_visibility(NULL, NULL);
1165     if(kbedit)
1166       kbedit_toggle_visibility(NULL, NULL);
1167     if(event_sender)
1168       event_sender_toggle_visibility(NULL, NULL);
1169     if(stream_infos)
1170       stream_infos_toggle_visibility(NULL, NULL);
1171     if(tvset)
1172       tvset_toggle_visibility(NULL, NULL);
1173     if(vpplugin)
1174       vpplugin_toggle_visibility(NULL, NULL);
1175     if(applugin)
1176       applugin_toggle_visibility(NULL, NULL);
1177     if(help)
1178       help_toggle_visibility(NULL, NULL);
1179   }
1180 
1181   video_window_set_fullscreen_mode (gui->vwin, fullscreen_mode);
1182 
1183   /* Drawable has changed, update cursor visiblity */
1184   if(!gui->cursor_visible)
1185     video_window_set_cursor_visibility (gui->vwin, gui->cursor_visible);
1186 
1187   if(panel)
1188     panel_toggle_visibility (NULL, gui->panel);
1189   else {
1190     if(mrl_browser)
1191       mrl_browser_toggle_visibility (NULL, gui->mrlb);
1192     if(playlist)
1193       playlist_toggle_visibility(NULL, NULL);
1194     if(control)
1195       control_toggle_visibility (NULL, gui->vctrl);
1196     if(setup)
1197       setup_toggle_visibility (NULL, gui->setup);
1198     if(viewlog)
1199       viewlog_toggle_visibility(NULL, NULL);
1200     if(kbedit)
1201       kbedit_toggle_visibility(NULL, NULL);
1202     if(event_sender)
1203       event_sender_toggle_visibility(NULL, NULL);
1204     if(stream_infos)
1205       stream_infos_toggle_visibility(NULL, NULL);
1206     if(tvset)
1207       tvset_toggle_visibility(NULL, NULL);
1208     if(vpplugin)
1209       vpplugin_toggle_visibility(NULL, NULL);
1210     if(applugin)
1211       applugin_toggle_visibility(NULL, NULL);
1212     if(help)
1213       help_toggle_visibility(NULL, NULL);
1214   }
1215 
1216 }
1217 
gui_set_fullscreen_mode(xitk_widget_t * w,void * data)1218 void gui_set_fullscreen_mode (xitk_widget_t *w, void *data) {
1219   (void)data;
1220   set_fullscreen_mode(FULLSCR_MODE);
1221 }
1222 
1223 #ifdef HAVE_XINERAMA
gui_set_xinerama_fullscreen_mode(void)1224 void gui_set_xinerama_fullscreen_mode(void) {
1225   set_fullscreen_mode(FULLSCR_XI_MODE);
1226 }
1227 #endif
1228 
gui_toggle_aspect(int aspect)1229 void gui_toggle_aspect(int aspect) {
1230   gGui_t *gui = gGui;
1231   static const char * const ratios[XINE_VO_ASPECT_NUM_RATIOS + 1] = {
1232     "Auto",
1233     "Square",
1234     "4:3",
1235     "Anamorphic",
1236     "DVB",
1237     NULL
1238   };
1239 
1240   if(aspect == -1)
1241     aspect = xine_get_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO) + 1;
1242 
1243   xine_set_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO, aspect);
1244 
1245   osd_display_info(_("Aspect ratio: %s"),
1246 		   ratios[xine_get_param(gui->stream, XINE_PARAM_VO_ASPECT_RATIO)]);
1247 
1248   if (panel_is_visible (gui->panel))  {
1249     gui->x_lock_display (gui->display);
1250     XRaiseWindow(gui->display, gui->panel_window);
1251     gui->x_unlock_display (gui->display);
1252     video_window_set_transient_for (gui->vwin, gui->panel_window);
1253   }
1254 }
1255 
gui_toggle_interlaced(void)1256 void gui_toggle_interlaced(void) {
1257   gGui_t *gui = gGui;
1258   gui->deinterlace_enable = !gui->deinterlace_enable;
1259   osd_display_info(_("Deinterlace: %s"), (gui->deinterlace_enable) ? _("enabled") : _("disabled"));
1260   post_deinterlace();
1261 
1262   if (panel_is_visible (gui->panel))  {
1263     gui->x_lock_display (gui->display);
1264     XRaiseWindow(gui->display, gui->panel_window);
1265     gui->x_unlock_display (gui->display);
1266     video_window_set_transient_for (gui->vwin, gui->panel_window);
1267   }
1268 }
1269 
gui_direct_change_audio_channel(xitk_widget_t * w,void * data,int value)1270 void gui_direct_change_audio_channel (xitk_widget_t *w, void *data, int value) {
1271   gGui_t *gui = data;
1272   xine_set_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL, value);
1273   panel_update_channel_display (gui->panel);
1274   osd_display_audio_lang();
1275 }
1276 
gui_change_audio_channel(xitk_widget_t * w,void * data)1277 void gui_change_audio_channel(xitk_widget_t *w, void *data) {
1278   gGui_t *gui = gGui;
1279   int dir = (int)(intptr_t)data;
1280   int channel;
1281 
1282   channel = xine_get_param(gui->stream, XINE_PARAM_AUDIO_CHANNEL_LOGICAL);
1283 
1284   if(dir == GUI_NEXT)
1285     channel++;
1286   else if(dir == GUI_PREV)
1287     channel--;
1288 
1289   gui_direct_change_audio_channel(w, gui, channel);
1290 }
1291 
gui_direct_change_spu_channel(xitk_widget_t * w,void * data,int value)1292 void gui_direct_change_spu_channel(xitk_widget_t *w, void *data, int value) {
1293   gGui_t *gui = gGui;
1294   xine_set_param(gui->stream, XINE_PARAM_SPU_CHANNEL, value);
1295   panel_update_channel_display (gui->panel);
1296   osd_display_spu_lang();
1297 }
1298 
gui_change_spu_channel(xitk_widget_t * w,void * data)1299 void gui_change_spu_channel(xitk_widget_t *w, void *data) {
1300   gGui_t *gui = gGui;
1301   int dir = (int)(intptr_t)data;
1302   int channel;
1303   int maxchannel;
1304 
1305   channel = xine_get_param(gui->stream, XINE_PARAM_SPU_CHANNEL);
1306   maxchannel = xine_get_stream_info(gui->stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1307 
1308   if (xine_get_status(gui->spu_stream) != XINE_STATUS_IDLE) /* if we have a slave SPU channel, take it into account */
1309     maxchannel += xine_get_stream_info(gui->spu_stream, XINE_STREAM_INFO_MAX_SPU_CHANNEL);
1310 
1311   /* XINE_STREAM_INFO_MAX_SPU_CHANNEL actually returns the number of available spu channels, i.e.
1312    * 0 means no SPUs, 1 means 1 SPU channel, etc. */
1313   --maxchannel;
1314 
1315   if(dir == GUI_NEXT)
1316     channel++;
1317   else if(dir == GUI_PREV)
1318     channel--;
1319 
1320   if (channel > maxchannel)
1321     channel = -2; /* -2 == off, -1 == auto, 0 == 1st channel */
1322   else if (channel < -2)
1323     channel = maxchannel;
1324 
1325   gui_direct_change_spu_channel(w, data, channel);
1326 }
1327 
gui_change_speed_playback(xitk_widget_t * w,void * data)1328 void gui_change_speed_playback(xitk_widget_t *w, void *data) {
1329   gGui_t *gui = gGui;
1330   int speed = xine_get_param(gui->stream, XINE_PARAM_SPEED);
1331 
1332   if(((intptr_t)data) == GUI_NEXT) {
1333     if (speed > XINE_SPEED_PAUSE) {
1334       xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed /= 2));
1335     }
1336 #ifdef XINE_PARAM_VO_SINGLE_STEP
1337     else {
1338       xine_set_param (gui->stream, XINE_PARAM_VO_SINGLE_STEP, 1);
1339       panel_update_runtime_display (gui->panel);
1340     }
1341 #endif
1342   }
1343   else if(((intptr_t)data) == GUI_PREV) {
1344     if(speed < XINE_SPEED_FAST_4) {
1345       if(speed > XINE_SPEED_PAUSE)
1346 	xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed *= 2));
1347       else {
1348 	xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed = XINE_SPEED_SLOW_4));
1349 	video_window_reset_ssaver (gui->vwin);
1350       }
1351     }
1352   }
1353   else if(((intptr_t)data) == GUI_RESET) {
1354     xine_set_param(gui->stream, XINE_PARAM_SPEED, (speed = XINE_SPEED_NORMAL));
1355   }
1356   if(speed != XINE_SPEED_PAUSE)
1357     gui->last_playback_speed = speed;
1358 
1359   panel_check_pause (gui->panel);
1360   /* Give xine engine some time before updating OSD, otherwise the        */
1361   /* time disp may be empty when switching to speeds < XINE_SPEED_NORMAL. */
1362   xine_usec_sleep(10000);
1363   osd_update_status();
1364 }
1365 
gui_seek_thread(void * data)1366 static void *gui_seek_thread (void *data) {
1367   gGui_t *gui = data;
1368   int update_mmk = 0, ret;
1369 
1370   pthread_detach (pthread_self ());
1371 
1372   do {
1373     {
1374       const char *mrl = mediamark_get_current_mrl ();
1375       if (gui->logo_mode && mrl) {
1376         gui_messages_off (gui);
1377         ret = xine_open (gui->stream, mrl);
1378         gui_messages_on (gui);
1379         if (!ret) {
1380           gui_handle_xine_error (gui->stream, (char *)mrl);
1381           break;
1382         }
1383       }
1384     }
1385 
1386     if (!xine_get_stream_info (gui->stream, XINE_STREAM_INFO_SEEKABLE) || (gui->ignore_next == 1))
1387       break;
1388 
1389     if (xine_get_status (gui->stream) != XINE_STATUS_PLAY) {
1390       gui_messages_off (gui);
1391       xine_open (gui->stream, gui->mmk.mrl);
1392       gui_messages_on (gui);
1393 
1394       if (gui->mmk.sub) {
1395         gui_messages_off (gui);
1396         ret = xine_open (gui->spu_stream, gui->mmk.sub);
1397         gui_messages_on (gui);
1398         if (ret)
1399           xine_stream_master_slave (gui->stream, gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
1400       } else {
1401         xine_close (gui->spu_stream);
1402       }
1403     }
1404 
1405     gui->ignore_next = 1;
1406 
1407     if ( gui->playlist.num &&
1408         (gui->playlist.cur >= 0) &&
1409          gui->playlist.mmk &&
1410          gui->playlist.mmk[gui->playlist.cur] &&
1411         !strcmp (gui->playlist.mmk[gui->playlist.cur]->mrl, gui->mmk.mrl))
1412       update_mmk = 1;
1413 
1414     {
1415       int pos = -1;
1416 
1417       while (1) {
1418         pthread_mutex_lock (&gui->seek_mutex);
1419         if ((pos == gui->seek_pos) && (gui->seek_timestep == 0)) {
1420           gui->seek_running = 0;
1421           gui->seek_pos = -1;
1422           pthread_mutex_unlock (&gui->seek_mutex);
1423           break;
1424         }
1425         if (pos != gui->seek_pos) {
1426 
1427           pos = gui->seek_pos;
1428           pthread_mutex_unlock (&gui->seek_mutex);
1429           /* panel_update_slider (gui->panel, pos); */
1430           osd_stream_position (pos);
1431           _gui_xine_play (gui, gui->stream, pos, 0, update_mmk);
1432           xine_get_pos_length (gui->stream,
1433             &gui->stream_length.pos, &gui->stream_length.time, &gui->stream_length.length);
1434           panel_update_runtime_display (gui->panel);
1435 
1436         } else {
1437 
1438           int cur_time;
1439           int timestep = gui->seek_timestep;
1440           gui->seek_timestep = 0;
1441           pthread_mutex_unlock (&gui->seek_mutex);
1442           if ( xine_get_stream_info (gui->stream, XINE_STREAM_INFO_SEEKABLE) &&
1443               (xine_get_status (gui->stream) == XINE_STATUS_PLAY) &&
1444                xine_get_pos_length (gui->stream, NULL, &cur_time, NULL)) {
1445             gui->ignore_next = 1;
1446             cur_time += timestep;
1447             if (cur_time < 0)
1448               cur_time = 0;
1449             _gui_xine_play (gui, gui->stream, 0, cur_time, 1);
1450             if (xine_get_pos_length (gui->stream,
1451               &gui->stream_length.pos, &gui->stream_length.time, &gui->stream_length.length)) {
1452               panel_update_slider (gui->panel, gui->stream_length.pos);
1453               osd_stream_position (gui->stream_length.pos);
1454             }
1455             gui->ignore_next = 0;
1456           }
1457 
1458         }
1459       }
1460     }
1461 
1462     gui->ignore_next = 0;
1463     osd_hide_status ();
1464     panel_check_pause (gui->panel);
1465 
1466     return NULL;
1467   } while (0);
1468 
1469   pthread_mutex_lock (&gui->seek_mutex);
1470   gui->seek_running = 0;
1471   gui->seek_pos = -1;
1472   gui->seek_timestep = 0;
1473   pthread_mutex_unlock (&gui->seek_mutex);
1474   return NULL;
1475 }
1476 
gui_set_current_position(int pos)1477 void gui_set_current_position (int pos) {
1478   gGui_t *gui = gGui;
1479 
1480   pthread_mutex_lock (&gui->seek_mutex);
1481   if (gui->seek_running == 0) {
1482     pthread_t pth;
1483     int err;
1484     gui->seek_running = 1;
1485     gui->seek_pos = pos;
1486     pthread_mutex_unlock (&gui->seek_mutex);
1487     err = pthread_create (&pth, NULL, gui_seek_thread, gui);
1488     if (err) {
1489       printf (_("%s(): can't create new thread (%s)\n"), __XINE_FUNCTION__, strerror (err));
1490       pthread_mutex_lock (&gui->seek_mutex);
1491       gui->seek_running = 0;
1492       gui->seek_pos = -1;
1493       gui->seek_timestep = 0;
1494       pthread_mutex_unlock (&gui->seek_mutex);
1495     }
1496   } else {
1497     gui->seek_pos = pos;
1498     pthread_mutex_unlock (&gui->seek_mutex);
1499   }
1500 }
1501 
gui_seek_relative(int off_sec)1502 void gui_seek_relative (int off_sec) {
1503   gGui_t *gui = gGui;
1504 
1505   if (off_sec == 0)
1506     return;
1507 
1508   pthread_mutex_lock (&gui->seek_mutex);
1509   if (gui->seek_running == 0) {
1510     pthread_t pth;
1511     int err;
1512     gui->seek_running = 1;
1513     gui->seek_timestep = off_sec * 1000;
1514     pthread_mutex_unlock (&gui->seek_mutex);
1515     err = pthread_create (&pth, NULL, gui_seek_thread, gui);
1516     if (err) {
1517       printf (_("%s(): can't create new thread (%s)\n"), __XINE_FUNCTION__, strerror (err));
1518       pthread_mutex_lock (&gui->seek_mutex);
1519       gui->seek_running = 0;
1520       gui->seek_pos = -1;
1521       gui->seek_timestep = 0;
1522       pthread_mutex_unlock (&gui->seek_mutex);
1523     }
1524   } else {
1525     gui->seek_timestep = off_sec * 1000;
1526     pthread_mutex_unlock (&gui->seek_mutex);
1527   }
1528 }
1529 
gui_dndcallback(const char * filename)1530 void gui_dndcallback(const char *filename) {
1531   gGui_t *gui = gGui;
1532   int   more_than_one = -2;
1533   char *mrl           = filename ? strdup(filename) : NULL;
1534 
1535   if(mrl) {
1536     char  buffer[strlen(mrl) + 10];
1537     char  buffer2[strlen(mrl) + 10];
1538     char *p;
1539 
1540     memset(&buffer, 0, sizeof(buffer));
1541     memset(&buffer2, 0, sizeof(buffer2));
1542 
1543     pthread_mutex_lock(&gui->mmk_mutex);
1544 
1545     if((strlen(mrl) > 6) &&
1546        (!strncmp(mrl, "file:", 5))) {
1547 
1548       if((p = strstr(mrl, ":/")) != NULL) {
1549 	struct stat pstat;
1550 
1551 	p += 2;
1552 
1553 	if(*(p + 1) == '/')
1554 	  p++;
1555 
1556       __second_stat:
1557 
1558 	if((stat(p, &pstat)) == 0) {
1559 	  if(is_a_dir(p)) {
1560 	    if(*(p + (strlen(p) - 1)) == '/')
1561 	      *(p + (strlen(p) - 1)) = '\0';
1562 
1563 	    mediamark_collect_from_directory(p);
1564 	    more_than_one = gui->playlist.cur;
1565 	    goto __do_play;
1566 	  }
1567 	  else
1568 	    snprintf(buffer, sizeof(buffer), "file:/%s", p);
1569 	}
1570 	else {
1571 	  snprintf(buffer2, sizeof(buffer2), "/%s", p);
1572 
1573 	  /* file don't exist, add it anyway */
1574 	  if((stat(buffer2, &pstat)) == -1)
1575 	    strlcpy(buffer, mrl, sizeof(buffer));
1576 	  else {
1577 	    if(is_a_dir(buffer2)) {
1578 
1579 	      if(buffer2[strlen(buffer2) - 1] == '/')
1580 		buffer2[strlen(buffer2) - 1] = '\0';
1581 
1582 	      mediamark_collect_from_directory(buffer2);
1583 	      more_than_one = gui->playlist.cur;
1584 	      goto __do_play;
1585 	    }
1586 	    else
1587 	      snprintf(buffer, sizeof(buffer), "file:/%s", buffer2);
1588 	  }
1589 
1590 	}
1591       }
1592       else {
1593 	p = mrl + 5;
1594 	goto __second_stat;
1595       }
1596     }
1597     else
1598       strlcpy(buffer, mrl, sizeof(buffer));
1599 
1600     if(is_a_dir(buffer)) {
1601       if(buffer[strlen(buffer) - 1] == '/')
1602 	buffer[strlen(buffer) - 1] = '\0';
1603 
1604       mediamark_collect_from_directory(buffer);
1605       more_than_one = gui->playlist.cur;
1606     }
1607     else {
1608       char *ident;
1609 
1610       /* If possible, use only base name as identifier to better fit into the display */
1611       if((ident = strrchr(buffer, '/')) && ident[1])
1612 	ident++;
1613       else
1614 	ident = buffer;
1615 
1616       if(mrl_look_like_playlist(buffer)) {
1617 	int cur = gui->playlist.cur;
1618 
1619 	more_than_one = (gui->playlist.cur - 1);
1620 	if(mediamark_concat_mediamarks(buffer))
1621 	  gui->playlist.cur = cur;
1622 	else
1623 	  mediamark_append_entry(buffer, ident, NULL, 0, -1, 0, 0);
1624       }
1625       else
1626 	mediamark_append_entry(buffer, ident, NULL, 0, -1, 0, 0);
1627 
1628     }
1629 
1630   __do_play:
1631 
1632     playlist_update_playlist();
1633 
1634     if(!(gui->playlist.control & PLAYLIST_CONTROL_IGNORE)) {
1635 
1636       if((xine_get_status(gui->stream) == XINE_STATUS_STOP) || gui->logo_mode) {
1637 	if((more_than_one > -2) && ((more_than_one + 1) < gui->playlist.num))
1638 	  gui->playlist.cur = more_than_one + 1;
1639 	else
1640 	  gui->playlist.cur = gui->playlist.num - 1;
1641 
1642         set_mmk(mediamark_get_current_mmk());
1643         mmk_set_update();
1644 	if(gui->smart_mode)
1645           gui_play (NULL, gui);
1646 
1647       }
1648     }
1649 
1650     if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
1651       enable_playback_controls (gui->panel, 1);
1652 
1653     pthread_mutex_unlock(&gui->mmk_mutex);
1654   }
1655 
1656   free(mrl);
1657 }
1658 
gui_direct_nextprev(xitk_widget_t * w,void * data,int value)1659 void gui_direct_nextprev(xitk_widget_t *w, void *data, int value) {
1660   gGui_t *gui = gGui;
1661   int            i, by_chapter;
1662   mediamark_t   *mmk = mediamark_get_current_mmk();
1663 
1664   by_chapter = (gui->skip_by_chapter &&
1665 		(xine_get_stream_info(gui->stream, XINE_STREAM_INFO_HAS_CHAPTERS))) ? 1 : 0;
1666 
1667   if(mmk && mediamark_got_alternate(mmk))
1668     mediamark_unset_got_alternate(mmk);
1669 
1670   if(((intptr_t)data) == GUI_NEXT) {
1671 
1672     osd_hide();
1673 
1674     if(by_chapter) {
1675 
1676       for(i = 0; i < value; i++)
1677         gui_execute_action_id (gui, ACTID_EVENT_NEXT);
1678 
1679     }
1680     else {
1681 
1682       switch(gui->playlist.loop) {
1683 
1684       case PLAYLIST_LOOP_SHUFFLE:
1685       case PLAYLIST_LOOP_SHUF_PLUS:
1686 	gui->ignore_next = 0;
1687         gui_playlist_start_next (gui);
1688 	break;
1689 
1690       case PLAYLIST_LOOP_NO_LOOP:
1691       case PLAYLIST_LOOP_REPEAT:
1692 	if((gui->playlist.cur + value) < gui->playlist.num) {
1693 
1694 	  if(gui->playlist.loop == PLAYLIST_LOOP_NO_LOOP)
1695 	    gui->playlist.cur += (value - 1);
1696 	  else
1697 	    gui->playlist.cur += value;
1698 
1699 	  gui->ignore_next = 0;
1700           gui_playlist_start_next (gui);
1701 	}
1702 	break;
1703 
1704       case PLAYLIST_LOOP_LOOP:
1705 	if((gui->playlist.cur + value) > gui->playlist.num) {
1706 	  int newcur = value - (gui->playlist.num - gui->playlist.cur);
1707 
1708 	  gui->ignore_next = 1;
1709 	  gui->playlist.cur = newcur;
1710 	  gui_set_current_mmk(mediamark_get_current_mmk());
1711 	  if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1712 				     gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1713 	    gui_display_logo();
1714 
1715 	  gui->ignore_next = 0;
1716 	}
1717 	else {
1718 	  gui->playlist.cur += (value - 1);
1719 	  gui->ignore_next = 0;
1720           gui_playlist_start_next (gui);
1721 	}
1722 	break;
1723       }
1724     }
1725   }
1726   else if(((intptr_t)data) == GUI_PREV) {
1727 
1728     osd_hide();
1729 
1730     if(by_chapter) {
1731 
1732       for(i = 0; i < value; i++)
1733         gui_execute_action_id (gui, ACTID_EVENT_PRIOR);
1734 
1735     }
1736     else {
1737 
1738       switch(gui->playlist.loop) {
1739       case PLAYLIST_LOOP_SHUFFLE:
1740       case PLAYLIST_LOOP_SHUF_PLUS:
1741 	gui->ignore_next = 0;
1742         gui_playlist_start_next (gui);
1743 	break;
1744 
1745       case PLAYLIST_LOOP_NO_LOOP:
1746       case PLAYLIST_LOOP_REPEAT:
1747 	if((gui->playlist.cur - value) >= 0) {
1748 
1749 	  gui->ignore_next = 1;
1750 	  gui->playlist.cur -= value;
1751 
1752 	  if((gui->playlist.cur < gui->playlist.num)) {
1753 	    gui_set_current_mmk(mediamark_get_current_mmk());
1754 	    if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1755 				       gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1756 	      gui_display_logo();
1757 
1758 	  }
1759 	  else
1760 	    gui->playlist.cur = 0;
1761 
1762 	  gui->ignore_next = 0;
1763 	}
1764 	break;
1765 
1766       case PLAYLIST_LOOP_LOOP:
1767 	gui->ignore_next = 1;
1768 
1769 	if((gui->playlist.cur - value) >= 0) {
1770 
1771 	  gui->playlist.cur -= value;
1772 
1773 	  if((gui->playlist.cur < gui->playlist.num)) {
1774 	    gui_set_current_mmk(mediamark_get_current_mmk());
1775 	    if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1776 				       gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1777 	      gui_display_logo();
1778 	  }
1779 	  else
1780 	    gui->playlist.cur = 0;
1781 
1782 	}
1783 	else {
1784 	  int newcur = (gui->playlist.cur - value) + gui->playlist.num;
1785 
1786 	  gui->playlist.cur = newcur;
1787 	  gui_set_current_mmk(mediamark_get_current_mmk());
1788 	  if(!gui_xine_open_and_play(gui->mmk.mrl, gui->mmk.sub, 0,
1789 				     gui->mmk.start, gui->mmk.av_offset, gui->mmk.spu_offset, 1))
1790 	    gui_display_logo();
1791 	}
1792 
1793 	gui->ignore_next = 0;
1794 	break;
1795       }
1796     }
1797   }
1798 
1799   panel_check_pause (gui->panel);
1800 }
1801 
gui_nextprev(xitk_widget_t * w,void * data)1802 void gui_nextprev(xitk_widget_t *w, void *data) {
1803   gui_direct_nextprev(w, data, 1);
1804 }
1805 
gui_playlist_show(xitk_widget_t * w,void * data)1806 void gui_playlist_show(xitk_widget_t *w, void *data) {
1807   gGui_t *gui = gGui;
1808 
1809   if(!playlist_is_running()) {
1810     playlist_editor();
1811   }
1812   else {
1813     if(playlist_is_visible())
1814       if(gui->use_root_window)
1815 	playlist_toggle_visibility(NULL, NULL);
1816       else
1817 	playlist_exit(NULL, NULL);
1818     else
1819       playlist_toggle_visibility(NULL, NULL);
1820   }
1821 
1822 }
1823 
gui_mrlbrowser_show(xitk_widget_t * w,void * data)1824 void gui_mrlbrowser_show(xitk_widget_t *w, void *data) {
1825   gGui_t *gui = gGui;
1826 
1827   gui->nongui_error_msg = NULL;
1828 
1829   if (!mrl_browser_is_running (gui->mrlb)) {
1830     open_mrlbrowser (NULL, gui);
1831   }
1832   else {
1833 
1834     if (!mrl_browser_is_visible (gui->mrlb)) {
1835       show_mrl_browser (gui->mrlb);
1836       if(!gui->use_root_window)
1837         set_mrl_browser_transient (gui->mrlb);
1838     }
1839     else {
1840       if(gui->use_root_window)
1841         show_mrl_browser (gui->mrlb);
1842       else
1843         destroy_mrl_browser (gui->mrlb);
1844     }
1845 
1846   }
1847 
1848 }
1849 
gui_set_current_mmk(mediamark_t * mmk)1850 void gui_set_current_mmk(mediamark_t *mmk) {
1851   gGui_t *gui = gGui;
1852 
1853   pthread_mutex_lock(&gui->mmk_mutex);
1854   set_mmk(mmk);
1855   pthread_mutex_unlock(&gui->mmk_mutex);
1856 
1857   mmk_set_update();
1858 }
1859 
gui_set_current_mmk_by_index(int idx)1860 void gui_set_current_mmk_by_index(int idx) {
1861   gGui_t *gui = gGui;
1862 
1863   pthread_mutex_lock(&gui->mmk_mutex);
1864   set_mmk(mediamark_get_mmk_by_index(idx));
1865   gui->playlist.cur = idx;
1866   pthread_mutex_unlock(&gui->mmk_mutex);
1867 
1868   mmk_set_update();
1869 }
1870 
gui_control_show(xitk_widget_t * w,void * data)1871 void gui_control_show(xitk_widget_t *w, void *data) {
1872   gGui_t *gui = gGui;
1873 
1874   control_toggle_window (w, gui->vctrl);
1875 }
1876 
gui_setup_show(xitk_widget_t * w,void * data)1877 void gui_setup_show(xitk_widget_t *w, void *data) {
1878   gGui_t *gui = gGui;
1879 
1880   if (setup_is_running (gui->setup) && !setup_is_visible (gui->setup))
1881     setup_toggle_visibility (NULL, gui->setup);
1882   else if (!setup_is_running (gui->setup))
1883     setup_panel (gui);
1884   else {
1885     if(gui->use_root_window)
1886       setup_toggle_visibility (NULL, gui->setup);
1887     else
1888       setup_end (gui->setup);
1889   }
1890 }
1891 
gui_event_sender_show(xitk_widget_t * w,void * data)1892 void gui_event_sender_show(xitk_widget_t *w, void *data) {
1893   gGui_t *gui = gGui;
1894 
1895   if (event_sender_is_running() && !event_sender_is_visible())
1896     event_sender_toggle_visibility(NULL, NULL);
1897   else if(!event_sender_is_running())
1898     event_sender_panel();
1899   else {
1900     if(gui->use_root_window)
1901       event_sender_toggle_visibility(NULL, NULL);
1902     else
1903       event_sender_end();
1904   }
1905 }
1906 
gui_stream_infos_show(xitk_widget_t * w,void * data)1907 void gui_stream_infos_show(xitk_widget_t *w, void *data) {
1908   gGui_t *gui = gGui;
1909 
1910   if (stream_infos_is_running() && !stream_infos_is_visible())
1911     stream_infos_toggle_visibility(NULL, NULL);
1912   else if(!stream_infos_is_running())
1913     stream_infos_panel();
1914   else {
1915     if(gui->use_root_window)
1916       stream_infos_toggle_visibility(NULL, NULL);
1917     else
1918       stream_infos_end();
1919   }
1920 }
1921 
gui_tvset_show(xitk_widget_t * w,void * data)1922 void gui_tvset_show(xitk_widget_t *w, void *data) {
1923   gGui_t *gui = gGui;
1924 
1925   if (tvset_is_running() && !tvset_is_visible())
1926     tvset_toggle_visibility(NULL, NULL);
1927   else if(!tvset_is_running())
1928     tvset_panel();
1929   else {
1930     if(gui->use_root_window)
1931       tvset_toggle_visibility(NULL, NULL);
1932     else
1933       tvset_end();
1934   }
1935 }
1936 
gui_vpp_show(xitk_widget_t * w,void * data)1937 void gui_vpp_show(xitk_widget_t *w, void *data) {
1938   gGui_t *gui = gGui;
1939 
1940   if (vpplugin_is_running() && !vpplugin_is_visible())
1941     vpplugin_toggle_visibility(NULL, NULL);
1942   else if(!vpplugin_is_running())
1943     vpplugin_panel();
1944   else {
1945     if(gui->use_root_window)
1946       vpplugin_toggle_visibility(NULL, NULL);
1947     else
1948       vpplugin_end();
1949   }
1950 }
1951 
gui_vpp_enable(void)1952 void gui_vpp_enable(void) {
1953   gGui_t *gui = gGui;
1954 
1955   if(vpplugin_is_post_selected()) {
1956     gui->post_video_enable = !gui->post_video_enable;
1957     osd_display_info(_("Video post plugins: %s."), (gui->post_video_enable) ? _("enabled") : _("disabled"));
1958     vpplugin_update_enable_button();
1959     if(vpplugin_is_visible())
1960       vpplugin_rewire_from_posts_window();
1961     else
1962       vpplugin_rewire_posts();
1963   }
1964 }
1965 
gui_viewlog_show(xitk_widget_t * w,void * data)1966 void gui_viewlog_show(xitk_widget_t *w, void *data) {
1967   gGui_t *gui = gGui;
1968 
1969   if (viewlog_is_running() && !viewlog_is_visible())
1970     viewlog_toggle_visibility(NULL, NULL);
1971   else if(!viewlog_is_running())
1972     viewlog_panel();
1973   else {
1974     if(gui->use_root_window)
1975       viewlog_toggle_visibility(NULL, NULL);
1976     else
1977       viewlog_end();
1978   }
1979 }
1980 
gui_kbedit_show(xitk_widget_t * w,void * data)1981 void gui_kbedit_show(xitk_widget_t *w, void *data) {
1982   gGui_t *gui = gGui;
1983 
1984   if (kbedit_is_running() && !kbedit_is_visible())
1985     kbedit_toggle_visibility(NULL, NULL);
1986   else if(!kbedit_is_running())
1987     kbedit_window();
1988   else {
1989     if(gui->use_root_window)
1990       kbedit_toggle_visibility(NULL, NULL);
1991     else
1992       kbedit_end();
1993   }
1994 }
1995 
gui_help_show(xitk_widget_t * w,void * data)1996 void gui_help_show(xitk_widget_t *w, void *data) {
1997   gGui_t *gui = gGui;
1998 
1999   if (help_is_running() && !help_is_visible())
2000     help_toggle_visibility(NULL, NULL);
2001   else if(!help_is_running())
2002     help_panel();
2003   else {
2004     if(gui->use_root_window)
2005       help_toggle_visibility(NULL, NULL);
2006     else
2007       help_end();
2008   }
2009 }
2010 
2011 /*
2012  * Return 1 if layer should be set
2013  */
is_layer_above(void)2014 int is_layer_above(void) {
2015   gGui_t *gui = gGui;
2016 
2017   return (gui->always_layer_above || gui->layer_above) ? 1 : 0;
2018 }
2019 /*
2020  * set window layer property to something above GNOME (and KDE?) panel
2021  * (reset to normal if do_raise == 0)
2022  */
layer_above_video(Window w)2023 void layer_above_video(Window w) {
2024   int layer = 10;
2025 
2026   if(!(is_layer_above()))
2027     return;
2028 
2029   if ((!(video_window_get_fullscreen_mode (gGui->vwin) & WINDOWED_MODE)) && video_window_is_visible (gGui->vwin)) {
2030     layer = xitk_get_layer_level();
2031   }
2032   else {
2033     if(is_layer_above())
2034       layer = xitk_get_layer_level();
2035     else
2036       layer = 4;
2037   }
2038 
2039   xitk_set_window_layer(w, layer);
2040 }
2041 
change_amp_vol(int value)2042 void change_amp_vol(int value) {
2043   gGui_t *gui = gGui;
2044   if(value < 0)
2045     value = 0;
2046   if(value > 200)
2047     value = 200;
2048   gui->mixer.amp_level = value;
2049   xine_set_param(gui->stream, XINE_PARAM_AUDIO_AMP_LEVEL, gui->mixer.amp_level);
2050   panel_update_mixer_display (gui->panel);
2051   osd_draw_bar(_("Amplification Level"), 0, 200, gui->mixer.amp_level, OSD_BAR_STEPPER);
2052 }
gui_increase_amp_level(void)2053 void gui_increase_amp_level(void) {
2054   gGui_t *gui = gGui;
2055   change_amp_vol((gui->mixer.amp_level + 1));
2056 }
gui_decrease_amp_level(void)2057 void gui_decrease_amp_level(void) {
2058   gGui_t *gui = gGui;
2059   change_amp_vol((gui->mixer.amp_level - 1));
2060 }
gui_reset_amp_level(void)2061 void gui_reset_amp_level(void) {
2062   change_amp_vol(100);
2063 }
2064 
change_audio_vol(int value)2065 void change_audio_vol(int value) {
2066   gGui_t *gui = gGui;
2067   if(value < 0)
2068     value = 0;
2069   if(value > 100)
2070     value = 100;
2071   gui->mixer.volume_level = value;
2072   xine_set_param(gui->stream, XINE_PARAM_AUDIO_VOLUME, gui->mixer.volume_level);
2073   panel_update_mixer_display (gui->panel);
2074   osd_draw_bar(_("Audio Volume"), 0, 100, gui->mixer.volume_level, OSD_BAR_STEPPER);
2075 }
gui_increase_audio_volume(void)2076 void gui_increase_audio_volume(void) {
2077   gGui_t *gui = gGui;
2078   if((gui->mixer.method == SOUND_CARD_MIXER) && (gui->mixer.caps & MIXER_CAP_VOL))
2079     change_audio_vol((gui->mixer.volume_level + 1));
2080   else if(gui->mixer.method == SOFTWARE_MIXER)
2081     gui_increase_amp_level();
2082 }
gui_decrease_audio_volume(void)2083 void gui_decrease_audio_volume(void) {
2084   gGui_t *gui = gGui;
2085   if((gui->mixer.method == SOUND_CARD_MIXER) && (gui->mixer.caps & MIXER_CAP_VOL))
2086     change_audio_vol((gui->mixer.volume_level - 1));
2087   else if(gui->mixer.method == SOFTWARE_MIXER)
2088     gui_decrease_amp_level();
2089 }
2090 
gui_app_show(xitk_widget_t * w,void * data)2091 void gui_app_show(xitk_widget_t *w, void *data) {
2092   gGui_t *gui = gGui;
2093 
2094   if (applugin_is_running() && !applugin_is_visible())
2095     applugin_toggle_visibility(NULL, NULL);
2096   else if(!applugin_is_running())
2097     applugin_panel();
2098   else {
2099     if(gui->use_root_window)
2100       applugin_toggle_visibility(NULL, NULL);
2101     else
2102       applugin_end();
2103   }
2104 }
2105 
gui_app_enable(void)2106 void gui_app_enable(void) {
2107   gGui_t *gui = gGui;
2108 
2109   if(applugin_is_post_selected()) {
2110     gui->post_audio_enable = !gui->post_audio_enable;
2111     osd_display_info(_("Audio post plugins: %s."), (gui->post_audio_enable) ? _("enabled") : _("disabled"));
2112     applugin_update_enable_button();
2113     if(applugin_is_visible())
2114       applugin_rewire_from_posts_window();
2115     else
2116       applugin_rewire_posts();
2117   }
2118 }
2119 
gui_change_zoom(int zoom_dx,int zoom_dy)2120 void gui_change_zoom(int zoom_dx, int zoom_dy) {
2121   gGui_t *gui = gGui;
2122 
2123   xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_X,
2124 		 xine_get_param(gui->stream, XINE_PARAM_VO_ZOOM_X) + zoom_dx);
2125   xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_Y,
2126 		 xine_get_param(gui->stream, XINE_PARAM_VO_ZOOM_Y) + zoom_dy);
2127 
2128   if (panel_is_visible (gui->panel))  {
2129     gui->x_lock_display (gui->display);
2130     XRaiseWindow(gui->display, gui->panel_window);
2131     gui->x_unlock_display (gui->display);
2132     video_window_set_transient_for (gui->vwin, gui->panel_window);
2133   }
2134 }
2135 
2136 /*
2137  * Reset zooming by recall aspect ratio.
2138  */
gui_reset_zoom(void)2139 void gui_reset_zoom(void) {
2140   gGui_t *gui = gGui;
2141 
2142   xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_X, 100);
2143   xine_set_param(gui->stream, XINE_PARAM_VO_ZOOM_Y, 100);
2144 
2145   if (panel_is_visible (gui->panel))  {
2146     gui->x_lock_display (gui->display);
2147     XRaiseWindow(gui->display, gui->panel_window);
2148     gui->x_unlock_display (gui->display);
2149     video_window_set_transient_for (gui->vwin, gui->panel_window);
2150   }
2151 }
2152 
2153 /*
2154  * Toggle TV Modes on the dxr3
2155  */
gui_toggle_tvmode(void)2156 void gui_toggle_tvmode(void) {
2157   gGui_t *gui = gGui;
2158 
2159   xine_set_param(gui->stream, XINE_PARAM_VO_TVMODE,
2160 		 xine_get_param(gui->stream, XINE_PARAM_VO_TVMODE) + 1);
2161 
2162   osd_display_info(_("TV Mode: %d"), xine_get_param(gui->stream, XINE_PARAM_VO_TVMODE));
2163 }
2164 
2165 /*
2166  * Send an Expose event to given window.
2167  */
gui_send_expose_to_window(Window window)2168 void gui_send_expose_to_window(Window window) {
2169   gGui_t *gui = gGui;
2170   XEvent xev;
2171 
2172   if(window == None)
2173     return;
2174 
2175   xev.xany.type          = Expose;
2176   xev.xexpose.type       = Expose;
2177   xev.xexpose.send_event = True;
2178   xev.xexpose.display    = gui->display;
2179   xev.xexpose.window     = window;
2180   xev.xexpose.count      = 0;
2181 
2182   gui->x_lock_display (gui->display);
2183   if(!XSendEvent(gui->display, window, False, ExposureMask, &xev)) {
2184     fprintf(stderr, _("XSendEvent(display, 0x%x ...) failed.\n"), (unsigned int) window);
2185   }
2186   XSync(gui->display, False);
2187   gui->x_unlock_display (gui->display);
2188 
2189 }
2190 
gui_add_mediamark(void)2191 void gui_add_mediamark(void) {
2192   gGui_t *gui = gGui;
2193 
2194   if((gui->logo_mode == 0) && (xine_get_status(gui->stream) == XINE_STATUS_PLAY)) {
2195     int secs;
2196 
2197     if(gui_xine_get_pos_length(gui->stream, NULL, &secs, NULL)) {
2198       secs /= 1000;
2199 
2200       mediamark_append_entry(gui->mmk.mrl, gui->mmk.ident,
2201 			     gui->mmk.sub, secs, -1, gui->mmk.av_offset, gui->mmk.spu_offset);
2202       playlist_update_playlist();
2203     }
2204   }
2205 }
2206 
fileselector_cancel_callback(filebrowser_t * fb)2207 static void fileselector_cancel_callback(filebrowser_t *fb) {
2208   gGui_t *gui = gGui;
2209   char *cur_dir = filebrowser_get_current_dir(fb);
2210 
2211   if (fb == gui->load_stream) {
2212     if(cur_dir && strlen(cur_dir)) {
2213       strlcpy(gui->curdir, cur_dir, sizeof(gui->curdir));
2214       config_update_string("media.files.origin_path", gui->curdir);
2215     }
2216     gui->load_stream = NULL;
2217   }
2218   else if (fb == gui->load_sub)
2219     gui->load_sub = NULL;
2220 
2221   free(cur_dir);
2222 }
2223 
2224 
2225 /* Callback function for file select button or double-click in file browser.
2226    Append selected file to the current playlist */
fileselector_callback(filebrowser_t * fb)2227 static void fileselector_callback(filebrowser_t *fb) {
2228   gGui_t *gui = gGui;
2229   char *file;
2230   char *cur_dir = filebrowser_get_current_dir(fb);
2231 
2232   /* Upate configuration with the selected directory path */
2233   if(cur_dir && strlen(cur_dir)) {
2234     strlcpy(gui->curdir, cur_dir, sizeof(gui->curdir));
2235     config_update_string("media.files.origin_path", gui->curdir);
2236   }
2237   free(cur_dir);
2238 
2239   /* Get the file path/name */
2240   if(((file = filebrowser_get_full_filename(fb)) != NULL) && strlen(file)) {
2241     int first  = gui->playlist.num;
2242     char *ident;
2243 
2244     /* Get the name only to use as an identifier in the playlist display */
2245     ident = filebrowser_get_current_filename(fb);
2246 
2247     /* If the file has an extension which could be a playlist, attempt to append
2248        it to the current list as a list; otherwise, append it as an ordinary file. */
2249     if(mrl_look_like_playlist(file)) {
2250       if(!mediamark_concat_mediamarks(file))
2251         mediamark_append_entry(file, ident, NULL, 0, -1, 0, 0);
2252     }
2253     else
2254       mediamark_append_entry(file, ident, NULL, 0, -1, 0, 0);
2255 
2256     playlist_update_playlist();
2257     free(ident);
2258 
2259     /* Enable controls on display */
2260     if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
2261       enable_playback_controls (gui->panel, 1);
2262 
2263     /* If an MRL is not being played, select the first file appended. If in "smart mode" start
2264        playing the entry.  If a an MRL is currently being played, let it continue normally */
2265     if((first != gui->playlist.num) &&
2266       (gui->logo_mode || (xine_get_status(gui->stream) == XINE_STATUS_STOP))) {
2267       gui->playlist.cur = first;
2268       if(gui->smart_mode) {
2269         gui_set_current_mmk(mediamark_get_current_mmk());
2270         gui_play (NULL, gui);
2271       }
2272     }
2273   } /* If valid file name */
2274 
2275   free(file);
2276   gui->load_stream = NULL;
2277 }
2278 
2279 
2280 /* Callback function for "Select All" button in file browser. Append all files in the
2281    currently selected directory to the current playlist. */
fileselector_all_callback(filebrowser_t * fb)2282 static void fileselector_all_callback(filebrowser_t *fb) {
2283   gGui_t *gui = gGui;
2284   char **files;
2285   char  *path = filebrowser_get_current_dir(fb);
2286 
2287   /* Update the configuration with the current path */
2288   if(path && strlen(path)) {
2289     strlcpy(gui->curdir, path, sizeof(gui->curdir));
2290     config_update_string("media.files.origin_path", gui->curdir);
2291   }
2292 
2293   /* Get all of the file names in the current directory as an array of pointers to strings */
2294   if((files = filebrowser_get_all_files(fb)) != NULL) {
2295     int i = 0;
2296 
2297     if(path && strlen(path)) {
2298       char pathname[XITK_PATH_MAX + 1 + 1]; /* +1 for trailing '/' */
2299       char fullfilename[XITK_PATH_MAX + XITK_NAME_MAX + 2];
2300       int  first = gui->playlist.num; /* current count of entries in playlist */
2301 
2302       /* If the path is anything other than "/", append a slash to it so that it can
2303          be concatenated with the file name */
2304       if(strcasecmp(path, "/"))
2305         snprintf(pathname, sizeof(pathname), "%s/", path);
2306       else
2307 	strlcpy(pathname, path, sizeof(pathname));
2308 
2309       /* For each file, concatenate the path with the name and append it to the playlist */
2310       while(files[i]) {
2311         snprintf(fullfilename, sizeof(fullfilename), "%s%s", pathname, files[i]);
2312 
2313         /* If the file has an extension which could be a playlist, attempt to append
2314            it to the current list as a list; otherwise, append it as an ordinary file. */
2315         if(mrl_look_like_playlist(fullfilename)) {
2316           if(!mediamark_concat_mediamarks(fullfilename))
2317             mediamark_append_entry(fullfilename, files[i], NULL, 0, -1, 0, 0);
2318         }
2319         else
2320           mediamark_append_entry(fullfilename, files[i], NULL, 0, -1, 0, 0);
2321 
2322         i++;
2323       } /* End while */
2324 
2325       playlist_update_playlist();
2326 
2327       /* Enable playback controls on display */
2328       if ((!is_playback_widgets_enabled (gui->panel)) && gui->playlist.num)
2329         enable_playback_controls (gui->panel, 1);
2330 
2331       /* If an MRL is not being played, select the first file appended. If in "smart mode" start
2332          playing the entry.  If an MRL is currently being played, let it continue normally */
2333       if((first != gui->playlist.num) && (xine_get_status(gui->stream) == XINE_STATUS_STOP)) {
2334         gui->playlist.cur = first;
2335         if(gui->smart_mode) {
2336           gui_set_current_mmk(mediamark_get_current_mmk());
2337           gui_play (NULL, gui);
2338         }
2339       }
2340     } /* If valid path */
2341 
2342     i = 0;
2343     while(files[i])
2344       free(files[i++]);
2345 
2346     free(files);
2347   } /* If valid file list */
2348 
2349   free(path);
2350 
2351   gui->load_stream = NULL;
2352 }
2353 
2354 
gui_file_selector(void)2355 void gui_file_selector(void) {
2356   gGui_t *gui = gGui;
2357   filebrowser_callback_button_t  cbb[3];
2358 
2359   gui->nongui_error_msg = NULL;
2360 
2361   if (gui->load_stream)
2362     filebrowser_raise_window (gui->load_stream);
2363   else {
2364     cbb[0].label = _("Select");
2365     cbb[0].callback = fileselector_callback;
2366     cbb[0].need_a_file = 0;
2367     cbb[1].label = _("Select all");
2368     cbb[1].callback = fileselector_all_callback;
2369     cbb[1].need_a_file = 0;
2370     cbb[2].callback = fileselector_cancel_callback;
2371     cbb[2].need_a_file = 0;
2372     gui->load_stream = create_filebrowser(_("Stream(s) Loading"), gui->curdir, hidden_file_cb, &cbb[0], &cbb[1], &cbb[2]);
2373   }
2374 }
2375 
subselector_callback(filebrowser_t * fb)2376 static void subselector_callback(filebrowser_t *fb) {
2377   gGui_t *gui = gGui;
2378   char *file;
2379   int ret;
2380 
2381   if((file = filebrowser_get_full_filename(fb)) != NULL) {
2382     if(file) {
2383       mediamark_t *mmk = mediamark_clone_mmk(mediamark_get_current_mmk());
2384 
2385       if(mmk) {
2386 	mediamark_replace_entry(&gui->playlist.mmk[gui->playlist.cur], mmk->mrl, mmk->ident,
2387 				file, mmk->start, mmk->end, mmk->av_offset, mmk->spu_offset);
2388 	mediamark_free_mmk(&mmk);
2389 
2390 	mmk = mediamark_get_current_mmk();
2391 	gui_set_current_mmk(mmk);
2392 
2393 	playlist_mrlident_toggle();
2394 
2395 	if(xine_get_status(gui->stream) == XINE_STATUS_PLAY) {
2396 	  int curpos;
2397 	  xine_close (gui->spu_stream);
2398 
2399 	  gui_messages_off (gui);
2400 	  ret = xine_open(gui->spu_stream, mmk->sub);
2401 	  gui_messages_on (gui);
2402 	  if (ret)
2403 	    xine_stream_master_slave(gui->stream,
2404 				     gui->spu_stream, XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP);
2405 
2406 	  if(gui_xine_get_pos_length(gui->stream, &curpos, NULL, NULL)) {
2407 	    xine_stop(gui->stream);
2408 	    gui_set_current_position(curpos);
2409 	  }
2410 	}
2411       }
2412     }
2413     free(file);
2414   }
2415 
2416   gui->load_sub = NULL;
2417 }
2418 
gui_select_sub(void)2419 void gui_select_sub(void) {
2420   gGui_t *gui = gGui;
2421 
2422   if(gui->playlist.num) {
2423     if (gui->load_sub)
2424       filebrowser_raise_window (gui->load_sub);
2425     else {
2426       filebrowser_callback_button_t  cbb[2];
2427       mediamark_t *mmk;
2428 
2429       mmk = mediamark_get_current_mmk();
2430 
2431       if(mmk) {
2432 	char *path, *open_path;
2433 
2434 	cbb[0].label = _("Select");
2435 	cbb[0].callback = subselector_callback;
2436 	cbb[0].need_a_file = 1;
2437 	cbb[1].callback = fileselector_cancel_callback;
2438 	cbb[1].need_a_file = 0;
2439 
2440 	path = mmk->sub ? mmk->sub : mmk->mrl;
2441 
2442 	if(mrl_look_like_file(path)) {
2443 	  char *p;
2444 
2445 	  open_path = strdup(path);
2446 
2447 	  if(!strncasecmp(path, "file:", 5))
2448 	    path += 5;
2449 
2450 	  p = strrchr(open_path, '/');
2451 	  if (p && strlen(p))
2452 	    *p = '\0';
2453 	}
2454 	else
2455 	  open_path = strdup(gui->curdir);
2456 
2457         gui->load_sub = create_filebrowser(_("Pick a subtitle file"), open_path, hidden_file_cb, &cbb[0], NULL, &cbb[1]);
2458 	free(open_path);
2459       }
2460     }
2461   }
2462 }
2463 
2464 /*
2465  *
2466  */
visual_anim_init(void)2467 void visual_anim_init(void) {
2468   gGui_t *gui = gGui;
2469   char *buffer;
2470 
2471   buffer = xitk_asprintf("%s/%s", XINE_VISDIR, "default.mpv");
2472 
2473   gui->visual_anim.mrls = (char **) malloc(sizeof(char *) * 3);
2474   gui->visual_anim.num_mrls = 0;
2475 
2476   if (buffer) {
2477     gui->visual_anim.mrls[gui->visual_anim.num_mrls++]   = buffer;
2478     gui->visual_anim.mrls[gui->visual_anim.num_mrls]     = NULL;
2479     gui->visual_anim.mrls[gui->visual_anim.num_mrls + 1] = NULL;
2480   }
2481 }
visual_anim_done(void)2482 void visual_anim_done(void) {
2483   gGui_t *gui = gGui;
2484   int i;
2485 
2486   for (i = 0; i < gui->visual_anim.num_mrls; i++) free(gui->visual_anim.mrls[i]);
2487   free(gui->visual_anim.mrls);
2488 }
visual_anim_add_animation(char * mrl)2489 void visual_anim_add_animation(char *mrl) {
2490   gGui_t *gui = gGui;
2491   gui->visual_anim.mrls = (char **) realloc(gui->visual_anim.mrls, sizeof(char *) *
2492 					     ((gui->visual_anim.num_mrls + 1) + 2));
2493 
2494   gui->visual_anim.mrls[gui->visual_anim.num_mrls++]   = strdup(mrl);
2495   gui->visual_anim.mrls[gui->visual_anim.num_mrls]     = NULL;
2496   gui->visual_anim.mrls[gui->visual_anim.num_mrls + 1] = NULL;
2497 }
visual_anim_open_and_play(xine_stream_t * stream,const char * mrl)2498 static int visual_anim_open_and_play(xine_stream_t *stream, const char *mrl) {
2499   if((!xine_open(stream, mrl)) || (!xine_play(stream, 0, 0)))
2500     return 0;
2501 
2502   return 1;
2503 }
visual_anim_play(void)2504 void visual_anim_play(void) {
2505   gGui_t *gui = gGui;
2506   if(gui->visual_anim.enabled == 2) {
2507     if(!visual_anim_open_and_play(gui->visual_anim.stream,
2508 				  gui->visual_anim.mrls[gui->visual_anim.current]))
2509       gui_handle_xine_error(gui->visual_anim.stream,
2510 			    gui->visual_anim.mrls[gui->visual_anim.current]);
2511     gui->visual_anim.running = 1;
2512   }
2513 }
visual_anim_play_next(void)2514 void visual_anim_play_next(void) {
2515   gGui_t *gui = gGui;
2516   if(gui->visual_anim.enabled == 2) {
2517     gui->visual_anim.current++;
2518     if(gui->visual_anim.mrls[gui->visual_anim.current] == NULL)
2519       gui->visual_anim.current = 0;
2520     visual_anim_play();
2521   }
2522 }
visual_anim_stop(void)2523 void visual_anim_stop(void) {
2524   gGui_t *gui = gGui;
2525   if(gui->visual_anim.enabled == 2) {
2526     xine_stop(gui->visual_anim.stream);
2527     gui->visual_anim.running = 0;
2528   }
2529 }
2530 
2531