|
1 /* GStreamer |
|
2 * Copyright (C) <2003> David A. Schleef <ds@schleef.org> |
|
3 * |
|
4 * This library is free software; you can redistribute it and/or |
|
5 * modify it under the terms of the GNU Library General Public |
|
6 * License as published by the Free Software Foundation; either |
|
7 * version 2 of the License, or (at your option) any later version. |
|
8 * |
|
9 * This library is distributed in the hope that it will be useful, |
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 * Library General Public License for more details. |
|
13 * |
|
14 * You should have received a copy of the GNU Library General Public |
|
15 * License along with this library; if not, write to the |
|
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|
17 * Boston, MA 02111-1307, USA. |
|
18 */ |
|
19 |
|
20 /** |
|
21 * SECTION:gsterror |
|
22 * @short_description: Categorized error messages |
|
23 * @see_also: #GstMessage |
|
24 * |
|
25 * GStreamer elements can throw non-fatal warnings and fatal errors. |
|
26 * Higher-level elements and applications can programatically filter |
|
27 * the ones they are interested in or can recover from, |
|
28 * and have a default handler handle the rest of them. |
|
29 * |
|
30 * The rest of this section will use the term <quote>error</quote> |
|
31 * to mean both (non-fatal) warnings and (fatal) errors; they are treated |
|
32 * similarly. |
|
33 * |
|
34 * Errors from elements are the combination of a #GError and a debug string. |
|
35 * The #GError contains: |
|
36 * - a domain type: CORE, LIBRARY, RESOURCE or STREAM |
|
37 * - a code: an enum value specific to the domain |
|
38 * - a translated, human-readable message |
|
39 * - a non-translated additional debug string, which also contains |
|
40 * - file and line information |
|
41 * |
|
42 * Elements do not have the context required to decide what to do with |
|
43 * errors. As such, they should only inform about errors, and stop their |
|
44 * processing. In short, an element doesn't know what it is being used for. |
|
45 * |
|
46 * It is the application or compound element using the given element that |
|
47 * has more context about the use of the element. Errors can be received by |
|
48 * listening to the #GstBus of the element/pipeline for #GstMessage objects with |
|
49 * the type %GST_MESSAGE_ERROR or %GST_MESSAGE_WARNING. The thrown errors should |
|
50 * be inspected, and filtered if appropriate. |
|
51 * |
|
52 * An application is expected to, by default, present the user with a |
|
53 * dialog box (or an equivalent) showing the error message. The dialog |
|
54 * should also allow a way to get at the additional debug information, |
|
55 * so the user can provide bug reporting information. |
|
56 * |
|
57 * A compound element is expected to forward errors by default higher up |
|
58 * the hierarchy; this is done by default in the same way as for other types |
|
59 * of #GstMessage. |
|
60 * |
|
61 * When applications or compound elements trigger errors that they can |
|
62 * recover from, they can filter out these errors and take appropriate action. |
|
63 * For example, an application that gets an error from xvimagesink |
|
64 * that indicates all XVideo ports are taken, the application can attempt |
|
65 * to use another sink instead. |
|
66 * |
|
67 * Elements throw errors using the #GST_ELEMENT_ERROR convenience macro: |
|
68 * |
|
69 * <example> |
|
70 * <title>Throwing an error</title> |
|
71 * <programlisting> |
|
72 * GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, |
|
73 * (_("No file name specified for reading.")), (NULL)); |
|
74 * </programlisting> |
|
75 * </example> |
|
76 * |
|
77 * Things to keep in mind: |
|
78 * <itemizedlist> |
|
79 * <listitem><para>Don't go off inventing new error codes. The ones |
|
80 * currently provided should be enough. If you find your type of error |
|
81 * does not fit the current codes, you should use FAILED.</para></listitem> |
|
82 * <listitem><para>Don't provide a message if the default one suffices. |
|
83 * this keeps messages more uniform. Use (NULL) - not forgetting the |
|
84 * parentheses.</para></listitem> |
|
85 * <listitem><para>If you do supply a custom message, it should be |
|
86 * marked for translation. The message should start with a capital |
|
87 * and end with a period. The message should describe the error in short, |
|
88 * in a human-readable form, and without any complex technical terms. |
|
89 * A user interface will present this message as the first thing a user |
|
90 * sees. Details, technical info, ... should go in the debug string. |
|
91 * </para></listitem> |
|
92 * <listitem><para>The debug string can be as you like. Again, use (NULL) |
|
93 * if there's nothing to add - file and line number will still be |
|
94 * passed. #GST_ERROR_SYSTEM can be used as a shortcut to give |
|
95 * debug information on a system call error.</para></listitem> |
|
96 * </itemizedlist> |
|
97 * |
|
98 * Last reviewed on 2006-09-15 (0.10.10) |
|
99 */ |
|
100 |
|
101 #ifdef HAVE_CONFIG_H |
|
102 #include "config.h" |
|
103 #endif |
|
104 |
|
105 #include "gst_private.h" |
|
106 #include <gst/gst.h> |
|
107 #include "gst-i18n-lib.h" |
|
108 |
|
109 #define TABLE(t, d, a, b) t[GST_ ## d ## _ERROR_ ## a] = g_strdup (b) |
|
110 #define QUARK_FUNC(string) \ |
|
111 __declspec(dllexport) GQuark gst_ ## string ## _error_quark (void) { \ |
|
112 static GQuark quark; \ |
|
113 if (!quark) \ |
|
114 quark = g_quark_from_static_string ("gst-" # string "-error-quark"); \ |
|
115 return quark; } |
|
116 #ifdef __SYMBIAN32__ |
|
117 EXPORT_C |
|
118 #endif |
|
119 |
|
120 |
|
121 GType |
|
122 gst_g_error_get_type (void) |
|
123 { |
|
124 static GType type = 0; |
|
125 |
|
126 if (G_UNLIKELY (type == 0)) |
|
127 type = g_boxed_type_register_static ("GstGError", |
|
128 (GBoxedCopyFunc) g_error_copy, (GBoxedFreeFunc) g_error_free); |
|
129 return type; |
|
130 } |
|
131 |
|
132 #define FILE_A_BUG " Please file a bug at " PACKAGE_BUGREPORT "." |
|
133 |
|
134 /* initialize the dynamic table of translated core errors */ |
|
135 static gchar ** |
|
136 _gst_core_errors_init (void) |
|
137 { |
|
138 gchar **t = NULL; |
|
139 |
|
140 t = g_new0 (gchar *, GST_CORE_ERROR_NUM_ERRORS); |
|
141 |
|
142 TABLE (t, CORE, FAILED, |
|
143 N_("GStreamer encountered a general core library error.")); |
|
144 TABLE (t, CORE, TOO_LAZY, |
|
145 N_("GStreamer developers were too lazy to assign an error code " |
|
146 "to this error." FILE_A_BUG)); |
|
147 TABLE (t, CORE, NOT_IMPLEMENTED, |
|
148 N_("Internal GStreamer error: code not implemented." FILE_A_BUG)); |
|
149 TABLE (t, CORE, STATE_CHANGE, |
|
150 N_("Internal GStreamer error: state change failed." FILE_A_BUG)); |
|
151 TABLE (t, CORE, PAD, N_("Internal GStreamer error: pad problem." FILE_A_BUG)); |
|
152 TABLE (t, CORE, THREAD, |
|
153 N_("Internal GStreamer error: thread problem." FILE_A_BUG)); |
|
154 TABLE (t, CORE, NEGOTIATION, |
|
155 N_("Internal GStreamer error: negotiation problem." FILE_A_BUG)); |
|
156 TABLE (t, CORE, EVENT, |
|
157 N_("Internal GStreamer error: event problem." FILE_A_BUG)); |
|
158 TABLE (t, CORE, SEEK, |
|
159 N_("Internal GStreamer error: seek problem." FILE_A_BUG)); |
|
160 TABLE (t, CORE, CAPS, |
|
161 N_("Internal GStreamer error: caps problem." FILE_A_BUG)); |
|
162 TABLE (t, CORE, TAG, N_("Internal GStreamer error: tag problem." FILE_A_BUG)); |
|
163 TABLE (t, CORE, MISSING_PLUGIN, |
|
164 N_("Your GStreamer installation is missing a plug-in.")); |
|
165 TABLE (t, CORE, CLOCK, |
|
166 N_("Internal GStreamer error: clock problem." FILE_A_BUG)); |
|
167 TABLE (t, CORE, DISABLED, |
|
168 N_("This application is trying to use GStreamer functionality that " |
|
169 "has been disabled.")); |
|
170 |
|
171 return t; |
|
172 } |
|
173 |
|
174 /* initialize the dynamic table of translated library errors */ |
|
175 static gchar ** |
|
176 _gst_library_errors_init (void) |
|
177 { |
|
178 gchar **t = NULL; |
|
179 |
|
180 t = g_new0 (gchar *, GST_LIBRARY_ERROR_NUM_ERRORS); |
|
181 |
|
182 TABLE (t, LIBRARY, FAILED, |
|
183 N_("GStreamer encountered a general supporting library error.")); |
|
184 TABLE (t, LIBRARY, TOO_LAZY, |
|
185 N_("GStreamer developers were too lazy to assign an error code " |
|
186 "to this error." FILE_A_BUG)); |
|
187 TABLE (t, LIBRARY, INIT, N_("Could not initialize supporting library.")); |
|
188 TABLE (t, LIBRARY, SHUTDOWN, N_("Could not close supporting library.")); |
|
189 TABLE (t, LIBRARY, SETTINGS, N_("Could not configure supporting library.")); |
|
190 |
|
191 return t; |
|
192 } |
|
193 |
|
194 /* initialize the dynamic table of translated resource errors */ |
|
195 static gchar ** |
|
196 _gst_resource_errors_init (void) |
|
197 { |
|
198 gchar **t = NULL; |
|
199 |
|
200 t = g_new0 (gchar *, GST_RESOURCE_ERROR_NUM_ERRORS); |
|
201 |
|
202 TABLE (t, RESOURCE, FAILED, |
|
203 N_("GStreamer encountered a general resource error.")); |
|
204 TABLE (t, RESOURCE, TOO_LAZY, |
|
205 N_("GStreamer developers were too lazy to assign an error code " |
|
206 "to this error." FILE_A_BUG)); |
|
207 TABLE (t, RESOURCE, NOT_FOUND, N_("Resource not found.")); |
|
208 TABLE (t, RESOURCE, BUSY, N_("Resource busy or not available.")); |
|
209 TABLE (t, RESOURCE, OPEN_READ, N_("Could not open resource for reading.")); |
|
210 TABLE (t, RESOURCE, OPEN_WRITE, N_("Could not open resource for writing.")); |
|
211 TABLE (t, RESOURCE, OPEN_READ_WRITE, |
|
212 N_("Could not open resource for reading and writing.")); |
|
213 TABLE (t, RESOURCE, CLOSE, N_("Could not close resource.")); |
|
214 TABLE (t, RESOURCE, READ, N_("Could not read from resource.")); |
|
215 TABLE (t, RESOURCE, WRITE, N_("Could not write to resource.")); |
|
216 TABLE (t, RESOURCE, SEEK, N_("Could not perform seek on resource.")); |
|
217 TABLE (t, RESOURCE, SYNC, N_("Could not synchronize on resource.")); |
|
218 TABLE (t, RESOURCE, SETTINGS, |
|
219 N_("Could not get/set settings from/on resource.")); |
|
220 TABLE (t, RESOURCE, NO_SPACE_LEFT, N_("No space left on the resource.")); |
|
221 |
|
222 return t; |
|
223 } |
|
224 |
|
225 /* initialize the dynamic table of translated stream errors */ |
|
226 static gchar ** |
|
227 _gst_stream_errors_init (void) |
|
228 { |
|
229 gchar **t = NULL; |
|
230 |
|
231 t = g_new0 (gchar *, GST_STREAM_ERROR_NUM_ERRORS); |
|
232 |
|
233 TABLE (t, STREAM, FAILED, |
|
234 N_("GStreamer encountered a general stream error.")); |
|
235 TABLE (t, STREAM, TOO_LAZY, |
|
236 N_("GStreamer developers were too lazy to assign an error code " |
|
237 "to this error." FILE_A_BUG)); |
|
238 TABLE (t, STREAM, NOT_IMPLEMENTED, |
|
239 N_("Element doesn't implement handling of this stream. " |
|
240 "Please file a bug.")); |
|
241 TABLE (t, STREAM, TYPE_NOT_FOUND, N_("Could not determine type of stream.")); |
|
242 TABLE (t, STREAM, WRONG_TYPE, |
|
243 N_("The stream is of a different type than handled by this element.")); |
|
244 TABLE (t, STREAM, CODEC_NOT_FOUND, |
|
245 N_("There is no codec present that can handle the stream's type.")); |
|
246 TABLE (t, STREAM, DECODE, N_("Could not decode stream.")); |
|
247 TABLE (t, STREAM, ENCODE, N_("Could not encode stream.")); |
|
248 TABLE (t, STREAM, DEMUX, N_("Could not demultiplex stream.")); |
|
249 TABLE (t, STREAM, MUX, N_("Could not multiplex stream.")); |
|
250 TABLE (t, STREAM, FORMAT, N_("The stream is in the wrong format.")); |
|
251 |
|
252 return t; |
|
253 } |
|
254 |
|
255 QUARK_FUNC (core); |
|
256 QUARK_FUNC (library); |
|
257 QUARK_FUNC (resource); |
|
258 QUARK_FUNC (stream); |
|
259 |
|
260 /** |
|
261 * gst_error_get_message: |
|
262 * @domain: the GStreamer error domain this error belongs to. |
|
263 * @code: the error code belonging to the domain. |
|
264 * |
|
265 * Get a string describing the error message in the current locale. |
|
266 * |
|
267 * Returns: a newly allocated string describing the error message in the |
|
268 * current locale. |
|
269 */ |
|
270 #ifdef __SYMBIAN32__ |
|
271 EXPORT_C |
|
272 #endif |
|
273 |
|
274 gchar * |
|
275 gst_error_get_message (GQuark domain, gint code) |
|
276 { |
|
277 static gchar **gst_core_errors = NULL; |
|
278 static gchar **gst_library_errors = NULL; |
|
279 static gchar **gst_resource_errors = NULL; |
|
280 static gchar **gst_stream_errors = NULL; |
|
281 |
|
282 gchar *message = NULL; |
|
283 |
|
284 /* initialize error message tables if necessary */ |
|
285 if (gst_core_errors == NULL) |
|
286 gst_core_errors = _gst_core_errors_init (); |
|
287 if (gst_library_errors == NULL) |
|
288 gst_library_errors = _gst_library_errors_init (); |
|
289 if (gst_resource_errors == NULL) |
|
290 gst_resource_errors = _gst_resource_errors_init (); |
|
291 if (gst_stream_errors == NULL) |
|
292 gst_stream_errors = _gst_stream_errors_init (); |
|
293 |
|
294 |
|
295 if (domain == GST_CORE_ERROR) |
|
296 message = gst_core_errors[code]; |
|
297 else if (domain == GST_LIBRARY_ERROR) |
|
298 message = gst_library_errors[code]; |
|
299 else if (domain == GST_RESOURCE_ERROR) |
|
300 message = gst_resource_errors[code]; |
|
301 else if (domain == GST_STREAM_ERROR) |
|
302 message = gst_stream_errors[code]; |
|
303 else { |
|
304 g_warning ("No error messages for domain %s", g_quark_to_string (domain)); |
|
305 return g_strdup_printf (_("No error message for domain %s."), |
|
306 g_quark_to_string (domain)); |
|
307 } |
|
308 if (message) |
|
309 return g_strdup (_(message)); |
|
310 else |
|
311 return |
|
312 g_strdup_printf (_ |
|
313 ("No standard error message for domain %s and code %d."), |
|
314 g_quark_to_string (domain), code); |
|
315 } |