Rename osl index entry stuff.
[paraslash.git] / krell.c
1 /*
2 * Copyright (C) 2004-2005 Andre Noll <maan@systemlinux.org>
3 *
4 * Licensed under the GPL v2. For licencing details see COPYING.
5 */
6
7
8 //#define PRINTF printf
9 #define PRINTF(a, ...)
10
11 #include <gkrellm2/gkrellm.h>
12 #include <utime.h>
13 #include <dirent.h>
14 #include <errno.h>
15 #include <stdio.h>
16 #include <sys/time.h>
17 #include <sys/wait.h>
18
19 static void create_para_ctrl(GtkWidget *, gint);
20 static void update_para_ctrl(void);
21 static void create_tab(GtkWidget *);
22 static void apply_config(void);
23 static void load_config(gchar *);
24 static void save_config(FILE *);
25
26 static GkrellmMonitor monitor = {
27 "Parakrell", /* Name, for config tab. */
28 0, /* Id, 0 if a plugin */
29 create_para_ctrl, /* The create function */
30 update_para_ctrl, /* The update function */
31 create_tab, /* The config tab create function */
32 apply_config, /* Apply the config function */
33 save_config, /* Save user config */
34 load_config, /* Load user config */
35 "para_krell", /* config keyword */
36 NULL, /* Undefined 2 */
37 NULL, /* Undefined 1 */
38 NULL, /* Undefined 0 */
39 MON_APM, /* Insert plugin before this monitor */
40 NULL, /* Handle if a plugin, filled in by GKrellM */
41 NULL /* path if a plugin, filled in by GKrellM */
42 };
43
44 typedef struct {
45 GkrellmPiximage *image;
46 GkrellmDecalbutton *button;
47 gint x,y,w,h;
48 double x_scale,y_scale;
49 } ControlButton;
50
51 static ControlButton prev_button = {
52 .image = NULL,
53 .button = NULL,
54 .x = 10,
55 .y = 10,
56 .w = 50,
57 .h = 50,
58 .x_scale = 1,
59 .y_scale = 1,
60 };
61
62 GkrellmPiximage *piximage;
63 GkrellmPanel *panel;
64 GtkWidget *fileread_vbox;
65 GdkPixbuf *pixbuf;
66 gint song_change_input_id;
67 FILE *song_change_fd;
68 GIOChannel *song_change_channel;
69
70 static struct timeval sc_open_time;
71
72 static gchar *info_text =
73 "Parakrell displays an image corresponding to the soundfile\n"
74 "currently played by paraslash.\n\n"
75
76 "The plugin's panel is divided in 9 small squares, like \n"
77 "the numpad on a PC keyboard. For each square there is an \n"
78 "associated button and a number between 1 and 9.\n \n"
79
80 "Each button is bound to three different commands for left, \n"
81 "middle and right mouse button. Middle and right button are \n"
82 "reserved for setting volume and jumping around in the song, \n"
83 "respectively. Left button works as follows:\n \n"
84
85 "7 8 9 7: slider, 8: sdl_gui, 9: next \n"
86 "4 5 6 4: ps, 5: play, 6: dbadm \n"
87 "1 2 3 1: stop, 2: gui, 3: pause\n"
88
89 "\n\nAuthor:\n"
90 "Andre Noll <maan@systemlinux.org>\n"
91 "Copyright (C) 2004-2005\n"
92 "Distributed under the GNU General Public License.\n";
93
94 #define MAXLINE 255
95
96 static gboolean launch_cmd(char *cmd)
97 {
98
99 gchar **argv;
100 GError *err = NULL;
101 gboolean res;
102
103 PRINTF("%s: \n", __func__);
104 if (!cmd || *cmd == '\0')
105 return -1;
106
107 g_shell_parse_argv(cmd, NULL, &argv, NULL);
108 res = g_spawn_async(
109 NULL,
110 argv,
111 NULL,
112 G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL,
113 NULL,
114 NULL,
115 NULL,
116 &err
117 );
118 if (!res && err) {
119 gkrellm_message_dialog(NULL, err->message);
120 g_error_free(err);
121 }
122 g_strfreev(argv);
123 return res;
124 }
125
126 static gboolean cb_in_button(GkrellmDecalbutton *b,
127 GdkEventButton *ev, ControlButton *cbut)
128 {
129 gint x, y, area, width = gkrellm_chart_width();
130 x = (int) (3 * ev->x / width);
131 y = (int) (3 - 3 * ev->y / width);
132 area = 3 * y + x + 1;
133 char buf[MAXLINE];
134
135 PRINTF("%s: button %i pressed on area %i\n", __func__,
136 ev->button, area);
137 if (ev->button == 1) {
138 switch (area) {
139 case 1:
140 launch_cmd("para_client stop");
141 return 0;
142 case 2:
143 launch_cmd("xterm -e para_gui -a");
144 return 0;
145 case 3:
146 launch_cmd("para_client pause");
147 return 0;
148 case 4:
149 launch_cmd("para_client ps");
150 return 0;
151 case 5:
152 launch_cmd("para_client play");
153 return 0;
154 case 6:
155 launch_cmd("xterm -e para_dbadm");
156 return 0;
157 case 7:
158 launch_cmd("para_slider");
159 return 0;
160 case 8:
161 launch_cmd("para_sdl_gui -f");
162 return 0;
163 case 9:
164 launch_cmd("para_client next");
165 return 0;
166 }
167 return 0;
168 }
169 sprintf(buf, "%s %i", ev->button == 2? "aumix -v" : "para_client jmp",
170 area * 10);
171 return launch_cmd(buf);
172 }
173
174 static void make_button(ControlButton *cbut, gint fn_id)
175 {
176 PRINTF("%s: gkrellm_make_scaled_button\n", __func__);
177 cbut->button = gkrellm_make_scaled_button(
178 panel,
179 cbut->image,
180 NULL,
181 GINT_TO_POINTER(fn_id),
182 FALSE,
183 FALSE,
184 2,
185 0,
186 1,
187 cbut->x,
188 cbut->y,
189 cbut->w,
190 cbut->h
191 );
192 PRINTF("%s: making botton\n", __func__);
193 gkrellm_set_in_button_callback(cbut->button, cb_in_button, cbut);
194 }
195
196
197 static void load_img(void)
198 {
199 gint width = gkrellm_chart_width();
200 gint out = 0, ret;
201 FILE *pipe = NULL;
202 char buf[MAXLINE];
203 size_t num_read = 0;
204 gchar *filename = gkrellm_make_data_file_name("para", "pic.jpg");
205
206 PRINTF("%s: Opening %s\n", __func__, filename);
207 if ((out = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
208 perror("open");
209 goto out;
210 }
211 pipe = popen("para_client pic", "r");
212 if (!pipe)
213 goto out;
214 while ((ret = read(fileno(pipe), buf, sizeof(buf) - 1)) > 0) {
215 if (write(out, buf, ret) < 0) {
216 perror("Write");
217 goto out;
218 }
219 num_read += ret;
220 }
221 if (ret < 0) {
222 PRINTF("%s: Read Error\n", __func__);
223 goto out;
224 }
225 PRINTF("%s: new pic created (%i bytes)\n", __func__, num_read);
226 if (num_read < 500)
227 goto out;
228
229 if (piximage) {
230 gkrellm_destroy_piximage(piximage);
231 g_free(pixbuf);
232 }
233 PRINTF("%s: creating new piximage\n", __func__);
234 piximage = gkrellm_piximage_new_from_file(filename);
235 if (!piximage) {
236 PRINTF("%s: can not load image\n", __func__);
237 goto out;
238 }
239 pixbuf = gkrellm_scale_piximage_to_pixbuf(piximage, width, width);
240 out:
241 g_free(filename);
242 if (pipe)
243 pclose(pipe);
244 if (out)
245 close(out);
246 }
247
248 static void create_tab(GtkWidget *tab_vbox)
249 {
250 GtkTextBuffer *textbuf;
251 GtkWidget *text;
252 GtkWidget *scrolled, *vbox = tab_vbox;
253
254 PRINTF("%s: \n", __func__);
255
256 scrolled = gtk_scrolled_window_new(NULL, NULL);
257 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
258 GTK_POLICY_AUTOMATIC,
259 GTK_POLICY_AUTOMATIC);
260 textbuf = gtk_text_buffer_new(NULL);
261 gtk_text_buffer_set_text(textbuf, info_text, -1);
262 text = gtk_text_view_new_with_buffer(textbuf);
263 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
264 gtk_container_add(GTK_CONTAINER(scrolled), text);
265 gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
266 }
267
268 static gboolean song_change(GIOChannel *channel, GIOCondition condition,
269 gpointer panel)
270 {
271 char *str_return;
272 gsize length;
273
274 PRINTF("%s: input condition %i "
275 "(song_change channel fd = %i)\n", __func__, condition,
276 g_io_channel_unix_get_fd(song_change_channel));
277 if (!song_change_fd) {
278 PRINTF("%s: no song_change_fd\n", __func__);
279 goto err_out;
280 }
281 if (!(condition & (G_IO_IN | G_IO_PRI))) {
282 PRINTF("%s: song change pipe died\n", __func__);
283 song_change_fd = NULL;
284 wait(NULL);
285 return TRUE;
286 goto err_out;
287 }
288 if (!channel->is_readable) {
289 PRINTF("%s: fd not readable\n", __func__);
290 goto err_out;
291 }
292 PRINTF("%s: reading data\n", __func__);
293 if (g_io_channel_read_line(channel, &str_return,
294 &length, NULL, NULL) == G_IO_STATUS_NORMAL) {
295 PRINTF("%s: next song: %s", __func__, str_return);
296 g_free(str_return);
297 if (channel != song_change_channel)
298 goto err_out;
299 load_img();
300 return TRUE;
301 }
302 err_out:
303 g_io_channel_unref(channel);
304 g_io_channel_shutdown(channel, TRUE, NULL);
305 return FALSE;
306 }
307
308 static void create_song_change(void)
309 {
310 if (song_change_fd)
311 return;
312 gettimeofday(&sc_open_time, NULL);
313 PRINTF("%s: para_client sc\n", __func__);
314 song_change_fd = popen("para_client sc", "r");
315 if (!song_change_fd) {
316 PRINTF("%s: para_client sc failed\n", __func__);
317 return;
318 }
319 song_change_channel = g_io_channel_unix_new(fileno(song_change_fd));
320 g_io_channel_set_close_on_unref(song_change_channel, TRUE);
321 g_io_add_watch(song_change_channel,
322 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
323 &song_change, panel);
324 }
325
326 static void update_para_ctrl(void)
327 {
328 GdkDrawable *drawable = panel->drawing_area->window;
329 gint width = gkrellm_chart_width();
330
331 if (!drawable)
332 PRINTF("%s: No drawable\n", __func__);
333 else
334 gkrellm_paste_pixbuf(pixbuf, drawable, 0, 0, width, width);
335 if (!song_change_fd) {
336 struct timeval now;
337 PRINTF("%s: no song_change_fd\n", __func__);
338
339 gettimeofday(&now, NULL);
340 if (now.tv_sec > sc_open_time.tv_sec + 5)
341 create_song_change();
342 }
343 }
344
345 static void destroy_panel(void)
346 {
347 PRINTF("%s: \n", __func__);
348 if (!panel)
349 return;
350 PRINTF("%s: destroying panel\n", __func__);
351 gkrellm_panel_destroy(panel);
352 panel = NULL;
353 }
354
355 #if 0
356 static void destroy_song_change(void)
357 {
358 PRINTF("%s: \n", __func__);
359 if (!song_change_fd)
360 return;
361 }
362 #endif
363 static void destroy_all(void)
364 {
365 // destroy_song_change();
366 destroy_panel();
367 }
368
369 static void create_para_ctrl(GtkWidget *vbox, gint first_create)
370 {
371 gint style_id = gkrellm_lookup_meter_style_id(UPTIME_STYLE_NAME);
372 GkrellmStyle *style = gkrellm_meter_style(style_id);
373 gint width = gkrellm_chart_width();
374
375 destroy_all();
376 create_song_change();
377 panel = gkrellm_panel_new0();
378 gkrellm_panel_configure(panel, NULL, style);
379 gkrellm_panel_configure_set_height(panel, width);
380 PRINTF("%s: creating panel\n", __func__);
381 gkrellm_panel_create(vbox, &monitor, panel);
382 make_button(&prev_button, 1);
383 }
384
385 static void apply_config(void)
386 {
387 PRINTF("%s: \n", __func__);
388 }
389
390 static void load_config(gchar * arg)
391 {
392 PRINTF("%s: \n", __func__);
393
394 }
395
396 static void save_config(FILE * f)
397 {
398 PRINTF("%s: \n", __func__);
399 }
400
401 GkrellmMonitor *gkrellm_init_plugin(void)
402 {
403 return &monitor;
404 }