X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst%2Fgsterror.c;h=820b51e0e78e50dcb913179e0e0496aa74a03cc2;hb=ce43de86902c4e9c8ed4e9682602664cb9bce2ee;hp=2b4b2361ca2bbe477bf6fd028632d19d6b32a427;hpb=ca7539c40ea26af548ae6b265149035aae22a38b;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst/gsterror.c b/gst/gsterror.c index 2b4b236..820b51e 100644 --- a/gst/gsterror.c +++ b/gst/gsterror.c @@ -13,10 +13,98 @@ * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. */ +/** + * SECTION:gsterror + * @title: GstError + * @short_description: Categorized error messages + * @see_also: #GstMessage + * + * GStreamer elements can throw non-fatal warnings and fatal errors. + * Higher-level elements and applications can programmatically filter + * the ones they are interested in or can recover from, + * and have a default handler handle the rest of them. + * + * The rest of this section will use the term error + * to mean both (non-fatal) warnings and (fatal) errors; they are treated + * similarly. + * + * Errors from elements are the combination of a #GError and a debug string. + * The #GError contains: + * - a domain type: CORE, LIBRARY, RESOURCE or STREAM + * - a code: an enum value specific to the domain + * - a translated, human-readable message + * - a non-translated additional debug string, which also contains + * - file and line information + * + * Elements do not have the context required to decide what to do with + * errors. As such, they should only inform about errors, and stop their + * processing. In short, an element doesn't know what it is being used for. + * + * It is the application or compound element using the given element that + * has more context about the use of the element. Errors can be received by + * listening to the #GstBus of the element/pipeline for #GstMessage objects with + * the type %GST_MESSAGE_ERROR or %GST_MESSAGE_WARNING. The thrown errors should + * be inspected, and filtered if appropriate. + * + * An application is expected to, by default, present the user with a + * dialog box (or an equivalent) showing the error message. The dialog + * should also allow a way to get at the additional debug information, + * so the user can provide bug reporting information. + * + * A compound element is expected to forward errors by default higher up + * the hierarchy; this is done by default in the same way as for other types + * of #GstMessage. + * + * When applications or compound elements trigger errors that they can + * recover from, they can filter out these errors and take appropriate action. + * For example, an application that gets an error from xvimagesink + * that indicates all XVideo ports are taken, the application can attempt + * to use another sink instead. + * + * Elements throw errors using the #GST_ELEMENT_ERROR convenience macro: + * + * ## Throwing an error + * + * |[ + * GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, + * (_("No file name specified for reading.")), (NULL)); + * ]| + * + * Things to keep in mind: + * + * * Don't go off inventing new error codes. The ones + * currently provided should be enough. If you find your type of error + * does not fit the current codes, you should use FAILED. + * * Don't provide a message if the default one suffices. + * this keeps messages more uniform. Use (%NULL) - not forgetting the + * parentheses. + * * If you do supply a custom message, it should be + * marked for translation. The message should start with a capital + * and end with a period. The message should describe the error in short, + * in a human-readable form, and without any complex technical terms. + * A user interface will present this message as the first thing a user + * sees. Details, technical info, ... should go in the debug string. + * + * * The debug string can be as you like. Again, use (%NULL) + * if there's nothing to add - file and line number will still be + * passed. #GST_ERROR_SYSTEM can be used as a shortcut to give + * debug information on a system call error. + * + */ + +/* FIXME 2.0: the entire error system needs an overhaul - it's not very + * useful the way it is. Also, we need to be able to specify additional + * 'details' for errors (e.g. disk/file/resource error -> out-of-space; or + * put the url/filename/device name that caused the error somewhere) + * without having to add enums for every little thing. + * + * FIXME 2.0: get rid of GST_{CORE,LIBRARY,RESOURCE,STREAM}_ERROR_NUM_ERRORS. + * Maybe also replace _quark() functions with g_quark_from_static_string()? + */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -25,190 +113,200 @@ #include #include "gst-i18n-lib.h" -#define TABLE(t, d, a, b) t[GST_ ## d ## _ERROR_ ## a] = g_strdup (b) -#define QUARK_FUNC(string) \ -GQuark gst_ ## string ## _error_quark (void) { \ - static GQuark quark; \ - if (!quark) \ +#define QUARK_FUNC(string) \ +GQuark gst_ ## string ## _error_quark (void) { \ + static GQuark quark; \ + if (!quark) \ quark = g_quark_from_static_string ("gst-" # string "-error-quark"); \ return quark; } -GType -gst_g_error_get_type (void) -{ - static GType type = 0; - - if (!type) - type = g_boxed_type_register_static ("GstGError", - (GBoxedCopyFunc) g_error_copy, (GBoxedFreeFunc) g_error_free); - return type; -} +#define FILE_A_BUG " Please file a bug at " PACKAGE_BUGREPORT "." -/* initialize the dynamic table of translated core errors */ -static gchar ** -_gst_core_errors_init () +static const gchar * +gst_error_get_core_error (GstCoreError code) { - gchar **t = NULL; - - t = g_new0 (gchar *, GST_CORE_ERROR_NUM_ERRORS); - - TABLE (t, CORE, FAILED, - N_("GStreamer encountered a general core library error.")); - TABLE (t, CORE, TOO_LAZY, - N_("GStreamer developers were too lazy to assign an error code " - "to this error. Please file a bug.")); - TABLE (t, CORE, NOT_IMPLEMENTED, - N_("Internal GStreamer error: code not implemented. File a bug.")); - TABLE (t, CORE, STATE_CHANGE, - N_("Internal GStreamer error: state change failed. File a bug.")); - TABLE (t, CORE, PAD, - N_("Internal GStreamer error: pad problem. File a bug.")); - TABLE (t, CORE, THREAD, - N_("Internal GStreamer error: thread problem. File a bug.")); - TABLE (t, CORE, SCHEDULER, - N_("Internal GStreamer error: scheduler problem. File a bug.")); - TABLE (t, CORE, NEGOTIATION, - N_("Internal GStreamer error: negotiation problem. File a bug.")); - TABLE (t, CORE, EVENT, - N_("Internal GStreamer error: event problem. File a bug.")); - TABLE (t, CORE, SEEK, - N_("Internal GStreamer error: seek problem. File a bug.")); - TABLE (t, CORE, CAPS, - N_("Internal GStreamer error: caps problem. File a bug.")); - TABLE (t, CORE, TAG, - N_("Internal GStreamer error: tag problem. File a bug.")); - - return t; + switch (code) { + case GST_CORE_ERROR_FAILED: + return _("GStreamer encountered a general core library error."); + case GST_CORE_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_CORE_ERROR_NOT_IMPLEMENTED: + return _("Internal GStreamer error: code not implemented." FILE_A_BUG); + case GST_CORE_ERROR_STATE_CHANGE: + return _("GStreamer error: state change failed and some element failed " + "to post a proper error message with the reason for the failure."); + case GST_CORE_ERROR_PAD: + return _("Internal GStreamer error: pad problem." FILE_A_BUG); + case GST_CORE_ERROR_THREAD: + return _("Internal GStreamer error: thread problem." FILE_A_BUG); + case GST_CORE_ERROR_NEGOTIATION: + return _("GStreamer error: negotiation problem."); + case GST_CORE_ERROR_EVENT: + return _("Internal GStreamer error: event problem." FILE_A_BUG); + case GST_CORE_ERROR_SEEK: + return _("Internal GStreamer error: seek problem." FILE_A_BUG); + case GST_CORE_ERROR_CAPS: + return _("Internal GStreamer error: caps problem." FILE_A_BUG); + case GST_CORE_ERROR_TAG: + return _("Internal GStreamer error: tag problem." FILE_A_BUG); + case GST_CORE_ERROR_MISSING_PLUGIN: + return _("Your GStreamer installation is missing a plug-in."); + case GST_CORE_ERROR_CLOCK: + return _("GStreamer error: clock problem."); + case GST_CORE_ERROR_DISABLED: + return _("This application is trying to use GStreamer functionality " + "that has been disabled."); + case GST_CORE_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; } -/* initialize the dynamic table of translated library errors */ -static gchar ** -_gst_library_errors_init () +static const gchar * +gst_error_get_library_error (GstLibraryError code) { - gchar **t = NULL; - - t = g_new0 (gchar *, GST_LIBRARY_ERROR_NUM_ERRORS); - - TABLE (t, LIBRARY, FAILED, - N_("GStreamer encountered a general supporting library error.")); - TABLE (t, LIBRARY, TOO_LAZY, - N_("GStreamer developers were too lazy to assign an error code " - "to this error. Please file a bug.")); - TABLE (t, LIBRARY, INIT, N_("Could not initialize supporting library.")); - TABLE (t, LIBRARY, SHUTDOWN, N_("Could not close supporting library.")); - TABLE (t, LIBRARY, SETTINGS, N_("Could not close supporting library.")); - - return t; + switch (code) { + case GST_LIBRARY_ERROR_FAILED: + return _("GStreamer encountered a general supporting library error."); + case GST_LIBRARY_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_LIBRARY_ERROR_INIT: + return _("Could not initialize supporting library."); + case GST_LIBRARY_ERROR_SHUTDOWN: + return _("Could not close supporting library."); + case GST_LIBRARY_ERROR_SETTINGS: + return _("Could not configure supporting library."); + case GST_LIBRARY_ERROR_ENCODE: + return _("Encoding error."); + case GST_LIBRARY_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; } -/* initialize the dynamic table of translated resource errors */ -static gchar ** -_gst_resource_errors_init () +static const gchar * +gst_error_get_resource_error (GstResourceError code) { - gchar **t = NULL; - - t = g_new0 (gchar *, GST_RESOURCE_ERROR_NUM_ERRORS); - - TABLE (t, RESOURCE, FAILED, - N_("GStreamer encountered a general supporting library error.")); - TABLE (t, RESOURCE, TOO_LAZY, - N_("GStreamer developers were too lazy to assign an error code " - "to this error. Please file a bug.")); - TABLE (t, RESOURCE, NOT_FOUND, N_("Resource not found.")); - TABLE (t, RESOURCE, BUSY, N_("Resource busy or not available.")); - TABLE (t, RESOURCE, OPEN_READ, N_("Could not open resource for reading.")); - TABLE (t, RESOURCE, OPEN_WRITE, N_("Could not open resource for writing.")); - TABLE (t, RESOURCE, OPEN_READ_WRITE, - N_("Could not open resource for reading and writing.")); - TABLE (t, RESOURCE, CLOSE, N_("Could not close resource.")); - TABLE (t, RESOURCE, READ, N_("Could not read from resource.")); - TABLE (t, RESOURCE, WRITE, N_("Could not write to resource.")); - TABLE (t, RESOURCE, SEEK, N_("Could not perform seek on resource.")); - TABLE (t, RESOURCE, SYNC, N_("Could not synchronize on resource.")); - TABLE (t, RESOURCE, SETTINGS, - N_("Could not get/set settings from/on resource.")); - - return t; + switch (code) { + case GST_RESOURCE_ERROR_FAILED: + return _("GStreamer encountered a general resource error."); + case GST_RESOURCE_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_RESOURCE_ERROR_NOT_FOUND: + return _("Resource not found."); + case GST_RESOURCE_ERROR_BUSY: + return _("Resource busy or not available."); + case GST_RESOURCE_ERROR_OPEN_READ: + return _("Could not open resource for reading."); + case GST_RESOURCE_ERROR_OPEN_WRITE: + return _("Could not open resource for writing."); + case GST_RESOURCE_ERROR_OPEN_READ_WRITE: + return _("Could not open resource for reading and writing."); + case GST_RESOURCE_ERROR_CLOSE: + return _("Could not close resource."); + case GST_RESOURCE_ERROR_READ: + return _("Could not read from resource."); + case GST_RESOURCE_ERROR_WRITE: + return _("Could not write to resource."); + case GST_RESOURCE_ERROR_SEEK: + return _("Could not perform seek on resource."); + case GST_RESOURCE_ERROR_SYNC: + return _("Could not synchronize on resource."); + case GST_RESOURCE_ERROR_SETTINGS: + return _("Could not get/set settings from/on resource."); + case GST_RESOURCE_ERROR_NO_SPACE_LEFT: + return _("No space left on the resource."); + case GST_RESOURCE_ERROR_NOT_AUTHORIZED: + return _("Not authorized to access resource."); + case GST_RESOURCE_ERROR_NUM_ERRORS: + default: + break; + } + return NULL; } -/* initialize the dynamic table of translated stream errors */ -static gchar ** -_gst_stream_errors_init () +static const gchar * +gst_error_get_stream_error (GstStreamError code) { - gchar **t = NULL; - - t = g_new0 (gchar *, GST_STREAM_ERROR_NUM_ERRORS); - - TABLE (t, STREAM, FAILED, - N_("GStreamer encountered a general supporting library error.")); - TABLE (t, STREAM, TOO_LAZY, - N_("GStreamer developers were too lazy to assign an error code " - "to this error. Please file a bug.")); - TABLE (t, STREAM, NOT_IMPLEMENTED, - N_("Element doesn't implement handling of this stream. " - "Please file a bug.")); - TABLE (t, STREAM, TYPE_NOT_FOUND, N_("Could not determine type of stream.")); - TABLE (t, STREAM, WRONG_TYPE, - N_("The stream is of a different type than handled by this element.")); - TABLE (t, STREAM, CODEC_NOT_FOUND, - N_("There is no codec present that can handle the stream's type.")); - TABLE (t, STREAM, DECODE, N_("Could not decode stream.")); - TABLE (t, STREAM, ENCODE, N_("Could not encode stream.")); - TABLE (t, STREAM, DEMUX, N_("Could not demultiplex stream.")); - TABLE (t, STREAM, MUX, N_("Could not multiplex stream.")); - TABLE (t, STREAM, FORMAT, N_("Stream is of the wrong format.")); + switch (code) { + case GST_STREAM_ERROR_FAILED: + return _("GStreamer encountered a general stream error."); + case GST_STREAM_ERROR_TOO_LAZY: + return _("GStreamer developers were too lazy to assign an error code " + "to this error." FILE_A_BUG); + case GST_STREAM_ERROR_NOT_IMPLEMENTED: + return _("Element doesn't implement handling of this stream. " + "Please file a bug."); + case GST_STREAM_ERROR_TYPE_NOT_FOUND: + return _("Could not determine type of stream."); + case GST_STREAM_ERROR_WRONG_TYPE: + return _("The stream is of a different type than handled by this " + "element."); + case GST_STREAM_ERROR_CODEC_NOT_FOUND: + return _("There is no codec present that can handle the stream's type."); + case GST_STREAM_ERROR_DECODE: + return _("Could not decode stream."); + case GST_STREAM_ERROR_ENCODE: + return _("Could not encode stream."); + case GST_STREAM_ERROR_DEMUX: + return _("Could not demultiplex stream."); + case GST_STREAM_ERROR_MUX: + return _("Could not multiplex stream."); + case GST_STREAM_ERROR_FORMAT: + return _("The stream is in the wrong format."); + case GST_STREAM_ERROR_DECRYPT: + return _("The stream is encrypted and decryption is not supported."); + case GST_STREAM_ERROR_DECRYPT_NOKEY: + return _("The stream is encrypted and can't be decrypted because no " + "suitable key has been supplied."); + case GST_STREAM_ERROR_NUM_ERRORS: + default: + break; + } - return t; + return NULL; } -QUARK_FUNC (core) - QUARK_FUNC (library) - QUARK_FUNC (resource) - QUARK_FUNC (stream) +QUARK_FUNC (core); +QUARK_FUNC (library); +QUARK_FUNC (resource); +QUARK_FUNC (stream); /** * gst_error_get_message: * @domain: the GStreamer error domain this error belongs to. * @code: the error code belonging to the domain. * - * Returns: a newly allocated string describing the error message in the - * current locale. + * Get a string describing the error message in the current locale. + * + * Returns: (transfer full): a newly allocated string describing + * the error message (in UTF-8 encoding) */ - gchar *gst_error_get_message (GQuark domain, gint code) +gchar * +gst_error_get_message (GQuark domain, gint code) { - static gchar **gst_core_errors = NULL; - static gchar **gst_library_errors = NULL; - static gchar **gst_resource_errors = NULL; - static gchar **gst_stream_errors = NULL; - - gchar *message = NULL; - - /* initialize error message tables if necessary */ - if (gst_core_errors == NULL) - gst_core_errors = _gst_core_errors_init (); - if (gst_library_errors == NULL) - gst_library_errors = _gst_library_errors_init (); - if (gst_resource_errors == NULL) - gst_resource_errors = _gst_resource_errors_init (); - if (gst_stream_errors == NULL) - gst_stream_errors = _gst_stream_errors_init (); - + const gchar *message = NULL; if (domain == GST_CORE_ERROR) - message = gst_core_errors[code]; + message = gst_error_get_core_error ((GstCoreError) code); else if (domain == GST_LIBRARY_ERROR) - message = gst_library_errors[code]; + message = gst_error_get_library_error ((GstLibraryError) code); else if (domain == GST_RESOURCE_ERROR) - message = gst_resource_errors[code]; + message = gst_error_get_resource_error ((GstResourceError) code); else if (domain == GST_STREAM_ERROR) - message = gst_stream_errors[code]; + message = gst_error_get_stream_error ((GstStreamError) code); else { g_warning ("No error messages for domain %s", g_quark_to_string (domain)); return g_strdup_printf (_("No error message for domain %s."), g_quark_to_string (domain)); } if (message) - return g_strdup (_(message)); + return g_strdup (message); else return g_strdup_printf (_