1 /* vi: set et sw=4 ts=8 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
3 /*
4  * This file is part of mission-control
5  *
6  * Copyright (C) 2007-2009 Nokia Corporation.
7  * Copyright (C) 2008 Collabora Ltd.
8  *
9  * Contact: Naba Kumar  <naba.kumar@nokia.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public License
13  * version 2.1 as published by the Free Software Foundation.
14  *
15  * This library is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  *
25  */
26 
27 /**
28  * SECTION:mcd-debug
29  * @title: Debugging
30  * @short_description: Debugging utilities
31  * @see_also:
32  * @stability: Unstable
33  * @include: mcd-debug.h
34  *
35  * FIXME
36  */
37 
38 #include <config.h>
39 
40 #include <stdlib.h>
41 
42 #include <telepathy-glib/telepathy-glib.h>
43 #include <telepathy-glib/telepathy-glib-dbus.h>
44 
45 #include <mission-control-plugins/mission-control-plugins.h>
46 
47 #include "mcd-debug.h"
48 #include "mcd-operation.h"
49 
50 gint mcd_debug_level = 0;
51 
52 static void
mcd_debug_print_tree_real(gpointer object,gint level)53 mcd_debug_print_tree_real (gpointer object, gint level)
54 {
55     GString *indent_str;
56     gchar *indent = "    ";
57     gint i;
58 
59     indent_str = g_string_new ("");
60 
61     for (i = 0; i < level; i++)
62     {
63 	g_string_append (indent_str, indent);
64     }
65 
66     g_debug ("%s%s (%p): %d", indent_str->str,
67 	     G_OBJECT_TYPE_NAME(object), object, G_OBJECT (object)->ref_count);
68 
69     if (MCD_IS_OPERATION (object))
70     {
71 	const GList *missions = mcd_operation_get_missions (MCD_OPERATION (object));
72 	const GList *node = missions;
73 	while (node)
74 	{
75 	    mcd_debug_print_tree_real (node->data, level + 1);
76 	    node = g_list_next (node);
77 	}
78     }
79     g_string_free (indent_str, TRUE);
80 }
81 
82 /* We don't really have debug categories yet */
83 
84 typedef enum {
85     MCD_DEBUG_MISC = 1 << 0,
86     MCD_DEBUG_TREES = 1 << 1
87 } McdDebugCategory;
88 
89 static GDebugKey const keys[] = {
90     { "misc", MCD_DEBUG_MISC },
91     { "trees", MCD_DEBUG_TREES },
92     { NULL, 0 }
93 };
94 
95 static McdDebugCategory categories = 0;
96 
97 void
mcd_debug_print_tree(gpointer object)98 mcd_debug_print_tree (gpointer object)
99 {
100     g_return_if_fail (MCD_IS_MISSION (object));
101 
102     if (categories & MCD_DEBUG_TREES)
103     {
104 	g_debug ("Object Hierarchy of object %p", object);
105 	g_debug ("[");
106 	mcd_debug_print_tree_real (object, 1);
107 	g_debug ("]");
108     }
109 }
110 
mcd_debug_init()111 void mcd_debug_init ()
112 {
113     gchar *mc_debug_str;
114     guint level;
115 
116     mc_debug_str = getenv ("MC_DEBUG");
117 
118     if (mc_debug_str)
119     {
120         /* historically, MC_DEBUG was an integer; try that first */
121         level = atoi (mc_debug_str);
122 
123         /* if it wasn't an integer; try interpreting it as a
124          * telepathy-glib-style flags-word */
125         if (level == 0)
126         {
127             categories = g_parse_debug_string (mc_debug_str, keys,
128                                                G_N_ELEMENTS (keys) - 1);
129             tp_debug_set_flags (mc_debug_str);
130 
131             /* mcd-debug.h uses the value of mcd_debug_level directly, so
132              * we need to set it nonzero to get uncategorized messages */
133             if ((categories & MCD_DEBUG_MISC) != 0 && mcd_debug_level == 0)
134             {
135                 mcd_debug_level = 1;
136             }
137         }
138         else
139         {
140             /* this is API, and will also try to set up categories from the
141              * level */
142             mcd_debug_set_level (level);
143         }
144     }
145 
146     mcp_set_debug ((mcd_debug_level >= 1));
147     mcp_debug_init ();
148 
149     tp_debug_divert_messages (g_getenv ("MC_LOGFILE"));
150 
151     if (mcd_debug_level >= 1)
152         g_debug ("%s version %s", PACKAGE, VERSION);
153 }
154 
155 void
mcd_debug_set_level(gint level)156 mcd_debug_set_level (gint level)
157 {
158     mcd_debug_level = level;
159 
160     mcp_set_debug ((mcd_debug_level >= 1));
161 
162     if (level >= 1)
163     {
164         categories |= MCD_DEBUG_MISC;
165     }
166     else
167     {
168         categories = 0;
169     }
170 
171     if (level >= 2)
172     {
173         categories |= MCD_DEBUG_TREES;
174     }
175 }
176 
177 void
mcd_debug(const gchar * format,...)178 mcd_debug (const gchar *format, ...)
179 {
180   gchar *message = NULL;
181   gchar **formatted = NULL;
182   TpDebugSender *dbg = tp_debug_sender_dup ();
183   va_list args;
184 
185   if (_mcd_debug_get_level () > 0)
186     formatted = &message;
187 
188   va_start (args, format);
189   tp_debug_sender_add_message_vprintf (dbg, NULL, formatted,
190       G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format, args);
191   va_end (args);
192 
193   if (!tp_str_empty (message))
194     {
195       g_debug ("%s", message);
196       g_free (message);
197     }
198 
199   /* NOTE: the sender must be cached elsewhere, or this gets EXPENSIVE: */
200   g_object_unref (dbg);
201 }
202