The problem that e17 couldn't move/resize window when the window fetch the rotation...
[platform/core/uifw/e17.git] / src / bin / e_log.c
1 #include "e.h"
2
3 #ifndef E_LOG_LEVEL
4 # define E_LOG_LEVEL EINA_LOG_LEVEL_INFO
5 #endif
6
7 EINTERN int e_log_dom = -1;
8
9 static const char *_names[] = {
10    "CRI",
11    "ERR",
12    "WRN",
13    "INF",
14    "DBG",
15 };
16
17 static void
18 _e_log_cb(const Eina_Log_Domain *d, Eina_Log_Level level, const char *file, const char *fnc __UNUSED__, int line, const char *fmt, void *data __UNUSED__, va_list args)
19 {
20    const char *color;
21
22    color = eina_log_level_color_get(level);
23    fprintf(stdout,
24            "%s%s<" EINA_COLOR_RESET "%s%s>" EINA_COLOR_RESET "%s:%d" EINA_COLOR_RESET " ",
25            color, _names[level > EINA_LOG_LEVEL_DBG ? EINA_LOG_LEVEL_DBG : level],
26            d->domain_str, color, file, line);
27    vfprintf(stdout, fmt, args);
28    putc('\n', stdout);
29 }
30
31 EINTERN int
32 e_log_init(void)
33 {
34    e_log_dom = eina_log_domain_register("e", EINA_COLOR_WHITE);
35    eina_log_domain_level_set("e", E_LOG_LEVEL);
36    eina_log_print_cb_set(_e_log_cb, NULL);
37    return (e_log_dom != -1);
38 }
39
40 EINTERN int
41 e_log_shutdown(void)
42 {
43    eina_log_domain_unregister(e_log_dom);
44    e_log_dom = -1;
45    return 0;
46 }
47
48 #ifdef _F_E_LOGBUF_
49 EAPI unsigned int e_logbuf_type = ELBT_NONE;
50
51 #define MAX_LOGS 9216
52 #define MAX_LOG_FUNC_STR_SIZE 20
53 #define MAX_LOG_STR_SIZE 80
54
55 typedef struct _E_Log
56 {
57    unsigned int      num;
58    unsigned int      type;
59    unsigned int      blank;
60    char              func[MAX_LOG_FUNC_STR_SIZE];
61    int               line;
62    unsigned int      id; // Ecore_X_Window or Zone ID
63    char              str[MAX_LOG_STR_SIZE];
64 } E_Log;
65
66 typedef struct _E_Logbuf
67 {
68    E_DBus_Interface    *iface;
69    int                  cur;
70    int                  num;
71    Eina_Bool            pts;
72    FILE                *fp;
73    Eina_List           *list; // list of E_Log
74    Ecore_Event_Handler *h;
75    Ecore_X_Atom         a;
76 } E_Logbuf;
77
78 static E_Logbuf *buf = NULL;
79
80 static void _log_disp(FILE *fp, E_Log *m);
81
82 EAPI void
83 e_logbuf_add(unsigned int type,
84              const char  *func,
85              int          line,
86              const char  *str,
87              unsigned int id)
88 {
89    E_Log *msg = NULL;
90    if (!buf) return;
91
92    if (eina_list_count(buf->list) < MAX_LOGS)
93      {
94         msg = E_NEW(E_Log, 1);
95         if (msg)
96           buf->list = eina_list_append(buf->list, msg);
97      }
98    else
99      {
100         buf->cur = (buf->cur) % MAX_LOGS;
101         msg = eina_list_nth(buf->list, buf->cur);
102      }
103
104    if (msg)
105      {
106         unsigned int n = 0;
107         msg->num = buf->num++;
108         msg->type = type;
109         msg->blank = 0;
110
111         n = sizeof(msg->func);
112         if (n >= MAX_LOG_FUNC_STR_SIZE)
113           {
114              strncpy(msg->func, func, MAX_LOG_FUNC_STR_SIZE-1);
115              msg->func[MAX_LOG_FUNC_STR_SIZE-1] = '\0';
116           }
117         else
118           {
119              strncpy(msg->func, func, n);
120           }
121
122         msg->line = line;
123         msg->id = id;
124
125         n = sizeof(msg->str);
126         if (n >= MAX_LOG_STR_SIZE)
127           {
128              strncpy(msg->str, str, MAX_LOG_STR_SIZE-1);
129              msg->str[MAX_LOG_STR_SIZE-1] = '\0';
130           }
131         else
132           {
133              strncpy(msg->str, str, n);
134           }
135
136         buf->cur = (buf->num) % MAX_LOGS;
137
138         if ((buf->pts) && (buf->fp))
139           _log_disp(buf->fp, msg);
140      }
141 }
142
143 EAPI void
144 e_logbuf_fmt_add(unsigned int type,
145                  unsigned int blank,
146                  const char  *func,
147                  int          line,
148                  unsigned int id,
149                  const char  *fmt,
150                  ...)
151 {
152    E_Log *msg = NULL;
153    va_list args;
154    if (!buf) return;
155
156    if (eina_list_count(buf->list) < MAX_LOGS)
157      {
158         msg = E_NEW(E_Log, 1);
159         if (msg)
160           buf->list = eina_list_append(buf->list, msg);
161      }
162    else
163      {
164         buf->cur = (buf->cur) % MAX_LOGS;
165         msg = eina_list_nth(buf->list, buf->cur);
166      }
167
168    if (msg)
169      {
170         unsigned int n = 0;
171         msg->num = buf->num++;
172         msg->type = type;
173         msg->blank = blank;
174
175         n = sizeof(msg->func);
176         if (n >= MAX_LOG_FUNC_STR_SIZE)
177           {
178              strncpy(msg->func, func, MAX_LOG_FUNC_STR_SIZE-1);
179              msg->func[MAX_LOG_FUNC_STR_SIZE-1] = '\0';
180           }
181         else
182           {
183              strncpy(msg->func, func, n);
184           }
185
186         msg->line = line;
187         msg->id = id;
188
189         va_start(args, fmt);
190         vsnprintf(msg->str, sizeof(msg->str), fmt, args);
191         va_end(args);
192
193         buf->cur = (buf->num) % MAX_LOGS;
194
195         if ((buf->pts) && (buf->fp))
196           _log_disp(buf->fp, msg);
197      }
198 }
199
200 static void
201 _e_logbuf_shutdown(void)
202 {
203    e_logbuf_type = ELBT_NONE;
204
205    if (buf)
206      {
207         E_Log *msg = NULL;
208         EINA_LIST_FREE(buf->list, msg) E_FREE(msg);
209         buf->list = NULL;
210         if (buf->iface)
211           {
212              e_msgbus_interface_detach(buf->iface);
213              e_dbus_interface_unref(buf->iface);
214              buf->iface = NULL;
215           }
216         if (buf->h)
217           ecore_event_handler_del(buf->h);
218         memset(buf, 0, sizeof(E_Logbuf));
219         E_FREE(buf);
220         buf = NULL;
221      }
222 }
223
224 static const char *
225 _type_name_get(unsigned int t)
226 {
227    switch (t)
228      {
229       case ELBT_NONE:   return "NONE";   break;
230       case ELBT_DFT:    return "DFT";    break;
231       case ELBT_MNG:    return "MNG";    break;
232       case ELBT_BD:     return "BD";     break;
233       case ELBT_ROT:    return "ROT";    break;
234       case ELBT_ILLUME: return "ILLUME"; break;
235       case ELBT_COMP:   return "COMP";   break;
236       case ELBT_MOVE:   return "MOVE";   break;
237       case ELBT_ALL:    return "ALL";    break;
238       default: break;
239      }
240    return NULL;
241 }
242
243 static void
244 _log_disp(FILE  *fp,
245           E_Log *m)
246 {
247    if (m->blank)
248      {
249         if (m->id)
250           fprintf(fp, "%38.38s|0x%08x|%s\n",
251                   "", m->id, m->str);
252         else
253           fprintf(fp, "%49.49s|%s\n",
254                   "", m->str);
255      }
256    else
257      {
258         if (m->id)
259           fprintf(fp, "%5d|%20.20s|%5d|%5.5s|0x%08x|%s\n",
260                   m->num, m->func, m->line,
261                   _type_name_get(m->type), m->id, m->str);
262         else
263           fprintf(fp, "%5d|%20.20s|%5d|%5.5s|%10.10s|%s\n",
264                   m->num, m->func, m->line,
265                   _type_name_get(m->type), "", m->str);
266      }
267 }
268
269 static void
270 _e_log_dump(FILE *fp)
271 {
272    Eina_List *l = NULL, *ll = NULL;
273    E_Log *msg = NULL;
274    unsigned int idx = 0;
275    if ((!buf) || (!fp)) return;
276
277    ll = eina_list_nth_list(buf->list, buf->cur);
278    EINA_LIST_FOREACH(ll, l, msg)
279      {
280         _log_disp(fp, msg);
281         idx = msg->num;
282      }
283    EINA_LIST_FOREACH(buf->list, l, msg)
284      {
285         if (msg->num < idx) break;
286         _log_disp(fp, msg);
287         idx = msg->num;
288      }
289    fprintf(fp, "Total:%d Num:%d\n", eina_list_count(buf->list), buf->num);
290    fflush(fp);
291 }
292
293 static DBusMessage *
294 _e_log_cb_enable(E_DBus_Object *obj __UNUSED__,
295                  DBusMessage       *msg)
296 {
297    e_logbuf_type = ELBT_ALL;
298    return dbus_message_new_method_return(msg);
299 }
300
301 static DBusMessage *
302 _e_log_cb_disable(E_DBus_Object *obj __UNUSED__,
303                   DBusMessage       *msg)
304 {
305    e_logbuf_type = ELBT_NONE;
306    return dbus_message_new_method_return(msg);
307 }
308
309 static DBusMessage *
310 _e_log_cb_dump(E_DBus_Object *obj __UNUSED__,
311                DBusMessage       *msg)
312 {
313    DBusError err;
314    const char *path = NULL;
315    FILE *fp = NULL;
316
317    dbus_error_init(&err);
318    if (!dbus_message_get_args(msg, &err,
319                               DBUS_TYPE_STRING, &path,
320                               DBUS_TYPE_INVALID))
321      {
322         fprintf(stderr,
323                 "could not get Log.Dump arguments: %s: %s",
324                 err.name, err.message);
325         dbus_error_free(&err);
326      }
327    else if (path)
328      {
329         if (buf)
330           {
331              Eina_Bool pts = EINA_FALSE;
332              if (strstr(path, "/dev/pts/"))
333                pts = EINA_TRUE;
334
335              fp = fopen(path, "w");
336              if (fp)
337                {
338                   _e_log_dump(fp);
339
340                   if (buf->fp)
341                     {
342                        fclose(buf->fp);
343                        buf->fp = NULL;
344                     }
345
346                   if (pts)
347                     {
348                        buf->pts = EINA_TRUE;
349                        buf->fp = fp;
350                     }
351                   else
352                     fclose(fp);
353
354                   fprintf(stdout,
355                           "dump log messages to file:%s\n",
356                           path);
357                }
358           }
359      }
360
361    return dbus_message_new_method_return(msg);
362 }
363
364 static Eina_Bool
365 _e_log_cb_prop(void *data __UNUSED__,
366                int type   __UNUSED__,
367                void      *event)
368 {
369    Ecore_X_Event_Window_Property *ev = event;
370    char *path = NULL;
371    FILE *fp = NULL;
372
373    if (!ev) return ECORE_CALLBACK_PASS_ON;
374    if (!ev->atom) return ECORE_CALLBACK_PASS_ON;
375    if (!buf) return ECORE_CALLBACK_PASS_ON;
376    if (ev->atom != buf->a) return ECORE_CALLBACK_PASS_ON;
377
378    path = ecore_x_window_prop_string_get(ev->win, ev->atom);
379    if (!path) return ECORE_CALLBACK_PASS_ON;
380
381    fp = fopen(path, "w");
382    if (!fp) return ECORE_CALLBACK_PASS_ON;
383
384    _e_log_dump(fp);
385    if (buf->fp)
386      {
387         fclose(buf->fp);
388         buf->pts = EINA_FALSE;
389         buf->fp = NULL;
390      }
391    fprintf(stdout,
392            "dump log messages to file:%s\n",
393            path);
394
395    fclose(fp);
396    return ECORE_CALLBACK_PASS_ON;
397 }
398
399 EINTERN int
400 e_logbuf_init(void)
401 {
402    _e_logbuf_shutdown();
403
404    buf = E_NEW(E_Logbuf, 1);
405    if (!buf) return 0;
406
407    buf->iface = e_dbus_interface_new("org.enlightenment.wm.Log");
408    if (!buf->iface)
409      {
410         fprintf(stderr, "Cannot add org.enlightenment.wm.Log interface\n");
411         memset(buf, 0, sizeof(E_Logbuf));
412         E_FREE(buf);
413         return 0;
414      }
415
416    e_dbus_interface_method_add(buf->iface, "Enable", "", "",   _e_log_cb_enable);
417    e_dbus_interface_method_add(buf->iface, "Disable", "", "",  _e_log_cb_disable);
418    e_dbus_interface_method_add(buf->iface, "Dump", "s", "",    _e_log_cb_dump);
419
420    e_msgbus_interface_attach(buf->iface);
421
422    buf->h = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, _e_log_cb_prop, NULL);
423    buf->a = ecore_x_atom_get("_E_LOG");
424
425    e_logbuf_type = ELBT_ALL;
426
427    return 1;
428 }
429
430 EINTERN int
431 e_logbuf_shutdown(void)
432 {
433    _e_logbuf_shutdown();
434    return 1;
435 }
436 #endif