7 #include "kernel/menu.h"
8 #include "kernel/timer.h"
9 #include "timed_menu.h"
10 #include "kernel/action.h"
11 #include "kernel/event.h"
13 #define TIMED_MENU(m) ((Menu *)m)
14 #define TIMED_MENU_DATA(m) ((Timed_Menu_Data *)((Menu *)m)->plugin_data)
15 static char *PLUGIN_NAME
= "timed_menu";
21 /* we can use various GIO channels to support reading menus (can we add them to
28 Timer
*timer
; /* timer code handles free */
29 char *command
; /* for the PIPE */
36 void plugin_setup_config() { }
39 void plugin_shutdown() { }
41 void timed_menu_clean_up(Menu
*m
) {
42 if (TIMED_MENU_DATA(m
)->buf
!= NULL
) {
43 fprintf(stderr
, "%s", TIMED_MENU_DATA(m
)->buf
);
44 g_free(TIMED_MENU_DATA(m
)->buf
);
45 TIMED_MENU_DATA(m
)->buf
= NULL
;
48 TIMED_MENU_DATA(m
)->buflen
= 0;
50 if (TIMED_MENU_DATA(m
)->fd
!= -1) {
51 event_remove_fd(TIMED_MENU_DATA(m
)->fd
);
52 close(TIMED_MENU_DATA(m
)->fd
);
53 TIMED_MENU_DATA(m
)->fd
= -1;
56 /* child is reaped by glib ? */
59 void timed_menu_read_pipe(int fd
, Menu
*menu
)
62 unsigned long num_read
;
64 Timed_Menu_Data
*d
= TIMED_MENU_DATA(menu
);
67 unsigned long num_realloc
;
68 /* if we have less than a quarter BUFSIZ left, allocate more */
69 num_realloc
= (BUFSIZ
- (TIMED_MENU_DATA(menu
)->buflen
% BUFSIZ
) <
73 tmpbuf
= g_try_realloc(TIMED_MENU_DATA(menu
)->buf
,
74 TIMED_MENU_DATA(menu
)->buflen
+ num_realloc
);
77 g_warning("Unable to allocate memory for read()");
81 TIMED_MENU_DATA(menu
)->buf
= tmpbuf
;
84 TIMED_MENU_DATA(menu
)->buf
+ TIMED_MENU_DATA(menu
)->buflen
,
87 unsigned long count
= 0;
94 (found
= strchr(&TIMED_MENU_DATA(menu
)->buf
[count
], '\n'))) {
95 TIMED_MENU_DATA(menu
)->buf
96 [found
- TIMED_MENU_DATA(menu
)->buf
] = '\0';
98 menu_entry_new_separator
99 (&TIMED_MENU_DATA(menu
)->buf
[count
]));
100 count
= found
- TIMED_MENU_DATA(menu
)->buf
+ 1;
104 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
105 timed_menu_clean_up(menu
);
106 } else if (num_read
> 0) {
107 TIMED_MENU_DATA(menu
)->buflen
+= num_read
;
108 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
109 } else { /* num_read < 1 */
110 g_warning("Error on read %s", strerror(errno
));
111 timed_menu_clean_up(menu
);
115 void timed_menu_timeout_handler(Menu
*data
)
119 if (!data
->shown
&& TIMED_MENU_DATA(data
)->fd
== -1) {
120 switch (TIMED_MENU_DATA(data
)->type
) {
121 case (TIMED_MENU_PIPE
):
123 /* if the menu is not shown, run a process and use its output
126 /* I hate you glib in all your hideous forms */
127 char *args
[] = {"/bin/sh", "-c", TIMED_MENU_DATA(data
)->command
,
130 if (g_spawn_async_with_pipes(
134 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
142 event_fd_handler
*h
= g_new(event_fd_handler
, 1);
143 TIMED_MENU_DATA(data
)->fd
= h
->fd
= child_stdout
;
144 h
->handler
= timed_menu_read_pipe
;
146 event_add_fd_handler(h
);
148 g_warning("unable to spawn child");
157 void *plugin_create()
159 Timed_Menu_Data
*d
= g_new(Timed_Menu_Data
, 1);
160 Menu
*m
= menu_new("", PLUGIN_NAME
, NULL
);
162 m
->plugin
= PLUGIN_NAME
;
164 d
->type
= TIMED_MENU_PIPE
;
165 d
->timer
= timer_start(60000000, &timed_menu_timeout_handler
, m
);
166 d
->command
= "find /media -name *.m3u";
171 m
->plugin_data
= (void *)d
;
173 timed_menu_timeout_handler(m
);
177 void plugin_destroy (void *m
)
179 /* this will be freed by timer_* */
180 timer_stop( ((Timed_Menu_Data
*)TIMED_MENU(m
)->plugin_data
)->timer
);
182 g_free( TIMED_MENU(m
)->plugin_data
);