gstinfo.c 48.6 KB
Newer Older
1
2
3
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
4
 *                    2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
5
 *
6
 * gstinfo.c: debugging functions
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
23

24
25
/**
 * SECTION:gstinfo
26
 * @short_description: Debugging and logging facilities
27
28
29
30
 * @see_also: #GstConfig, #Gst for command line parameters
 * and environment variables that affect the debugging output.
 *
 * GStreamer's debugging subsystem is an easy way to get information about what
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
31
32
 * the application is doing.  It is not meant for programming errors. Use GLib
 * methods (g_warning and friends) for that.
33
 *
34
 * The debugging subsystem works only after GStreamer has been initialized
35
36
37
 * - for example by calling gst_init().
 *
 * The debugging subsystem is used to log informational messages while the
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
38
39
40
41
42
43
 * application runs.  Each messages has some properties attached to it. Among
 * these properties are the debugging category, the severity (called "level"
 * here) and an optional #GObject it belongs to. Each of these messages is sent
 * to all registered debugging handlers, which then handle the messages.
 * GStreamer attaches a default handler on startup, which outputs requested
 * messages to stderr.
44
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
45
 * Messages are output by using shortcut macros like #GST_DEBUG,
46
47
 * #GST_CAT_ERROR_OBJECT or similar. These all expand to calling gst_debug_log()
 * with the right parameters.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48
 * The only thing a developer will probably want to do is define his own
49
50
 * categories. This is easily done with 3 lines. At the top of your code,
 * declare
51
52
53
 * the variables and set the default category.
 * <informalexample>
 * <programlisting>
54
 * GST_DEBUG_CATEGORY_STATIC (my_category);     // define category (statically)
55
56
57
58
59
60
 * &hash;define GST_CAT_DEFAULT my_category     // set as default
 * </programlisting>
 * </informalexample>
 * After that you only need to initialize the category.
 * <informalexample>
 * <programlisting>
61
62
 * GST_DEBUG_CATEGORY_INIT (my_category, "my category",
 *                          0, "This is my very own");
63
64
 * </programlisting>
 * </informalexample>
65
 * Initialization must be done before the category is used first.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
66
 * Plugins do this
67
68
69
70
 * in their plugin_init function, libraries and applications should do that
 * during their initialization.
 *
 * 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,
Stefan Kost's avatar
Stefan Kost committed
72
73
74
 * macro and even structs described in this file evaluate to default values or
 * nothing at all.
 * So don't take addresses of these functions or use other tricks.
75
76
77
78
 * If you must do that for some reason, there is still an option.
 * If the debugging
 * subsystem was compiled out, #GST_DISABLE_GST_DEBUG is defined in
 * &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)
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
81
 * speed increase and will reduce the size of your compiled code. The GStreamer
82
83
 * library itself becomes around 10% smaller.
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84
 * Please note that there are naming conventions for the names of debugging
85
86
 * categories. These are explained at GST_DEBUG_CATEGORY_INIT().
 */
87

88
89
90
91
92
#include "gst_private.h"
#include "gstinfo.h"

#ifndef GST_DISABLE_GST_DEBUG

93
#ifdef HAVE_DLFCN_H
94
#  include <dlfcn.h>
95
#endif
96
#ifdef HAVE_PRINTF_EXTENSION
97
#  include <printf.h>
98
#endif
99
#include <stdio.h>              /* fprintf */
100
#ifdef HAVE_UNISTD_H
101
102
103
104
#  include <unistd.h>           /* getpid on UNIX */
#endif
#ifdef HAVE_PROCESS_H
#  include <process.h>          /* getpid on win32 */
105
#endif
106
#include <string.h>             /* G_VA_COPY */
107
108
109
110
#ifdef G_OS_WIN32
#  define WIN32_LEAN_AND_MEAN   /* prevents from including too many things */
#  include <windows.h>          /* GetStdHandle, windows console */
#endif
111

112
#include "gst_private.h"
113
#include "gstutils.h"
114
#include "gstsegment.h"
115
#ifdef HAVE_VALGRIND_H
116
#  include <valgrind/valgrind.h>
117
#endif
118
#include <glib/gprintf.h>       /* g_sprintf */
119

120
121
/* underscore is to prevent conflict with GST_CAT_DEBUG define */
GST_DEBUG_CATEGORY_STATIC (_GST_CAT_DEBUG);
122
123
124
125
126

/* time of initialization, so we get useful debugging output times
 * FIXME: we use this in gstdebugutils.c, what about a function + macro to
 * get the running time: GST_DEBUG_RUNNING_TIME
 */
127
GstClockTime _priv_gst_info_start_time;
128

129
#if 0
130
131
#if defined __sgi__
#include <rld_interface.h>
132
133
134
135
136
137
138
139
140
typedef struct DL_INFO
{
  const char *dli_fname;
  void *dli_fbase;
  const char *dli_sname;
  void *dli_saddr;
  int dli_version;
  int dli_reserved1;
  long dli_reserved[4];
141
142
}
Dl_info;
143

144
#define _RLD_DLADDR             14
145
int dladdr (void *address, Dl_info * dl);
146

147
148
int
dladdr (void *address, Dl_info * dl)
149
150
{
  void *v;
151
152
153

  v = _rld_new_interface (_RLD_DLADDR, address, dl);
  return (int) v;
154
}
155
#endif /* __sgi__ */
156
#endif
157

158
159
static void gst_debug_reset_threshold (gpointer category, gpointer unused);
static void gst_debug_reset_all_thresholds (void);
160

161
#ifdef HAVE_PRINTF_EXTENSION
162
163
164
static int _gst_info_printf_extension_ptr (FILE * stream,
    const struct printf_info *info, const void *const *args);
