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 */
38 void plugin_setup_config() { }
41 void plugin_shutdown() { }
43 void timed_menu_clean_up(Menu
*m
) {
44 if (TIMED_MENU_DATA(m
)->buf
!= NULL
) {
45 fprintf(stderr
, "%s", TIMED_MENU_DATA(m
)->buf
);
46 g_free(TIMED_MENU_DATA(m
)->buf
);
47 TIMED_MENU_DATA(m
)->buf
= NULL
;
50 TIMED_MENU_DATA(m
)->buflen
= 0;
52 if (TIMED_MENU_DATA(m
)->fd
!= -1) {
53 event_remove_fd(TIMED_MENU_DATA(m
)->fd
);
54 close(TIMED_MENU_DATA(m
)->fd
);
55 TIMED_MENU_DATA(m
)->fd
= -1;
58 if (TIMED_MENU_DATA(m
)->pid
!= -1) {
59 waitpid(TIMED_MENU_DATA(m
)->pid
, NULL
, 0);
60 TIMED_MENU_DATA(m
)->pid
= -1;
64 void timed_menu_read_pipe(int fd
, Menu
*menu
)
67 unsigned long num_read
;
69 Timed_Menu_Data
*d
= TIMED_MENU_DATA(menu
);
72 unsigned long num_realloc
;
73 /* if we have less than a quarter BUFSIZ left, allocate more */
74 num_realloc
= (BUFSIZ
- (TIMED_MENU_DATA(menu
)->buflen
% BUFSIZ
) <
78 tmpbuf
= g_try_realloc(TIMED_MENU_DATA(menu
)->buf
,
79 TIMED_MENU_DATA(menu
)->buflen
+ num_realloc
);
82 g_warning("Unable to allocate memory for read()");
86 TIMED_MENU_DATA(menu
)->buf
= tmpbuf
;
89 TIMED_MENU_DATA(menu
)->buf
+ TIMED_MENU_DATA(menu
)->buflen
,
92 unsigned long count
= 0;
99 (found
= strchr(&TIMED_MENU_DATA(menu
)->buf
[count
], '\n'))) {
100 TIMED_MENU_DATA(menu
)->buf
101 [found
- TIMED_MENU_DATA(menu
)->buf
] = '\0';
103 menu_entry_new_separator
104 (&TIMED_MENU_DATA(menu
)->buf
[count
]));
105 count
= found
- TIMED_MENU_DATA(menu
)->buf
+ 1;
109 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
110 timed_menu_clean_up(menu
);
111 } else if (num_read
> 0) {
112 TIMED_MENU_DATA(menu
)->buflen
+= num_read
;
113 TIMED_MENU_DATA(menu
)->buf
[TIMED_MENU_DATA(menu
)->buflen
] = '\0';
114 } else { /* num_read < 1 */
115 g_warning("Error on read %s", strerror(errno
));
116 timed_menu_clean_up(menu
);
120 void timed_menu_timeout_handler(Menu
*data
)
124 if (!data
->shown
&& TIMED_MENU_DATA(data
)->fd
== -1) {
125 switch (TIMED_MENU_DATA(data
)->type
) {
126 case (TIMED_MENU_PIPE
):
128 /* if the menu is not shown, run a process and use its output
131 /* I hate you glib in all your hideous forms */
132 char *args
[] = {"/bin/sh", "-c", TIMED_MENU_DATA(data
)->command
,
135 if (g_spawn_async_with_pipes(
139 G_SPAWN_SEARCH_PATH
| G_SPAWN_DO_NOT_REAP_CHILD
,
141 &TIMED_MENU_DATA(data
)->pid
,
147 event_fd_handler
*h
= g_new(event_fd_handler
, 1);
148 TIMED_MENU_DATA(data
)->fd
= h
->fd
= child_stdout
;
149 h
->handler
= timed_menu_read_pipe
;
151 event_add_fd_handler(h
);
153 g_warning("unable to spawn child");
162 void *plugin_create()
164 Timed_Menu_Data
*d
= g_new(Timed_Menu_Data
, 1);
165 Menu
*m
= menu_new("", PLUGIN_NAME
, NULL
);
167 m
->plugin
= PLUGIN_NAME
;
169 d
->type
= TIMED_MENU_PIPE
;
170 d
->timer
= timer_start(60000000, &timed_menu_timeout_handler
, m
);
171 d
->command
= "find /media -name *.m3u";
177 m
->plugin_data
= (void *)d
;
179 timed_menu_timeout_handler(m
);
183 void plugin_destroy (void *m
)
185 /* this will be freed by timer_* */
186 timer_stop( ((Timed_Menu_Data
*)TIMED_MENU(m
)->plugin_data
)->timer
);
188 g_free( TIMED_MENU(m
)->plugin_data
);