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 engine error handling/notification
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <stdio.h>
28 #include <stdarg.h>
29 
30 #include <X11/Xlib.h>
31 #include <X11/Xutil.h>
32 #include <X11/keysym.h>
33 
34 #include "common.h"
35 
36 
37 /*
38  * Callback used to display the viewlog window.
39  */
_errors_display_log(xitk_widget_t * w,void * data,int state)40 static void _errors_display_log(xitk_widget_t *w, void *data, int state) {
41 
42   if(viewlog_is_visible())
43     viewlog_raise_window();
44   else
45     viewlog_panel();
46 }
47 
48 /*
49  * Create the real window.
50  */
errors_create_window(char * title,char * message)51 static void errors_create_window(char *title, char *message) {
52   xitk_window_t *xw;
53 
54   if((title == NULL) || (message == NULL))
55     return;
56 
57   dump_error(message);
58 
59   if( gGui->nongui_error_msg ) {
60     gGui->nongui_error_msg( message );
61     return;
62   }
63 
64   xw = xitk_window_dialog_two_buttons_with_width(gGui->imlib_data, title,
65 						 _("Done"), _("More..."),
66 						 NULL, _errors_display_log,
67 						 NULL, 400, ALIGN_CENTER,
68 						 "%s", message);
69 
70   xitk_window_set_parent_window(xw, gGui->video_window);
71 
72   if(!gGui->use_root_window && gGui->video_display == gGui->display) {
73     gGui->x_lock_display (gGui->display);
74     XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
75     gGui->x_unlock_display (gGui->display);
76   }
77 
78   layer_above_video(xitk_window_get_window(xw));
79 }
80 
81 /*
82  * Display an error window.
83  */
xine_error(const char * message,...)84 void xine_error(const char *message, ...) {
85   va_list   args;
86   char     *buf;
87 
88   va_start(args, message);
89   buf = xitk_vasprintf(message, args);
90   va_end(args);
91 
92   if (!buf)
93     return;
94 
95   if(gGui->stdctl_enable || !gGui->display) {
96     printf("%s\n", buf);
97   }
98   else {
99     dump_error(buf);
100 
101     if( gGui->nongui_error_msg ) {
102       gGui->nongui_error_msg( buf );
103     } else {
104       xitk_window_t *xw;
105 
106       xw = xitk_window_dialog_error(gGui->imlib_data, "%s", buf);
107 
108       if(!gGui->use_root_window && gGui->video_display == gGui->display) {
109         gGui->x_lock_display (gGui->display);
110         XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
111         gGui->x_unlock_display (gGui->display);
112       }
113       layer_above_video(xitk_window_get_window(xw));
114     }
115   }
116 
117   free(buf);
118 }
119 
120 /*
121  * Display an error window, with more button.
122  */
xine_error_with_more(const char * message,...)123 void xine_error_with_more(const char *message, ...) {
124   va_list   args;
125   char     *buf;
126 
127   va_start(args, message);
128   buf = xitk_vasprintf(message, args);
129   va_end(args);
130 
131   if (!buf)
132     return;
133 
134   dump_error(buf);
135 
136   if(gGui->stdctl_enable) {
137     printf("%s\n", buf);
138   }
139   else {
140     errors_create_window(_("Error"), buf);
141   }
142 
143   free(buf);
144 }
145 
146 /*
147  * Display an informative window.
148  */
xine_info(const char * message,...)149 void xine_info(const char *message, ...) {
150   va_list   args;
151   char     *buf;
152 
153   va_start(args, message);
154   buf = xitk_vasprintf(message, args);
155   va_end(args);
156 
157   if (!buf)
158     return;
159 
160   dump_info(buf);
161 
162   if(gGui->stdctl_enable) {
163     printf("%s\n", buf);
164   }
165   else {
166     if( gGui->nongui_error_msg ) {
167       gGui->nongui_error_msg( buf );
168     } else {
169       xitk_window_t *xw;
170 
171       xw = xitk_window_dialog_info(gGui->imlib_data, "%s", buf);
172 
173       if(!gGui->use_root_window && gGui->video_display == gGui->display) {
174         gGui->x_lock_display (gGui->display);
175         XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
176         gGui->x_unlock_display (gGui->display);
177       }
178       layer_above_video(xitk_window_get_window(xw));
179     }
180   }
181 
182   free(buf);
183 }
184 
185 /*
186  * Display an error window error from a xine engine error.
187  */
gui_handle_xine_error(xine_stream_t * stream,const char * mrl)188 void gui_handle_xine_error(xine_stream_t *stream, const char *mrl) {
189   int   err;
190   const char *_mrl = mrl;
191 
192   if(_mrl == NULL)
193     _mrl = (stream == gGui->stream) ? gGui->mmk.mrl : gGui->visual_anim.mrls[gGui->visual_anim.current];
194 
195   err = xine_get_error(stream);
196 
197   switch(err) {
198 
199   case XINE_ERROR_NONE:
200     dump_error("got XINE_ERROR_NONE.");
201     /* noop */
202     break;
203 
204   case XINE_ERROR_NO_INPUT_PLUGIN:
205     dump_error("got XINE_ERROR_NO_INPUT_PLUGIN.");
206     xine_error_with_more(_("- xine engine error -\n\n"
207 			   "There is no input plugin available to handle '%s'.\n"
208 			   "Maybe MRL syntax is wrong or file/stream source doesn't exist."),
209 			 _mrl);
210     break;
211 
212   case XINE_ERROR_NO_DEMUX_PLUGIN:
213     dump_error("got XINE_ERROR_NO_DEMUX_PLUGIN.");
214     xine_error_with_more(_("- xine engine error -\n\nThere is no demuxer plugin available "
215 			   "to handle '%s'.\n"
216 			   "Usually this means that the file format was not recognized."),
217 			 _mrl);
218     break;
219 
220   case XINE_ERROR_DEMUX_FAILED:
221     dump_error("got XINE_ERROR_DEMUX_FAILED.");
222     xine_error_with_more(_("- xine engine error -\n\nDemuxer failed. "
223 			   "Maybe '%s' is a broken file?\n"), _mrl);
224     break;
225 
226   case XINE_ERROR_MALFORMED_MRL:
227     dump_error("got XINE_ERROR_MALFORMED_MRL.");
228     xine_error_with_more(_("- xine engine error -\n\nMalformed mrl. "
229 			   "Mrl '%s' seems malformed/invalid.\n"), _mrl);
230     break;
231 
232   case XINE_ERROR_INPUT_FAILED:
233     dump_error("got XINE_ERROR_INPUT_FAILED.");
234     xine_error_with_more(_("- xine engine error -\n\nInput plugin failed to open "
235 			   "mrl '%s'\n"), _mrl);
236     break;
237 
238   default:
239     dump_error("got unhandle error.");
240     xine_error_with_more(_("- xine engine error -\n\n!! Unhandled error !!\n"));
241     break;
242   }
243 
244   /* gGui->new_pos = -1; */
245 }
246 
247 
_dont_show_too_slow_again(xitk_widget_t * w,void * data,int state)248 static void _dont_show_too_slow_again(xitk_widget_t *w, void *data, int state) {
249   config_update_num ("gui.dropped_frames_warning", !state);
250 }
251 
_learn_more_about_too_slow(xitk_widget_t * w,void * data,int state)252 static void _learn_more_about_too_slow(xitk_widget_t *w, void *data, int state) {
253   /*
254    * fixme: how to properly open the system browser?
255    * should we just make it configurable?
256    */
257   xine_info(_("Opening mozilla web browser, this might take a while..."));
258   system ("mozilla http://www.xine-project.org/faq#SPEEDUP");
259 }
260 
261 /*
262  * Create the real window.
263  */
too_slow_window(void)264 void too_slow_window(void) {
265   xitk_window_t *xw;
266   char *title, *message;
267   int display_warning;
268   int checked = 0;
269 
270   title = _("Warning");
271   message = _("The amount of dropped frame is too high, your system might be slow, not properly optimized or just too loaded.\n\nhttp://www.xine-project.org/faq#SPEEDUP");
272 
273   dump_error(message);
274 
275   display_warning = xine_config_register_bool (__xineui_global_xine_instance, "gui.dropped_frames_warning",
276 		     1,
277 		     _("Warn user when too much frames are dropped."),
278 		     CONFIG_NO_HELP,
279 		     CONFIG_LEVEL_ADV,
280 		     CONFIG_NO_CB,
281 		     CONFIG_NO_DATA);
282 
283   if( !display_warning )
284     return;
285 
286   if( gGui->nongui_error_msg || gGui->stdctl_enable )
287     return;
288 
289   _dont_show_too_slow_again(NULL, NULL, checked);
290 
291   xw = xitk_window_dialog_checkbox_two_buttons_with_width(gGui->imlib_data, title,
292 						 _("Done"), _("Learn More..."),
293 						 NULL, _learn_more_about_too_slow,
294                                                  _("Disable this warning."),
295                                                  checked, _dont_show_too_slow_again,
296 						 NULL, 500, ALIGN_CENTER,
297 						 "%s", message);
298   if(!gGui->use_root_window && gGui->video_display == gGui->display) {
299     gGui->x_lock_display (gGui->display);
300     XSetTransientForHint(gGui->display, xitk_window_get_window(xw), gGui->video_window);
301     gGui->x_unlock_display (gGui->display);
302   }
303   layer_above_video(xitk_window_get_window(xw));
304 }
305