gstreamer_core/gst/gstinfo.c
changeset 0 0e761a78d257
child 7 567bb019e3e3
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *                    2000 Wim Taymans <wtay@chello.be>
       
     4  *                    2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
       
     5  *
       
     6  * gstinfo.c: debugging functions
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Library General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Library General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Library General Public
       
    19  * License along with this library; if not, write to the
       
    20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    21  * Boston, MA 02111-1307, USA.
       
    22  */
       
    23 
       
    24 /**
       
    25  * SECTION:gstinfo
       
    26  * @short_description: Debugging and logging facilities
       
    27  * @see_also: #GstConfig, #Gst for command line parameters
       
    28  * and environment variables that affect the debugging output.
       
    29  *
       
    30  * GStreamer's debugging subsystem is an easy way to get information about what
       
    31  * the application is doing.  It is not meant for programming errors. Use GLib
       
    32  * methods (g_warning and friends) for that.
       
    33  *
       
    34  * The debugging subsystem works only after GStreamer has been initialized
       
    35  * - for example by calling gst_init().
       
    36  *
       
    37  * The debugging subsystem is used to log informational messages while the
       
    38  * application runs.  Each messages has some properties attached to it. Among
       
    39  * these properties are the debugging category, the severity (called "level"
       
    40  * here) and an optional #GObject it belongs to. Each of these messages is sent
       
    41  * to all registered debugging handlers, which then handle the messages.
       
    42  * GStreamer attaches a default handler on startup, which outputs requested
       
    43  * messages to stderr.
       
    44  *
       
    45  * Messages are output by using shortcut macros like #GST_DEBUG,
       
    46  * #GST_CAT_ERROR_OBJECT or similar. These all expand to calling gst_debug_log()
       
    47  * with the right parameters.
       
    48  * The only thing a developer will probably want to do is define his own
       
    49  * categories. This is easily done with 3 lines. At the top of your code,
       
    50  * declare
       
    51  * the variables and set the default category.
       
    52  * <informalexample>
       
    53  * <programlisting>
       
    54  * GST_DEBUG_CATEGORY_STATIC (my_category);     // define category (statically)
       
    55  * &hash;define GST_CAT_DEFAULT my_category     // set as default
       
    56  * </programlisting>
       
    57  * </informalexample>
       
    58  * After that you only need to initialize the category.
       
    59  * <informalexample>
       
    60  * <programlisting>
       
    61  * GST_DEBUG_CATEGORY_INIT (my_category, "my category",
       
    62  *                          0, "This is my very own");
       
    63  * </programlisting>
       
    64  * </informalexample>
       
    65  * Initialization must be done before the category is used first.
       
    66  * Plugins do this
       
    67  * in their plugin_init function, libraries and applications should do that
       
    68  * during their initialization.
       
    69  *
       
    70  * The whole debugging subsystem can be disabled at build time with passing the
       
    71  * --disable-gst-debug switch to configure. If this is done, every function,
       
    72  * macro and even structs described in this file evaluate to default values or
       
    73  * nothing at all.
       
    74  * So don't take addresses of these functions or use other tricks.
       
    75  * If you must do that for some reason, there is still an option.
       
    76  * If the debugging
       
    77  * subsystem was compiled out, #GST_DISABLE_GST_DEBUG is defined in
       
    78  * &lt;gst/gst.h&gt;,
       
    79  * so you can check that before doing your trick.
       
    80  * Disabling the debugging subsystem will give you a slight (read: unnoticeable)
       
    81  * speed increase and will reduce the size of your compiled code. The GStreamer
       
    82  * library itself becomes around 10% smaller.
       
    83  *
       
    84  * Please note that there are naming conventions for the names of debugging
       
    85  * categories. These are explained at GST_DEBUG_CATEGORY_INIT().
       
    86  */
       
    87 
       
    88 #include "gst_private.h"
       
    89 #include "gstinfo.h"
       
    90 
       
    91 #ifndef GST_DISABLE_GST_DEBUG
       
    92 
       
    93 #ifdef HAVE_DLFCN_H
       
    94 #  include <dlfcn.h>
       
    95 #endif
       
    96 #ifdef HAVE_PRINTF_EXTENSION
       
    97 #  include <printf.h>
       
    98 #endif
       
    99 #include <stdio.h>              /* fprintf */
       
   100 #ifdef HAVE_UNISTD_H
       
   101 #  include <unistd.h>           /* getpid on UNIX */
       
   102 #endif
       
   103 #ifdef HAVE_PROCESS_H
       
   104 #  include <process.h>          /* getpid on win32 */
       
   105 #endif
       
   106 #include <string.h>             /* G_VA_COPY */
       
   107 
       
   108 #include "gst_private.h"
       
   109 #include "gstutils.h"
       
   110 #include "gstsegment.h"
       
   111 #ifdef HAVE_VALGRIND
       
   112 #  include <valgrind/valgrind.h>
       
   113 #endif
       
   114 #include <glib/gprintf.h>       /* g_sprintf */
       
   115 
       
   116 #ifdef __SYMBIAN32__
       
   117 #include <glib_global.h>
       
   118 #endif
       
   119 
       
   120 /* underscore is to prevent conflict with GST_CAT_DEBUG define */
       
   121 GST_DEBUG_CATEGORY_STATIC (_GST_CAT_DEBUG);
       
   122 
       
   123 /* time of initialization, so we get useful debugging output times
       
   124  * FIXME: we use this in gstdebugutils.c, what about a function + macro to
       
   125  * get the running time: GST_DEBUG_RUNNING_TIME
       
   126  */
       
   127 GstClockTime _priv_gst_info_start_time;
       
   128 
       
   129 #if 0
       
   130 #if defined __sgi__
       
   131 #include <rld_interface.h>
       
   132 typedef struct DL_INFO
       
   133 {
       
   134   const char *dli_fname;
       
   135   void *dli_fbase;
       
   136   const char *dli_sname;
       
   137   void *dli_saddr;
       
   138   int dli_version;
       
   139   int dli_reserved1;
       
   140   long dli_reserved[4];
       
   141 }
       
   142 Dl_info;
       
   143 
       
   144 #define _RLD_DLADDR             14
       
   145 int dladdr (void *address, Dl_info * dl);
       
   146 
       
   147 int
       
   148 dladdr (void *address, Dl_info * dl)
       
   149 {
       
   150   void *v;
       
   151 
       
   152   v = _rld_new_interface (_RLD_DLADDR, address, dl);
       
   153   return (int) v;
       
   154 }
       
   155 #endif /* __sgi__ */
       
   156 #endif
       
   157 
       
   158 static void gst_debug_reset_threshold (gpointer category, gpointer unused);
       
   159 static void gst_debug_reset_all_thresholds (void);
       
   160 
       
   161 #ifdef HAVE_PRINTF_EXTENSION
       
   162 static int _gst_info_printf_extension_ptr (FILE * stream,
       
   163     const struct printf_info *info, const void *const *args);
       
   164 static int _gst_info_printf_extension_segment (FILE * stream,
       
   165     const struct printf_info *info, const void *const *args);
       
   166 static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
       
   167     size_t n, int *argtypes);
       
   168 #endif
       
   169 
       
   170 struct _GstDebugMessage
       
   171 {
       
   172   gchar *message;
       
   173   const gchar *format;
       
   174   va_list arguments;
       
   175 };
       
   176 
       
   177 /* list of all name/level pairs from --gst-debug and GST_DEBUG */
       
   178 static GStaticMutex __level_name_mutex = G_STATIC_MUTEX_INIT;
       
   179 static GSList *__level_name = NULL;
       
   180 typedef struct
       
   181 {
       
   182   GPatternSpec *pat;
       
   183   GstDebugLevel level;
       
   184 }
       
   185 LevelNameEntry;
       
   186 
       
   187 /* list of all categories */
       
   188 static GStaticMutex __cat_mutex = G_STATIC_MUTEX_INIT;
       
   189 static GSList *__categories = NULL;
       
   190 
       
   191 /* all registered debug handlers */
       
   192 typedef struct
       
   193 {
       
   194   GstLogFunction func;
       
   195   gpointer user_data;
       
   196 }
       
   197 LogFuncEntry;
       
   198 static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
       
   199 static GSList *__log_functions = NULL;
       
   200 
       
   201 static gint __default_level;
       
   202 static gint __use_color;
       
   203 
       
   204 /* disabled by default, as soon as some threshold is set > NONE,
       
   205  * it becomes enabled. */
       
   206 gboolean __gst_debug_enabled = FALSE;
       
   207 GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
       
   208 
       
   209 GstDebugCategory *GST_CAT_DEFAULT = NULL;
       
   210 
       
   211 GstDebugCategory *GST_CAT_GST_INIT = NULL;
       
   212 GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
       
   213 GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
       
   214 GstDebugCategory *GST_CAT_PARENTAGE = NULL;
       
   215 GstDebugCategory *GST_CAT_STATES = NULL;
       
   216 GstDebugCategory *GST_CAT_SCHEDULING = NULL;
       
   217 
       
   218 GstDebugCategory *GST_CAT_BUFFER = NULL;
       
   219 GstDebugCategory *GST_CAT_BUS = NULL;
       
   220 GstDebugCategory *GST_CAT_CAPS = NULL;
       
   221 GstDebugCategory *GST_CAT_CLOCK = NULL;
       
   222 GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
       
   223 GstDebugCategory *GST_CAT_PADS = NULL;
       
   224 GstDebugCategory *GST_CAT_PIPELINE = NULL;
       
   225 GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
       
   226 GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
       
   227 GstDebugCategory *GST_CAT_PROPERTIES = NULL;
       
   228 GstDebugCategory *GST_CAT_TYPES = NULL;
       
   229 GstDebugCategory *GST_CAT_XML = NULL;
       
   230 GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
       
   231 GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
       
   232 GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
       
   233 GstDebugCategory *GST_CAT_EVENT = NULL;
       
   234 GstDebugCategory *GST_CAT_MESSAGE = NULL;
       
   235 GstDebugCategory *GST_CAT_PARAMS = NULL;
       
   236 GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
       
   237 GstDebugCategory *GST_CAT_SIGNAL = NULL;
       
   238 GstDebugCategory *GST_CAT_PROBE = NULL;
       
   239 GstDebugCategory *GST_CAT_REGISTRY = NULL;
       
   240 GstDebugCategory *GST_CAT_QOS = NULL;
       
   241 
       
   242 /* FIXME: export this? */
       
   243 #ifdef __SYMBIAN32__
       
   244 EXPORT_C
       
   245 #endif
       
   246 
       
   247 gboolean
       
   248 _priv_gst_in_valgrind (void)
       
   249 {
       
   250   static enum
       
   251   {
       
   252     GST_VG_UNCHECKED,
       
   253     GST_VG_NO_VALGRIND,
       
   254     GST_VG_INSIDE
       
   255   }
       
   256   in_valgrind = GST_VG_UNCHECKED;
       
   257 
       
   258   if (in_valgrind == GST_VG_UNCHECKED) {
       
   259 #ifdef HAVE_VALGRIND
       
   260     if (RUNNING_ON_VALGRIND) {
       
   261       GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind");
       
   262       printf ("GStreamer has detected that it is running inside valgrind.\n");
       
   263       printf ("It might now take different code paths to ease debugging.\n");
       
   264       printf ("Of course, this may also lead to different bugs.\n");
       
   265       in_valgrind = GST_VG_INSIDE;
       
   266     } else {
       
   267       GST_CAT_LOG (GST_CAT_GST_INIT, "not doing extra valgrind stuff");
       
   268       in_valgrind = GST_VG_NO_VALGRIND;
       
   269     }
       
   270 #else
       
   271     in_valgrind = GST_VG_NO_VALGRIND;
       
   272 #endif
       
   273     g_assert (in_valgrind == GST_VG_NO_VALGRIND ||
       
   274         in_valgrind == GST_VG_INSIDE);
       
   275   }
       
   276   return (in_valgrind == GST_VG_INSIDE) ? TRUE : FALSE;
       
   277 }
       
   278 
       
   279 /**
       
   280  * _gst_debug_init:
       
   281  *
       
   282  * Initializes the debugging system.
       
   283  * Normally you don't want to call this, because gst_init() does it for you.
       
   284  */
       
   285 #ifdef __SYMBIAN32__
       
   286 EXPORT_C
       
   287 #endif
       
   288 
       
   289 void
       
   290 _gst_debug_init (void)
       
   291 {
       
   292   gst_atomic_int_set (&__default_level, GST_LEVEL_DEFAULT);
       
   293   gst_atomic_int_set (&__use_color, 1);
       
   294 
       
   295   /* get time we started for debugging messages */
       
   296   _priv_gst_info_start_time = gst_util_get_timestamp ();
       
   297 
       
   298 #ifdef HAVE_PRINTF_EXTENSION
       
   299   register_printf_function (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
       
   300       _gst_info_printf_extension_arginfo);
       
   301   register_printf_function (GST_SEGMENT_FORMAT[0],
       
   302       _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
       
   303 #endif
       
   304 
       
   305   /* do NOT use a single debug function before this line has been run */
       
   306   GST_CAT_DEFAULT = _gst_debug_category_new ("default",
       
   307       GST_DEBUG_UNDERLINE, NULL);
       
   308   _GST_CAT_DEBUG = _gst_debug_category_new ("GST_DEBUG",
       
   309       GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, "debugging subsystem");
       
   310 
       
   311   gst_debug_add_log_function (gst_debug_log_default, NULL);
       
   312 
       
   313   /* FIXME: add descriptions here */
       
   314   GST_CAT_GST_INIT = _gst_debug_category_new ("GST_INIT",
       
   315       GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
       
   316   GST_CAT_AUTOPLUG = _gst_debug_category_new ("GST_AUTOPLUG",
       
   317       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
       
   318   GST_CAT_AUTOPLUG_ATTEMPT = _gst_debug_category_new ("GST_AUTOPLUG_ATTEMPT",
       
   319       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN | GST_DEBUG_BG_BLUE, NULL);
       
   320   GST_CAT_PARENTAGE = _gst_debug_category_new ("GST_PARENTAGE",
       
   321       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   322   GST_CAT_STATES = _gst_debug_category_new ("GST_STATES",
       
   323       GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
       
   324   GST_CAT_SCHEDULING = _gst_debug_category_new ("GST_SCHEDULING",
       
   325       GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
       
   326   GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER",
       
   327       GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
       
   328   GST_CAT_BUS = _gst_debug_category_new ("GST_BUS", GST_DEBUG_BG_YELLOW, NULL);
       
   329   GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS",
       
   330       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
       
   331   GST_CAT_CLOCK = _gst_debug_category_new ("GST_CLOCK",
       
   332       GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, NULL);
       
   333   GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS",
       
   334       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   335   GST_CAT_PADS = _gst_debug_category_new ("GST_PADS",
       
   336       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   337   GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE",
       
   338       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   339   GST_CAT_PLUGIN_LOADING = _gst_debug_category_new ("GST_PLUGIN_LOADING",
       
   340       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
       
   341   GST_CAT_PLUGIN_INFO = _gst_debug_category_new ("GST_PLUGIN_INFO",
       
   342       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
       
   343   GST_CAT_PROPERTIES = _gst_debug_category_new ("GST_PROPERTIES",
       
   344       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL);
       
   345   GST_CAT_TYPES = _gst_debug_category_new ("GST_TYPES",
       
   346       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   347   GST_CAT_XML = _gst_debug_category_new ("GST_XML",
       
   348       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   349   GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION",
       
   350       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
       
   351   GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING",
       
   352       GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_BLUE, NULL);
       
   353   GST_CAT_ERROR_SYSTEM = _gst_debug_category_new ("GST_ERROR_SYSTEM",
       
   354       GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_WHITE, NULL);
       
   355 
       
   356   GST_CAT_EVENT = _gst_debug_category_new ("GST_EVENT",
       
   357       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
       
   358   GST_CAT_MESSAGE = _gst_debug_category_new ("GST_MESSAGE",
       
   359       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   360   GST_CAT_PARAMS = _gst_debug_category_new ("GST_PARAMS",
       
   361       GST_DEBUG_BOLD | GST_DEBUG_FG_BLACK | GST_DEBUG_BG_YELLOW, NULL);
       
   362   GST_CAT_CALL_TRACE = _gst_debug_category_new ("GST_CALL_TRACE",
       
   363       GST_DEBUG_BOLD, NULL);
       
   364   GST_CAT_SIGNAL = _gst_debug_category_new ("GST_SIGNAL",
       
   365       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
       
   366   GST_CAT_PROBE = _gst_debug_category_new ("GST_PROBE",
       
   367       GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "pad probes");
       
   368   GST_CAT_REGISTRY = _gst_debug_category_new ("GST_REGISTRY", 0, "registry");
       
   369   GST_CAT_QOS = _gst_debug_category_new ("GST_QOS", 0, "QoS");
       
   370 
       
   371 
       
   372   /* print out the valgrind message if we're in valgrind */
       
   373   _priv_gst_in_valgrind ();
       
   374 }
       
   375 
       
   376 /* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
       
   377 #define GST_CAT_DEFAULT _GST_CAT_DEBUG
       
   378 
       
   379 /**
       
   380  * gst_debug_log:
       
   381  * @category: category to log
       
   382  * @level: level of the message is in
       
   383  * @file: the file that emitted the message, usually the __FILE__ identifier
       
   384  * @function: the function that emitted the message
       
   385  * @line: the line from that the message was emitted, usually __LINE__
       
   386  * @object: the object this message relates to or NULL if none
       
   387  * @format: a printf style format string
       
   388  * @...: optional arguments for the format
       
   389  *
       
   390  * Logs the given message using the currently registered debugging handlers.
       
   391  */
       
   392 #ifdef __SYMBIAN32__
       
   393 EXPORT_C
       
   394 #endif
       
   395 
       
   396 void
       
   397 gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
       
   398     const gchar * file, const gchar * function, gint line,
       
   399     GObject * object, const gchar * format, ...)
       
   400 {
       
   401   va_list var_args;
       
   402 
       
   403   va_start (var_args, format);
       
   404   gst_debug_log_valist (category, level, file, function, line, object, format,
       
   405       var_args);
       
   406   va_end (var_args);
       
   407 }
       
   408 
       
   409 /**
       
   410  * gst_debug_log_valist:
       
   411  * @category: category to log
       
   412  * @level: level of the message is in
       
   413  * @file: the file that emitted the message, usually the __FILE__ identifier
       
   414  * @function: the function that emitted the message
       
   415  * @line: the line from that the message was emitted, usually __LINE__
       
   416  * @object: the object this message relates to or NULL if none
       
   417  * @format: a printf style format string
       
   418  * @args: optional arguments for the format
       
   419  *
       
   420  * Logs the given message using the currently registered debugging handlers.
       
   421  */
       
   422 #ifdef __SYMBIAN32__
       
   423 EXPORT_C
       
   424 #endif
       
   425 
       
   426 void
       
   427 gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
       
   428     const gchar * file, const gchar * function, gint line,
       
   429     GObject * object, const gchar * format, va_list args)
       
   430 {
       
   431   GstDebugMessage message;
       
   432   LogFuncEntry *entry;
       
   433   GSList *handler;
       
   434 
       
   435   g_return_if_fail (category != NULL);
       
   436   g_return_if_fail (file != NULL);
       
   437   g_return_if_fail (function != NULL);
       
   438   g_return_if_fail (format != NULL);
       
   439 
       
   440   message.message = NULL;
       
   441   message.format = format;
       
   442   G_VA_COPY (message.arguments, args);
       
   443 
       
   444   handler = __log_functions;
       
   445   while (handler) {
       
   446     entry = handler->data;
       
   447     handler = g_slist_next (handler);
       
   448     entry->func (category, level, file, function, line, object, &message,
       
   449         entry->user_data);
       
   450   }
       
   451   g_free (message.message);
       
   452   va_end (message.arguments);
       
   453 }
       
   454 
       
   455 /**
       
   456  * gst_debug_message_get:
       
   457  * @message: a debug message
       
   458  *
       
   459  * Gets the string representation of a #GstDebugMessage. This function is used
       
   460  * in debug handlers to extract the message.
       
   461  *
       
   462  * Returns: the string representation of a #GstDebugMessage.
       
   463  */
       
   464 #ifdef __SYMBIAN32__
       
   465 EXPORT_C
       
   466 #endif
       
   467 
       
   468 const gchar *
       
   469 gst_debug_message_get (GstDebugMessage * message)
       
   470 {
       
   471   if (message->message == NULL) {
       
   472     message->message = g_strdup_vprintf (message->format, message->arguments);
       
   473   }
       
   474   return message->message;
       
   475 }
       
   476 
       
   477 
       
   478 static gchar *
       
   479 gst_debug_print_object (gpointer ptr)
       
   480 {
       
   481   GObject *object = (GObject *) ptr;
       
   482 
       
   483 #ifdef unused
       
   484   /* This is a cute trick to detect unmapped memory, but is unportable,
       
   485    * slow, screws around with madvise, and not actually that useful. */
       
   486   {
       
   487     int ret;
       
   488 
       
   489     ret = madvise ((void *) ((unsigned long) ptr & (~0xfff)), 4096, 0);
       
   490     if (ret == -1 && errno == ENOMEM) {
       
   491       buffer = g_strdup_printf ("%p (unmapped memory)", ptr);
       
   492     }
       
   493   }
       
   494 #endif
       
   495 
       
   496   /* nicely printed object */
       
   497   if (object == NULL) {
       
   498     return g_strdup ("(NULL)");
       
   499   }
       
   500   if (*(GType *) ptr == GST_TYPE_CAPS) {
       
   501     return gst_caps_to_string ((GstCaps *) ptr);
       
   502   }
       
   503   if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
       
   504     return gst_structure_to_string ((GstStructure *) ptr);
       
   505   }
       
   506 #ifdef USE_POISONING
       
   507   if (*(guint32 *) ptr == 0xffffffff) {
       
   508     return g_strdup_printf ("<poisoned@%p>", ptr);
       
   509   }
       
   510 #endif
       
   511   if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) {
       
   512     return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object));
       
   513   }
       
   514   if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) {
       
   515     return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object));
       
   516   }
       
   517   if (G_IS_OBJECT (object)) {
       
   518     return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object);
       
   519   }
       
   520   if (GST_IS_MESSAGE (object)) {
       
   521     GstMessage *msg = GST_MESSAGE_CAST (object);
       
   522     gchar *s, *ret;
       
   523 
       
   524     if (msg->structure) {
       
   525       s = gst_structure_to_string (msg->structure);
       
   526     } else {
       
   527       s = g_strdup ("(NULL)");
       
   528     }
       
   529 
       
   530     ret = g_strdup_printf ("%s message from element '%s': %s",
       
   531         GST_MESSAGE_TYPE_NAME (msg), (msg->src != NULL) ?
       
   532         GST_ELEMENT_NAME (msg->src) : "(NULL)", s);
       
   533     g_free (s);
       
   534     return ret;
       
   535   }
       
   536 
       
   537   return g_strdup_printf ("%p", ptr);
       
   538 }
       
   539 
       
   540 #ifdef HAVE_PRINTF_EXTENSION
       
   541 
       
   542 static gchar *
       
   543 gst_debug_print_segment (gpointer ptr)
       
   544 {
       
   545   GstSegment *segment = (GstSegment *) ptr;
       
   546 
       
   547   /* nicely printed segment */
       
   548   if (segment == NULL) {
       
   549     return g_strdup ("(NULL)");
       
   550   }
       
   551 
       
   552   switch (segment->format) {
       
   553     case GST_FORMAT_UNDEFINED:{
       
   554       return g_strdup_printf ("UNDEFINED segment");
       
   555     }
       
   556     case GST_FORMAT_TIME:{
       
   557       return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT
       
   558           ", stop=%" GST_TIME_FORMAT ", last_stop=%" GST_TIME_FORMAT
       
   559           ", duration=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f"
       
   560           ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
       
   561           GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
       
   562           GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (segment->duration),
       
   563           segment->rate, segment->applied_rate, (guint) segment->flags,
       
   564           GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->accum));
       
   565     }
       
   566     default:{
       
   567       const gchar *format_name;
       
   568 
       
   569       format_name = gst_format_get_name (segment->format);
       
   570       if (G_UNLIKELY (format_name == NULL))
       
   571         format_name = "(UNKNOWN FORMAT)";
       
   572       return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT
       
   573           ", stop=%" G_GINT64_FORMAT ", last_stop=%" G_GINT64_FORMAT
       
   574           ", duration=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f"
       
   575           ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
       
   576           format_name, segment->start, segment->stop, segment->last_stop,
       
   577           segment->duration, segment->rate, segment->applied_rate,
       
   578           (guint) segment->flags, GST_TIME_ARGS (segment->time),
       
   579           GST_TIME_ARGS (segment->accum));
       
   580     }
       
   581   }
       
   582 }
       
   583 
       
   584 #endif /* HAVE_PRINTF_EXTENSION */
       
   585 
       
   586 /**
       
   587  * gst_debug_construct_term_color:
       
   588  * @colorinfo: the color info
       
   589  *
       
   590  * Constructs a string that can be used for getting the desired color in color
       
   591  * terminals.
       
   592  * You need to free the string after use.
       
   593  *
       
   594  * Returns: a string containing the color definition
       
   595  */
       
   596 #ifdef __SYMBIAN32__
       
   597 EXPORT_C
       
   598 #endif
       
   599 
       
   600 gchar *
       
   601 gst_debug_construct_term_color (guint colorinfo)
       
   602 {
       
   603   GString *color;
       
   604 
       
   605   color = g_string_new ("\033[00");
       
   606 
       
   607   if (colorinfo & GST_DEBUG_BOLD) {
       
   608     g_string_append_len (color, ";01", 3);
       
   609   }
       
   610   if (colorinfo & GST_DEBUG_UNDERLINE) {
       
   611     g_string_append_len (color, ";04", 3);
       
   612   }
       
   613   if (colorinfo & GST_DEBUG_FG_MASK) {
       
   614     g_string_append_printf (color, ";3%1d", colorinfo & GST_DEBUG_FG_MASK);
       
   615   }
       
   616   if (colorinfo & GST_DEBUG_BG_MASK) {
       
   617     g_string_append_printf (color, ";4%1d",
       
   618         (colorinfo & GST_DEBUG_BG_MASK) >> 4);
       
   619   }
       
   620   g_string_append_c (color, 'm');
       
   621 
       
   622   return g_string_free (color, FALSE);
       
   623 }
       
   624 
       
   625 /**
       
   626  * gst_debug_log_default:
       
   627  * @category: category to log
       
   628  * @level: level of the message
       
   629  * @file: the file that emitted the message, usually the __FILE__ identifier
       
   630  * @function: the function that emitted the message
       
   631  * @line: the line from that the message was emitted, usually __LINE__
       
   632  * @message: the actual message
       
   633  * @object: the object this message relates to or NULL if none
       
   634  * @unused: an unused variable, reserved for some user_data.
       
   635  *
       
   636  * The default logging handler used by GStreamer. Logging functions get called
       
   637  * whenever a macro like GST_DEBUG or similar is used. This function outputs the
       
   638  * message and additional info using the glib error handler.
       
   639  * You can add other handlers by using gst_debug_add_log_function().
       
   640  * And you can remove this handler by calling
       
   641  * gst_debug_remove_log_function(gst_debug_log_default);
       
   642  */
       
   643 #ifdef __SYMBIAN32__
       
   644 EXPORT_C
       
   645 #endif
       
   646 
       
   647 void
       
   648 gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
       
   649     const gchar * file, const gchar * function, gint line,
       
   650     GObject * object, GstDebugMessage * message, gpointer unused)
       
   651 {
       
   652   gchar *color = NULL;
       
   653   gchar *clear;
       
   654   gchar *obj = NULL;
       
   655   gchar pidcolor[10];
       
   656   const gchar *levelcolor;
       
   657   gint pid;
       
   658   GstClockTime elapsed;
       
   659   gboolean free_color = TRUE;
       
   660   gboolean free_obj = TRUE;
       
   661   static const gchar *levelcolormap[] = {
       
   662     "\033[37m",                 /* GST_LEVEL_NONE */
       
   663     "\033[31;01m",              /* GST_LEVEL_ERROR */
       
   664     "\033[33;01m",              /* GST_LEVEL_WARNING */
       
   665     "\033[32;01m",              /* GST_LEVEL_INFO */
       
   666     "\033[36m",                 /* GST_LEVEL_DEBUG */
       
   667     "\033[37m"                  /* GST_LEVEL_LOG */
       
   668   };
       
   669 
       
   670   if (level > gst_debug_category_get_threshold (category))
       
   671     return;
       
   672 
       
   673   pid = getpid ();
       
   674 
       
   675   /* color info */
       
   676   if (gst_debug_is_colored ()) {
       
   677     color = gst_debug_construct_term_color (gst_debug_category_get_color
       
   678         (category));
       
   679     clear = "\033[00m";
       
   680     g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
       
   681     levelcolor = levelcolormap[level];
       
   682   } else {
       
   683     color = "\0";
       
   684     free_color = FALSE;
       
   685     clear = "";
       
   686     pidcolor[0] = '\0';
       
   687     levelcolor = "\0";
       
   688   }
       
   689 
       
   690   if (object) {
       
   691     obj = gst_debug_print_object (object);
       
   692   } else {
       
   693     obj = "\0";
       
   694     free_obj = FALSE;
       
   695   }
       
   696 
       
   697   elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
       
   698       gst_util_get_timestamp ());
       
   699 
       
   700   /*
       
   701      g_printerr ("%s (%p - %" GST_TIME_FORMAT ") %s%20s%s(%s%5d%s) %s%s(%d):%s:%s%s %s\n",
       
   702      gst_debug_level_get_name (level), g_thread_self (),
       
   703      GST_TIME_ARGS (elapsed), color,
       
   704      gst_debug_category_get_name (category), clear, pidcolor, pid, clear,
       
   705      color, file, line, function, obj, clear, gst_debug_message_get (message));
       
   706    */
       
   707 
       
   708   g_printerr ("%" GST_TIME_FORMAT
       
   709       " %s%5d%s %p %s%s%s %s%20s %s:%d:%s:%s%s %s\n", GST_TIME_ARGS (elapsed),
       
   710       pidcolor, pid, clear, g_thread_self (), levelcolor,
       
   711       gst_debug_level_get_name (level), clear, color,
       
   712       gst_debug_category_get_name (category), file, line, function, obj, clear,
       
   713       gst_debug_message_get (message));
       
   714 
       
   715   if (free_color)
       
   716     g_free (color);
       
   717   if (free_obj)
       
   718     g_free (obj);
       
   719 }
       
   720 
       
   721 /**
       
   722  * gst_debug_level_get_name:
       
   723  * @level: the level to get the name for
       
   724  *
       
   725  * Get the string representation of a debugging level
       
   726  *
       
   727  * Returns: the name
       
   728  */
       
   729 #ifdef __SYMBIAN32__
       
   730 EXPORT_C
       
   731 #endif
       
   732 
       
   733 const gchar *
       
   734 gst_debug_level_get_name (GstDebugLevel level)
       
   735 {
       
   736   switch (level) {
       
   737     case GST_LEVEL_NONE:
       
   738       return "";
       
   739     case GST_LEVEL_ERROR:
       
   740       return "ERROR";
       
   741     case GST_LEVEL_WARNING:
       
   742       return "WARN ";
       
   743     case GST_LEVEL_INFO:
       
   744       return "INFO ";
       
   745     case GST_LEVEL_DEBUG:
       
   746       return "DEBUG";
       
   747     case GST_LEVEL_LOG:
       
   748       return "LOG  ";
       
   749     default:
       
   750       g_warning ("invalid level specified for gst_debug_level_get_name");
       
   751       return "";
       
   752   }
       
   753 }
       
   754 
       
   755 /**
       
   756  * gst_debug_add_log_function:
       
   757  * @func: the function to use
       
   758  * @data: user data
       
   759  *
       
   760  * Adds the logging function to the list of logging functions.
       
   761  * Be sure to use G_GNUC_NO_INSTRUMENT on that function, it is needed.
       
   762  */
       
   763 #ifdef __SYMBIAN32__
       
   764 EXPORT_C
       
   765 #endif
       
   766 
       
   767 void
       
   768 gst_debug_add_log_function (GstLogFunction func, gpointer data)
       
   769 {
       
   770   LogFuncEntry *entry;
       
   771   GSList *list;
       
   772 
       
   773   g_return_if_fail (func != NULL);
       
   774 
       
   775   entry = g_new (LogFuncEntry, 1);
       
   776   entry->func = func;
       
   777   entry->user_data = data;
       
   778   /* FIXME: we leak the old list here - other threads might access it right now
       
   779    * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv,
       
   780    * but that is waaay costly.
       
   781    * It'd probably be clever to use some kind of RCU here, but I don't know
       
   782    * anything about that.
       
   783    */
       
   784   g_static_mutex_lock (&__log_func_mutex);
       
   785   list = g_slist_copy (__log_functions);
       
   786   __log_functions = g_slist_prepend (list, entry);
       
   787   g_static_mutex_unlock (&__log_func_mutex);
       
   788 
       
   789   GST_DEBUG ("prepended log function %p (user data %p) to log functions",
       
   790       func, data);
       
   791 }
       
   792 
       
   793 static gint
       
   794 gst_debug_compare_log_function_by_func (gconstpointer entry, gconstpointer func)
       
   795 {
       
   796   gpointer entryfunc = (gpointer) (((LogFuncEntry *) entry)->func);
       
   797 
       
   798   return (entryfunc < func) ? -1 : (entryfunc > func) ? 1 : 0;
       
   799 }
       
   800 
       
   801 static gint
       
   802 gst_debug_compare_log_function_by_data (gconstpointer entry, gconstpointer data)
       
   803 {
       
   804   gpointer entrydata = ((LogFuncEntry *) entry)->user_data;
       
   805 
       
   806   return (entrydata < data) ? -1 : (entrydata > data) ? 1 : 0;
       
   807 }
       
   808 
       
   809 static guint
       
   810 gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
       
   811 {
       
   812   GSList *found;
       
   813   GSList *new;
       
   814   guint removals = 0;
       
   815 
       
   816   g_static_mutex_lock (&__log_func_mutex);
       
   817   new = __log_functions;
       
   818   while ((found = g_slist_find_custom (new, data, func))) {
       
   819     if (new == __log_functions) {
       
   820       new = g_slist_copy (new);
       
   821       continue;
       
   822     }
       
   823     g_free (found->data);
       
   824     new = g_slist_delete_link (new, found);
       
   825     removals++;
       
   826   }
       
   827   /* FIXME: We leak the old list here. See _add_log_function for why. */
       
   828   __log_functions = new;
       
   829   g_static_mutex_unlock (&__log_func_mutex);
       
   830 
       
   831   return removals;
       
   832 }
       
   833 
       
   834 /**
       
   835  * gst_debug_remove_log_function:
       
   836  * @func: the log function to remove
       
   837  *
       
   838  * Removes all registered instances of the given logging functions.
       
   839  *
       
   840  * Returns: How many instances of the function were removed
       
   841  */
       
   842 #ifdef __SYMBIAN32__
       
   843 EXPORT_C
       
   844 #endif
       
   845 
       
   846 guint
       
   847 gst_debug_remove_log_function (GstLogFunction func)
       
   848 {
       
   849   guint removals;
       
   850 
       
   851   g_return_val_if_fail (func != NULL, 0);
       
   852 
       
   853   removals =
       
   854       gst_debug_remove_with_compare_func
       
   855       (gst_debug_compare_log_function_by_func, (gpointer) func);
       
   856   GST_DEBUG ("removed log function %p %d times from log function list", func,
       
   857       removals);
       
   858 
       
   859   return removals;
       
   860 }
       
   861 
       
   862 /**
       
   863  * gst_debug_remove_log_function_by_data:
       
   864  * @data: user data of the log function to remove
       
   865  *
       
   866  * Removes all registered instances of log functions with the given user data.
       
   867  *
       
   868  * Returns: How many instances of the function were removed
       
   869  */
       
   870 #ifdef __SYMBIAN32__
       
   871 EXPORT_C
       
   872 #endif
       
   873 
       
   874 guint
       
   875 gst_debug_remove_log_function_by_data (gpointer data)
       
   876 {
       
   877   guint removals;
       
   878 
       
   879   removals =
       
   880       gst_debug_remove_with_compare_func
       
   881       (gst_debug_compare_log_function_by_data, data);
       
   882   GST_DEBUG
       
   883       ("removed %d log functions with user data %p from log function list",
       
   884       removals, data);
       
   885 
       
   886   return removals;
       
   887 }
       
   888 
       
   889 /**
       
   890  * gst_debug_set_colored:
       
   891  * @colored: Whether to use colored output or not
       
   892  *
       
   893  * Sets or unsets the use of coloured debugging output.
       
   894  */
       
   895 #ifdef __SYMBIAN32__
       
   896 EXPORT_C
       
   897 #endif
       
   898 
       
   899 void
       
   900 gst_debug_set_colored (gboolean colored)
       
   901 {
       
   902   gst_atomic_int_set (&__use_color, colored ? 1 : 0);
       
   903 }
       
   904 
       
   905 /**
       
   906  * gst_debug_is_colored:
       
   907  *
       
   908  * Checks if the debugging output should be colored.
       
   909  *
       
   910  * Returns: TRUE, if the debug output should be colored.
       
   911  */
       
   912 #ifdef __SYMBIAN32__
       
   913 EXPORT_C
       
   914 #endif
       
   915 
       
   916 gboolean
       
   917 gst_debug_is_colored (void)
       
   918 {
       
   919   return g_atomic_int_get (&__use_color) == 0 ? FALSE : TRUE;
       
   920 }
       
   921 
       
   922 /**
       
   923  * gst_debug_set_active:
       
   924  * @active: Whether to use debugging output or not
       
   925  *
       
   926  * If activated, debugging messages are sent to the debugging
       
   927  * handlers.
       
   928  * It makes sense to deactivate it for speed issues.
       
   929  * <note><para>This function is not threadsafe. It makes sense to only call it
       
   930  * during initialization.</para></note>
       
   931  */
       
   932 #ifdef __SYMBIAN32__
       
   933 EXPORT_C
       
   934 #endif
       
   935 
       
   936 void
       
   937 gst_debug_set_active (gboolean active)
       
   938 {
       
   939   __gst_debug_enabled = active;
       
   940   if (active)
       
   941     __gst_debug_min = GST_LEVEL_COUNT;
       
   942   else
       
   943     __gst_debug_min = GST_LEVEL_NONE;
       
   944 }
       
   945 
       
   946 /**
       
   947  * gst_debug_is_active:
       
   948  *
       
   949  * Checks if debugging output is activated.
       
   950  *
       
   951  * Returns: TRUE, if debugging is activated
       
   952  */
       
   953 #ifdef __SYMBIAN32__
       
   954 EXPORT_C
       
   955 #endif
       
   956 
       
   957 gboolean
       
   958 gst_debug_is_active (void)
       
   959 {
       
   960   return __gst_debug_enabled;
       
   961 }
       
   962 
       
   963 /**
       
   964  * gst_debug_set_default_threshold:
       
   965  * @level: level to set
       
   966  *
       
   967  * Sets the default threshold to the given level and updates all categories to
       
   968  * use this threshold.
       
   969  */
       
   970 #ifdef __SYMBIAN32__
       
   971 EXPORT_C
       
   972 #endif
       
   973 
       
   974 void
       
   975 gst_debug_set_default_threshold (GstDebugLevel level)
       
   976 {
       
   977   gst_atomic_int_set (&__default_level, level);
       
   978   gst_debug_reset_all_thresholds ();
       
   979 }
       
   980 
       
   981 /**
       
   982  * gst_debug_get_default_threshold:
       
   983  *
       
   984  * Returns the default threshold that is used for new categories.
       
   985  *
       
   986  * Returns: the default threshold level
       
   987  */
       
   988 #ifdef __SYMBIAN32__
       
   989 EXPORT_C
       
   990 #endif
       
   991 
       
   992 GstDebugLevel
       
   993 gst_debug_get_default_threshold (void)
       
   994 {
       
   995   return (GstDebugLevel) g_atomic_int_get (&__default_level);
       
   996 }
       
   997 static void
       
   998 gst_debug_reset_threshold (gpointer category, gpointer unused)
       
   999 {
       
  1000   GstDebugCategory *cat = (GstDebugCategory *) category;
       
  1001   GSList *walk;
       
  1002 
       
  1003   g_static_mutex_lock (&__level_name_mutex);
       
  1004   walk = __level_name;
       
  1005   while (walk) {
       
  1006     LevelNameEntry *entry = walk->data;
       
  1007 
       
  1008     walk = g_slist_next (walk);
       
  1009     if (g_pattern_match_string (entry->pat, cat->name)) {
       
  1010       GST_LOG ("category %s matches pattern %p - gets set to level %d",
       
  1011           cat->name, entry->pat, entry->level);
       
  1012       gst_debug_category_set_threshold (cat, entry->level);
       
  1013       goto exit;
       
  1014     }
       
  1015   }
       
  1016   gst_debug_category_set_threshold (cat, gst_debug_get_default_threshold ());
       
  1017 
       
  1018 exit:
       
  1019   g_static_mutex_unlock (&__level_name_mutex);
       
  1020 }
       
  1021 static void
       
  1022 gst_debug_reset_all_thresholds (void)
       
  1023 {
       
  1024   g_static_mutex_lock (&__cat_mutex);
       
  1025   g_slist_foreach (__categories, gst_debug_reset_threshold, NULL);
       
  1026   g_static_mutex_unlock (&__cat_mutex);
       
  1027 }
       
  1028 static void
       
  1029 for_each_threshold_by_entry (gpointer data, gpointer user_data)
       
  1030 {
       
  1031   GstDebugCategory *cat = (GstDebugCategory *) data;
       
  1032   LevelNameEntry *entry = (LevelNameEntry *) user_data;
       
  1033 
       
  1034   if (g_pattern_match_string (entry->pat, cat->name)) {
       
  1035     GST_LOG ("category %s matches pattern %p - gets set to level %d",
       
  1036         cat->name, entry->pat, entry->level);
       
  1037     gst_debug_category_set_threshold (cat, entry->level);
       
  1038   }
       
  1039 }
       
  1040 
       
  1041 /**
       
  1042  * gst_debug_set_threshold_for_name:
       
  1043  * @name: name of the categories to set
       
  1044  * @level: level to set them to
       
  1045  *
       
  1046  * Sets all categories which match the given glob style pattern to the given
       
  1047  * level.
       
  1048  */
       
  1049 #ifdef __SYMBIAN32__
       
  1050 EXPORT_C
       
  1051 #endif
       
  1052 
       
  1053 void
       
  1054 gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
       
  1055 {
       
  1056   GPatternSpec *pat;
       
  1057   LevelNameEntry *entry;
       
  1058 
       
  1059   g_return_if_fail (name != NULL);
       
  1060 
       
  1061   pat = g_pattern_spec_new (name);
       
  1062   entry = g_new (LevelNameEntry, 1);
       
  1063   entry->pat = pat;
       
  1064   entry->level = level;
       
  1065   g_static_mutex_lock (&__level_name_mutex);
       
  1066   __level_name = g_slist_prepend (__level_name, entry);
       
  1067   g_static_mutex_unlock (&__level_name_mutex);
       
  1068   g_static_mutex_lock (&__cat_mutex);
       
  1069   g_slist_foreach (__categories, for_each_threshold_by_entry, entry);
       
  1070   g_static_mutex_unlock (&__cat_mutex);
       
  1071 }
       
  1072 
       
  1073 /**
       
  1074  * gst_debug_unset_threshold_for_name:
       
  1075  * @name: name of the categories to set
       
  1076  *
       
  1077  * Resets all categories with the given name back to the default level.
       
  1078  */
       
  1079 #ifdef __SYMBIAN32__
       
  1080 EXPORT_C
       
  1081 #endif
       
  1082 
       
  1083 void
       
  1084 gst_debug_unset_threshold_for_name (const gchar * name)
       
  1085 {
       
  1086   GSList *walk;
       
  1087   GPatternSpec *pat;
       
  1088 
       
  1089   g_return_if_fail (name != NULL);
       
  1090 
       
  1091   pat = g_pattern_spec_new (name);
       
  1092   g_static_mutex_lock (&__level_name_mutex);
       
  1093   walk = __level_name;
       
  1094   /* improve this if you want, it's mighty slow */
       
  1095   while (walk) {
       
  1096     LevelNameEntry *entry = walk->data;
       
  1097 
       
  1098     if (g_pattern_spec_equal (entry->pat, pat)) {
       
  1099       __level_name = g_slist_remove_link (__level_name, walk);
       
  1100       g_pattern_spec_free (entry->pat);
       
  1101       g_free (entry);
       
  1102       g_slist_free_1 (walk);
       
  1103       walk = __level_name;
       
  1104     }
       
  1105   }
       
  1106   g_static_mutex_unlock (&__level_name_mutex);
       
  1107   g_pattern_spec_free (pat);
       
  1108   gst_debug_reset_all_thresholds ();
       
  1109 }
       
  1110 #ifdef __SYMBIAN32__
       
  1111 EXPORT_C
       
  1112 #endif
       
  1113 
       
  1114 
       
  1115 GstDebugCategory *
       
  1116 _gst_debug_category_new (const gchar * name, guint color,
       
  1117     const gchar * description)
       
  1118 {
       
  1119   GstDebugCategory *cat;
       
  1120 
       
  1121   g_return_val_if_fail (name != NULL, NULL);
       
  1122 
       
  1123   cat = g_new (GstDebugCategory, 1);
       
  1124   cat->name = g_strdup (name);
       
  1125   cat->color = color;
       
  1126   if (description != NULL) {
       
  1127     cat->description = g_strdup (description);
       
  1128   } else {
       
  1129     cat->description = g_strdup ("no description");
       
  1130   }
       
  1131   gst_atomic_int_set (&cat->threshold, 0);
       
  1132   gst_debug_reset_threshold (cat, NULL);
       
  1133 
       
  1134   /* add to category list */
       
  1135   g_static_mutex_lock (&__cat_mutex);
       
  1136   __categories = g_slist_prepend (__categories, cat);
       
  1137   g_static_mutex_unlock (&__cat_mutex);
       
  1138 
       
  1139   return cat;
       
  1140 }
       
  1141 
       
  1142 /**
       
  1143  * gst_debug_category_free:
       
  1144  * @category: #GstDebugCategory to free.
       
  1145  *
       
  1146  * Removes and frees the category and all associated resources.
       
  1147  */
       
  1148 #ifdef __SYMBIAN32__
       
  1149 EXPORT_C
       
  1150 #endif
       
  1151 
       
  1152 void
       
  1153 gst_debug_category_free (GstDebugCategory * category)
       
  1154 {
       
  1155   if (category == NULL)
       
  1156     return;
       
  1157 
       
  1158   /* remove from category list */
       
  1159   g_static_mutex_lock (&__cat_mutex);
       
  1160   __categories = g_slist_remove (__categories, category);
       
  1161   g_static_mutex_unlock (&__cat_mutex);
       
  1162 
       
  1163   g_free ((gpointer) category->name);
       
  1164   g_free ((gpointer) category->description);
       
  1165   g_free (category);
       
  1166 }
       
  1167 
       
  1168 /**
       
  1169  * gst_debug_category_set_threshold:
       
  1170  * @category: a #GstDebugCategory to set threshold of.
       
  1171  * @level: the #GstDebugLevel threshold to set.
       
  1172  *
       
  1173  * Sets the threshold of the category to the given level. Debug information will
       
  1174  * only be output if the threshold is lower or equal to the level of the
       
  1175  * debugging message.
       
  1176  * <note><para>
       
  1177  * Do not use this function in production code, because other functions may
       
  1178  * change the threshold of categories as side effect. It is however a nice
       
  1179  * function to use when debugging (even from gdb).
       
  1180  * </para></note>
       
  1181  */
       
  1182 #ifdef __SYMBIAN32__
       
  1183 EXPORT_C
       
  1184 #endif
       
  1185 
       
  1186 void
       
  1187 gst_debug_category_set_threshold (GstDebugCategory * category,
       
  1188     GstDebugLevel level)
       
  1189 {
       
  1190   g_return_if_fail (category != NULL);
       
  1191 
       
  1192   if (level > __gst_debug_min) {
       
  1193     __gst_debug_enabled = TRUE;
       
  1194     __gst_debug_min = level;
       
  1195   }
       
  1196 
       
  1197   gst_atomic_int_set (&category->threshold, level);
       
  1198 }
       
  1199 
       
  1200 /**
       
  1201  * gst_debug_category_reset_threshold:
       
  1202  * @category: a #GstDebugCategory to reset threshold of.
       
  1203  *
       
  1204  * Resets the threshold of the category to the default level. Debug information
       
  1205  * will only be output if the threshold is lower or equal to the level of the
       
  1206  * debugging message.
       
  1207  * Use this function to set the threshold back to where it was after using
       
  1208  * gst_debug_category_set_threshold().
       
  1209  */
       
  1210 #ifdef __SYMBIAN32__
       
  1211 EXPORT_C
       
  1212 #endif
       
  1213 
       
  1214 void
       
  1215 gst_debug_category_reset_threshold (GstDebugCategory * category)
       
  1216 {
       
  1217   gst_debug_reset_threshold (category, NULL);
       
  1218 }
       
  1219 
       
  1220 /**
       
  1221  * gst_debug_category_get_threshold:
       
  1222  * @category: a #GstDebugCategory to get threshold of.
       
  1223  *
       
  1224  * Returns the threshold of a #GstDebugCategory.
       
  1225  *
       
  1226  * Returns: the #GstDebugLevel that is used as threshold.
       
  1227  */
       
  1228 #ifdef __SYMBIAN32__
       
  1229 EXPORT_C
       
  1230 #endif
       
  1231 
       
  1232 GstDebugLevel
       
  1233 gst_debug_category_get_threshold (GstDebugCategory * category)
       
  1234 {
       
  1235   return g_atomic_int_get (&category->threshold);
       
  1236 }
       
  1237 
       
  1238 /**
       
  1239  * gst_debug_category_get_name:
       
  1240  * @category: a #GstDebugCategory to get name of.
       
  1241  *
       
  1242  * Returns the name of a debug category.
       
  1243  *
       
  1244  * Returns: the name of the category.
       
  1245  */
       
  1246 #ifdef __SYMBIAN32__
       
  1247 EXPORT_C
       
  1248 #endif
       
  1249 
       
  1250 const gchar *
       
  1251 gst_debug_category_get_name (GstDebugCategory * category)
       
  1252 {
       
  1253   return category->name;
       
  1254 }
       
  1255 
       
  1256 /**
       
  1257  * gst_debug_category_get_color:
       
  1258  * @category: a #GstDebugCategory to get the color of.
       
  1259  *
       
  1260  * Returns the color of a debug category used when printing output in this
       
  1261  * category.
       
  1262  *
       
  1263  * Returns: the color of the category.
       
  1264  */
       
  1265 #ifdef __SYMBIAN32__
       
  1266 EXPORT_C
       
  1267 #endif
       
  1268 
       
  1269 guint
       
  1270 gst_debug_category_get_color (GstDebugCategory * category)
       
  1271 {
       
  1272   return category->color;
       
  1273 }
       
  1274 
       
  1275 /**
       
  1276  * gst_debug_category_get_description:
       
  1277  * @category: a #GstDebugCategory to get the description of.
       
  1278  *
       
  1279  * Returns the description of a debug category.
       
  1280  *
       
  1281  * Returns: the description of the category.
       
  1282  */
       
  1283 #ifdef __SYMBIAN32__
       
  1284 EXPORT_C
       
  1285 #endif
       
  1286 
       
  1287 const gchar *
       
  1288 gst_debug_category_get_description (GstDebugCategory * category)
       
  1289 {
       
  1290   return category->description;
       
  1291 }
       
  1292 
       
  1293 /**
       
  1294  * gst_debug_get_all_categories:
       
  1295  *
       
  1296  * Returns a snapshot of a all categories that are currently in use . This list
       
  1297  * may change anytime.
       
  1298  * The caller has to free the list after use.
       
  1299  *
       
  1300  * Returns: the list of categories
       
  1301  */
       
  1302 #ifdef __SYMBIAN32__
       
  1303 EXPORT_C
       
  1304 #endif
       
  1305 
       
  1306 GSList *
       
  1307 gst_debug_get_all_categories (void)
       
  1308 {
       
  1309   GSList *ret;
       
  1310 
       
  1311   g_static_mutex_lock (&__cat_mutex);
       
  1312   ret = g_slist_copy (__categories);
       
  1313   g_static_mutex_unlock (&__cat_mutex);
       
  1314 
       
  1315   return ret;
       
  1316 }
       
  1317 
       
  1318 /*** FUNCTION POINTERS ********************************************************/
       
  1319 
       
  1320 static GHashTable *__gst_function_pointers;     /* NULL */
       
  1321 static GStaticMutex __dbg_functions_mutex = G_STATIC_MUTEX_INIT;
       
  1322 
       
  1323 const gchar *
       
  1324 _gst_debug_nameof_funcptr (GstDebugFuncPtr ptr)
       
  1325     G_GNUC_NO_INSTRUMENT;
       
  1326 
       
  1327 /* This function MUST NOT return NULL */
       
  1328 #ifdef __SYMBIAN32__
       
  1329 EXPORT_C
       
  1330 #endif
       
  1331 
       
  1332      const gchar *_gst_debug_nameof_funcptr (GstDebugFuncPtr func)
       
  1333 {
       
  1334   gchar *ptrname;
       
  1335 
       
  1336 #ifdef HAVE_DLADDR
       
  1337   Dl_info dl_info;
       
  1338 #endif
       
  1339 
       
  1340   if (G_UNLIKELY (func == NULL))
       
  1341     return "(NULL)";
       
  1342 
       
  1343   g_static_mutex_lock (&__dbg_functions_mutex);
       
  1344   if (G_LIKELY (__gst_function_pointers)) {
       
  1345     ptrname = g_hash_table_lookup (__gst_function_pointers, (gpointer) func);
       
  1346     g_static_mutex_unlock (&__dbg_functions_mutex);
       
  1347     if (G_LIKELY (ptrname))
       
  1348       return ptrname;
       
  1349   } else {
       
  1350     g_static_mutex_unlock (&__dbg_functions_mutex);
       
  1351   }
       
  1352   /* we need to create an entry in the hash table for this one so we don't leak
       
  1353    * the name */
       
  1354 #ifdef HAVE_DLADDR
       
  1355   if (dladdr ((gpointer) func, &dl_info) && dl_info.dli_sname) {
       
  1356     gchar *name = g_strdup (dl_info.dli_sname);
       
  1357 
       
  1358     _gst_debug_register_funcptr (func, name);
       
  1359     return name;
       
  1360   } else
       
  1361 #endif
       
  1362   {
       
  1363     gchar *name = g_strdup_printf ("%p", (gpointer) func);
       
  1364 
       
  1365     _gst_debug_register_funcptr (func, name);
       
  1366     return name;
       
  1367   }
       
  1368 }
       
  1369 #ifdef __SYMBIAN32__
       
  1370 EXPORT_C
       
  1371 #endif
       
  1372 
       
  1373 
       
  1374 void
       
  1375 _gst_debug_register_funcptr (GstDebugFuncPtr func, const gchar * ptrname)
       
  1376 {
       
  1377   gpointer ptr = (gpointer) func;
       
  1378 
       
  1379   g_static_mutex_lock (&__dbg_functions_mutex);
       
  1380 
       
  1381   if (!__gst_function_pointers)
       
  1382     __gst_function_pointers = g_hash_table_new (g_direct_hash, g_direct_equal);
       
  1383   if (!g_hash_table_lookup (__gst_function_pointers, ptr))
       
  1384     g_hash_table_insert (__gst_function_pointers, ptr, (gpointer) ptrname);
       
  1385 
       
  1386   g_static_mutex_unlock (&__dbg_functions_mutex);
       
  1387 }
       
  1388 
       
  1389 /*** PRINTF EXTENSIONS ********************************************************/
       
  1390 
       
  1391 #ifdef HAVE_PRINTF_EXTENSION
       
  1392 static int
       
  1393 _gst_info_printf_extension_ptr (FILE * stream, const struct printf_info *info,
       
  1394     const void *const *args)
       
  1395 {
       
  1396   char *buffer;
       
  1397   int len;
       
  1398   void *ptr;
       
  1399 
       
  1400   buffer = NULL;
       
  1401   ptr = *(void **) args[0];
       
  1402 
       
  1403   buffer = gst_debug_print_object (ptr);
       
  1404   len = fprintf (stream, "%*s", (info->left ? -info->width : info->width),
       
  1405       buffer);
       
  1406 
       
  1407   g_free (buffer);
       
  1408   return len;
       
  1409 }
       
  1410 
       
  1411 static int
       
  1412 _gst_info_printf_extension_segment (FILE * stream,
       
  1413     const struct printf_info *info, const void *const *args)
       
  1414 {
       
  1415   char *buffer;
       
  1416   int len;
       
  1417   void *ptr;
       
  1418 
       
  1419   buffer = NULL;
       
  1420   ptr = *(void **) args[0];
       
  1421 
       
  1422   buffer = gst_debug_print_segment (ptr);
       
  1423   len = fprintf (stream, "%*s", (info->left ? -info->width : info->width),
       
  1424       buffer);
       
  1425 
       
  1426   g_free (buffer);
       
  1427   return len;
       
  1428 }
       
  1429 
       
  1430 static int
       
  1431 _gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
       
  1432     int *argtypes)
       
  1433 {
       
  1434   if (n > 0)
       
  1435     argtypes[0] = PA_POINTER;
       
  1436   return 1;
       
  1437 }
       
  1438 #endif /* HAVE_PRINTF_EXTENSION */
       
  1439 
       
  1440 #else /* !GST_DISABLE_GST_DEBUG */
       
  1441 guint
       
  1442 gst_debug_remove_log_function (GstLogFunction func)
       
  1443 {
       
  1444   return 0;
       
  1445 }
       
  1446 
       
  1447 guint
       
  1448 gst_debug_remove_log_function_by_data (gpointer data)
       
  1449 {
       
  1450   return 0;
       
  1451 }
       
  1452 
       
  1453 gboolean
       
  1454 _priv_gst_in_valgrind (void)
       
  1455 {
       
  1456   return FALSE;
       
  1457 }
       
  1458 
       
  1459 #endif /* GST_DISABLE_GST_DEBUG */
       
  1460 
       
  1461 
       
  1462 #ifdef GST_ENABLE_FUNC_INSTRUMENTATION
       
  1463 /* FIXME make this thread specific */
       
  1464 static GSList *stack_trace = NULL;
       
  1465 
       
  1466 void
       
  1467 __cyg_profile_func_enter (void *this_fn, void *call_site)
       
  1468     G_GNUC_NO_INSTRUMENT;
       
  1469      void __cyg_profile_func_enter (void *this_fn, void *call_site)
       
  1470 {
       
  1471   gchar *name = _gst_debug_nameof_funcptr (this_fn);
       
  1472   gchar *site = _gst_debug_nameof_funcptr (call_site);
       
  1473 
       
  1474   GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "entering function %s from %s", name,
       
  1475       site);
       
  1476   stack_trace =
       
  1477       g_slist_prepend (stack_trace, g_strdup_printf ("%8p in %s from %p (%s)",
       
  1478           this_fn, name, call_site, site));
       
  1479 
       
  1480   g_free (name);
       
  1481   g_free (site);
       
  1482 }
       
  1483 
       
  1484 void
       
  1485 __cyg_profile_func_exit (void *this_fn, void *call_site)
       
  1486     G_GNUC_NO_INSTRUMENT;
       
  1487      void __cyg_profile_func_exit (void *this_fn, void *call_site)
       
  1488 {
       
  1489   gchar *name = _gst_debug_nameof_funcptr (this_fn);
       
  1490 
       
  1491   GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "leaving function %s", name);
       
  1492   g_free (stack_trace->data);
       
  1493   stack_trace = g_slist_delete_link (stack_trace, stack_trace);
       
  1494 
       
  1495   g_free (name);
       
  1496 }
       
  1497 
       
  1498 /**
       
  1499  * gst_debug_print_stack_trace:
       
  1500  *
       
  1501  * If GST_ENABLE_FUNC_INSTRUMENTATION is defined a stacktrace is available for
       
  1502  * gstreamer code, which can be printed with this function.
       
  1503  */
       
  1504 #ifdef __SYMBIAN32__
       
  1505 EXPORT_C
       
  1506 #endif
       
  1507 
       
  1508 void
       
  1509 gst_debug_print_stack_trace (void)
       
  1510 {
       
  1511   GSList *walk = stack_trace;
       
  1512   gint count = 0;
       
  1513 
       
  1514   if (walk)
       
  1515     walk = g_slist_next (walk);
       
  1516 
       
  1517   while (walk) {
       
  1518     gchar *name = (gchar *) walk->data;
       
  1519 
       
  1520     g_print ("#%-2d %s\n", count++, name);
       
  1521 
       
  1522     walk = g_slist_next (walk);
       
  1523   }
       
  1524 }
       
  1525 #else
       
  1526 void
       
  1527 gst_debug_print_stack_trace (void)
       
  1528 {
       
  1529   /* nothing because it's compiled out */
       
  1530 }
       
  1531 
       
  1532 #endif /* GST_ENABLE_FUNC_INSTRUMENTATION */
       
  1533 
       
  1534 #ifdef __SYMBIAN32__
       
  1535 EXPORT_C
       
  1536 #endif
       
  1537 GstDebugCategory ** _GST_CAT_DEFAULT()
       
  1538 {
       
  1539 	return &GST_CAT_DEFAULT;
       
  1540 }
       
  1541 #ifdef __SYMBIAN32__
       
  1542 EXPORT_C
       
  1543 #endif
       
  1544 
       
  1545 gboolean*	gst_debug_enabled()
       
  1546 {
       
  1547 	return &__gst_debug_enabled;
       
  1548 }
       
  1549 #ifdef __SYMBIAN32__
       
  1550 EXPORT_C
       
  1551 #endif
       
  1552 
       
  1553 GstDebugCategory** _GST_CAT_QOS()
       
  1554 {
       
  1555 	return &GST_CAT_QOS;
       
  1556 }
       
  1557 #ifdef __SYMBIAN32__
       
  1558 EXPORT_C
       
  1559 #endif
       
  1560 
       
  1561 
       
  1562 
       
  1563 GstDebugCategory ** _GST_CAT_EVENT()
       
  1564 {
       
  1565 	return &GST_CAT_EVENT;
       
  1566 }
       
  1567 
       
  1568 
       
  1569 //#endif