static int _gst_info_printf_extension_segment (FILE * stream,
165
166
167
    const struct printf_info *info, const void *const *args);
static int _gst_info_printf_extension_arginfo (const struct printf_info *info,
    size_t n, int *argtypes);
168
169
#endif

170
171
172
173
174
struct _GstDebugMessage
{
  gchar *message;
  const gchar *format;
  va_list arguments;
175
176
};

177
178
179
/* list of all name/level pairs from --gst-debug and GST_DEBUG */
static GStaticMutex __level_name_mutex = G_STATIC_MUTEX_INIT;
static GSList *__level_name = NULL;
180
181
182
183
typedef struct
{
  GPatternSpec *pat;
  GstDebugLevel level;
184
185
}
LevelNameEntry;
186
187
188
189
190
191

/* list of all categories */
static GStaticMutex __cat_mutex = G_STATIC_MUTEX_INIT;
static GSList *__categories = NULL;

/* all registered debug handlers */
192
193
194
195
typedef struct
{
  GstLogFunction func;
  gpointer user_data;
196
197
}
LogFuncEntry;
198
199
200
static GStaticMutex __log_func_mutex = G_STATIC_MUTEX_INIT;
static GSList *__log_functions = NULL;

201
202
static gint __default_level;
static gint __use_color;
Wim Taymans's avatar
Wim Taymans committed
203

204
205
206
/* disabled by default, as soon as some threshold is set > NONE,
 * it becomes enabled. */
gboolean __gst_debug_enabled = FALSE;
207
GstDebugLevel __gst_debug_min = GST_LEVEL_NONE;
208
209
210
211
212
213
214
215
216

GstDebugCategory *GST_CAT_DEFAULT = NULL;

GstDebugCategory *GST_CAT_GST_INIT = NULL;
GstDebugCategory *GST_CAT_AUTOPLUG = NULL;
GstDebugCategory *GST_CAT_AUTOPLUG_ATTEMPT = NULL;
GstDebugCategory *GST_CAT_PARENTAGE = NULL;
GstDebugCategory *GST_CAT_STATES = NULL;
GstDebugCategory *GST_CAT_SCHEDULING = NULL;
217

218
GstDebugCategory *GST_CAT_BUFFER = NULL;
219
GstDebugCategory *GST_CAT_BUS = NULL;
220
221
222
223
224
225
226
227
228
229
230
231
GstDebugCategory *GST_CAT_CAPS = NULL;
GstDebugCategory *GST_CAT_CLOCK = NULL;
GstDebugCategory *GST_CAT_ELEMENT_PADS = NULL;
GstDebugCategory *GST_CAT_PADS = NULL;
GstDebugCategory *GST_CAT_PIPELINE = NULL;
GstDebugCategory *GST_CAT_PLUGIN_LOADING = NULL;
GstDebugCategory *GST_CAT_PLUGIN_INFO = NULL;
GstDebugCategory *GST_CAT_PROPERTIES = NULL;
GstDebugCategory *GST_CAT_TYPES = NULL;
GstDebugCategory *GST_CAT_XML = NULL;
GstDebugCategory *GST_CAT_NEGOTIATION = NULL;
GstDebugCategory *GST_CAT_REFCOUNTING = NULL;
232
GstDebugCategory *GST_CAT_ERROR_SYSTEM = NULL;
233
GstDebugCategory *GST_CAT_EVENT = NULL;
234
GstDebugCategory *GST_CAT_MESSAGE = NULL;
235
236
GstDebugCategory *GST_CAT_PARAMS = NULL;
GstDebugCategory *GST_CAT_CALL_TRACE = NULL;
237
GstDebugCategory *GST_CAT_SIGNAL = NULL;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
238
GstDebugCategory *GST_CAT_PROBE = NULL;
David Schleef's avatar
remove    
David Schleef committed
239
GstDebugCategory *GST_CAT_REGISTRY = NULL;
Wim Taymans's avatar
Wim Taymans committed
240
GstDebugCategory *GST_CAT_QOS = NULL;
241

242
243
/* FIXME: export this? */
gboolean
244
_priv_gst_in_valgrind (void)
245
246
247
248
249
250
251
252
253
254
{
  static enum
  {
    GST_VG_UNCHECKED,
    GST_VG_NO_VALGRIND,
    GST_VG_INSIDE
  }
  in_valgrind = GST_VG_UNCHECKED;

  if (in_valgrind == GST_VG_UNCHECKED) {
255
#ifdef HAVE_VALGRIND_H
256
257
    if (RUNNING_ON_VALGRIND) {
      GST_CAT_INFO (GST_CAT_GST_INIT, "we're running inside valgrind");
258
259
260
      printf ("GStreamer has detected that it is running inside valgrind.\n");
      printf ("It might now take different code paths to ease debugging.\n");
      printf ("Of course, this may also lead to different bugs.\n");
261
262
263
264
265
266
267
268
269
270
271
272
273
274
      in_valgrind = GST_VG_INSIDE;
    } else {
      GST_CAT_LOG (GST_CAT_GST_INIT, "not doing extra valgrind stuff");
      in_valgrind = GST_VG_NO_VALGRIND;
    }
#else
    in_valgrind = GST_VG_NO_VALGRIND;
#endif
    g_assert (in_valgrind == GST_VG_NO_VALGRIND ||
        in_valgrind == GST_VG_INSIDE);
  }
  return (in_valgrind == GST_VG_INSIDE) ? TRUE : FALSE;
}

275
/**
276
 * _gst_debug_init:
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
277
 *
278
 * Initializes the debugging system.
Stefan Kost's avatar
Stefan Kost committed
279
 * Normally you don't want to call this, because gst_init() does it for you.
280
 */
