bufferlist: fix a comment
[platform/upstream/gstreamer.git] / gst / gstinfo.c
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 #define GST_INFO_C
89 #include "gst_private.h"
90 #include "gstinfo.h"
91
92 #ifndef GST_DISABLE_GST_DEBUG
93
94 #ifdef HAVE_DLFCN_H
95 #  include <dlfcn.h>
96 #endif
97 #ifdef HAVE_PRINTF_EXTENSION
98 #  include <printf.h>
99 #endif
100 #include <stdio.h>              /* fprintf */
101 #ifdef HAVE_UNISTD_H
102 #  include <unistd.h>           /* getpid on UNIX */
103 #endif
104 #ifdef HAVE_PROCESS_H
105 #  include <process.h>          /* getpid on win32 */
106 #endif
107 #include <string.h>             /* G_VA_COPY */
108 #ifdef G_OS_WIN32
109 #  define WIN32_LEAN_AND_MEAN   /* prevents from including too many things */
110 #  include <windows.h>          /* GetStdHandle, windows console */
111 #endif
112
113 #include "gst_private.h"
114 #include "gstutils.h"
115 #include "gstsegment.h"
116 #ifdef HAVE_VALGRIND_H
117 #  include <valgrind/valgrind.h>
118 #endif
119 #include <glib/gprintf.h>       /* g_sprintf */
120
121 /* underscore is to prevent conflict with GST_CAT_DEBUG define */
122 GST_DEBUG_CATEGORY_STATIC (_GST_CAT_DEBUG);
123
124 /* time of initialization, so we get useful debugging output times
125  * FIXME: we use this in gstdebugutils.c, what about a function + macro to
126  * get the running time: GST_DEBUG_RUNNING_TIME
127  */
128 GstClockTime _priv_gst_info_start_time;
129
130 #if 0
131 #if defined __sgi__
132 #include <rld_interface.h>
133 typedef struct DL_INFO
134 {
135   const char *dli_fname;
136   void *dli_fbase;
137   const char *dli_sname;
138   void *dli_saddr;
139   int dli_version;
140   int dli_reserved1;
141   long dli_reserved[4];
142 }
143 Dl_info;
144
145 #define _RLD_DLADDR             14
146 int dladdr (void *address, Dl_info * dl);
147
148 int
149 dladdr (void *address, Dl_info * dl)
150 {
151   void *v;
152
153   v = _rld_new_interface (_RLD_DLADDR, address, dl);
154   return (int) v;
155 }
156 #endif /* __sgi__ */
157 #endif
158
159 static void gst_debug_reset_threshold (gpointer category, gpointer unused);
160 static void gst_debug_reset_all_thresholds (void);
161
162 #ifdef HAVE_PRINTF_EXTENSION
163 static int _gst_info_printf_extension_ptr (FILE * stream,
164     const struct printf_info *info, const void *const *args);
165 static int _gst_info_printf_extension_segment (FILE * stream,
166     const struct printf_info *info, const void *const *args);
167 #if HAVE_REGISTER_PRINTF_SPECIFIER
168 static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
169     size_t n, int *argtypes, int *size);
170 #else
171 static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
172     size_t n, int *argtypes);
173 #endif
174 #endif
175
176 struct _GstDebugMessage
177 {
178   gchar *message;
179   const gchar *format;
180   va_list arguments;
181 };
182
183 /* list of all name/level pairs from --gst-debug and GST_DEBUG */
184 static GStaticMutex __level_name_mutex = G_STATIC_MUTEX_INIT;
185 static GSList *__level_name = NULL;
186 typedef struct
187 {
188   GPatternSpec *pat;
189   GstDebugLevel level;
190 }
191 LevelNameEntry;
192
193 /* list of all categories */
194 static GStaticMutex __cat_mutex = G_STATIC_MUTEX_INIT;
195 static GSList *__categories = NULL;
196
197 /* all registered debug handlers */
198 typedef struct
199 {
200   GstLogFunction func;
201   gpointer user_data;
202 }
203 LogFuncEntry;
204 static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
205 static GSList *__log_functions = NULL;
206
207 static gint __default_level;
208 static gint __use_color;
209
210 /* disabled by default, as soon as some threshold is set > NONE,
211  * it becomes enabled. */
212 gboolean __gst_debug_enabled = FALSE;
213 GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
214
215 GstDebugCategory *GST_CAT_DEFAULT = NULL;
216
217 GstDebugCategory *GST_CAT_GST_INIT = NULL;
218 GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
219 GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
220 GstDebugCategory *GST_CAT_PARENTAGE = NULL;
221 GstDebugCategory *GST_CAT_STATES = NULL;
222 GstDebugCategory *GST_CAT_SCHEDULING = NULL;
223
224 GstDebugCategory *GST_CAT_BUFFER = NULL;
225 GstDebugCategory *GST_CAT_BUFFER_LIST = NULL;
226 GstDebugCategory *GST_CAT_BUS = NULL;
227 GstDebugCategory *GST_CAT_CAPS = NULL;
228 GstDebugCategory *GST_CAT_CLOCK = NULL;
229 GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
230 GstDebugCategory *GST_CAT_PADS = NULL;
231 GstDebugCategory *GST_CAT_PIPELINE = NULL;
232 GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
233 GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
234 GstDebugCategory *GST_CAT_PROPERTIES = NULL;
235 GstDebugCategory *GST_CAT_TYPES = NULL;
236 GstDebugCategory *GST_CAT_XML = NULL;
237 GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
238 GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
239 GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
240 GstDebugCategory *GST_CAT_EVENT = NULL;
241 GstDebugCategory *GST_CAT_MESSAGE = NULL;
242 GstDebugCategory *GST_CAT_PARAMS = NULL;
243 GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
244 GstDebugCategory *GST_CAT_SIGNAL = NULL;
245 GstDebugCategory *GST_CAT_PROBE = NULL;
246 GstDebugCategory *GST_CAT_REGISTRY = NULL;
247 GstDebugCategory *GST_CAT_QOS = NULL;
248
249 /* FIXME: export this? */
250 gboolean
251 _priv_gst_in_valgrind (void)
252 {
253   static enum
254   {
255     GST_VG_UNCHECKED,
256     GST_VG_NO_VALGRIND,
257     GST_VG_INSIDE
258   }
259   in_valgrind = GST_VG_UNCHECKED;
260
261   if (in_valgrind == GST_VG_UNCHECKED) {
262 #ifdef HAVE_VALGRIND_H
263     if (RUNNING_ON_VALGRIND) {
264       GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind");
265       printf ("GStreamer has detected that it is running inside valgrind.\n");
266       printf ("It might now take different code paths to ease debugging.\n");
267       printf ("Of course, this may also lead to different bugs.\n");
268       in_valgrind = GST_VG_INSIDE;
269     } else {
270       GST_CAT_LOG (GST_CAT_GST_INIT, "not doing extra valgrind stuff");
271       in_valgrind = GST_VG_NO_VALGRIND;
272     }
273 #else
274     in_valgrind = GST_VG_NO_VALGRIND;
275 #endif
276     g_assert (in_valgrind == GST_VG_NO_VALGRIND ||
277         in_valgrind == GST_VG_INSIDE);
278   }
279   return (in_valgrind == GST_VG_INSIDE) ? TRUE : FALSE;
280 }
281
282 /**
283  * _gst_debug_init:
284  *
285  * Initializes the debugging system.
286  * Normally you don't want to call this, because gst_init() does it for you.
287  */
288 void
289 _gst_debug_init (void)
290 {
291   g_atomic_int_set (&__default_level, GST_LEVEL_DEFAULT);
292   g_atomic_int_set (&__use_color, 1);
293
294   /* get time we started for debugging messages */
295   _priv_gst_info_start_time = gst_util_get_timestamp ();
296
297 #ifdef HAVE_PRINTF_EXTENSION
298 #if HAVE_REGISTER_PRINTF_SPECIFIER
299   register_printf_specifier (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
300       _gst_info_printf_extension_arginfo);
301   register_printf_specifier (GST_SEGMENT_FORMAT[0],
302       _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
303 #else
304   register_printf_function (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
305       _gst_info_printf_extension_arginfo);
306   register_printf_function (GST_SEGMENT_FORMAT[0],
307       _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
308 #endif
309 #endif
310
311   /* do NOT use a single debug function before this line has been run */
312   GST_CAT_DEFAULT = _gst_debug_category_new ("default",
313       GST_DEBUG_UNDERLINE, NULL);
314   _GST_CAT_DEBUG = _gst_debug_category_new ("GST_DEBUG",
315       GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, "debugging subsystem");
316
317   gst_debug_add_log_function (gst_debug_log_default, NULL);
318
319   /* FIXME: add descriptions here */
320   GST_CAT_GST_INIT = _gst_debug_category_new ("GST_INIT",
321       GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
322   GST_CAT_AUTOPLUG = _gst_debug_category_new ("GST_AUTOPLUG",
323       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
324   GST_CAT_AUTOPLUG_ATTEMPT = _gst_debug_category_new ("GST_AUTOPLUG_ATTEMPT",
325       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN | GST_DEBUG_BG_BLUE, NULL);
326   GST_CAT_PARENTAGE = _gst_debug_category_new ("GST_PARENTAGE",
327       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
328   GST_CAT_STATES = _gst_debug_category_new ("GST_STATES",
329       GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
330   GST_CAT_SCHEDULING = _gst_debug_category_new ("GST_SCHEDULING",
331       GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
332   GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER",
333       GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
334   GST_CAT_BUFFER_LIST = _gst_debug_category_new ("GST_BUFFER_LIST",
335       GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
336   GST_CAT_BUS = _gst_debug_category_new ("GST_BUS", GST_DEBUG_BG_YELLOW, NULL);
337   GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS",
338       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
339   GST_CAT_CLOCK = _gst_debug_category_new ("GST_CLOCK",
340       GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, NULL);
341   GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS",
342       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
343   GST_CAT_PADS = _gst_debug_category_new ("GST_PADS",
344       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
345   GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE",
346       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
347   GST_CAT_PLUGIN_LOADING = _gst_debug_category_new ("GST_PLUGIN_LOADING",
348       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
349   GST_CAT_PLUGIN_INFO = _gst_debug_category_new ("GST_PLUGIN_INFO",
350       GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
351   GST_CAT_PROPERTIES = _gst_debug_category_new ("GST_PROPERTIES",
352       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL);
353   GST_CAT_TYPES = _gst_debug_category_new ("GST_TYPES",
354       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
355   GST_CAT_XML = _gst_debug_category_new ("GST_XML",
356       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
357   GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION",
358       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
359   GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING",
360       GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_BLUE, NULL);
361   GST_CAT_ERROR_SYSTEM = _gst_debug_category_new ("GST_ERROR_SYSTEM",
362       GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_WHITE, NULL);
363
364   GST_CAT_EVENT = _gst_debug_category_new ("GST_EVENT",
365       GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
366   GST_CAT_MESSAGE = _gst_debug_category_new ("GST_MESSAGE",
367       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
368   GST_CAT_PARAMS = _gst_debug_category_new ("GST_PARAMS",
369       GST_DEBUG_BOLD | GST_DEBUG_FG_BLACK | GST_DEBUG_BG_YELLOW, NULL);
370   GST_CAT_CALL_TRACE = _gst_debug_category_new ("GST_CALL_TRACE",
371       GST_DEBUG_BOLD, NULL);
372   GST_CAT_SIGNAL = _gst_debug_category_new ("GST_SIGNAL",
373       GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
374   GST_CAT_PROBE = _gst_debug_category_new ("GST_PROBE",
375       GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "pad probes");
376   GST_CAT_REGISTRY = _gst_debug_category_new ("GST_REGISTRY", 0, "registry");
377   GST_CAT_QOS = _gst_debug_category_new ("GST_QOS", 0, "QoS");
378
379
380   /* print out the valgrind message if we're in valgrind */
381   _priv_gst_in_valgrind ();
382 }
383
384 /* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
385 #define GST_CAT_DEFAULT _GST_CAT_DEBUG
386
387 /**
388  * gst_debug_log:
389  * @category: category to log
390  * @level: level of the message is in
391  * @file: the file that emitted the message, usually the __FILE__ identifier
392  * @function: the function that emitted the message
393  * @line: the line from that the message was emitted, usually __LINE__
394  * @object: the object this message relates to or NULL if none
395  * @format: a printf style format string
396  * @...: optional arguments for the format
397  *
398  * Logs the given message using the currently registered debugging handlers.
399  */
400 void
401 gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
402     const gchar * file, const gchar * function, gint line,
403     GObject * object, const gchar * format, ...)
404 {
405   va_list var_args;
406
407   va_start (var_args, format);
408   gst_debug_log_valist (category, level, file, function, line, object, format,
409       var_args);
410   va_end (var_args);
411 }
412
413 /**
414  * gst_debug_log_valist:
415  * @category: category to log
416  * @level: level of the message is in
417  * @file: the file that emitted the message, usually the __FILE__ identifier
418  * @function: the function that emitted the message
419  * @line: the line from that the message was emitted, usually __LINE__
420  * @object: the object this message relates to or NULL if none
421  * @format: a printf style format string
422  * @args: optional arguments for the format
423  *
424  * Logs the given message using the currently registered debugging handlers.
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 #ifdef _MSC_VER
436   gchar *file_basename;
437 #endif
438
439   g_return_if_fail (category != NULL);
440   g_return_if_fail (file != NULL);
441   g_return_if_fail (function != NULL);
442   g_return_if_fail (format != NULL);
443
444 #ifdef _MSC_VER
445   /*
446    * The predefined macro __FILE__ is always the exact path given to the
447    * compiler with MSVC, which may or may not be the basename.  We work
448    * around it at runtime to improve the readability.
449    */
450   file = file_basename = g_path_get_basename (file);
451 #endif
452
453   message.message = NULL;
454   message.format = format;
455   G_VA_COPY (message.arguments, args);
456
457   handler = __log_functions;
458   while (handler) {
459     entry = handler->data;
460     handler = g_slist_next (handler);
461     entry->func (category, level, file, function, line, object, &message,
462         entry->user_data);
463   }
464   g_free (message.message);
465   va_end (message.arguments);
466
467 #ifdef _MSC_VER
468   g_free (file_basename);
469 #endif
470 }
471
472 /**
473  * gst_debug_message_get:
474  * @message: a debug message
475  *
476  * Gets the string representation of a #GstDebugMessage. This function is used
477  * in debug handlers to extract the message.
478  *
479  * Returns: the string representation of a #GstDebugMessage.
480  */
481 const gchar *
482 gst_debug_message_get (GstDebugMessage * message)
483 {
484   if (message->message == NULL) {
485     message->message = g_strdup_vprintf (message->format, message->arguments);
486   }
487   return message->message;
488 }
489
490
491 static gchar *
492 gst_debug_print_object (gpointer ptr)
493 {
494   GObject *object = (GObject *) ptr;
495
496 #ifdef unused
497   /* This is a cute trick to detect unmapped memory, but is unportable,
498    * slow, screws around with madvise, and not actually that useful. */
499   {
500     int ret;
501
502     ret = madvise ((void *) ((unsigned long) ptr & (~0xfff)), 4096, 0);
503     if (ret == -1 && errno == ENOMEM) {
504       buffer = g_strdup_printf ("%p (unmapped memory)", ptr);
505     }
506   }
507 #endif
508
509   /* nicely printed object */
510   if (object == NULL) {
511     return g_strdup ("(NULL)");
512   }
513   if (*(GType *) ptr == GST_TYPE_CAPS) {
514     return gst_caps_to_string ((GstCaps *) ptr);
515   }
516   if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
517     return gst_structure_to_string ((GstStructure *) ptr);
518   }
519 #ifdef USE_POISONING
520   if (*(guint32 *) ptr == 0xffffffff) {
521     return g_strdup_printf ("<poisoned@%p>", ptr);
522   }
523 #endif
524   if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) {
525     return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object));
526   }
527   if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) {
528     return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object));
529   }
530   if (G_IS_OBJECT (object)) {
531     return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object);
532   }
533   if (GST_IS_MESSAGE (object)) {
534     GstMessage *msg = GST_MESSAGE_CAST (object);
535     gchar *s, *ret;
536
537     if (msg->structure) {
538       s = gst_structure_to_string (msg->structure);
539     } else {
540       s = g_strdup ("(NULL)");
541     }
542
543     ret = g_strdup_printf ("%s message from element '%s': %s",
544         GST_MESSAGE_TYPE_NAME (msg), (msg->src != NULL) ?
545         GST_ELEMENT_NAME (msg->src) : "(NULL)", s);
546     g_free (s);
547     return ret;
548   }
549   if (GST_IS_QUERY (object)) {
550     GstQuery *query = GST_QUERY_CAST (object);
551
552     if (query->structure) {
553       return gst_structure_to_string (query->structure);
554     } else {
555       const gchar *query_type_name;
556
557       query_type_name = gst_query_type_get_name (query->type);
558       if (G_LIKELY (query_type_name != NULL)) {
559         return g_strdup_printf ("%s query", query_type_name);
560       } else {
561         return g_strdup_printf ("query of unknown type %d", query->type);
562       }
563     }
564   }
565
566   return g_strdup_printf ("%p", ptr);
567 }
568
569 #ifdef HAVE_PRINTF_EXTENSION
570
571 static gchar *
572 gst_debug_print_segment (gpointer ptr)
573 {
574   GstSegment *segment = (GstSegment *) ptr;
575
576   /* nicely printed segment */
577   if (segment == NULL) {
578     return g_strdup ("(NULL)");
579   }
580
581   switch (segment->format) {
582     case GST_FORMAT_UNDEFINED:{
583       return g_strdup_printf ("UNDEFINED segment");
584     }
585     case GST_FORMAT_TIME:{
586       return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT
587           ", stop=%" GST_TIME_FORMAT ", last_stop=%" GST_TIME_FORMAT
588           ", duration=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f"
589           ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
590           GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
591           GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (segment->duration),
592           segment->rate, segment->applied_rate, (guint) segment->flags,
593           GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->accum));
594     }
595     default:{
596       const gchar *format_name;
597
598       format_name = gst_format_get_name (segment->format);
599       if (G_UNLIKELY (format_name == NULL))
600         format_name = "(UNKNOWN FORMAT)";
601       return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT
602           ", stop=%" G_GINT64_FORMAT ", last_stop=%" G_GINT64_FORMAT
603           ", duration=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f"
604           ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
605           format_name, segment->start, segment->stop, segment->last_stop,
606           segment->duration, segment->rate, segment->applied_rate,
607           (guint) segment->flags, GST_TIME_ARGS (segment->time),
608           GST_TIME_ARGS (segment->accum));
609     }
610   }
611 }
612
613 #endif /* HAVE_PRINTF_EXTENSION */
614
615 /**
616  * gst_debug_construct_term_color:
617  * @colorinfo: the color info
618  *
619  * Constructs a string that can be used for getting the desired color in color
620  * terminals.
621  * You need to free the string after use.
622  *
623  * Returns: a string containing the color definition
624  */
625 gchar *
626 gst_debug_construct_term_color (guint colorinfo)
627 {
628   GString *color;
629
630   color = g_string_new ("\033[00");
631
632   if (colorinfo & GST_DEBUG_BOLD) {
633     g_string_append_len (color, ";01", 3);
634   }
635   if (colorinfo & GST_DEBUG_UNDERLINE) {
636     g_string_append_len (color, ";04", 3);
637   }
638   if (colorinfo & GST_DEBUG_FG_MASK) {
639     g_string_append_printf (color, ";3%1d", colorinfo & GST_DEBUG_FG_MASK);
640   }
641   if (colorinfo & GST_DEBUG_BG_MASK) {
642     g_string_append_printf (color, ";4%1d",
643         (colorinfo & GST_DEBUG_BG_MASK) >> 4);
644   }
645   g_string_append_c (color, 'm');
646
647   return g_string_free (color, FALSE);
648 }
649
650 /**
651  * gst_debug_construct_win_color:
652  * @colorinfo: the color info
653  *
654  * Constructs an integer that can be used for getting the desired color in
655  * windows' terminals (cmd.exe). As there is no mean to underline, we simply
656  * ignore this attribute.
657  *
658  * This function returns 0 on non-windows machines.
659  *
660  * Returns: an integer containing the color definition
661  *
662  * Since: 0.10.23
663  */
664 gint
665 gst_debug_construct_win_color (guint colorinfo)
666 {
667   gint color = 0;
668 #ifdef G_OS_WIN32
669   static const guchar ansi_to_win_fg[8] = {
670     0,                          /* black   */
671     FOREGROUND_RED,             /* red     */
672     FOREGROUND_GREEN,           /* green   */
673     FOREGROUND_RED | FOREGROUND_GREEN,  /* yellow  */
674     FOREGROUND_BLUE,            /* blue    */
675     FOREGROUND_RED | FOREGROUND_BLUE,   /* magenta */
676     FOREGROUND_GREEN | FOREGROUND_BLUE, /* cyan    */
677     FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* white   */
678   };
679   static const guchar ansi_to_win_bg[8] = {
680     0,
681     BACKGROUND_RED,
682     BACKGROUND_GREEN,
683     BACKGROUND_RED | BACKGROUND_GREEN,
684     BACKGROUND_BLUE,
685     BACKGROUND_RED | BACKGROUND_BLUE,
686     BACKGROUND_GREEN | FOREGROUND_BLUE,
687     BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
688   };
689
690   /* we draw black as white, as cmd.exe can only have black bg */
691   if (colorinfo == 0) {
692     return ansi_to_win_fg[7];
693   }
694
695   if (colorinfo & GST_DEBUG_BOLD) {
696     color |= FOREGROUND_INTENSITY;
697   }
698   if (colorinfo & GST_DEBUG_FG_MASK) {
699     color |= ansi_to_win_fg[colorinfo & GST_DEBUG_FG_MASK];
700   }
701   if (colorinfo & GST_DEBUG_BG_MASK) {
702     color |= ansi_to_win_bg[(colorinfo & GST_DEBUG_BG_MASK) >> 4];
703   }
704 #endif
705   return color;
706 }
707
708 /* width of %p varies depending on actual value of pointer, which can make
709  * output unevenly aligned if multiple threads are involved, hence the %14p
710  * (should really be %18p, but %14p seems a good compromise between too many
711  * white spaces and likely unalignment on my system) */
712 #if defined (GLIB_SIZEOF_VOID_P) && GLIB_SIZEOF_VOID_P == 8
713 #define PTR_FMT "%14p"
714 #else
715 #define PTR_FMT "%10p"
716 #endif
717 #define PID_FMT "%5d"
718 #define CAT_FMT "%20s %s:%d:%s:%s"
719
720 #ifdef G_OS_WIN32
721 static const guchar levelcolormap[GST_LEVEL_COUNT] = {
722   /* GST_LEVEL_NONE */
723   FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
724   /* GST_LEVEL_ERROR */
725   FOREGROUND_RED | FOREGROUND_INTENSITY,
726   /* GST_LEVEL_WARNING */
727   FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
728   /* GST_LEVEL_INFO */
729   FOREGROUND_GREEN | FOREGROUND_INTENSITY,
730   /* GST_LEVEL_DEBUG */
731   FOREGROUND_GREEN | FOREGROUND_BLUE,
732   /* GST_LEVEL_LOG */
733   FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
734   /* GST_LEVEL_FIXME */
735   FOREGROUND_RED | FOREGROUND_GREEN,
736   /* placeholder for log level 7 */
737   0,
738   /* placeholder for log level 8 */
739   0,
740   /* GST_LEVEL_MEMDUMP */
741   FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
742 };
743
744 static const guchar available_colors[] = {
745   FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_RED | FOREGROUND_GREEN,
746   FOREGROUND_BLUE, FOREGROUND_RED | FOREGROUND_BLUE,
747   FOREGROUND_GREEN | FOREGROUND_BLUE,
748 };
749 #else
750 static const gchar *levelcolormap[GST_LEVEL_COUNT] = {
751   "\033[37m",                   /* GST_LEVEL_NONE */
752   "\033[31;01m",                /* GST_LEVEL_ERROR */
753   "\033[33;01m",                /* GST_LEVEL_WARNING */
754   "\033[32;01m",                /* GST_LEVEL_INFO */
755   "\033[36m",                   /* GST_LEVEL_DEBUG */
756   "\033[37m",                   /* GST_LEVEL_LOG */
757   "\033[33;01m",                /* GST_LEVEL_FIXME */
758   "\033[37m",                   /* placeholder for log level 7 */
759   "\033[37m",                   /* placeholder for log level 8 */
760   "\033[37m"                    /* GST_LEVEL_MEMDUMP */
761 };
762 #endif
763
764 /**
765  * gst_debug_log_default:
766  * @category: category to log
767  * @level: level of the message
768  * @file: the file that emitted the message, usually the __FILE__ identifier
769  * @function: the function that emitted the message
770  * @line: the line from that the message was emitted, usually __LINE__
771  * @message: the actual message
772  * @object: the object this message relates to or NULL if none
773  * @unused: an unused variable, reserved for some user_data.
774  *
775  * The default logging handler used by GStreamer. Logging functions get called
776  * whenever a macro like GST_DEBUG or similar is used. This function outputs the
777  * message and additional info using the glib error handler.
778  * You can add other handlers by using gst_debug_add_log_function().
779  * And you can remove this handler by calling
780  * gst_debug_remove_log_function(gst_debug_log_default);
781  */
782 void
783 gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
784     const gchar * file, const gchar * function, gint line,
785     GObject * object, GstDebugMessage * message, gpointer unused)
786 {
787   gint pid;
788   GstClockTime elapsed;
789   gchar *obj = NULL;
790   gboolean free_obj = TRUE;
791   gboolean is_colored;
792
793   if (level > gst_debug_category_get_threshold (category))
794     return;
795
796   pid = getpid ();
797   is_colored = gst_debug_is_colored ();
798
799   elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
800       gst_util_get_timestamp ());
801
802   if (object) {
803     obj = gst_debug_print_object (object);
804   } else {
805     obj = "\0";
806     free_obj = FALSE;
807   }
808
809   if (is_colored) {
810 #ifndef G_OS_WIN32
811     /* colors, non-windows */
812     gchar *color = NULL;
813     gchar *clear;
814     gchar pidcolor[10];
815     const gchar *levelcolor;
816
817     color = gst_debug_construct_term_color (gst_debug_category_get_color
818         (category));
819     clear = "\033[00m";
820     g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
821     levelcolor = levelcolormap[level];
822
823 #define PRINT_FMT " %s"PID_FMT"%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n"
824     g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
825         pidcolor, pid, clear, g_thread_self (), levelcolor,
826         gst_debug_level_get_name (level), clear, color,
827         gst_debug_category_get_name (category), file, line, function, obj,
828         clear, gst_debug_message_get (message));
829 #undef PRINT_FMT
830     g_free (color);
831 #else
832     /* colors, windows. We take a lock to keep colors and content together.
833      * Maybe there is a better way but for now this will do the right
834      * thing. */
835     static GStaticMutex win_print_mutex = G_STATIC_MUTEX_INIT;
836     const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
837 #define SET_COLOR(c) \
838   SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c));
839     g_static_mutex_lock (&win_print_mutex);
840     /* timestamp */
841     g_printerr ("%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed));
842     /* pid */
843     SET_COLOR (available_colors[pid % G_N_ELEMENTS (available_colors)]);
844     g_printerr (PID_FMT, pid);
845     /* thread */
846     SET_COLOR (clear);
847     g_printerr (" " PTR_FMT " ", g_thread_self ());
848     /* level */
849     SET_COLOR (levelcolormap[level]);
850     g_printerr ("%s ", gst_debug_level_get_name (level));
851     /* category */
852     SET_COLOR (gst_debug_construct_win_color (gst_debug_category_get_color
853             (category)));
854     g_printerr (CAT_FMT, gst_debug_category_get_name (category),
855         file, line, function, obj);
856     /* message */
857     SET_COLOR (clear);
858     g_printerr (" %s\n", gst_debug_message_get (message));
859     g_static_mutex_unlock (&win_print_mutex);
860 #endif
861   } else {
862     /* no color, all platforms */
863 #define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
864     g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), pid,
865         g_thread_self (), gst_debug_level_get_name (level),
866         gst_debug_category_get_name (category), file, line, function, obj,
867         gst_debug_message_get (message));
868 #undef PRINT_FMT
869   }
870
871   if (free_obj)
872     g_free (obj);
873 }
874
875 /**
876  * gst_debug_level_get_name:
877  * @level: the level to get the name for
878  *
879  * Get the string representation of a debugging level
880  *
881  * Returns: the name
882  */
883 const gchar *
884 gst_debug_level_get_name (GstDebugLevel level)
885 {
886   switch (level) {
887     case GST_LEVEL_NONE:
888       return "";
889     case GST_LEVEL_ERROR:
890       return "ERROR";
891     case GST_LEVEL_WARNING:
892       return "WARN ";
893     case GST_LEVEL_INFO:
894       return "INFO ";
895     case GST_LEVEL_DEBUG:
896       return "DEBUG";
897     case GST_LEVEL_LOG:
898       return "LOG  ";
899     case GST_LEVEL_FIXME:
900       return "FIXME";
901     case GST_LEVEL_MEMDUMP:
902       return "MEMDUMP  ";
903     default:
904       g_warning ("invalid level specified for gst_debug_level_get_name");
905       return "";
906   }
907 }
908
909 /**
910  * gst_debug_add_log_function:
911  * @func: the function to use
912  * @data: user data
913  *
914  * Adds the logging function to the list of logging functions.
915  * Be sure to use G_GNUC_NO_INSTRUMENT on that function, it is needed.
916  */
917 void
918 gst_debug_add_log_function (GstLogFunction func, gpointer data)
919 {
920   LogFuncEntry *entry;
921   GSList *list;
922
923   g_return_if_fail (func != NULL);
924
925   entry = g_new (LogFuncEntry, 1);
926   entry->func = func;
927   entry->user_data = data;
928   /* FIXME: we leak the old list here - other threads might access it right now
929    * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv,
930    * but that is waaay costly.
931    * It'd probably be clever to use some kind of RCU here, but I don't know
932    * anything about that.
933    */
934   g_static_mutex_lock (&__log_func_mutex);
935   list = g_slist_copy (__log_functions);
936   __log_functions = g_slist_prepend (list, entry);
937   g_static_mutex_unlock (&__log_func_mutex);
938
939   GST_DEBUG ("prepended log function %p (user data %p) to log functions",
940       func, data);
941 }
942
943 static gint
944 gst_debug_compare_log_function_by_func (gconstpointer entry, gconstpointer func)
945 {
946   gpointer entryfunc = (gpointer) (((LogFuncEntry *) entry)->func);
947
948   return (entryfunc < func) ? -1 : (entryfunc > func) ? 1 : 0;
949 }
950
951 static gint
952 gst_debug_compare_log_function_by_data (gconstpointer entry, gconstpointer data)
953 {
954   gpointer entrydata = ((LogFuncEntry *) entry)->user_data;
955
956   return (entrydata < data) ? -1 : (entrydata > data) ? 1 : 0;
957 }
958
959 static guint
960 gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
961 {
962   GSList *found;
963   GSList *new;
964   guint removals = 0;
965
966   g_static_mutex_lock (&__log_func_mutex);
967   new = __log_functions;
968   while ((found = g_slist_find_custom (new, data, func))) {
969     if (new == __log_functions) {
970       /* make a copy when we have the first hit, so that we modify the copy and
971        * make that the new list later */
972       new = g_slist_copy (new);
973       continue;
974     }
975     g_free (found->data);
976     new = g_slist_delete_link (new, found);
977     removals++;
978   }
979   /* FIXME: We leak the old list here. See _add_log_function for why. */
980   __log_functions = new;
981   g_static_mutex_unlock (&__log_func_mutex);
982
983   return removals;
984 }
985
986 /**
987  * gst_debug_remove_log_function:
988  * @func: the log function to remove
989  *
990  * Removes all registered instances of the given logging functions.
991  *
992  * Returns: How many instances of the function were removed
993  */
994 guint
995 gst_debug_remove_log_function (GstLogFunction func)
996 {
997   guint removals;
998
999   g_return_val_if_fail (func != NULL, 0);
1000
1001   removals =
1002       gst_debug_remove_with_compare_func
1003       (gst_debug_compare_log_function_by_func, (gpointer) func);
1004   GST_DEBUG ("removed log function %p %d times from log function list", func,
1005       removals);
1006
1007   return removals;
1008 }
1009
1010 /**
1011  * gst_debug_remove_log_function_by_data:
1012  * @data: user data of the log function to remove
1013  *
1014  * Removes all registered instances of log functions with the given user data.
1015  *
1016  * Returns: How many instances of the function were removed
1017  */
1018 guint
1019 gst_debug_remove_log_function_by_data (gpointer data)
1020 {
1021   guint removals;
1022
1023   removals =
1024       gst_debug_remove_with_compare_func
1025       (gst_debug_compare_log_function_by_data, data);
1026   GST_DEBUG
1027       ("removed %d log functions with user data %p from log function list",
1028       removals, data);
1029
1030   return removals;
1031 }
1032
1033 /**
1034  * gst_debug_set_colored:
1035  * @colored: Whether to use colored output or not
1036  *
1037  * Sets or unsets the use of coloured debugging output.
1038  */
1039 void
1040 gst_debug_set_colored (gboolean colored)
1041 {
1042   g_atomic_int_set (&__use_color, colored ? 1 : 0);
1043 }
1044
1045 /**
1046  * gst_debug_is_colored:
1047  *
1048  * Checks if the debugging output should be colored.
1049  *
1050  * Returns: TRUE, if the debug output should be colored.
1051  */
1052 gboolean
1053 gst_debug_is_colored (void)
1054 {
1055   return g_atomic_int_get (&__use_color) == 0 ? FALSE : TRUE;
1056 }
1057
1058 /**
1059  * gst_debug_set_active:
1060  * @active: Whether to use debugging output or not
1061  *
1062  * If activated, debugging messages are sent to the debugging
1063  * handlers.
1064  * It makes sense to deactivate it for speed issues.
1065  * <note><para>This function is not threadsafe. It makes sense to only call it
1066  * during initialization.</para></note>
1067  */
1068 void
1069 gst_debug_set_active (gboolean active)
1070 {
1071   __gst_debug_enabled = active;
1072   if (active)
1073     __gst_debug_min = GST_LEVEL_COUNT;
1074   else
1075     __gst_debug_min = GST_LEVEL_NONE;
1076 }
1077
1078 /**
1079  * gst_debug_is_active:
1080  *
1081  * Checks if debugging output is activated.
1082  *
1083  * Returns: TRUE, if debugging is activated
1084  */
1085 gboolean
1086 gst_debug_is_active (void)
1087 {
1088   return __gst_debug_enabled;
1089 }
1090
1091 /**
1092  * gst_debug_set_default_threshold:
1093  * @level: level to set
1094  *
1095  * Sets the default threshold to the given level and updates all categories to
1096  * use this threshold.
1097  */
1098 void
1099 gst_debug_set_default_threshold (GstDebugLevel level)
1100 {
1101   g_atomic_int_set (&__default_level, level);
1102   gst_debug_reset_all_thresholds ();
1103 }
1104
1105 /**
1106  * gst_debug_get_default_threshold:
1107  *
1108  * Returns the default threshold that is used for new categories.
1109  *
1110  * Returns: the default threshold level
1111  */
1112 GstDebugLevel
1113 gst_debug_get_default_threshold (void)
1114 {
1115   return (GstDebugLevel) g_atomic_int_get (&__default_level);
1116 }
1117
1118 static void
1119 gst_debug_reset_threshold (gpointer category, gpointer unused)
1120 {
1121   GstDebugCategory *cat = (GstDebugCategory *) category;
1122   GSList *walk;
1123
1124   g_static_mutex_lock (&__level_name_mutex);
1125   walk = __level_name;
1126   while (walk) {
1127     LevelNameEntry *entry = walk->data;
1128
1129     walk = g_slist_next (walk);
1130     if (g_pattern_match_string (entry->pat, cat->name)) {
1131       GST_LOG ("category %s matches pattern %p - gets set to level %d",
1132           cat->name, entry->pat, entry->level);
1133       gst_debug_category_set_threshold (cat, entry->level);
1134       goto exit;
1135     }
1136   }
1137   gst_debug_category_set_threshold (cat, gst_debug_get_default_threshold ());
1138
1139 exit:
1140   g_static_mutex_unlock (&__level_name_mutex);
1141 }
1142
1143 static void
1144 gst_debug_reset_all_thresholds (void)
1145 {
1146   g_static_mutex_lock (&__cat_mutex);
1147   g_slist_foreach (__categories, gst_debug_reset_threshold, NULL);
1148   g_static_mutex_unlock (&__cat_mutex);
1149 }
1150
1151 static void
1152 for_each_threshold_by_entry (gpointer data, gpointer user_data)
1153 {
1154   GstDebugCategory *cat = (GstDebugCategory *) data;
1155   LevelNameEntry *entry = (LevelNameEntry *) user_data;
1156
1157   if (g_pattern_match_string (entry->pat, cat->name)) {
1158     GST_LOG ("category %s matches pattern %p - gets set to level %d",
1159         cat->name, entry->pat, entry->level);
1160     gst_debug_category_set_threshold (cat, entry->level);
1161   }
1162 }
1163
1164 /**
1165  * gst_debug_set_threshold_for_name:
1166  * @name: name of the categories to set
1167  * @level: level to set them to
1168  *
1169  * Sets all categories which match the given glob style pattern to the given
1170  * level.
1171  */
1172 void
1173 gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
1174 {
1175   GPatternSpec *pat;
1176   LevelNameEntry *entry;
1177
1178   g_return_if_fail (name != NULL);
1179
1180   pat = g_pattern_spec_new (name);
1181   entry = g_new (LevelNameEntry, 1);
1182   entry->pat = pat;
1183   entry->level = level;
1184   g_static_mutex_lock (&__level_name_mutex);
1185   __level_name = g_slist_prepend (__level_name, entry);
1186   g_static_mutex_unlock (&__level_name_mutex);
1187   g_static_mutex_lock (&__cat_mutex);
1188   g_slist_foreach (__categories, for_each_threshold_by_entry, entry);
1189   g_static_mutex_unlock (&__cat_mutex);
1190 }
1191
1192 /**
1193  * gst_debug_unset_threshold_for_name:
1194  * @name: name of the categories to set
1195  *
1196  * Resets all categories with the given name back to the default level.
1197  */
1198 void
1199 gst_debug_unset_threshold_for_name (const gchar * name)
1200 {
1201   GSList *walk;
1202   GPatternSpec *pat;
1203
1204   g_return_if_fail (name != NULL);
1205
1206   pat = g_pattern_spec_new (name);
1207   g_static_mutex_lock (&__level_name_mutex);
1208   walk = __level_name;
1209   /* improve this if you want, it's mighty slow */
1210   while (walk) {
1211     LevelNameEntry *entry = walk->data;
1212
1213     if (g_pattern_spec_equal (entry->pat, pat)) {
1214       __level_name = g_slist_remove_link (__level_name, walk);
1215       g_pattern_spec_free (entry->pat);
1216       g_free (entry);
1217       g_slist_free_1 (walk);
1218       walk = __level_name;
1219     }
1220   }
1221   g_static_mutex_unlock (&__level_name_mutex);
1222   g_pattern_spec_free (pat);
1223   gst_debug_reset_all_thresholds ();
1224 }
1225
1226 GstDebugCategory *
1227 _gst_debug_category_new (const gchar * name, guint color,
1228     const gchar * description)
1229 {
1230   GstDebugCategory *cat;
1231
1232   g_return_val_if_fail (name != NULL, NULL);
1233
1234   cat = g_new (GstDebugCategory, 1);
1235   cat->name = g_strdup (name);
1236   cat->color = color;
1237   if (description != NULL) {
1238     cat->description = g_strdup (description);
1239   } else {
1240     cat->description = g_strdup ("no description");
1241   }
1242   g_atomic_int_set (&cat->threshold, 0);
1243   gst_debug_reset_threshold (cat, NULL);
1244
1245   /* add to category list */
1246   g_static_mutex_lock (&__cat_mutex);
1247   __categories = g_slist_prepend (__categories, cat);
1248   g_static_mutex_unlock (&__cat_mutex);
1249
1250   return cat;
1251 }
1252
1253 /**
1254  * gst_debug_category_free:
1255  * @category: #GstDebugCategory to free.
1256  *
1257  * Removes and frees the category and all associated resources.
1258  */
1259 void
1260 gst_debug_category_free (GstDebugCategory * category)
1261 {
1262   if (category == NULL)
1263     return;
1264
1265   /* remove from category list */
1266   g_static_mutex_lock (&__cat_mutex);
1267   __categories = g_slist_remove (__categories, category);
1268   g_static_mutex_unlock (&__cat_mutex);
1269
1270   g_free ((gpointer) category->name);
1271   g_free ((gpointer) category->description);
1272   g_free (category);
1273 }
1274
1275 /**
1276  * gst_debug_category_set_threshold:
1277  * @category: a #GstDebugCategory to set threshold of.
1278  * @level: the #GstDebugLevel threshold to set.
1279  *
1280  * Sets the threshold of the category to the given level. Debug information will
1281  * only be output if the threshold is lower or equal to the level of the
1282  * debugging message.
1283  * <note><para>
1284  * Do not use this function in production code, because other functions may
1285  * change the threshold of categories as side effect. It is however a nice
1286  * function to use when debugging (even from gdb).
1287  * </para></note>
1288  */
1289 void
1290 gst_debug_category_set_threshold (GstDebugCategory * category,
1291     GstDebugLevel level)
1292 {
1293   g_return_if_fail (category != NULL);
1294
1295   if (level > __gst_debug_min) {
1296     __gst_debug_enabled = TRUE;
1297     __gst_debug_min = level;
1298   }
1299
1300   g_atomic_int_set (&category->threshold, level);
1301 }
1302
1303 /**
1304  * gst_debug_category_reset_threshold:
1305  * @category: a #GstDebugCategory to reset threshold of.
1306  *
1307  * Resets the threshold of the category to the default level. Debug information
1308  * will only be output if the threshold is lower or equal to the level of the
1309  * debugging message.
1310  * Use this function to set the threshold back to where it was after using
1311  * gst_debug_category_set_threshold().
1312  */
1313 void
1314 gst_debug_category_reset_threshold (GstDebugCategory * category)
1315 {
1316   gst_debug_reset_threshold (category, NULL);
1317 }
1318
1319 /**
1320  * gst_debug_category_get_threshold:
1321  * @category: a #GstDebugCategory to get threshold of.
1322  *
1323  * Returns the threshold of a #GstDebugCategory.
1324  *
1325  * Returns: the #GstDebugLevel that is used as threshold.
1326  */
1327 GstDebugLevel
1328 gst_debug_category_get_threshold (GstDebugCategory * category)
1329 {
1330   return g_atomic_int_get (&category->threshold);
1331 }
1332
1333 /**
1334  * gst_debug_category_get_name:
1335  * @category: a #GstDebugCategory to get name of.
1336  *
1337  * Returns the name of a debug category.
1338  *
1339  * Returns: the name of the category.
1340  */
1341 const gchar *
1342 gst_debug_category_get_name (GstDebugCategory * category)
1343 {
1344   return category->name;
1345 }
1346
1347 /**
1348  * gst_debug_category_get_color:
1349  * @category: a #GstDebugCategory to get the color of.
1350  *
1351  * Returns the color of a debug category used when printing output in this
1352  * category.
1353  *
1354  * Returns: the color of the category.
1355  */
1356 guint
1357 gst_debug_category_get_color (GstDebugCategory * category)
1358 {
1359   return category->color;
1360 }
1361
1362 /**
1363  * gst_debug_category_get_description:
1364  * @category: a #GstDebugCategory to get the description of.
1365  *
1366  * Returns the description of a debug category.
1367  *
1368  * Returns: the description of the category.
1369  */
1370 const gchar *
1371 gst_debug_category_get_description (GstDebugCategory * category)
1372 {
1373   return category->description;
1374 }
1375
1376 /**
1377  * gst_debug_get_all_categories:
1378  *
1379  * Returns a snapshot of a all categories that are currently in use . This list
1380  * may change anytime.
1381  * The caller has to free the list after use.
1382  *
1383  * Returns: the list of categories
1384  */
1385 GSList *
1386 gst_debug_get_all_categories (void)
1387 {
1388   GSList *ret;
1389
1390   g_static_mutex_lock (&__cat_mutex);
1391   ret = g_slist_copy (__categories);
1392   g_static_mutex_unlock (&__cat_mutex);
1393
1394   return ret;
1395 }
1396
1397 /*** FUNCTION POINTERS ********************************************************/
1398
1399 static GHashTable *__gst_function_pointers;     /* NULL */
1400 static GStaticMutex __dbg_functions_mutex = G_STATIC_MUTEX_INIT;
1401
1402 const gchar *
1403 _gst_debug_nameof_funcptr (GstDebugFuncPtr ptr)
1404     G_GNUC_NO_INSTRUMENT;
1405
1406 /* This function MUST NOT return NULL */
1407      const gchar *_gst_debug_nameof_funcptr (GstDebugFuncPtr func)
1408 {
1409   gchar *ptrname;
1410
1411 #ifdef HAVE_DLADDR
1412   Dl_info dl_info;
1413 #endif
1414
1415   if (G_UNLIKELY (func == NULL))
1416     return "(NULL)";
1417
1418   g_static_mutex_lock (&__dbg_functions_mutex);
1419   if (G_LIKELY (__gst_function_pointers)) {
1420     ptrname = g_hash_table_lookup (__gst_function_pointers, (gpointer) func);
1421     g_static_mutex_unlock (&__dbg_functions_mutex);
1422     if (G_LIKELY (ptrname))
1423       return ptrname;
1424   } else {
1425     g_static_mutex_unlock (&__dbg_functions_mutex);
1426   }
1427   /* we need to create an entry in the hash table for this one so we don't leak
1428    * the name */
1429 #ifdef HAVE_DLADDR
1430   if (dladdr ((gpointer) func, &dl_info) && dl_info.dli_sname) {
1431     gchar *name = g_strdup (dl_info.dli_sname);
1432
1433     _gst_debug_register_funcptr (func, name);
1434     return name;
1435   } else
1436 #endif
1437   {
1438     gchar *name = g_strdup_printf ("%p", (gpointer) func);
1439
1440     _gst_debug_register_funcptr (func, name);
1441     return name;
1442   }
1443 }
1444
1445 void
1446 _gst_debug_register_funcptr (GstDebugFuncPtr func, const gchar * ptrname)
1447 {
1448   gpointer ptr = (gpointer) func;
1449
1450   g_static_mutex_lock (&__dbg_functions_mutex);
1451
1452   if (!__gst_function_pointers)
1453     __gst_function_pointers = g_hash_table_new (g_direct_hash, g_direct_equal);
1454   if (!g_hash_table_lookup (__gst_function_pointers, ptr))
1455     g_hash_table_insert (__gst_function_pointers, ptr, (gpointer) ptrname);
1456
1457   g_static_mutex_unlock (&__dbg_functions_mutex);
1458 }
1459
1460 /*** PRINTF EXTENSIONS ********************************************************/
1461
1462 #ifdef HAVE_PRINTF_EXTENSION
1463 static int
1464 _gst_info_printf_extension_ptr (FILE * stream, const struct printf_info *info,
1465     const void *const *args)
1466 {
1467   char *buffer;
1468   int len;
1469   void *ptr;
1470
1471   buffer = NULL;
1472   ptr = *(void **) args[0];
1473
1474   buffer = gst_debug_print_object (ptr);
1475   len = fprintf (stream, "%*s", (info->left ? -info->width : info->width),
1476       buffer);
1477
1478   g_free (buffer);
1479   return len;
1480 }
1481
1482 static int
1483 _gst_info_printf_extension_segment (FILE * stream,
1484     const struct printf_info *info, const void *const *args)
1485 {
1486   char *buffer;
1487   int len;
1488   void *ptr;
1489
1490   buffer = NULL;
1491   ptr = *(void **) args[0];
1492
1493   buffer = gst_debug_print_segment (ptr);
1494   len = fprintf (stream, "%*s", (info->left ? -info->width : info->width),
1495       buffer);
1496
1497   g_free (buffer);
1498   return len;
1499 }
1500
1501 #if HAVE_REGISTER_PRINTF_SPECIFIER
1502 static int
1503 _gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
1504     int *argtypes, int *size)
1505 #else
1506 static int
1507 _gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
1508     int *argtypes)
1509 #endif
1510 {
1511   if (n > 0) {
1512     argtypes[0] = PA_POINTER;
1513 #if HAVE_REGISTER_PRINTF_SPECIFIER
1514     *size = sizeof (gpointer);
1515 #endif
1516   }
1517   return 1;
1518 }
1519 #endif /* HAVE_PRINTF_EXTENSION */
1520
1521 static void
1522 gst_info_dump_mem_line (gchar * linebuf, gsize linebuf_size,
1523     const guint8 * mem, gsize mem_offset, gsize mem_size)
1524 {
1525   gchar hexstr[50], ascstr[18], digitstr[4];
1526
1527   if (mem_size > 16)
1528     mem_size = 16;
1529
1530   hexstr[0] = '\0';
1531   ascstr[0] = '\0';
1532
1533   if (mem != NULL) {
1534     guint i = 0;
1535
1536     mem += mem_offset;
1537     while (i < mem_size) {
1538       ascstr[i] = (g_ascii_isprint (mem[i])) ? mem[i] : '.';
1539       g_snprintf (digitstr, sizeof (digitstr), "%02x ", mem[i]);
1540       g_strlcat (hexstr, digitstr, sizeof (hexstr));
1541       ++i;
1542     }
1543     ascstr[i] = '\0';
1544   }
1545
1546   g_snprintf (linebuf, linebuf_size, "%08x: %-48.48s %-16.16s",
1547       (guint) mem_offset, hexstr, ascstr);
1548 }
1549
1550 void
1551 _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
1552     const gchar * func, gint line, GObject * obj, const gchar * msg,
1553     const guint8 * data, guint length)
1554 {
1555   guint off = 0;
1556
1557   gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------"
1558       "-------------------------------------------------------------------");
1559
1560   if (msg != NULL && *msg != '\0') {
1561     gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, msg);
1562   }
1563
1564   while (off < length) {
1565     gchar buf[128];
1566
1567     /* gst_info_dump_mem_line will process 16 bytes at most */
1568     gst_info_dump_mem_line (buf, sizeof (buf), data, off, length - off);
1569     gst_debug_log (cat, GST_LEVEL_MEMDUMP, file, func, line, obj, "%s", buf);
1570     off += 16;
1571   }
1572
1573   gst_debug_log ((cat), GST_LEVEL_MEMDUMP, file, func, line, obj, "--------"
1574       "-------------------------------------------------------------------");
1575 }
1576
1577 #else /* !GST_DISABLE_GST_DEBUG */
1578 #ifndef GST_REMOVE_DISABLED
1579 void
1580 gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
1581     const gchar * file, const gchar * function, gint line,
1582     GObject * object, const gchar * format, ...)
1583 {
1584 }
1585
1586 void
1587 gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
1588     const gchar * file, const gchar * function, gint line,
1589     GObject * object, const gchar * format, va_list args)
1590 {
1591 }
1592
1593 const gchar *
1594 gst_debug_message_get (GstDebugMessage * message)
1595 {
1596   return "";
1597 }
1598
1599 void
1600 gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
1601     const gchar * file, const gchar * function, gint line,
1602     GObject * object, GstDebugMessage * message, gpointer unused)
1603 {
1604 }
1605
1606 G_CONST_RETURN gchar *
1607 gst_debug_level_get_name (GstDebugLevel level)
1608 {
1609   return "NONE";
1610 }
1611
1612 void
1613 gst_debug_add_log_function (GstLogFunction func, gpointer data)
1614 {
1615 }
1616
1617 guint
1618 gst_debug_remove_log_function (GstLogFunction func)
1619 {
1620   return 0;
1621 }
1622
1623 guint
1624 gst_debug_remove_log_function_by_data (gpointer data)
1625 {
1626   return 0;
1627 }
1628
1629 void
1630 gst_debug_set_active (gboolean active)
1631 {
1632 }
1633
1634 gboolean
1635 gst_debug_is_active (void)
1636 {
1637   return FALSE;
1638 }
1639
1640 void
1641 gst_debug_set_colored (gboolean colored)
1642 {
1643 }
1644
1645 gboolean
1646 gst_debug_is_colored (void)
1647 {
1648   return FALSE;
1649 }
1650
1651 void
1652 gst_debug_set_default_threshold (GstDebugLevel level)
1653 {
1654 }
1655
1656 GstDebugLevel
1657 gst_debug_get_default_threshold (void)
1658 {
1659   return GST_LEVEL_NONE;
1660 }
1661
1662 void
1663 gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
1664 {
1665 }
1666
1667 void
1668 gst_debug_unset_threshold_for_name (const gchar * name)
1669 {
1670 }
1671
1672 void
1673 gst_debug_category_free (GstDebugCategory * category)
1674 {
1675 }
1676
1677 void
1678 gst_debug_category_set_threshold (GstDebugCategory * category,
1679     GstDebugLevel level)
1680 {
1681 }
1682
1683 void
1684 gst_debug_category_reset_threshold (GstDebugCategory * category)
1685 {
1686 }
1687
1688 GstDebugLevel
1689 gst_debug_category_get_threshold (GstDebugCategory * category)
1690 {
1691   return GST_LEVEL_NONE;
1692 }
1693
1694 G_CONST_RETURN gchar *
1695 gst_debug_category_get_name (GstDebugCategory * category)
1696 {
1697   return "";
1698 }
1699
1700 guint
1701 gst_debug_category_get_color (GstDebugCategory * category)
1702 {
1703   return 0;
1704 }
1705
1706 G_CONST_RETURN gchar *
1707 gst_debug_category_get_description (GstDebugCategory * category)
1708 {
1709   return "";
1710 }
1711
1712 GSList *
1713 gst_debug_get_all_categories (void)
1714 {
1715   return NULL;
1716 }
1717
1718 gchar *
1719 gst_debug_construct_term_color (guint colorinfo)
1720 {
1721   return g_strdup ("00");
1722 }
1723
1724 gint
1725 gst_debug_construct_win_color (guint colorinfo)
1726 {
1727   return 0;
1728 }
1729
1730 gboolean
1731 _priv_gst_in_valgrind (void)
1732 {
1733   return FALSE;
1734 }
1735
1736 void
1737 _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
1738     const gchar * func, gint line, GObject * obj, const gchar * msg,
1739     const guint8 * data, guint length)
1740 {
1741 }
1742 #endif /* GST_REMOVE_DISABLED */
1743 #endif /* GST_DISABLE_GST_DEBUG */
1744
1745
1746 #ifdef GST_ENABLE_FUNC_INSTRUMENTATION
1747 /* FIXME make this thread specific */
1748 static GSList *stack_trace = NULL;
1749
1750 void
1751 __cyg_profile_func_enter (void *this_fn, void *call_site)
1752     G_GNUC_NO_INSTRUMENT;
1753      void __cyg_profile_func_enter (void *this_fn, void *call_site)
1754 {
1755   gchar *name = _gst_debug_nameof_funcptr (this_fn);
1756   gchar *site = _gst_debug_nameof_funcptr (call_site);
1757
1758   GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "entering function %s from %s", name,
1759       site);
1760   stack_trace =
1761       g_slist_prepend (stack_trace, g_strdup_printf ("%8p in %s from %p (%s)",
1762           this_fn, name, call_site, site));
1763
1764   g_free (name);
1765   g_free (site);
1766 }
1767
1768 void
1769 __cyg_profile_func_exit (void *this_fn, void *call_site)
1770     G_GNUC_NO_INSTRUMENT;
1771      void __cyg_profile_func_exit (void *this_fn, void *call_site)
1772 {
1773   gchar *name = _gst_debug_nameof_funcptr (this_fn);
1774
1775   GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "leaving function %s", name);
1776   g_free (stack_trace->data);
1777   stack_trace = g_slist_delete_link (stack_trace, stack_trace);
1778
1779   g_free (name);
1780 }
1781
1782 /**
1783  * gst_debug_print_stack_trace:
1784  *
1785  * If GST_ENABLE_FUNC_INSTRUMENTATION is defined a stacktrace is available for
1786  * gstreamer code, which can be printed with this function.
1787  */
1788 void
1789 gst_debug_print_stack_trace (void)
1790 {
1791   GSList *walk = stack_trace;
1792   gint count = 0;
1793
1794   if (walk)
1795     walk = g_slist_next (walk);
1796
1797   while (walk) {
1798     gchar *name = (gchar *) walk->data;
1799
1800     g_print ("#%-2d %s\n", count++, name);
1801
1802     walk = g_slist_next (walk);
1803   }
1804 }
1805 #else
1806 void
1807 gst_debug_print_stack_trace (void)
1808 {
1809   /* nothing because it's compiled out */
1810 }
1811
1812 #endif /* GST_ENABLE_FUNC_INSTRUMENTATION */