]> icculus.org git repositories - mikachu/openbox.git/blob - plugins/menu/timed_menu.c
ignore the build shit
[mikachu/openbox.git] / plugins / menu / timed_menu.c
1 #include <glib.h>
2
3 #include "kernel/menu.h"
4 #include "kernel/timer.h"
5 #include "timed_menu.h"
6 #include "kernel/action.h"
7
8 #define TIMED_MENU(m) ((Menu *)m)
9 #define TIMED_MENU_DATA(m) ((Timed_Menu_Data *)((Menu *)m)->plugin_data)
10 static char *PLUGIN_NAME = "timed_menu";
11
12 typedef enum {
13     TIMED_MENU_PIPE
14 } Timed_Menu_Type;
15
16 /* we can use various GIO channels to support reading menus (can we add them to
17    the event loop? )
18    stat() based update
19    exec() based read
20 */
21 typedef struct {
22     Timed_Menu_Type type;
23     Timer *timer; /* timer code handles free */
24     char *command; /* for the PIPE */
25 } Timed_Menu_Data;
26
27
28 void plugin_setup_config() { }
29 void plugin_startup()
30 { }
31 void plugin_shutdown() { }
32
33 void timed_menu_timeout_handler(void *data)
34 {
35     Action *a;
36     ((Menu *)data)->invalid = TRUE;
37
38     if (!TIMED_MENU(data)->shown) {
39         switch (TIMED_MENU_DATA(data)->type) {
40             case (TIMED_MENU_PIPE):
41             {
42                 /* if the menu is not shown, run a process and use its output
43                    as menu */
44                 char *args[] = {"/bin/sh", "-c", TIMED_MENU_DATA(data)->command,
45                                 NULL};
46                 GIOChannel *io;
47                 char *line;
48                 gint child, c_stdout, line_len, terminator_pos;
49                 GIOStatus status;
50                 /* this blocks for now, until the event stuff can handle it */
51                 if (!g_spawn_async_with_pipes(NULL,
52                         args,
53                         NULL,
54                         G_SPAWN_DO_NOT_REAP_CHILD,
55                         NULL, NULL,
56                         &child, NULL, &c_stdout, NULL,
57                         NULL)) {
58                     g_warning("%s: Unable to run timed_menu program",
59                         __FUNCTION__);
60                     break;
61                 }
62                 
63                 io = g_io_channel_unix_new(c_stdout);
64                 if (io == NULL) {
65                     g_error("%s: Unable to get IO channel", __FUNCTION__);
66                     break;
67                 }
68
69                 menu_clear(TIMED_MENU(data));
70                 
71                 while ( G_IO_STATUS_NORMAL == (status =
72                             g_io_channel_read_line
73                             (io, &line, &line_len, &terminator_pos, NULL))
74                     ) {
75                     /* the \n looks ugly */
76                     line[terminator_pos] = '\0';
77                     menu_add_entry(TIMED_MENU(data),
78                         menu_entry_new_separator(line));
79                     g_message("%s", line);
80                     g_free(line);
81                 }
82                 break;
83             }
84         }
85     }
86 }
87
88 void *plugin_create()
89 {
90     Timed_Menu_Data *d = g_new(Timed_Menu_Data, 1);
91     Menu *m = menu_new("", PLUGIN_NAME, NULL);
92     
93     m->plugin = PLUGIN_NAME;
94
95     d->type = TIMED_MENU_PIPE;
96     d->timer = timer_start(1000000, &timed_menu_timeout_handler, m);
97     d->command = "ls";
98     
99     m->plugin_data = (void *)d;
100   
101     return (void *)m;
102 }
103
104 void plugin_destroy (void *m)
105 {
106     /* this will be freed by timer_* */
107     timer_stop( ((Timed_Menu_Data *)TIMED_MENU(m)->plugin_data)->timer);
108     
109     g_free( TIMED_MENU(m)->plugin_data );
110 }