281
282
void
_gst_debug_init (void)
283
{
284
285
  g_atomic_int_set (&__default_level, GST_LEVEL_DEFAULT);
  g_atomic_int_set (&__use_color, 1);
286

287
  /* get time we started for debugging messages */
288
  _priv_gst_info_start_time = gst_util_get_timestamp ();
289

290
#ifdef HAVE_PRINTF_EXTENSION
291
  register_printf_function (GST_PTR_FORMAT[0], _gst_info_printf_extension_ptr,
292
      _gst_info_printf_extension_arginfo);
293
294
  register_printf_function (GST_SEGMENT_FORMAT[0],
      _gst_info_printf_extension_segment, _gst_info_printf_extension_arginfo);
295
296
#endif

297
  /* do NOT use a single debug function before this line has been run */
298
299
  GST_CAT_DEFAULT = _gst_debug_category_new ("default",
      GST_DEBUG_UNDERLINE, NULL);
300
  _GST_CAT_DEBUG = _gst_debug_category_new ("GST_DEBUG",
301
      GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, "debugging subsystem");
302
303
304
305

  gst_debug_add_log_function (gst_debug_log_default, NULL);

  /* FIXME: add descriptions here */
306
307
308
309
  GST_CAT_GST_INIT = _gst_debug_category_new ("GST_INIT",
      GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
  GST_CAT_AUTOPLUG = _gst_debug_category_new ("GST_AUTOPLUG",
      GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
310
  GST_CAT_AUTOPLUG_ATTEMPT = _gst_debug_category_new ("GST_AUTOPLUG_ATTEMPT",
311
312
313
314
315
316
317
318
      GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN | GST_DEBUG_BG_BLUE, NULL);
  GST_CAT_PARENTAGE = _gst_debug_category_new ("GST_PARENTAGE",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_STATES = _gst_debug_category_new ("GST_STATES",
      GST_DEBUG_BOLD | GST_DEBUG_FG_RED, NULL);
  GST_CAT_SCHEDULING = _gst_debug_category_new ("GST_SCHEDULING",
      GST_DEBUG_BOLD | GST_DEBUG_FG_MAGENTA, NULL);
  GST_CAT_BUFFER = _gst_debug_category_new ("GST_BUFFER",
319
320
      GST_DEBUG_BOLD | GST_DEBUG_BG_GREEN, NULL);
  GST_CAT_BUS = _gst_debug_category_new ("GST_BUS", GST_DEBUG_BG_YELLOW, NULL);
321
322
323
324
325
326
327
328
329
330
  GST_CAT_CAPS = _gst_debug_category_new ("GST_CAPS",
      GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
  GST_CAT_CLOCK = _gst_debug_category_new ("GST_CLOCK",
      GST_DEBUG_BOLD | GST_DEBUG_FG_YELLOW, NULL);
  GST_CAT_ELEMENT_PADS = _gst_debug_category_new ("GST_ELEMENT_PADS",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_PADS = _gst_debug_category_new ("GST_PADS",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_PIPELINE = _gst_debug_category_new ("GST_PIPELINE",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
331
  GST_CAT_PLUGIN_LOADING = _gst_debug_category_new ("GST_PLUGIN_LOADING",
332
333
334
335
336
337
338
339
340
341
342
343
      GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
  GST_CAT_PLUGIN_INFO = _gst_debug_category_new ("GST_PLUGIN_INFO",
      GST_DEBUG_BOLD | GST_DEBUG_FG_CYAN, NULL);
  GST_CAT_PROPERTIES = _gst_debug_category_new ("GST_PROPERTIES",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_BLUE, NULL);
  GST_CAT_TYPES = _gst_debug_category_new ("GST_TYPES",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_XML = _gst_debug_category_new ("GST_XML",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_NEGOTIATION = _gst_debug_category_new ("GST_NEGOTIATION",
      GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
  GST_CAT_REFCOUNTING = _gst_debug_category_new ("GST_REFCOUNTING",
344
      GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_BLUE, NULL);
345
346
347
348
  GST_CAT_ERROR_SYSTEM = _gst_debug_category_new ("GST_ERROR_SYSTEM",
      GST_DEBUG_BOLD | GST_DEBUG_FG_RED | GST_DEBUG_BG_WHITE, NULL);

  GST_CAT_EVENT = _gst_debug_category_new ("GST_EVENT",
349
      GST_DEBUG_BOLD | GST_DEBUG_FG_BLUE, NULL);
350
351
  GST_CAT_MESSAGE = _gst_debug_category_new ("GST_MESSAGE",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
352
353
354
355
  GST_CAT_PARAMS = _gst_debug_category_new ("GST_PARAMS",
      GST_DEBUG_BOLD | GST_DEBUG_FG_BLACK | GST_DEBUG_BG_YELLOW, NULL);
  GST_CAT_CALL_TRACE = _gst_debug_category_new ("GST_CALL_TRACE",
      GST_DEBUG_BOLD, NULL);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
356
357
358
359
  GST_CAT_SIGNAL = _gst_debug_category_new ("GST_SIGNAL",
      GST_DEBUG_BOLD | GST_DEBUG_FG_WHITE | GST_DEBUG_BG_RED, NULL);
  GST_CAT_PROBE = _gst_debug_category_new ("GST_PROBE",
      GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "pad probes");
David Schleef's avatar
remove    
David Schleef committed
360
  GST_CAT_REGISTRY = _gst_debug_category_new ("GST_REGISTRY", 0, "registry");
Wim Taymans's avatar
Wim Taymans committed
361
  GST_CAT_QOS = _gst_debug_category_new ("GST_QOS", 0, "QoS");
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
362

363
364

  /* print out the valgrind message if we're in valgrind */
365
  _priv_gst_in_valgrind ();
366
367
}

368
/* we can't do this further above, because we initialize the GST_CAT_DEFAULT struct */
369
#define GST_CAT_DEFAULT _GST_CAT_DEBUG
370

371
372
373
374
375
376
377
378
379
380
/**
 * gst_debug_log:
 * @category: category to log
 * @level: level of the message is in
 * @file: the file that emitted the message, usually the __FILE__ identifier
 * @function: the function that emitted the message
 * @line: the line from that the message was emitted, usually __LINE__
 * @object: the object this message relates to or NULL if none
 * @format: a printf style format string
 * @...: optional arguments for the format
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
381
 *
382
 * Logs the given message using the currently registered debugging handlers.
383
 */
384
385
386
387
void
gst_debug_log (GstDebugCategory * category, GstDebugLevel level,
    const gchar * file, const gchar * function, gint line,
    GObject * object, const gchar * format, ...)
388
389
{
  va_list var_args;
390

391
  va_start (var_args, format);
392
393
  gst_debug_log_valist (category, level, file, function, line, object, format,
      var_args);
394
395
  va_end (var_args);
}
396

397
/**
Benjamin Otte's avatar
Benjamin Otte committed
398
 * gst_debug_log_valist:
399
400
401
402
403
404
405
406
 * @category: category to log
 * @level: level of the message is in
 * @file: the file that emitted the message, usually the __FILE__ identifier
 * @function: the function that emitted the message
 * @line: the line from that the message was emitted, usually __LINE__
 * @object: the object this message relates to or NULL if none
 * @format: a printf style format string
 * @args: optional arguments for the format
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
407
 *
408
 * Logs the given message using the currently registered debugging handlers.
409
 */
410
411
412
413
void
gst_debug_log_valist (GstDebugCategory * category, GstDebugLevel level,
    const gchar * file, const gchar * function, gint line,
    GObject * object, const gchar * format, va_list args)
414
{
415
  GstDebugMessage message;
416
417
418
  LogFuncEntry *entry;
  GSList *handler;

419
420
421
422
#ifdef _MSC_VER
  gchar *file_basename;
#endif

423
424
425
426
427
  g_return_if_fail (category != NULL);
  g_return_if_fail (file != NULL);
  g_return_if_fail (function != NULL);
  g_return_if_fail (format != NULL);

428
429
430
431
432
433
434
435
436
#ifdef _MSC_VER
  /*
   * The predefined macro __FILE__ is always the exact path given to the
   * compiler with MSVC, which may or may not be the basename.  We work
   * around it at runtime to improve the readability.
   */
  file = file_basename = g_path_get_basename (file);
#endif

437
438
  message.message = NULL;
  message.format = format;
439
  G_VA_COPY (message.arguments, args);
440

441
442
443
444
  handler = __log_functions;
  while (handler) {
    entry = handler->data;
    handler = g_slist_next (handler);
445
    entry->func (category, level, file, function, line, object, &message,
446
        entry->user_data);
447
448
  }
  g_free (message.message);
449
  va_end (message.arguments);
450
451
452
453

#ifdef _MSC_VER
  g_free (file_basename);
#endif
454
}
455

456
457
458
459
/**
 * gst_debug_message_get:
 * @message: a debug message
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
460
 * Gets the string representation of a #GstDebugMessage. This function is used
461
 * in debug handlers to extract the message.
462
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
463
 * Returns: the string representation of a #GstDebugMessage.
464
465
 */
const gchar *
466
gst_debug_message_get (GstDebugMessage * message)
467
468
469
{
  if (message->message == NULL) {
    message->message = g_strdup_vprintf (message->format, message->arguments);
470
  }
471
  return message->message;
472
}
473

474
475
476
477

static gchar *
gst_debug_print_object (gpointer ptr)
{
478
  GObject *object = (GObject *) ptr;
479
480
481
482
483
484
485

#ifdef unused
  /* This is a cute trick to detect unmapped memory, but is unportable,
   * slow, screws around with madvise, and not actually that useful. */
  {
    int ret;

486
    ret = madvise ((void *) ((unsigned long) ptr & (~0xfff)), 4096, 0);
487
488
489
490
491
492
493
494
    if (ret == -1 && errno == ENOMEM) {
      buffer = g_strdup_printf ("%p (unmapped memory)", ptr);
    }
  }
#endif

  /* nicely printed object */
  if (object == NULL) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
495
    return g_strdup ("(NULL)");
496
  }
497
498
  if (*(GType *) ptr == GST_TYPE_CAPS) {
    return gst_caps_to_string ((GstCaps *) ptr);
499
  }
500
501
  if (*(GType *) ptr == GST_TYPE_STRUCTURE) {
    return gst_structure_to_string ((GstStructure *) ptr);
502
503
  }
#ifdef USE_POISONING
504
  if (*(guint32 *) ptr == 0xffffffff) {
505
506
507
508
509
510
511
512
513
514
    return g_strdup_printf ("<poisoned@%p>", ptr);
  }
#endif
  if (GST_IS_PAD (object) && GST_OBJECT_NAME (object)) {
    return g_strdup_printf ("<%s:%s>", GST_DEBUG_PAD_NAME (object));
  }
  if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object)) {
    return g_strdup_printf ("<%s>", GST_OBJECT_NAME (object));
  }
  if (G_IS_OBJECT (object)) {
515
    return g_strdup_printf ("<%s@%p>", G_OBJECT_TYPE_NAME (object), object);
516
  }
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
  if (GST_IS_MESSAGE (object)) {
    GstMessage *msg = GST_MESSAGE_CAST (object);
    gchar *s, *ret;

    if (msg->structure) {
      s = gst_structure_to_string (msg->structure);
    } else {
      s = g_strdup ("(NULL)");
    }

    ret = g_strdup_printf ("%s message from element '%s': %s",
        GST_MESSAGE_TYPE_NAME (msg), (msg->src != NULL) ?
        GST_ELEMENT_NAME (msg->src) : "(NULL)", s);
    g_free (s);
    return ret;
  }
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  if (GST_IS_QUERY (object)) {
    GstQuery *query = GST_QUERY_CAST (object);

    if (query->structure) {
      return gst_structure_to_string (query->structure);
    } else {
      const gchar *query_type_name;

      query_type_name = gst_query_type_get_name (query->type);
      if (G_LIKELY (query_type_name != NULL)) {
        return g_strdup_printf ("%s query", query_type_name);
      } else {
        return g_strdup_printf ("query of unknown type %d", query->type);
      }
    }
  }
549
550
551
552

  return g_strdup_printf ("%p", ptr);
}

553
554
#ifdef HAVE_PRINTF_EXTENSION

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
static gchar *
gst_debug_print_segment (gpointer ptr)
{
  GstSegment *segment = (GstSegment *) ptr;

  /* nicely printed segment */
  if (segment == NULL) {
    return g_strdup ("(NULL)");
  }

  switch (segment->format) {
    case GST_FORMAT_UNDEFINED:{
      return g_strdup_printf ("UNDEFINED segment");
    }
    case GST_FORMAT_TIME:{
      return g_strdup_printf ("time segment start=%" GST_TIME_FORMAT
          ", stop=%" GST_TIME_FORMAT ", last_stop=%" GST_TIME_FORMAT
          ", duration=%" GST_TIME_FORMAT ", rate=%f, applied_rate=%f"
          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
          GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop),
          GST_TIME_ARGS (segment->last_stop), GST_TIME_ARGS (segment->duration),
          segment->rate, segment->applied_rate, (guint) segment->flags,
          GST_TIME_ARGS (segment->time), GST_TIME_ARGS (segment->accum));
    }
    default:{
      const gchar *format_name;

      format_name = gst_format_get_name (segment->format);
      if (G_UNLIKELY (format_name == NULL))
        format_name = "(UNKNOWN FORMAT)";
      return g_strdup_printf ("%s segment start=%" G_GINT64_FORMAT
          ", stop=%" G_GINT64_FORMAT ", last_stop=%" G_GINT64_FORMAT
          ", duration=%" G_GINT64_FORMAT ", rate=%f, applied_rate=%f"
          ", flags=0x%02x, time=%" GST_TIME_FORMAT ", accum=%" GST_TIME_FORMAT,
          format_name, segment->start, segment->stop, segment->last_stop,
          segment->duration, segment->rate, segment->applied_rate,
          (guint) segment->flags, GST_TIME_ARGS (segment->time),
          GST_TIME_ARGS (segment->accum));
    }
  }
}

597
598
#endif /* HAVE_PRINTF_EXTENSION */

599
600
601
/**
 * gst_debug_construct_term_color:
 * @colorinfo: the color info
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
602
 *
603
604
605
 * Constructs a string that can be used for getting the desired color in color
 * terminals.
 * You need to free the string after use.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
606
 *
607
608
609
610
611
612
 * Returns: a string containing the color definition
 */
gchar *
gst_debug_construct_term_color (guint colorinfo)
{
  GString *color;
613

614
  color = g_string_new ("\033[00");
615

616
  if (colorinfo & GST_DEBUG_BOLD) {
617
    g_string_append_len (color, ";01", 3);
618
619
  }
  if (colorinfo & GST_DEBUG_UNDERLINE) {
620
    g_string_append_len (color, ";04", 3);
621
622
623
624
625
  }
  if (colorinfo & GST_DEBUG_FG_MASK) {
    g_string_append_printf (color, ";3%1d", colorinfo & GST_DEBUG_FG_MASK);
  }
  if (colorinfo & GST_DEBUG_BG_MASK) {
626
    g_string_append_printf (color, ";4%1d",
627
        (colorinfo & GST_DEBUG_BG_MASK) >> 4);
628
  }
629
  g_string_append_c (color, 'm');
630

631
  return g_string_free (color, FALSE);
632
}
633

634
635
636
637
638
639
640
641
/**
 * gst_debug_construct_win_color:
 * @colorinfo: the color info
 *
 * Constructs an integer that can be used for getting the desired color in
 * windows' terminals (cmd.exe). As there is no mean to underline, we simply
 * ignore this attribute.
 *
642
643
 * This function returns 0 on non-windows machines.
 *
644
 * Returns: an integer containing the color definition
645
646
 *
 * Since: 0.10.23
647
648
649
650
651
 */
gint
gst_debug_construct_win_color (guint colorinfo)
{
  gint color = 0;
652
#ifdef G_OS_WIN32
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
  static const guchar ansi_to_win_fg[8] = {
    0,                          /* black   */
    FOREGROUND_RED,             /* red     */
    FOREGROUND_GREEN,           /* green   */
    FOREGROUND_RED | FOREGROUND_GREEN,  /* yellow  */
    FOREGROUND_BLUE,            /* blue    */
    FOREGROUND_RED | FOREGROUND_BLUE,   /* magenta */
    FOREGROUND_GREEN | FOREGROUND_BLUE, /* cyan    */
    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE /* white   */
  };
  static const guchar ansi_to_win_bg[8] = {
    0,
    BACKGROUND_RED,
    BACKGROUND_GREEN,
    BACKGROUND_RED | BACKGROUND_GREEN,
    BACKGROUND_BLUE,
    BACKGROUND_RED | BACKGROUND_BLUE,
    BACKGROUND_GREEN | FOREGROUND_BLUE,
    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
  };

  /* we draw black as white, as cmd.exe can only have black bg */
  if (colorinfo == 0) {
    return ansi_to_win_fg[7];
  }

  if (colorinfo & GST_DEBUG_BOLD) {
    color |= FOREGROUND_INTENSITY;
  }
  if (colorinfo & GST_DEBUG_FG_MASK) {
    color |= ansi_to_win_fg[colorinfo & GST_DEBUG_FG_MASK];
  }
  if (colorinfo & GST_DEBUG_BG_MASK) {
    color |= ansi_to_win_bg[(colorinfo & GST_DEBUG_BG_MASK) >> 4];
  }
688
#endif
689
690
691
  return color;
}

692
693
694
695
696
697
698
699
700
701
702
703
704
/* width of %p varies depending on actual value of pointer, which can make
 * output unevenly aligned if multiple threads are involved, hence the %14p
 * (should really be %18p, but %14p seems a good compromise between too many
 * white spaces and likely unalignment on my system) */
#if defined (GLIB_SIZEOF_VOID_P) && GLIB_SIZEOF_VOID_P == 8
#define PTR_FMT "%14p"
#else
#define PTR_FMT "%10p"
#endif
#define PID_FMT "%5d"
#define CAT_FMT "%20s %s:%d:%s:%s"

#ifdef G_OS_WIN32
705
static const guchar levelcolormap[GST_LEVEL_COUNT] = {
706
707
708
709
710
711
712
713
714
715
716
  /* GST_LEVEL_NONE */
  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
  /* GST_LEVEL_ERROR */
  FOREGROUND_RED | FOREGROUND_INTENSITY,
  /* GST_LEVEL_WARNING */
  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
  /* GST_LEVEL_INFO */
  FOREGROUND_GREEN | FOREGROUND_INTENSITY,
  /* GST_LEVEL_DEBUG */
  FOREGROUND_GREEN | FOREGROUND_BLUE,
  /* GST_LEVEL_LOG */
717
718
719
720
721
722
723
724
  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
  /* GST_LEVEL_FIXME */
  FOREGROUND_RED | FOREGROUND_GREEN,
  /* placeholder for log level 7 */
  0,
  /* placeholder for log level 8 */
  0,
  /* GST_LEVEL_MEMDUMP */
725
726
727
  FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
};

728
static const guchar available_colors[] = {
729
730
731
732
733
  FOREGROUND_RED, FOREGROUND_GREEN, FOREGROUND_RED | FOREGROUND_GREEN,
  FOREGROUND_BLUE, FOREGROUND_RED | FOREGROUND_BLUE,
  FOREGROUND_GREEN | FOREGROUND_BLUE,
};
#else
734
static const gchar *levelcolormap[GST_LEVEL_COUNT] = {
735
736
737
738
739
  "\033[37m",                   /* GST_LEVEL_NONE */
  "\033[31;01m",                /* GST_LEVEL_ERROR */
  "\033[33;01m",                /* GST_LEVEL_WARNING */
  "\033[32;01m",                /* GST_LEVEL_INFO */
  "\033[36m",                   /* GST_LEVEL_DEBUG */
740
741
742
743
744
  "\033[37m",                   /* GST_LEVEL_LOG */
  "\033[33;01m",                /* GST_LEVEL_FIXME */
  "\033[37m",                   /* placeholder for log level 7 */
  "\033[37m",                   /* placeholder for log level 8 */
  "\033[37m"                    /* GST_LEVEL_MEMDUMP */
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
};
#endif

/**
 * gst_debug_log_default:
 * @category: category to log
 * @level: level of the message
 * @file: the file that emitted the message, usually the __FILE__ identifier
 * @function: the function that emitted the message
 * @line: the line from that the message was emitted, usually __LINE__
 * @message: the actual message
 * @object: the object this message relates to or NULL if none
 * @unused: an unused variable, reserved for some user_data.
 *
 * The default logging handler used by GStreamer. Logging functions get called
 * whenever a macro like GST_DEBUG or similar is used. This function outputs the
 * message and additional info using the glib error handler.
 * You can add other handlers by using gst_debug_add_log_function().
 * And you can remove this handler by calling
 * gst_debug_remove_log_function(gst_debug_log_default);
 */
766
767
768
769
770
void
gst_debug_log_default (GstDebugCategory * category, GstDebugLevel level,
    const gchar * file, const gchar * function, gint line,
    GObject * object, GstDebugMessage * message, gpointer unused)
{
771
  gint pid;
772
  GstClockTime elapsed;
773
  gchar *obj = NULL;
774
  gboolean free_obj = TRUE;
775
  gboolean is_colored;
776
777
778
779
780

  if (level > gst_debug_category_get_threshold (category))
    return;

  pid = getpid ();
781
782
783
784
  is_colored = gst_debug_is_colored ();

  elapsed = GST_CLOCK_DIFF (_priv_gst_info_start_time,
      gst_util_get_timestamp ());
785
786
787
788
789
790
791
792

  if (object) {
    obj = gst_debug_print_object (object);
  } else {
    obj = "\0";
    free_obj = FALSE;
  }

793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
  if (is_colored) {
#ifndef G_OS_WIN32
    gchar *color = NULL;
    gchar *clear;
    gchar pidcolor[10];
    const gchar *levelcolor;

    color = gst_debug_construct_term_color (gst_debug_category_get_color
        (category));
    clear = "\033[00m";
    g_sprintf (pidcolor, "\033[3%1dm", pid % 6 + 31);
    levelcolor = levelcolormap[level];

#define PRINT_FMT " %s"PID_FMT"%s "PTR_FMT" %s%s%s %s"CAT_FMT"%s %s\n"
    g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed),
        pidcolor, pid, clear, g_thread_self (), levelcolor,
        gst_debug_level_get_name (level), clear, color,
        gst_debug_category_get_name (category), file, line, function, obj,
        clear, gst_debug_message_get (message));
#undef PRINT_FMT
    g_free (color);
#else
    const gint clear = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
Wim Taymans's avatar
Wim Taymans committed
816
817
#define SET_COLOR(c) \
  SetConsoleTextAttribute (GetStdHandle (STD_ERROR_HANDLE), (c));
818
819
820
    /* timestamp */
    g_printerr ("%" GST_TIME_FORMAT " ", GST_TIME_ARGS (elapsed));
    /* pid */
821
    SET_COLOR (available_colors[pid % G_N_ELEMENTS (available_colors)]);
822
    g_printerr (PID_FMT, pid);
823
    /* thread */
Wim Taymans's avatar
Wim Taymans committed
824
    SET_COLOR (clear);
825
    g_printerr (" " PTR_FMT " ", g_thread_self ());
826
    /* level */
Wim Taymans's avatar
Wim Taymans committed
827
    SET_COLOR (levelcolormap[level]);
828
829
    g_printerr ("%s ", gst_debug_level_get_name (level));
    /* category */
Wim Taymans's avatar
Wim Taymans committed
830
831
    SET_COLOR (gst_debug_construct_win_color (gst_debug_category_get_color
            (category)));
832
    g_printerr (CAT_FMT, gst_debug_category_get_name (category),
833
834
        file, line, function, obj);
    /* message */
Wim Taymans's avatar
Wim Taymans committed
835
    SET_COLOR (clear);
836
    g_printerr (" %s\n", gst_debug_message_get (message));
837
#endif
838
  } else {
839
840
#define PRINT_FMT " "PID_FMT" "PTR_FMT" %s "CAT_FMT" %s\n"
    g_printerr ("%" GST_TIME_FORMAT PRINT_FMT, GST_TIME_ARGS (elapsed), pid,
841
842
843
        g_thread_self (), gst_debug_level_get_name (level),
        gst_debug_category_get_name (category), file, line, function, obj,
        gst_debug_message_get (message));
844
#undef PRINT_FMT
845
846
847
848
849
850
  }

  if (free_obj)
    g_free (obj);
}

851
/**
852
853
 * gst_debug_level_get_name:
 * @level: the level to get the name for
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
854
 *
855
 * Get the string representation of a debugging level
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
856
 *
857
 * Returns: the name
858
 */
859
860
861
862
const gchar *
gst_debug_level_get_name (GstDebugLevel level)
{
  switch (level) {
863
864
865
866
867
868
869
870
871
872
873
874
    case GST_LEVEL_NONE:
      return "";
    case GST_LEVEL_ERROR:
      return "ERROR";
    case GST_LEVEL_WARNING:
      return "WARN ";
    case GST_LEVEL_INFO:
      return "INFO ";
    case GST_LEVEL_DEBUG:
      return "DEBUG";
    case GST_LEVEL_LOG:
      return "LOG  ";
875
876
877
878
    case GST_LEVEL_FIXME:
      return "FIXME";
    case GST_LEVEL_MEMDUMP:
      return "MEMDUMP  ";
879
880
881
882
    default:
      g_warning ("invalid level specified for gst_debug_level_get_name");
      return "";
  }
883
}
884

885
/**
886
887
888
 * gst_debug_add_log_function:
 * @func: the function to use
 * @data: user data
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
889
 *
890
891
 * Adds the logging function to the list of logging functions.
 * Be sure to use G_GNUC_NO_INSTRUMENT on that function, it is needed.
892
893
 */
void
894
895
896
gst_debug_add_log_function (GstLogFunction func, gpointer data)
{
  LogFuncEntry *entry;
Benjamin Otte's avatar
Benjamin Otte committed
897
  GSList *list;
898

899
  g_return_if_fail (func != NULL);
900

901
902
903
  entry = g_new (LogFuncEntry, 1);
  entry->func = func;
  entry->user_data = data;
Benjamin Otte's avatar
Benjamin Otte committed
904
905
906
  /* FIXME: we leak the old list here - other threads might access it right now
   * in gst_debug_logv. Another solution is to lock the mutex in gst_debug_logv,
   * but that is waaay costly.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
907
   * It'd probably be clever to use some kind of RCU here, but I don't know
Benjamin Otte's avatar
Benjamin Otte committed
908
909
   * anything about that.
   */
910
  g_static_mutex_lock (&__log_func_mutex);
Benjamin Otte's avatar
Benjamin Otte committed
911
912
  list = g_slist_copy (__log_functions);
  __log_functions = g_slist_prepend (list, entry);
913
914
915
  g_static_mutex_unlock (&__log_func_mutex);

  GST_DEBUG ("prepended log function %p (user data %p) to log functions",
916
      func, data);
917
}
918

919
920
921
static gint
gst_debug_compare_log_function_by_func (gconstpointer entry, gconstpointer func)
{
922
  gpointer entryfunc = (gpointer) (((LogFuncEntry *) entry)->func);
923

924
925
  return (entryfunc < func) ? -1 : (entryfunc > func) ? 1 : 0;
}
926

927
928
929
930
static gint
gst_debug_compare_log_function_by_data (gconstpointer entry, gconstpointer data)
{
  gpointer entrydata = ((LogFuncEntry *) entry)->user_data;
931

932
933
  return (entrydata < data) ? -1 : (entrydata > data) ? 1 : 0;
}
934

Benjamin Otte's avatar
Benjamin Otte committed
935
936
937
938
939
940
static guint
gst_debug_remove_with_compare_func (GCompareFunc func, gpointer data)
{
  GSList *found;
  GSList *new;
  guint removals = 0;
941

Benjamin Otte's avatar
Benjamin Otte committed
942
943
  g_static_mutex_lock (&__log_func_mutex);
  new = __log_functions;
944
945
  while ((found = g_slist_find_custom (new, data, func))) {
    if (new == __log_functions) {
946
947
      /* make a copy when we have the first hit, so that we modify the copy and
       * make that the new list later */
Benjamin Otte's avatar
Benjamin Otte committed
948
      new = g_slist_copy (new);
949
      continue;
Benjamin Otte's avatar
Benjamin Otte committed
950
    }
951
    g_free (found->data);
Benjamin Otte's avatar
Benjamin Otte committed
952
    new = g_slist_delete_link (new, found);
Benjamin Otte's avatar
Benjamin Otte committed
953
954
955
956
957
958
959
960
    removals++;
  }
  /* FIXME: We leak the old list here. See _add_log_function for why. */
  __log_functions = new;
  g_static_mutex_unlock (&__log_func_mutex);

  return removals;
}
961

Erik Walthinsen's avatar
Erik Walthinsen committed
962
/**
963
964
 * gst_debug_remove_log_function:
 * @func: the log function to remove
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
965
 *
966
 * Removes all registered instances of the given logging functions.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
967
 *
968
 * Returns: How many instances of the function were removed
Erik Walthinsen's avatar
Erik Walthinsen committed
969
 */
970
971
972
guint
gst_debug_remove_log_function (GstLogFunction func)
{
Benjamin Otte's avatar
Benjamin Otte committed
973
  guint removals;
974

975
  g_return_val_if_fail (func != NULL, 0);
976

977
978
  removals =
      gst_debug_remove_with_compare_func
979
      (gst_debug_compare_log_function_by_func, (gpointer) func);
980
981
  GST_DEBUG ("removed log function %p %d times from log function list", func,
      removals);
982

983
  return removals;
984
}
985

986
987
988
/**
 * gst_debug_remove_log_function_by_data:
 * @data: user data of the log function to remove
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
989
 *
990
 * Removes all registered instances of log functions with the given user data.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
991
 *
992
993
994
995
996
 * Returns: How many instances of the function were removed
 */
guint
gst_debug_remove_log_function_by_data (gpointer data)
{
Benjamin Otte's avatar
Benjamin Otte committed
997
  guint removals;
998

999
1000
1001
1002
1003
1004
  removals =
      gst_debug_remove_with_compare_func
      (gst_debug_compare_log_function_by_data, data);
  GST_DEBUG
      ("removed %d log functions with user data %p from log function list",
      removals, data);
1005

1006
1007
  return removals;
}
1008

Erik Walthinsen's avatar
Erik Walthinsen committed
1009
/**
1010
1011
 * gst_debug_set_colored:
 * @colored: Whether to use colored output or not
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1012
 *
1013
 * Sets or unsets the use of coloured debugging output.
Erik Walthinsen's avatar
Erik Walthinsen committed
1014
 */
1015
void
1016
1017
gst_debug_set_colored (gboolean colored)
{
1018
  g_atomic_int_set (&__use_color, colored ? 1 : 0);
1019
}
1020

Erik Walthinsen's avatar
Erik Walthinsen committed
1021
/**
1022
 * gst_debug_is_colored:
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1023
 *
1024
 * Checks if the debugging output should be colored.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1025
 *
1026
 * Returns: TRUE, if the debug output should be colored.
Erik Walthinsen's avatar
Erik Walthinsen committed
1027
 */
1028
1029
1030
gboolean
gst_debug_is_colored (void)
{
1031
  return g_atomic_int_get (&__use_color) == 0 ? FALSE : TRUE;
1032
}
1033

Erik Walthinsen's avatar
Erik Walthinsen committed
1034
/**
1035
1036
 * gst_debug_set_active:
 * @active: Whether to use debugging output or not
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1037
 *
1038
1039
1040
 * If activated, debugging messages are sent to the debugging
 * handlers.
 * It makes sense to deactivate it for speed issues.
Benjamin Otte's avatar
Benjamin Otte committed
1041
1042
 * <note><para>This function is not threadsafe. It makes sense to only call it
 * during initialization.</para></note>
Erik Walthinsen's avatar
Erik Walthinsen committed
1043
 */
1044
void
1045
1046
gst_debug_set_active (gboolean active)
{
Benjamin Otte's avatar
Benjamin Otte committed
1047
  __gst_debug_enabled = active;
1048
1049
  if (active)
    __gst_debug_min = GST_LEVEL_COUNT;
1050
1051
  else
    __gst_debug_min = GST_LEVEL_NONE;
1052
}
1053

Erik Walthinsen's avatar
Erik Walthinsen committed
1054
/**
1055
 * gst_debug_is_active:
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1056
 *
1057
 * Checks if debugging output is activated.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1058
 *
1059
1060
1061
1062
1063
 * Returns: TRUE, if debugging is activated
 */
gboolean
gst_debug_is_active (void)
{
Benjamin Otte's avatar
Benjamin Otte committed
1064
  return __gst_debug_enabled;
1065
}
1066

1067
1068
1069
/**
 * gst_debug_set_default_threshold:
 * @level: level to set
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1070
 *
1071
1072
 * Sets the default threshold to the given level and updates all categories to
 * use this threshold.
Erik Walthinsen's avatar
Erik Walthinsen committed
1073
 */
1074
void
1075
1076
gst_debug_set_default_threshold (GstDebugLevel level)
{
1077
  g_atomic_int_set (&__default_level, level);
1078
  gst_debug_reset_all_thresholds ();
1079
}
1080

1081
1082
/**
 * gst_debug_get_default_threshold:
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1083
 *
1084
 * Returns the default threshold that is used for new categories.
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
1085
 *
1086
1087
1088
1089
 * Returns: the default threshold level
 */
GstDebugLevel
gst_debug_get_default_threshold (void)
1090
{
1091
  return (GstDebugLevel) g_atomic_int_get (&__default_level);
1092
}