8 #include "kernel/menu.h"
9 #include "kernel/timer.h"
10 #include "timed_menu.h"
11 #include "kernel/action.h"
12 #include "kernel/event.h"
14 #define TIMED_MENU(m) ((Menu *)m)
15 #define TIMED_MENU_DATA(m) ((Timed_Menu_Data *)((Menu *)m)->plugin_data)
16 static char *PLUGIN_NAME
= "timed_menu";
22 /* we can use various GIO channels to support reading menus (can we add them to
29 Timer
*timer
; /* timer code handles free */
30 char *command
; /* for the PIPE */
37 void plugin_setup_config() { }
40 void plugin_shutdown() { }
42 void timed_menu_clean_up(Menu
*m
) {
43 if (TIMED_MENU_DATA(m
)->buf
!= NULL
) {
44 fprintf(stderr
, "%s", TIMED_MENU_DATA(m
)->buf
);
45 g_free(TIMED_MENU_DATA(m
)->buf
);
46 TIMED_MENU_DATA(m
)->buf
= NULL
;
49 TIMED_MENU_DATA(m
)->buflen
= 0;
51 if (TIMED_MENU_DATA(m
)->fd
!= -1) {
52 event_remove_fd(TIMED_MENU_DATA(m
)->fd
);
53 close(TIMED_MENU_DATA(m
)->fd
);
54 TIMED_MENU_DATA(m
)->fd
= -1;
57 /* child is reaped by glib ? */
60 void timed_menu_read_pipe(int fd
, Menu
*menu
)
63 unsigned long num_read
;
65 Timed_Menu_Data
*d
= TIMED_MENU_DATA(menu
);
68 unsigned long num_realloc
;
69 /* if we have less than a quarter BUFSIZ left, allocate more */
70 num_realloc
= (BUFSIZ
- (TIMED_MENU_DATA(menu
)->buflen
% BUFSIZ
) <
74 tmpbuf
= g_try_realloc(TIMED_MENU_DATA(menu
)->buf
,
75 TIMED_MENU_DATA(menu
)->buflen
+ num_realloc
);
78 g_warning("Unable to allocate memory for read()");
82 TIMED_MENU_DATA(menu
)->buf
= tmpbuf
;
85 TIMED_MENU_DATA(menu
)->buf
+ TIMED_MENU_DATA(menu
)->buflen
,
88 unsigned long count
= 0;
95 (found
= strchr(&TIMED_MENU_DATA(menu
)->buf
[count
], '\n'))) {
96 TIMED_MENU_DATA(menu
)->buf
97 [found
- TIMED_MENU_DATA(menu
)->buf
] = '\0';
99 menu_entry_new_separator
100 (&TIMED_MENU_DATA(menu
)->buf
[count
]));
101 count
= found
- TIMED_MENU_DATA(menu
)->buf
+ 1;
105 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
106 timed_menu_clean_up(menu
);
107 } else if (num_read
> 0) {
108 TIMED_MENU_DATA(menu
)->buflen
+= num_read
;
109 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
110 } else { /* num_read < 1 */
111 g_warning("Error on read %s", strerror(errno
));
112 timed_menu_clean_up(menu
);
116 void timed_menu_timeout_handler(Menu
*data
)
120 if (!data
->shown
&& TIMED_MENU_DATA(data
)->fd
== -1) {
121 switch (TIMED_MENU_DATA(data
)->type
) {
122 case (TIMED_MENU_PIPE
):
124 /* if the menu is not shown, run a process and use its output
127 /* I hate you glib in all your hideous forms */
128 char *args
[] = {"/bin/sh", "-c", TIMED_MENU_DATA(data
)->command
,
131 if (g_spawn_async_with_pipes(
135 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
143 event_fd_handler
*h
= g_new(event_fd_handler
, 1);
144 TIMED_MENU_DATA(data
)->fd
= h
->fd
= child_stdout
;
145 h
->handler
= timed_menu_read_pipe
;
147 event_add_fd_handler(h
);
149 g_warning("unable to spawn child");
158 void *plugin_create()
160 Timed_Menu_Data
*d
= g_new(Timed_Menu_Data
, 1);
161 Menu
*m
= menu_new("", PLUGIN_NAME
, NULL
);
163 m
->plugin
= PLUGIN_NAME
;
165 d
->type
= TIMED_MENU_PIPE
;
166 d
->timer
= timer_start(60000000, &timed_menu_timeout_handler
, m
);
167 d
->command
= "find /media -name *.m3u";
172 m
->plugin_data
= (void *)d
;
174 timed_menu_timeout_handler(m
);
178 void plugin_destroy (void *m
)
180 /* this will be freed by timer_* */
181 timer_stop( ((Timed_Menu_Data
*)TIMED_MENU(m
)->plugin_data
)->timer
);
183 g_free( TIMED_MENU(m
)->plugin_data
);