Updated Macedonian Translation <arangela@cvs.gnome.org>
[rhythmbox.git] / lib / rb-debug.c
blob4c2aaa643adfccd385337f5e11c91b582075dbe6
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * arch-tag: Implementation of simple Rhythmbox debugging interface
5 * Copyright (C) 2002 Jorn Baayen
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 * NOTES: log domain hack stolen from nautilus
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <signal.h>
30 #include <time.h>
32 #include <glib.h>
34 #include "rb-debug.h"
36 static void log_handler (const char *domain,
37 GLogLevelFlags level,
38 const char *message,
39 gpointer data);
41 static const char *debug_everything = "everything";
42 static const char *debug_match = NULL;
44 /* Our own funky debugging function, should only be used when something
45 * is not going wrong, if something *is* wrong use g_warning.
47 void
48 rb_debug_real (const char *func,
49 const char *file,
50 const int line,
51 const char *format, ...)
53 va_list args;
54 char buffer[1025];
55 char *str_time;
56 time_t the_time;
58 if (debug_match == NULL ||
59 (debug_match != debug_everything &&
60 (strstr (file, debug_match) == NULL) &&
61 (strstr (func, debug_match) == NULL)))
62 return;
64 va_start (args, format);
66 g_vsnprintf (buffer, 1024, format, args);
68 va_end (args);
70 time (&the_time);
71 str_time = g_new0 (char, 255);
72 strftime (str_time, 254, "%H:%M:%S", localtime (&the_time));
74 g_printerr ("(%s) [%p] [%s] %s:%d: %s\n", str_time, g_thread_self (),
75 func, file, line, buffer);
77 g_free (str_time);
80 void
81 rb_debug_init (gboolean debug)
83 rb_debug_init_match (debug ? debug_everything : NULL);
86 void
87 rb_debug_init_match (const char *match)
89 guint i;
91 /* This is a workaround for the fact that there is not way to
92 * make this useful debugging feature happen for ALL domains.
94 * What we did here is list all the ones we could think of that
95 * were interesting to us. It's OK to add more to the list.
97 static const char * const standard_log_domains[] = {
98 "",
99 "Bonobo",
100 "BonoboUI",
101 "Echo",
102 "Eel",
103 "GConf",
104 "GConf-Backends",
105 "GConf-Tests",
106 "GConfEd",
107 "GLib",
108 "GLib-GObject",
109 "GModule",
110 "GThread",
111 "GStreamer",
112 "Gdk",
113 "Gdk-Pixbuf",
114 "GdkPixbuf",
115 "Glib",
116 "Gnome",
117 "GnomeCanvas",
118 "GnomePrint",
119 "GnomeUI",
120 "GnomeVFS",
121 "GnomeVFS-CORBA",
122 "GnomeVFS-pthread",
123 "GnomeVFSMonikers",
124 "Gtk",
125 "Rhythmbox",
126 "RhythmDB",
127 "MonkeyMedia",
128 "ORBit",
129 "ZVT",
130 "libIDL",
131 "libgconf-scm",
132 "libglade",
133 "libgnomevfs",
134 "librsvg",
137 debug_match = match;
139 if (debug_match != NULL)
140 for (i = 0; i < G_N_ELEMENTS (standard_log_domains); i++)
141 g_log_set_handler (standard_log_domains[i], G_LOG_LEVEL_MASK, log_handler, NULL);
143 rb_debug ("Debugging enabled");
146 /* Raise a SIGINT signal to get the attention of the debugger.
147 * When not running under the debugger, we don't want to stop,
148 * so we ignore the signal for just the moment that we raise it.
150 void
151 rb_debug_stop_in_debugger (void)
153 void (* saved_handler) (int);
155 saved_handler = signal (SIGINT, SIG_IGN);
156 raise (SIGINT);
157 signal (SIGINT, saved_handler);
160 /* Stop in the debugger after running the default log handler.
161 * This makes certain kinds of messages stop in the debugger
162 * without making them fatal (you can continue).
164 static void
165 log_handler (const char *domain,
166 GLogLevelFlags level,
167 const char *message,
168 gpointer data)
170 g_log_default_handler (domain, level, message, data);
171 if ((level & (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING)) != 0)
173 rb_debug_stop_in_debugger ();
177 struct RBProfiler
179 GTimer *timer;
180 char *name;
183 RBProfiler *
184 rb_profiler_new (const char *name)
186 RBProfiler *profiler;
188 if (debug_match == FALSE)
189 return NULL;
191 profiler = g_new0 (RBProfiler, 1);
192 profiler->timer = g_timer_new ();
193 profiler->name = g_strdup (name);
195 g_timer_start (profiler->timer);
197 return profiler;
200 void
201 rb_profiler_dump (RBProfiler *profiler)
203 gulong elapsed;
204 double seconds;
206 if (debug_match == NULL)
207 return;
208 if (profiler == NULL)
209 return;
211 seconds = g_timer_elapsed (profiler->timer, &elapsed);
213 rb_debug ("PROFILER %s %ld ms (%f s) elapsed", profiler->name,
214 elapsed / (G_USEC_PER_SEC / 1000), seconds);
217 void
218 rb_profiler_reset (RBProfiler *profiler)
220 if (debug_match == NULL)
221 return;
222 if (profiler == NULL)
223 return;
225 g_timer_start (profiler->timer);
228 void
229 rb_profiler_free (RBProfiler *profiler)
231 if (debug_match == NULL)
232 return;
233 if (profiler == NULL)
234 return;
236 g_timer_destroy (profiler->timer);
237 g_free (profiler->name);
238 g_free (profiler);
241 /* Profiling */
243 static int profile_indent;
245 static void
246 profile_add_indent (int indent)
248 profile_indent += indent;
249 if (profile_indent < 0) {
250 g_error ("You screwed up your indentation");
254 void
255 _rb_profile_log (const char *func,
256 const char *file,
257 int line,
258 int indent,
259 const char *msg1,
260 const char *msg2)
262 char *str;
264 if (indent < 0) {
265 profile_add_indent (indent);
268 if (profile_indent == 0) {
269 str = g_strdup_printf ("MARK: [%s %s %d] %s %s", file, func, line, msg1 ? msg1 : "", msg2 ? msg2 : "");
270 } else {
271 str = g_strdup_printf ("MARK: %*c [%s %s %d] %s %s", profile_indent - 1, ' ', file, func, line, msg1 ? msg1 : "", msg2 ? msg2 : "");
274 access (str, F_OK);
276 g_free (str);
278 if (indent > 0) {
279 profile_add_indent (indent);