tracer: simplify hook api
[platform/upstream/gstreamer.git] / gst / gsttracerutils.c
1 /* GStreamer
2  * Copyright (C) 2013 Stefan Sauer <ensonic@users.sf.net>
3  *
4  * gsttracerutils.c: tracing subsystem
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 /**
23  * SECTION:gsttracerutils
24  * @short_description: Tracing subsystem
25  *
26  * The tracing subsystem provides hooks in the core library and API for modules
27  * to attach to them.
28  *
29  * The user can activate tracers by setting the environment variable GST_TRACE
30  * to a ';' separated list of tracers.
31  */
32
33 #define GST_USE_UNSTABLE_API
34
35 #include "gst_private.h"
36 #include "gsttracer.h"
37 #include "gsttracerfactory.h"
38 #include "gsttracerutils.h"
39
40 #ifndef GST_DISABLE_GST_DEBUG
41
42 /* tracing helpers */
43
44 gboolean _priv_tracer_enabled = FALSE;
45 /* TODO(ensonic): use array of GPtrArray* ? */
46 GList *_priv_tracers[GST_TRACER_HOOK_ID_LAST] = { NULL, };
47
48 typedef struct
49 {
50   GstTracer *tracer;
51   GstTracerHookFunction func;
52 } GstTracerHook;
53
54 /* Initialize the tracing system */
55 void
56 _priv_gst_tracer_init (void)
57 {
58   const gchar *env = g_getenv ("GST_TRACE");
59
60   if (env != NULL && *env != '\0') {
61     GstRegistry *registry = gst_registry_get ();
62     GstPluginFeature *feature;
63     GstTracerFactory *factory;
64     gchar **t = g_strsplit_set (env, ";", 0);
65     gint i = 0;
66     gchar *params;
67
68     GST_INFO ("enabling tracers: '%s'", env);
69
70     while (t[i]) {
71       // check t[i] for params
72       if ((params = strchr (t[i], '('))) {
73         gchar *end = strchr (&params[1], ')');
74         *params = '\0';
75         params++;
76         if (end)
77           *end = '\0';
78       } else {
79         params = NULL;
80       }
81
82       GST_INFO ("checking tracer: '%s'", t[i]);
83
84       if ((feature = gst_registry_lookup_feature (registry, t[i]))) {
85         factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
86         if (factory) {
87           GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
88               (guint) factory->type);
89
90           /* tracers register them self to the hooks */
91           gst_object_unref (g_object_new (factory->type, "params", params,
92                   NULL));
93         } else {
94           GST_WARNING_OBJECT (feature,
95               "loading plugin containing feature %s failed!", t[i]);
96         }
97       } else {
98         GST_WARNING ("no tracer named '%s'", t[i]);
99       }
100       i++;
101     }
102     g_strfreev (t);
103   }
104 }
105
106 void
107 _priv_gst_tracer_deinit (void)
108 {
109   gint i;
110   GList *node;
111   GstTracerHook *hook;
112
113   /* shutdown tracers for final reports */
114   for (i = 0; i < GST_TRACER_HOOK_ID_LAST; i++) {
115     for (node = _priv_tracers[i]; node; node = g_list_next (node)) {
116       hook = (GstTracerHook *) node->data;
117       gst_object_unref (hook->tracer);
118       g_slice_free (GstTracerHook, hook);
119     }
120     g_list_free (_priv_tracers[i]);
121     _priv_tracers[i] = NULL;
122   }
123   _priv_tracer_enabled = FALSE;
124 }
125
126 void
127 gst_tracer_register_hook (GstTracer * tracer, GstTracerHookId id,
128     GstTracerHookFunction func)
129 {
130   GstTracerHook *hook = g_slice_new0 (GstTracerHook);
131   hook->tracer = gst_object_ref (tracer);
132   hook->func = func;
133   _priv_tracers[id] = g_list_prepend (_priv_tracers[id], hook);
134   GST_DEBUG_OBJECT (tracer, "added tracer to hook %d", id);
135   _priv_tracer_enabled = TRUE;
136 }
137
138 void
139 gst_tracer_dispatch (GstTracerHookId id, ...)
140 {
141   va_list var_args;
142   GList *node;
143   GstTracerHook *hook;
144
145   for (node = _priv_tracers[id]; node; node = g_list_next (node)) {
146     hook = (GstTracerHook *) node->data;
147     va_start (var_args, id);
148     hook->func (hook->tracer, var_args);
149     va_end (var_args);
150   }
151 }
152
153 #endif /* GST_DISABLE_GST_DEBUG */