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>
6 * gstinfo.c: debugging functions
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.
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.
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.
24 #include "gst_private.h"
28 #ifndef GST_DISABLE_GST_DEBUG
33 #ifdef HAVE_PRINTF_EXTENSION
36 #include <stdio.h> /* fprintf */
38 #include <string.h> /* G_VA_COPY */
41 #include "gst_private.h"
42 #include "gstelement.h"
44 #include "gstscheduler.h"
45 #include "gst_private.h"
47 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEBUG);
51 #include <rld_interface.h>
52 typedef struct DL_INFO
54 const char *dli_fname;
56 const char *dli_sname;
63 #define _RLD_DLADDR 14
64 int dladdr (void *address, Dl_info * dl);
67 dladdr (void *address, Dl_info * dl)
71 v = _rld_new_interface (_RLD_DLADDR, address, dl);
77 extern gchar *_gst_progname;
79 static void gst_debug_reset_threshold (gpointer category, gpointer unused);
80 static void gst_debug_reset_all_thresholds (void);
82 #ifdef HAVE_PRINTF_EXTENSION
83 static int _gst_info_printf_extension (FILE * stream,
84 const struct printf_info *info, const void *const *args);
85 static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
86 size_t n, int *argtypes);
89 struct _GstDebugMessage
96 /* list of all name/level pairs from --gst-debug and GST_DEBUG */
97 static GStaticMutex __level_name_mutex = G_STATIC_MUTEX_INIT;
98 static GSList *__level_name = NULL;
105 /* list of all categories */
106 static GStaticMutex __cat_mutex = G_STATIC_MUTEX_INIT;
107 static GSList *__categories = NULL;
109 /* all registered debug handlers */
115 static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
116 static GSList *__log_functions = NULL;
118 static GstAtomicInt __default_level;
119 static GstAtomicInt __use_color;
120 gboolean __gst_debug_enabled = TRUE;
123 GstDebugCategory *GST_CAT_DEFAULT = NULL;
125 GstDebugCategory *GST_CAT_GST_INIT = NULL;
126 GstDebugCategory *GST_CAT_COTHREADS = NULL;
127 GstDebugCategory *GST_CAT_COTHREAD_SWITCH = NULL;
128 GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
129 GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
130 GstDebugCategory *GST_CAT_PARENTAGE = NULL;
131 GstDebugCategory *GST_CAT_STATES = NULL;
132 GstDebugCategory *GST_CAT_PLANNING = NULL;
133 GstDebugCategory *GST_CAT_SCHEDULING = NULL;
134 GstDebugCategory *GST_CAT_DATAFLOW = NULL;
135 GstDebugCategory *GST_CAT_BUFFER = NULL;
136 GstDebugCategory *GST_CAT_CAPS = NULL;
137 GstDebugCategory *GST_CAT_CLOCK = NULL;
138 GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
139 GstDebugCategory *GST_CAT_PADS = NULL;
140 GstDebugCategory *GST_CAT_PIPELINE = NULL;
141 GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
142 GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
143 GstDebugCategory *GST_CAT_PROPERTIES = NULL;
144 GstDebugCategory *GST_CAT_THREAD = NULL;
145 GstDebugCategory *GST_CAT_TYPES = NULL;
146 GstDebugCategory *GST_CAT_XML = NULL;
147 GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
148 GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
149 GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
150 GstDebugCategory *GST_CAT_EVENT = NULL;
151 GstDebugCategory *GST_CAT_PARAMS = NULL;
152 GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
153 GstDebugCategory *GST_CAT_SEEK = NULL;
158 * Initializes the debugging system.
159 * Normally you don't want to call this, because gst_init does it for you.
162 _gst_debug_init (void)
164 gst_atomic_int_init (&__default_level, GST_LEVEL_DEFAULT);
165 gst_atomic_int_init (&__use_color, 1);
167 #ifdef HAVE_PRINTF_EXTENSION
168 register_printf_function (GST_PTR_FORMAT[0], _gst_info_printf_extension,
169 _gst_info_printf_extension_arginfo);
172 /* do NOT use a single debug function before this line has been run */
173 GST_CAT_DEFAULT = _gst_debug_category_new ("default",
174 GST_DEBUG_UNDERLINE, NULL);
175 GST_CAT_DEBUG = _gst_debug_category_new ("GST_DEBUG",
176 GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, "debugging subsystem");
178 gst_debug_add_log_function (gst_debug_log_default, NULL);
180 /* FIXME: add descriptions here */
181 GST_CAT_GST_INIT = _gst_debug_category_new ("GST_INIT",
182 GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
183 GST_CAT_COTHREADS = _gst_debug_category_new ("GST_COTHREADS",
184 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, NULL);
185 GST_CAT_COTHREAD_SWITCH = _gst_debug_category_new ("GST_COTHREAD_SWITCH",
186 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_GREEN, NULL);
187 GST_CAT_AUTOPLUG = _gst_debug_category_new ("GST_AUTOPLUG",
188 GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
189 GST_CAT_AUTOPLUG_ATTEMPT = _gst_debug_category_new ("GST_AUTOPLUG_ATTEMPT",
190 GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN | GST_DEBUG_BG_BLUE, NULL);
191 GST_CAT_PARENTAGE = _gst_debug_category_new ("GST_PARENTAGE",
192 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
193 GST_CAT_STATES = _gst_debug_category_new ("GST_STATES",
194 GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
195 GST_CAT_PLANNING = _gst_debug_category_new ("GST_PLANNING",
196 GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
197 GST_CAT_SCHEDULING = _gst_debug_category_new ("GST_SCHEDULING",
198 GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
199 GST_CAT_DATAFLOW = _gst_debug_category_new ("GST_DATAFLOW",
200 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, NULL);
201 GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER",
202 GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, NULL);
203 GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS",
204 GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
205 GST_CAT_CLOCK = _gst_debug_category_new ("GST_CLOCK",
206 GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, NULL);
207 GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS",
208 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
209 GST_CAT_PADS = _gst_debug_category_new ("GST_PADS",
210 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
211 GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE",
212 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
213 GST_CAT_PLUGIN_LOADING = _gst_debug_category_new ("GST_PLUGIN_LOADING",
214 GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
215 GST_CAT_PLUGIN_INFO = _gst_debug_category_new ("GST_PLUGIN_INFO",
216 GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
217 GST_CAT_PROPERTIES = _gst_debug_category_new ("GST_PROPERTIES",
218 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL);
219 GST_CAT_THREAD = _gst_debug_category_new ("GST_THREAD",
220 GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
221 GST_CAT_TYPES = _gst_debug_category_new ("GST_TYPES",
222 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
223 GST_CAT_XML = _gst_debug_category_new ("GST_XML",
224 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
225 GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION",
226 GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
227 GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING",
228 GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE | GST_DEBUG_BG_GREEN, NULL);
229 GST_CAT_ERROR_SYSTEM = _gst_debug_category_new ("GST_ERROR_SYSTEM",
230 GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_WHITE, NULL);
232 GST_CAT_EVENT = _gst_debug_category_new ("GST_EVENT",
233 GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
234 GST_CAT_PARAMS = _gst_debug_category_new ("GST_PARAMS",
235 GST_DEBUG_BOLD | GST_DEBUG_FG_BLACK | GST_DEBUG_BG_YELLOW, NULL);
236 GST_CAT_CALL_TRACE = _gst_debug_category_new ("GST_CALL_TRACE",
237 GST_DEBUG_BOLD, NULL);
238 GST_CAT_SEEK = _gst_debug_category_new ("GST_SEEK",
239 0, "plugins reacting to seek events");
242 /* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
243 #define GST_CAT_DEFAULT GST_CAT_DEBUG
247 * @category: category to log
248 * @level: level of the message is in
249 * @file: the file that emitted the message, usually the __FILE__ identifier
250 * @function: the function that emitted the message
251 * @line: the line from that the message was emitted, usually __LINE__
252 * @object: the object this message relates to or NULL if none
253 * @format: a printf style format string
254 * @...: optional arguments for the format
256 * Logs the given message using the currently registered debugging handlers.
259 gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
260 const gchar * file, const gchar * function, gint line,
261 GObject * object, const gchar * format, ...)
265 va_start (var_args, format);
266 gst_debug_log_valist (category, level, file, function, line, object, format,
272 * gst_debug_log_valist:
273 * @category: category to log
274 * @level: level of the message is in
275 * @file: the file that emitted the message, usually the __FILE__ identifier
276 * @function: the function that emitted the message
277 * @line: the line from that the message was emitted, usually __LINE__
278 * @object: the object this message relates to or NULL if none
279 * @format: a printf style format string
280 * @args: optional arguments for the format
282 * Logs the given message using the currently registered debugging handlers.
285 gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
286 const gchar * file, const gchar * function, gint line,
287 GObject * object, const gchar * format, va_list args)
289 GstDebugMessage message;
293 g_return_if_fail (category != NULL);
294 g_return_if_fail (file != NULL);
295 g_return_if_fail (function != NULL);
296 g_return_if_fail (format != NULL);
298 message.message = NULL;
299 message.format = format;
300 G_VA_COPY (message.arguments, args);
302 handler = __log_functions;
304 entry = handler->data;
305 handler = g_slist_next (handler);
306 entry->func (category, level, file, function, line, object, &message,
309 g_free (message.message);
310 va_end (message.arguments);
314 * gst_debug_message_get:
315 * @message: a debug message
317 * Gets the string representation of a GstDebugMessage. This function is used
318 * in debug handlers to extract the message.
321 gst_debug_message_get (GstDebugMessage * message)
323 if (message->message == NULL) {
324 message->message = g_strdup_vprintf (message->format, message->arguments);
326 return message->message;
331 gst_debug_print_object (gpointer ptr)
333 GObject *object = (GObject *) ptr;
336 /* This is a cute trick to detect unmapped memory, but is unportable,
337 * slow, screws around with madvise, and not actually that useful. */
341 ret = madvise ((void *) ((unsigned long) ptr & (~0xfff)), 4096, 0);
342 if (ret == -1 && errno == ENOMEM) {
343 buffer = g_strdup_printf ("%p (unmapped memory)", ptr);
348 /* nicely printed object */
349 if (object == NULL) {
350 return g_strdup ("(NULL)");
352 if (*(GType *) ptr == GST_TYPE_CAPS) {
353 return gst_caps_to_string ((GstCaps *) ptr);
355 if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
356 return gst_structure_to_string ((GstStructure *) ptr);
359 if (*(guint32 *) ptr == 0xffffffff) {
360 return g_strdup_printf ("<poisoned@%p>", ptr);
363 if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) {
364 return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object));
366 if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) {
367 return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object));
369 if (G_IS_OBJECT (object)) {
370 return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object);
373 return g_strdup_printf ("%p", ptr);
377 * gst_debug_construct_term_color:
378 * @colorinfo: the color info
380 * Constructs a string that can be used for getting the desired color in color
382 * You need to free the string after use.
384 * Returns: a string containing the color definition
387 gst_debug_construct_term_color (guint colorinfo)
392 color = g_string_new ("\033[00");
394 if (colorinfo & GST_DEBUG_BOLD) {
395 g_string_append (color, ";01");
397 if (colorinfo & GST_DEBUG_UNDERLINE) {
398 g_string_append (color, ";04");
400 if (colorinfo & GST_DEBUG_FG_MASK) {
401 g_string_append_printf (color, ";3%1d", colorinfo & GST_DEBUG_FG_MASK);
403 if (colorinfo & GST_DEBUG_BG_MASK) {
404 g_string_append_printf (color, ";4%1d",
405 (colorinfo & GST_DEBUG_BG_MASK) >> 4);
407 g_string_append (color, "m");
410 g_string_free (color, FALSE);
415 * gst_debug_log_default:
416 * @category: category to log
417 * @level: level of the message
418 * @file: the file that emitted the message, usually the __FILE__ identifier
419 * @function: the function that emitted the message
420 * @line: the line from that the message was emitted, usually __LINE__
421 * @message: the actual message
422 * @object: the object this message relates to or NULL if none
423 * @unused: an unused variable, reserved for some user_data.
425 * The default logging handler used by GStreamer. Logging functions get called
426 * whenever a macro like GST_DEBUG or similar is used. This function outputs the
427 * message and additional info using the glib error handler.
428 * You can add other handlers by using #gst_debug_add_log_function.
429 * And you can remove this handler by calling
430 * gst_debug_remove_log_function (gst_debug_log_default);
433 gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
434 const gchar * file, const gchar * function, gint line,
435 GObject * object, GstDebugMessage * message, gpointer unused)
443 if (level > gst_debug_category_get_threshold (category))
449 if (gst_debug_is_colored ()) {
451 gst_debug_construct_term_color (gst_debug_category_get_color
454 pidcolor = g_strdup_printf ("\033[3%1dm", pid % 6 + 31);
456 color = g_strdup ("");
458 pidcolor = g_strdup ("");
461 obj = object ? gst_debug_print_object (object) : g_strdup ("");
463 g_printerr ("%s %s%15s%s(%s%5d%s) %s%s(%d):%s:%s%s %s\n",
464 gst_debug_level_get_name (level),
465 color, gst_debug_category_get_name (category), clear,
466 pidcolor, pid, clear,
467 color, file, line, function, obj, clear, gst_debug_message_get (message));
475 * gst_debug_level_get_name:
476 * @level: the level to get the name for
478 * Get the string trepresentation of a debugging level
483 gst_debug_level_get_name (GstDebugLevel level)
488 case GST_LEVEL_ERROR:
490 case GST_LEVEL_WARNING:
494 case GST_LEVEL_DEBUG:
499 g_warning ("invalid level specified for gst_debug_level_get_name");
505 * gst_debug_add_log_function:
506 * @func: the function to use
509 * Adds the logging function to the list of logging functions.
510 * Be sure to use G_GNUC_NO_INSTRUMENT on that function, it is needed.
513 gst_debug_add_log_function (GstLogFunction func, gpointer data)
518 g_return_if_fail (func != NULL);
520 entry = g_new (LogFuncEntry, 1);
522 entry->user_data = data;
523 /* FIXME: we leak the old list here - other threads might access it right now
524 * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv,
525 * but that is waaay costly.
526 * It'd probably be clever to use some kind of RCU here, but I don't know
527 * anything about that.
529 g_static_mutex_lock (&__log_func_mutex);
530 list = g_slist_copy (__log_functions);
531 __log_functions = g_slist_prepend (list, entry);
532 g_static_mutex_unlock (&__log_func_mutex);
534 GST_DEBUG ("prepended log function %p (user data %p) to log functions",
539 gst_debug_compare_log_function_by_func (gconstpointer entry, gconstpointer func)
541 gpointer entryfunc = ((LogFuncEntry *) entry)->func;
543 return (entryfunc < func) ? -1 : (entryfunc > func) ? 1 : 0;
547 gst_debug_compare_log_function_by_data (gconstpointer entry, gconstpointer data)
549 gpointer entrydata = ((LogFuncEntry *) entry)->user_data;
551 return (entrydata < data) ? -1 : (entrydata > data) ? 1 : 0;
555 gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
561 g_static_mutex_lock (&__log_func_mutex);
562 new = __log_functions;
563 while ((found = g_slist_find_custom (new, data, func))) {
564 if (new == __log_functions) {
565 new = g_slist_copy (new);
568 g_free (found->data);
569 new = g_slist_delete_link (new, found);
572 /* FIXME: We leak the old list here. See _add_log_function for why. */
573 __log_functions = new;
574 g_static_mutex_unlock (&__log_func_mutex);
580 * gst_debug_remove_log_function:
581 * @func: the log function to remove
583 * Removes all registrered instances of the given logging functions.
585 * Returns: How many instances of the function were removed
588 gst_debug_remove_log_function (GstLogFunction func)
592 g_return_val_if_fail (func != NULL, 0);
595 gst_debug_remove_with_compare_func
596 (gst_debug_compare_log_function_by_func, func);
597 GST_DEBUG ("removed log function %p %d times from log function list", func,
604 * gst_debug_remove_log_function_by_data:
605 * @data: user data of the log function to remove
607 * Removes all registrered instances of log functions with the given user data.
609 * Returns: How many instances of the function were removed
612 gst_debug_remove_log_function_by_data (gpointer data)
617 gst_debug_remove_with_compare_func
618 (gst_debug_compare_log_function_by_data, data);
620 ("removed %d log functions with user data %p from log function list",
627 * gst_debug_set_colored:
628 * @colored: Whether to use colored output or not
630 * Sets or unsets the use of coloured debugging output.
633 gst_debug_set_colored (gboolean colored)
635 gst_atomic_int_set (&__use_color, colored ? 1 : 0);
639 * gst_debug_is_colored:
641 * Checks if the debugging output should be colored.
643 * Returns: TRUE, if the debug output should be colored.
646 gst_debug_is_colored (void)
648 return gst_atomic_int_read (&__use_color) == 0 ? FALSE : TRUE;
652 * gst_debug_set_active:
653 * @active: Whether to use debugging output or not
655 * If activated, debugging messages are sent to the debugging
657 * It makes sense to deactivate it for speed issues.
658 * <note><para>This function is not threadsafe. It makes sense to only call it
659 * during initialization.</para></note>
662 gst_debug_set_active (gboolean active)
664 __gst_debug_enabled = active;
668 * gst_debug_is_active:
670 * Checks if debugging output is activated.
672 * Returns: TRUE, if debugging is activated
675 gst_debug_is_active (void)
677 return __gst_debug_enabled;
681 * gst_debug_set_default_threshold:
682 * @level: level to set
684 * Sets the default threshold to the given level and updates all categories to
685 * use this threshold.
688 gst_debug_set_default_threshold (GstDebugLevel level)
690 gst_atomic_int_set (&__default_level, level);
691 gst_debug_reset_all_thresholds ();
695 * gst_debug_get_default_threshold:
697 * Returns the default threshold that is used for new categories.
699 * Returns: the default threshold level
702 gst_debug_get_default_threshold (void)
704 return (GstDebugLevel) gst_atomic_int_read (&__default_level);
707 gst_debug_reset_threshold (gpointer category, gpointer unused)
709 GstDebugCategory *cat = (GstDebugCategory *) category;
712 g_static_mutex_lock (&__level_name_mutex);
715 LevelNameEntry *entry = walk->data;
717 walk = g_slist_next (walk);
718 if (g_pattern_match_string (entry->pat, cat->name)) {
719 GST_LOG ("category %s matches pattern %p - gets set to level %d",
720 cat->name, entry->pat, entry->level);
721 gst_debug_category_set_threshold (cat, entry->level);
725 gst_debug_category_set_threshold (cat, gst_debug_get_default_threshold ());
728 g_static_mutex_unlock (&__level_name_mutex);
731 gst_debug_reset_all_thresholds (void)
733 g_static_mutex_lock (&__cat_mutex);
734 g_slist_foreach (__categories, gst_debug_reset_threshold, NULL);
735 g_static_mutex_unlock (&__cat_mutex);
738 for_each_threshold_by_entry (gpointer data, gpointer user_data)
740 GstDebugCategory *cat = (GstDebugCategory *) data;
741 LevelNameEntry *entry = (LevelNameEntry *) user_data;
743 if (g_pattern_match_string (entry->pat, cat->name)) {
744 GST_LOG ("category %s matches pattern %p - gets set to level %d",
745 cat->name, entry->pat, entry->level);
746 gst_debug_category_set_threshold (cat, entry->level);
751 * gst_debug_set_threshold_for_name:
752 * @name: name of the categories to set
753 * @level: level to set them to
755 * Sets all categories which match the gven glob style pattern to the given
759 gst_debug_set_threshold_for_name (const gchar * name, GstDebugLevel level)
762 LevelNameEntry *entry;
764 g_return_if_fail (name != NULL);
766 pat = g_pattern_spec_new (name);
767 entry = g_new (LevelNameEntry, 1);
769 entry->level = level;
770 g_static_mutex_lock (&__level_name_mutex);
771 __level_name = g_slist_prepend (__level_name, entry);
772 g_static_mutex_unlock (&__level_name_mutex);
773 g_static_mutex_lock (&__cat_mutex);
774 g_slist_foreach (__categories, for_each_threshold_by_entry, entry);
775 g_static_mutex_unlock (&__cat_mutex);
779 * gst_debug_unset_threshold_for_name:
780 * @name: name of the categories to set
782 * Resets all categories with the given name back to the default level.
785 gst_debug_unset_threshold_for_name (const gchar * name)
790 g_return_if_fail (name != NULL);
792 pat = g_pattern_spec_new (name);
793 g_static_mutex_lock (&__level_name_mutex);
795 /* improve this if you want, it's mighty slow */
797 LevelNameEntry *entry = walk->data;
799 if (g_pattern_spec_equal (entry->pat, pat)) {
800 __level_name = g_slist_remove_link (__level_name, walk);
801 g_pattern_spec_free (entry->pat);
803 g_slist_free_1 (walk);
807 g_static_mutex_unlock (&__level_name_mutex);
808 g_pattern_spec_free (pat);
809 gst_debug_reset_all_thresholds ();
813 _gst_debug_category_new (gchar * name, guint color, gchar * description)
815 GstDebugCategory *cat;
817 g_return_val_if_fail (name != NULL, NULL);
819 cat = g_new (GstDebugCategory, 1);
820 cat->name = g_strdup (name);
822 if (description != NULL) {
823 cat->description = g_strdup (description);
825 cat->description = g_strdup ("no description");
827 cat->threshold = g_new (GstAtomicInt, 1);
828 gst_atomic_int_init (cat->threshold, 0);
829 gst_debug_reset_threshold (cat, NULL);
831 /* add to category list */
832 g_static_mutex_lock (&__cat_mutex);
833 __categories = g_slist_prepend (__categories, cat);
834 g_static_mutex_unlock (&__cat_mutex);
840 * gst_debug_category_free:
841 * @category: #GstDebugCategory to free.
843 * Removes and frees the category and all associated resources.
846 gst_debug_category_free (GstDebugCategory * category)
848 if (category == NULL)
851 /* remove from category list */
852 g_static_mutex_lock (&__cat_mutex);
853 __categories = g_slist_remove (__categories, category);
854 g_static_mutex_unlock (&__cat_mutex);
856 g_free ((gpointer) category->name);
857 g_free ((gpointer) category->description);
858 gst_atomic_int_destroy (category->threshold);
859 g_free (category->threshold);
864 * gst_debug_category_set_threshold:
865 * @category: a #GstDebugCategory to set threshold of.
866 * @level: the #GstDebugLevel threshold to set.
868 * Sets the threshold of the category to the given level. Debug information will
869 * only be output if the threshold is lower or equal to the level of the
872 * Do not use this function in production code, because other functions may
873 * change the threshold of categories as side effect. It is however a nice
874 * function to use when debugging (even from gdb).
878 gst_debug_category_set_threshold (GstDebugCategory * category,
881 g_return_if_fail (category != NULL);
883 gst_atomic_int_set (category->threshold, level);
887 * gst_debug_category_reset_threshold:
888 * @category: a #GstDebugCategory to reset threshold of.
890 * Resets the threshold of the category to the default level. Debug information
891 * will only be output if the threshold is lower or equal to the level of the
893 * Use this function to set the threshold back to where it was after using
894 * gst_debug_category_set_threshold().
897 gst_debug_category_reset_threshold (GstDebugCategory * category)
899 gst_debug_reset_threshold (category, NULL);
903 * gst_debug_category_get_threshold:
904 * @category: a #GstDebugCategory to get threshold of.
906 * Returns the threshold of a #GstCategory.
908 * Returns: the #GstDebugLevel that is used as threshold.
911 gst_debug_category_get_threshold (GstDebugCategory * category)
913 return gst_atomic_int_read (category->threshold);
917 * gst_debug_category_get_name:
918 * @category: a #GstDebugCategory to get name of.
920 * Returns the name of a debug category.
922 * Returns: the name of the category.
925 gst_debug_category_get_name (GstDebugCategory * category)
927 return category->name;
931 * gst_debug_category_get_color:
932 * @category: a #GstDebugCategory to get the color of.
934 * Returns the color of a debug category used when printing output in this
937 * Returns: the color of the category.
940 gst_debug_category_get_color (GstDebugCategory * category)
942 return category->color;
946 * gst_debug_category_get_description:
947 * @category: a #GstDebugCategory to get the description of.
949 * Returns the description of a debug category.
951 * Returns: the description of the category.
954 gst_debug_category_get_description (GstDebugCategory * category)
956 return category->description;
960 * gst_debug_get_all_categories:
962 * Returns a snapshot of a all categories that are currently in use . This list
963 * may change anytime.
964 * The caller has to free the list after use.
965 * <emphasis>This function is not threadsafe, so only use it while only the
966 * main thread is running.</emphasis>
968 * Returns: the list of categories
971 gst_debug_get_all_categories (void)
975 g_static_mutex_lock (&__cat_mutex);
976 ret = g_slist_copy (__categories);
977 g_static_mutex_unlock (&__cat_mutex);
982 /*** FUNCTION POINTERS ********************************************************/
984 GHashTable *__gst_function_pointers = NULL;
986 _gst_debug_nameof_funcptr (void *ptr)
987 G_GNUC_NO_INSTRUMENT;
989 /* This function MUST NOT return NULL */
990 const gchar *_gst_debug_nameof_funcptr (void *ptr)
998 if (__gst_function_pointers
999 && (ptrname = g_hash_table_lookup (__gst_function_pointers, ptr))) {
1002 /* we need to create an entry in the hash table for this one so we don't leak
1005 if (dladdr (ptr, &dlinfo) && dlinfo.dli_sname) {
1006 gchar *name = g_strdup (dlinfo.dli_sname);
1008 _gst_debug_register_funcptr (ptr, name);
1013 gchar *name = g_strdup_printf ("%p", ptr);
1015 _gst_debug_register_funcptr (ptr, name);
1021 _gst_debug_register_funcptr (void *ptr, gchar * ptrname)
1023 if (!__gst_function_pointers)
1024 __gst_function_pointers = g_hash_table_new (g_direct_hash, g_direct_equal);
1025 if (!g_hash_table_lookup (__gst_function_pointers, ptr))
1026 g_hash_table_insert (__gst_function_pointers, ptr, ptrname);
1031 #ifdef HAVE_PRINTF_EXTENSION
1033 _gst_info_printf_extension (FILE * stream, const struct printf_info *info,
1034 const void *const *args)
1041 ptr = *(void **) args[0];
1043 buffer = gst_debug_print_object (ptr);
1044 len = fprintf (stream, "%*s", (info->left ? -info->width : info->width),
1052 _gst_info_printf_extension_arginfo (const struct printf_info *info, size_t n,
1056 argtypes[0] = PA_POINTER;
1059 #endif /* HAVE_PRINTF_EXTENSION */
1061 #endif /* GST_DISABLE_GST_DEBUG */
1063 #ifdef GST_ENABLE_FUNC_INSTRUMENTATION
1064 /* FIXME make this thread specific */
1065 static GSList *stack_trace = NULL;
1068 __cyg_profile_func_enter (void *this_fn, void *call_site)
1069 G_GNUC_NO_INSTRUMENT;
1070 void __cyg_profile_func_enter (void *this_fn, void *call_site)
1072 gchar *name = _gst_debug_nameof_funcptr (this_fn);
1073 gchar *site = _gst_debug_nameof_funcptr (call_site);
1075 GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "entering function %s from %s", name,
1078 g_slist_prepend (stack_trace, g_strdup_printf ("%8p in %s from %p (%s)",
1079 this_fn, name, call_site, site));
1086 __cyg_profile_func_exit (void *this_fn, void *call_site)
1087 G_GNUC_NO_INSTRUMENT;
1088 void __cyg_profile_func_exit (void *this_fn, void *call_site)
1090 gchar *name = _gst_debug_nameof_funcptr (this_fn);
1092 GST_CAT_DEBUG (GST_CAT_CALL_TRACE, "leaving function %s", name);
1093 g_free (stack_trace->data);
1094 stack_trace = g_slist_delete_link (stack_trace, stack_trace);
1100 gst_debug_print_stack_trace (void)
1102 GSList *walk = stack_trace;
1106 walk = g_slist_next (walk);
1109 gchar *name = (gchar *) walk->data;
1111 g_print ("#%-2d %s\n", count++, name);
1113 walk = g_slist_next (walk);
1118 gst_debug_print_stack_trace (void)
1120 /* nothing because it's compiled out */
1123 #endif /* GST_ENABLE_FUNC_INTSTRUMENTATION */