wmpager: allow WMPAGER_DEFAULT_INSTALL_DIR to be defined in $FLAGS
[dockapps.git] / wmauda / wmauda.c
blobaaf762d6ea05f6abd0db47f6acac8c345372587f
1 /* wmauda - Dockapp for controlling Audacious
2 *
3 * Copyright (C) 2006 Michael Stewart <michael@alteredeclipse.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <gtk/gtk.h>
20 #include <gdk/gdkx.h>
21 #include <X11/Xlib.h>
22 #include <X11/Xatom.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <ctype.h>
29 #include <audacious/dbus.h>
30 #include <audacious/audctrl.h>
32 #include "dock-master.xpm"
34 #include <getopt.h>
36 #ifndef VERSION
37 # define VERSION 0.8
38 #endif
40 #ifndef PIXMAP_DIR
41 # define PIXMAP_DIR "/usr/local/share/pixmaps"
42 #endif
44 typedef struct
46 int x, y, width, height, pressed_x, pressed_y, normal_x, normal_y;
47 gboolean focus, pressed;
48 void (*callback) (void);
50 Button;
52 void action_play(void);
53 void action_pause(void);
54 void action_eject(void);
55 void action_prev(void);
56 void action_next(void);
57 void action_stop(void);
59 Button buttons[] =
61 {21, 32, 9, 11, 84, 0, 64, 0, FALSE, FALSE, action_play}, /* PLAY */
62 {34, 32, 9, 11, 94, 0, 74, 0, FALSE, FALSE, action_pause}, /* PAUSE */
63 {47, 32, 9, 11, 84, 11, 64, 11, FALSE, FALSE, action_eject}, /* EJECT */
64 {21, 46, 9, 11, 84, 22, 64, 22, FALSE, FALSE, action_prev}, /* PREV */
65 {34, 46, 9, 11, 94, 22, 74, 22, FALSE, FALSE, action_next}, /* NEXT */
66 {47, 46, 9, 11, 94, 11, 74, 11, FALSE, FALSE, action_stop}, /* STOP */
69 #define NUM_BUTTONS 6
71 GList *button_list;
73 typedef struct
75 unsigned char ascii; gint x, y;
76 } Charentry;
78 Charentry chartable[] =
80 { '-', 60, 73}, /* put here coordinates of characters */
81 { '.', 72, 73}, /* in xmms-dock-master.xpm */
82 { ',', 78, 73},
83 { '\\', 84, 73},
84 { '/', 90, 73},
85 { '(', 96, 73},
86 { ')', 102, 73},
87 { '%', 108, 73},
88 { 'Ä', 114, 73},
89 { 'ä', 114, 73}, /* toupper doesn't convert umlauts */
90 { 'Ö', 120, 73},
91 { 'ö', 120, 73},
92 { 'Ü', 126, 73},
93 { 'ü', 126, 73},
94 { '?', 132, 73},
95 { '!', 138, 73},
96 { '&', 144, 73},
97 { ':', 150, 73},
98 { ' ', 66, 73},
100 #define NUM_CHARS 19
102 #define VOLSLIDER_X 8
103 #define VOLSLIDER_Y 17
104 #define VOLSLIDER_WIDTH 7
107 #define VOLSLIDER_HEIGHT 40
109 #define SEEKSLIDER_X 21
110 #define SEEKSLIDER_Y 20
111 #define SEEKSLIDER_WIDTH 30
112 #define SEEKSLIDER_HEIGHT 7
113 #define SEEKSLIDER_KNOB_WIDTH 3
114 #define SEEKSLIDER_MAX (SEEKSLIDER_WIDTH - SEEKSLIDER_KNOB_WIDTH)
116 #define SCROLLTEXT_X 5
117 #define SCROLLTEXT_Y 6
118 #define SCROLLTEXT_WIDTH 40
119 #define SCROLLTEXT_HEIGHT 9
120 #define SCROLLTEXT_CHARS 9
122 gboolean volslider_dragging = FALSE;
123 int volslider_pos = 0;
124 gboolean seekslider_visible = FALSE, seekslider_dragging = FALSE;
125 int seekslider_pos = -1, seekslider_drag_offset = 0;
126 gint scrollpos = 0;
127 int timeout_tag = 0;
129 void init(void);
131 GtkWidget *icon_win;
132 GdkPixmap *pixmap, *launch_pixmap;
133 GdkBitmap *mask, *launch_mask;
134 GdkGC *dock_gc;
135 GtkTooltips *tooltips = NULL;
137 char *xmms_cmd = "audacious";
138 gboolean xmms_running = FALSE;
140 gboolean has_geometry = FALSE, single_click = FALSE, song_title = FALSE;
141 char *icon_name = NULL;
142 int win_x, win_y;
144 DBusGProxy *dbus_proxy = NULL;
145 static DBusGConnection *connection = NULL;
147 GtkTargetEntry drop_types[] =
149 {"text/plain", 0, 1}
152 void action_play(void)
154 audacious_remote_play(dbus_proxy);
157 void action_pause(void)
159 audacious_remote_pause(dbus_proxy);
162 void action_eject(void)
164 audacious_remote_playlist_clear(dbus_proxy);
165 audacious_remote_stop(dbus_proxy);
168 void action_prev(void)
170 audacious_remote_playlist_prev(dbus_proxy);
173 void action_next(void)
175 audacious_remote_playlist_next(dbus_proxy);
178 void action_stop(void)
180 audacious_remote_stop(dbus_proxy);
183 gboolean inside_region(int mx, int my, int x, int y, int w, int h)
185 if ((mx >= x && mx < x + w) && (my >= y && my < y + h))
186 return TRUE;
187 return FALSE;
190 void real_draw_button(GdkWindow *w, Button *button)
193 if (button->pressed)
194 gdk_draw_pixmap(w, dock_gc, pixmap,
195 button->pressed_x, button->pressed_y,
196 button->x, button->y,
197 button->width, button->height);
198 else
199 gdk_draw_pixmap(w, dock_gc, pixmap,
200 button->normal_x, button->normal_y,
201 button->x, button->y,
202 button->width, button->height);
205 void draw_button(Button *button)
207 real_draw_button(icon_win->window, button);
210 void draw_buttons(GList *list)
212 for (; list; list = g_list_next(list))
213 draw_button(list->data);
216 void real_draw_volslider(GdkWindow *w)
218 gdk_draw_pixmap(w, dock_gc, pixmap, 112, 1, VOLSLIDER_X, VOLSLIDER_Y,
219 VOLSLIDER_WIDTH, VOLSLIDER_HEIGHT);
220 gdk_draw_pixmap(w, dock_gc, pixmap, 106,
221 1 + VOLSLIDER_HEIGHT - volslider_pos,
222 VOLSLIDER_X,
223 VOLSLIDER_Y + VOLSLIDER_HEIGHT - volslider_pos,
224 VOLSLIDER_WIDTH, volslider_pos);
227 void draw_volslider(void)
229 real_draw_volslider(icon_win->window);
232 void real_draw_seekslider(GdkWindow *w)
234 int slider_x;
236 if (seekslider_visible)
238 gdk_draw_pixmap(w, dock_gc, pixmap, 66, 54,
239 SEEKSLIDER_X, SEEKSLIDER_Y, 35, 10);
240 if (seekslider_pos < SEEKSLIDER_MAX / 3)
241 slider_x = 108;
242 else if (seekslider_pos < (SEEKSLIDER_MAX * 2) / 3)
243 slider_x = 111;
244 else
245 slider_x = 114;
246 gdk_draw_pixmap(w, dock_gc, pixmap, slider_x, 48,
247 SEEKSLIDER_X + seekslider_pos,
248 SEEKSLIDER_Y, 3, SEEKSLIDER_HEIGHT);
250 else
251 gdk_draw_pixmap(w, dock_gc, pixmap, 66, 39,
252 SEEKSLIDER_X, SEEKSLIDER_Y, 35, 10);
255 void draw_seekslider(void)
257 real_draw_seekslider(icon_win->window);
260 void real_draw_scrolltext(GdkWindow * w)
262 /* get titlestring */
263 gint pl_pos = audacious_remote_get_playlist_pos(dbus_proxy);
265 if (pl_pos != -1)
267 char *title = audacious_remote_get_playlist_title(dbus_proxy, pl_pos);
268 if (title)
270 /* render text */
271 gint i = 0, c = 0, pos = 0, dest = 0;
273 for (i=0; i<SCROLLTEXT_CHARS; i++)
275 gint x = 66, y = 73;
276 scrollpos %= (strlen(title)+16) * 6;
277 pos = i + (scrollpos / 6) -8;
278 if (pos < strlen(title) && pos >= 0)
279 c = toupper(title[pos]);
280 else
281 c = ' ';
283 dest = SCROLLTEXT_X + (i * 6 - (scrollpos % 6));
285 if (c >= 'A' && c <= 'Z')
287 x = (c-'A')*6;
288 y = 64;
290 else if (c >= '0' && c <= '9')
291 x = (c-'0')*6;
292 else
294 int i = 0;
295 for (i=0; i<NUM_CHARS; i++)
296 if (c == chartable[i].ascii)
298 x = chartable[i].x;
299 y = chartable[i].y;
300 break;
303 gdk_draw_pixmap(w, dock_gc, pixmap, x, y,
304 dest, SCROLLTEXT_Y, 7, 9);
307 scrollpos++;
308 g_free(title);
313 void draw_scrolltext(void)
315 real_draw_scrolltext(icon_win->window);
318 void redraw_window(void)
320 if (xmms_running)
322 gdk_draw_pixmap(icon_win->window, dock_gc, pixmap,
323 0, 0, 0, 0, 64, 64);
324 draw_buttons(button_list);
325 draw_volslider();
326 draw_seekslider();
327 draw_scrolltext();
329 else
331 gdk_draw_pixmap(icon_win->window, dock_gc, launch_pixmap,
332 0, 0, 0, 0, 64, 64);
336 void expose_cb(GtkWidget *w, GdkEventExpose *event, gpointer data)
338 redraw_window();
341 void wheel_scroll_cb(GtkWidget *w, GdkEventScroll *event)
343 if (xmms_running)
345 if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
347 if (event->direction == GDK_SCROLL_UP)
348 volslider_pos += 3;
349 else
350 volslider_pos -= 3;
351 if (volslider_pos < 0)
352 volslider_pos = 0;
353 if (volslider_pos > VOLSLIDER_HEIGHT)
354 volslider_pos = VOLSLIDER_HEIGHT;
355 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
356 draw_volslider();
360 void button_press_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
362 GList *node;
363 Button *btn;
364 int pos;
365 char *cmd;
367 if (xmms_running)
369 if ((event->button == 2) || (event->button == 3))
371 if(audacious_remote_is_main_win(dbus_proxy))
372 audacious_remote_main_win_toggle(dbus_proxy, FALSE);
373 else
374 audacious_remote_main_win_toggle(dbus_proxy, TRUE);
378 if (event->button != 1)
379 return;
380 if (xmms_running)
382 for (node = button_list; node; node = g_list_next(node))
384 btn = node->data;
385 if (inside_region(event->x, event->y, btn->x, btn->y, btn->width, btn->height))
387 btn->focus = TRUE;
388 btn->pressed = TRUE;
389 draw_button(btn);
392 if (inside_region(event->x, event->y, VOLSLIDER_X, VOLSLIDER_Y, VOLSLIDER_WIDTH, VOLSLIDER_HEIGHT))
394 volslider_pos = VOLSLIDER_HEIGHT - (event->y - VOLSLIDER_Y);
395 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
396 draw_volslider();
397 volslider_dragging = TRUE;
399 if (inside_region(event->x, event->y, SEEKSLIDER_X, SEEKSLIDER_Y, SEEKSLIDER_WIDTH, SEEKSLIDER_HEIGHT) && seekslider_visible)
401 pos = event->x - SEEKSLIDER_X;
403 if (pos >= seekslider_pos &&
404 pos < seekslider_pos + SEEKSLIDER_KNOB_WIDTH)
405 seekslider_drag_offset = pos - seekslider_pos;
406 else
408 seekslider_drag_offset = 1;
409 seekslider_pos = pos - seekslider_drag_offset;
410 if (seekslider_pos < 0)
411 seekslider_pos = 0;
412 if (seekslider_pos > SEEKSLIDER_MAX)
413 seekslider_pos = SEEKSLIDER_MAX;
415 draw_seekslider();
416 seekslider_dragging = TRUE;
419 else if ((!single_click && event->type == GDK_2BUTTON_PRESS) ||
420 (single_click && event->type == GDK_BUTTON_PRESS))
422 cmd = g_strconcat(xmms_cmd, " &", NULL);
423 system(cmd);
424 g_free(cmd);
428 void button_release_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
430 GList *node;
431 Button *btn;
432 int len;
434 if (event->button != 1)
435 return;
437 for (node = button_list; node; node = g_list_next(node))
439 btn = node->data;
440 if (btn->pressed)
442 btn->focus = FALSE;
443 btn->pressed = FALSE;
444 draw_button(btn);
445 if (btn->callback)
446 btn->callback();
449 volslider_dragging = FALSE;
450 if (seekslider_dragging)
452 len = audacious_remote_get_playlist_time(dbus_proxy, audacious_remote_get_playlist_pos(dbus_proxy));
453 audacious_remote_jump_to_time(dbus_proxy, (seekslider_pos * len) / SEEKSLIDER_MAX);
454 seekslider_dragging = FALSE;
459 void motion_notify_cb(GtkWidget *w, GdkEventMotion *event, gpointer data)
461 GList *node;
462 Button *btn;
463 gboolean inside;
465 for (node = button_list; node; node = g_list_next(node))
467 btn = node->data;
468 if (btn->focus)
470 inside = inside_region(event->x, event->y,
471 btn->x, btn->y,
472 btn->width, btn->height);
473 if ((inside && !btn->pressed) ||
474 (!inside && btn->pressed))
476 btn->pressed = inside;
477 draw_button(btn);
481 if (volslider_dragging)
483 volslider_pos = VOLSLIDER_HEIGHT - (event->y - VOLSLIDER_Y);
484 if (volslider_pos < 0)
485 volslider_pos = 0;
486 if (volslider_pos > VOLSLIDER_HEIGHT)
487 volslider_pos = VOLSLIDER_HEIGHT;
488 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
489 draw_volslider();
491 if (seekslider_dragging)
493 seekslider_pos =
494 event->x - SEEKSLIDER_X - seekslider_drag_offset;
495 if (seekslider_pos < 0)
496 seekslider_pos = 0;
497 if (seekslider_pos > SEEKSLIDER_MAX)
498 seekslider_pos = SEEKSLIDER_MAX;
499 draw_seekslider();
504 void destroy_cb(GtkWidget *w, gpointer data)
506 gtk_exit(0);
509 static void update_tooltip(void)
511 static int pl_pos = -1;
512 static char *filename;
513 int new_pos;
515 if (!tooltips)
516 return;
518 new_pos = audacious_remote_get_playlist_pos(dbus_proxy);
520 if (new_pos == 0)
523 * Need to do some extra checking, as we get 0 also on
524 * a empty playlist
526 char *current = audacious_remote_get_playlist_file(dbus_proxy, 0);
527 if (!filename && current)
529 filename = current;
530 new_pos = -1;
532 else if (filename && !current)
534 g_free(filename);
535 filename = NULL;
536 new_pos = -1;
538 else if (filename && current && strcmp(filename, current))
540 g_free(filename);
541 filename = current;
542 new_pos = -1;
546 if (pl_pos != new_pos)
548 char *tip = NULL;
549 char *title =
550 audacious_remote_get_playlist_title(dbus_proxy, new_pos);
551 if (title)
553 tip = g_strdup_printf("%d. %s", new_pos+1, title);
554 g_free(title);
556 gtk_tooltips_set_tip(tooltips, icon_win, tip, NULL);
557 g_free(tip);
558 pl_pos = new_pos;
562 int timeout_func(gpointer data)
564 int new_pos, pos;
565 gboolean playing, running;
567 running = audacious_remote_is_running(dbus_proxy);
569 if (running)
571 if (!xmms_running)
573 gtk_widget_shape_combine_mask(icon_win, mask, 0, 0);
574 xmms_running = running;
575 redraw_window();
577 if (!volslider_dragging)
579 new_pos = (audacious_remote_get_main_volume(dbus_proxy) * 40) / 100;
581 if (new_pos < 0)
582 new_pos = 0;
583 if (new_pos > VOLSLIDER_HEIGHT)
584 new_pos = VOLSLIDER_HEIGHT;
586 if (volslider_pos != new_pos)
588 volslider_pos = new_pos;
589 draw_volslider();
593 update_tooltip();
594 draw_scrolltext();
596 playing = audacious_remote_is_playing(dbus_proxy);
597 if (!playing && seekslider_visible)
599 seekslider_visible = FALSE;
600 seekslider_dragging = FALSE;
601 seekslider_pos = -1;
602 draw_seekslider();
604 else if (playing)
606 int len, p = audacious_remote_get_playlist_pos(dbus_proxy);
607 len = audacious_remote_get_playlist_time(dbus_proxy, p);
608 if (len == -1)
610 seekslider_visible = FALSE;
611 seekslider_dragging = FALSE;
612 seekslider_pos = -1;
613 draw_seekslider();
615 else if (!seekslider_dragging)
617 seekslider_visible = TRUE;
618 pos = audacious_remote_get_output_time(dbus_proxy);
619 if (len != 0)
620 new_pos = (pos * SEEKSLIDER_MAX) / len;
621 else
622 new_pos = 0;
623 if (new_pos < 0)
624 new_pos = 0;
625 if (new_pos > SEEKSLIDER_MAX)
626 new_pos = SEEKSLIDER_MAX;
627 if (seekslider_pos != new_pos)
629 seekslider_pos = new_pos;
630 draw_seekslider();
635 else
637 if (xmms_running)
639 if (tooltips != NULL)
640 gtk_tooltips_set_tip(tooltips, icon_win, NULL, NULL);
641 gtk_widget_shape_combine_mask(icon_win, launch_mask, 0, 0);
642 xmms_running = FALSE;
643 redraw_window();
647 return TRUE;
650 void drag_data_received(GtkWidget *widget, GdkDragContext *context,
651 int x, int y, GtkSelectionData *selection_data,
652 guint info, guint time)
654 if (selection_data->data)
656 char *url = selection_data->data;
657 audacious_remote_playlist_clear(dbus_proxy);
658 audacious_remote_playlist_add_url_string(dbus_proxy, url);
659 audacious_remote_play(dbus_proxy);
663 static gboolean dbus_init(void)
665 GError *error = NULL;
667 connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
668 if (connection == NULL)
669 return FALSE;
671 dbus_proxy = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
672 AUDACIOUS_DBUS_PATH,
673 AUDACIOUS_DBUS_INTERFACE);
674 if (dbus_proxy == NULL)
675 return FALSE;
677 return TRUE;
680 void init(void)
682 GdkWindowAttr attr;
683 GdkColor bg_color;
684 GdkWindow *leader;
685 XWMHints hints;
686 int i, w, h;
687 GdkGC *mask_gc;
689 for (i = 0; i < NUM_BUTTONS; i++)
690 button_list = g_list_append(button_list, &buttons[i]);
692 if (song_title)
694 tooltips = gtk_tooltips_new();
695 gtk_tooltips_set_delay(tooltips, 1000);
698 icon_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
699 gtk_widget_set_app_paintable(icon_win, TRUE);
700 gtk_widget_set_uposition(icon_win, 0, 0);
701 gtk_widget_set_usize(icon_win, 64, 64);
702 gtk_widget_set_events(icon_win,
703 GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
704 GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
705 gtk_signal_connect(GTK_OBJECT(icon_win), "expose_event",
706 GTK_SIGNAL_FUNC(expose_cb), NULL);
707 gtk_signal_connect(GTK_OBJECT(icon_win), "button_press_event",
708 GTK_SIGNAL_FUNC(button_press_cb), NULL);
709 gtk_signal_connect(GTK_OBJECT(icon_win), "scroll_event",
710 GTK_SIGNAL_FUNC(wheel_scroll_cb), NULL);
711 gtk_signal_connect(GTK_OBJECT(icon_win), "button_release_event",
712 GTK_SIGNAL_FUNC(button_release_cb), NULL);
713 gtk_signal_connect(GTK_OBJECT(icon_win), "motion_notify_event",
714 GTK_SIGNAL_FUNC(motion_notify_cb), NULL);
715 gtk_signal_connect(GTK_OBJECT(icon_win), "destroy",
716 GTK_SIGNAL_FUNC(destroy_cb), NULL);
717 gtk_drag_dest_set(icon_win, GTK_DEST_DEFAULT_ALL, drop_types, 1,
718 GDK_ACTION_COPY);
719 gtk_signal_connect(GTK_OBJECT(icon_win), "drag_data_received",
720 GTK_SIGNAL_FUNC(drag_data_received), NULL);
721 gtk_widget_realize(icon_win);
722 bg_color.red = 0;
723 bg_color.green = 0;
724 bg_color.blue = 0;
725 gdk_colormap_alloc_color(gdk_colormap_get_system(),
726 &bg_color, FALSE, TRUE);
727 gdk_window_set_background(icon_win->window, &bg_color);
728 gdk_window_clear(icon_win->window);
729 dock_gc = gdk_gc_new(icon_win->window);
731 launch_pixmap = gdk_pixmap_new(icon_win->window, 64, 64, -1);
733 launch_mask = gdk_pixmap_new(icon_win->window, 64, 64, 1);
734 mask_gc = gdk_gc_new(launch_mask);
735 bg_color.pixel = 0;
736 gdk_gc_set_foreground(mask_gc, &bg_color);
737 gdk_draw_rectangle(launch_mask, mask_gc, TRUE, 0, 0, -1, -1);
739 if (!icon_name)
740 icon_name = g_strdup_printf("%s/wmauda.xpm", PIXMAP_DIR);
741 pixmap = gdk_pixmap_create_from_xpm(icon_win->window, &mask,
742 NULL, icon_name);
743 if (!pixmap)
745 printf("ERROR: Couldn't find %s\n", icon_name);
746 g_free(icon_name);
747 gtk_exit(1);
749 g_free(icon_name);
750 gdk_window_get_size(pixmap, &w, &h);
751 if (w > 64)
752 w = 64;
753 if (h > 64)
754 h = 64;
755 gdk_draw_pixmap(launch_pixmap, dock_gc, pixmap,
756 0, 0, 32 - (w / 2), 32 - (h / 2), w, h);
757 gdk_draw_pixmap(launch_mask, mask_gc, mask,
758 0, 0, 32 - (w / 2), 32 - (h / 2), w, h);
759 gdk_gc_unref(mask_gc);
760 gdk_pixmap_unref(pixmap);
761 gdk_bitmap_unref(mask);
763 gtk_widget_shape_combine_mask(icon_win, launch_mask, 0, 0);
765 pixmap = gdk_pixmap_create_from_xpm_d(icon_win->window,
766 &mask, NULL, dock_master_xpm);
768 attr.width = 64;
769 attr.height = 64;
770 attr.title = "wmauda";
771 attr.event_mask = GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_HINT_MASK;
772 attr.wclass = GDK_INPUT_OUTPUT;
773 attr.visual = gdk_visual_get_system();
774 attr.colormap = gdk_colormap_get_system();
775 attr.wmclass_name = "wmauda";
776 attr.wmclass_class = "wmauda";
777 attr.window_type = GDK_WINDOW_TOPLEVEL;
779 leader = gdk_window_new(NULL, &attr, GDK_WA_TITLE | GDK_WA_WMCLASS | GDK_WA_VISUAL | GDK_WA_COLORMAP);
781 gdk_window_set_icon(leader, icon_win->window, NULL, NULL);
782 gdk_window_reparent(icon_win->window, leader, 0, 0);
783 gdk_window_show(leader);
785 hints.initial_state = WithdrawnState;
786 hints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
787 hints.icon_window = GDK_WINDOW_XWINDOW(icon_win->window);
788 hints.icon_x = 0;
789 hints.icon_y = 0;
790 hints.window_group = GDK_WINDOW_XWINDOW(leader);
792 XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(leader), &hints);
794 gtk_widget_show(icon_win);
795 timeout_tag = gtk_timeout_add(100, timeout_func, NULL);
799 void display_usage(char *cmd)
801 printf( "Usage: %s [options]\n\n"
802 "Options:\n"
803 "--------\n\n"
804 "-h, --help Display this text and exit.\n"
805 "-g, --geometry Set the geometry (for example +20+20)\n"
806 "-c, --command Command to launch Audacious (Default: audacious)\n"
807 "-i, --icon Set the icon to use when Audacious is not running\n"
808 "-n, --single Only a single click is needed to start Audacious\n"
809 "-t, --title Display song title when mouse is in window\n"
810 "-v, --version Display version information and exit\n\n",
811 cmd);
814 int main(int argc, char **argv)
816 int c, dummy;
818 static struct option lopt[] =
820 {"help", no_argument, 0, 'h'},
821 {"geometry", required_argument, 0, 'g'},
822 {"session", required_argument, 0, 's'},
823 {"command", required_argument, 0, 'c'},
824 {"icon", required_argument, 0, 'i'},
825 {"single", no_argument, 0, 'n'},
826 {"title", no_argument, 0, 't'},
827 {"version", no_argument, 0, 'v'},
828 {0, 0, 0, 0}
831 gtk_set_locale();
833 gtk_init(&argc, &argv);
835 while ((c = getopt_long(argc, argv, "hg:s:c:i:ntv", lopt, NULL)) != -1)
837 switch (c)
839 case 'h':
840 display_usage(argv[0]);
841 gtk_exit(0);
842 break;
843 case 'g':
844 XParseGeometry(optarg, &win_x, &win_y,
845 &dummy, &dummy);
846 has_geometry = TRUE;
847 break;
848 case 'c':
849 xmms_cmd = g_strdup(optarg);
850 break;
851 case 'i':
852 icon_name = g_strdup(optarg);
853 break;
854 case 'n':
855 single_click = TRUE;
856 break;
857 case 't':
858 song_title = TRUE;
859 break;
860 case 'v':
861 printf("wmauda %s\n", VERSION);
862 gtk_exit(0);
863 break;
866 if (!dbus_init())
867 return 1;
869 init();
870 gtk_main();
871 return 0;