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