Add wmauda-0.8
[dockapps.git] / wmauda-0.8 / wmauda.c
blobf2b83b0ee96a18ca5289887dc9122203e5aeaaf6
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "config.h"
34 #include "dock-master.xpm"
36 #include <getopt.h>
38 typedef struct
40 int x, y, width, height, pressed_x, pressed_y, normal_x, normal_y;
41 gboolean focus, pressed;
42 void (*callback) (void);
44 Button;
46 void action_play(void);
47 void action_pause(void);
48 void action_eject(void);
49 void action_prev(void);
50 void action_next(void);
51 void action_stop(void);
53 Button buttons[] =
55 {21, 32, 9, 11, 84, 0, 64, 0, FALSE, FALSE, action_play}, /* PLAY */
56 {34, 32, 9, 11, 94, 0, 74, 0, FALSE, FALSE, action_pause}, /* PAUSE */
57 {47, 32, 9, 11, 84, 11, 64, 11, FALSE, FALSE, action_eject}, /* EJECT */
58 {21, 46, 9, 11, 84, 22, 64, 22, FALSE, FALSE, action_prev}, /* PREV */
59 {34, 46, 9, 11, 94, 22, 74, 22, FALSE, FALSE, action_next}, /* NEXT */
60 {47, 46, 9, 11, 94, 11, 74, 11, FALSE, FALSE, action_stop}, /* STOP */
63 #define NUM_BUTTONS 6
65 GList *button_list;
67 typedef struct
69 unsigned char ascii; gint x, y;
70 } Charentry;
72 Charentry chartable[] =
74 { '-', 60, 73}, /* put here coordinates of characters */
75 { '.', 72, 73}, /* in xmms-dock-master.xpm */
76 { ',', 78, 73},
77 { '\\', 84, 73},
78 { '/', 90, 73},
79 { '(', 96, 73},
80 { ')', 102, 73},
81 { '%', 108, 73},
82 { 'Ä', 114, 73},
83 { 'ä', 114, 73}, /* toupper doesn't convert umlauts */
84 { 'Ö', 120, 73},
85 { 'ö', 120, 73},
86 { 'Ü', 126, 73},
87 { 'ü', 126, 73},
88 { '?', 132, 73},
89 { '!', 138, 73},
90 { '&', 144, 73},
91 { ':', 150, 73},
92 { ' ', 66, 73},
94 #define NUM_CHARS 19
96 #define VOLSLIDER_X 8
97 #define VOLSLIDER_Y 17
98 #define VOLSLIDER_WIDTH 7
101 #define VOLSLIDER_HEIGHT 40
103 #define SEEKSLIDER_X 21
104 #define SEEKSLIDER_Y 20
105 #define SEEKSLIDER_WIDTH 30
106 #define SEEKSLIDER_HEIGHT 7
107 #define SEEKSLIDER_KNOB_WIDTH 3
108 #define SEEKSLIDER_MAX (SEEKSLIDER_WIDTH - SEEKSLIDER_KNOB_WIDTH)
110 #define SCROLLTEXT_X 5
111 #define SCROLLTEXT_Y 6
112 #define SCROLLTEXT_WIDTH 40
113 #define SCROLLTEXT_HEIGHT 9
114 #define SCROLLTEXT_CHARS 9
116 gboolean volslider_dragging = FALSE;
117 int volslider_pos = 0;
118 gboolean seekslider_visible = FALSE, seekslider_dragging = FALSE;
119 int seekslider_pos = -1, seekslider_drag_offset = 0;
120 gint scrollpos = 0;
121 int timeout_tag = 0;
123 void init(void);
125 GtkWidget *icon_win;
126 GdkPixmap *pixmap, *launch_pixmap;
127 GdkBitmap *mask, *launch_mask;
128 GdkGC *dock_gc;
129 GtkTooltips *tooltips = NULL;
131 char *xmms_cmd = "audacious";
132 gboolean xmms_running = FALSE;
134 gboolean has_geometry = FALSE, single_click = FALSE, song_title = FALSE;
135 char *icon_name = NULL;
136 int win_x, win_y;
138 DBusGProxy *dbus_proxy = NULL;
139 static DBusGConnection *connection = NULL;
141 GtkTargetEntry drop_types[] =
143 {"text/plain", 0, 1}
146 void action_play(void)
148 audacious_remote_play(dbus_proxy);
151 void action_pause(void)
153 audacious_remote_pause(dbus_proxy);
156 void action_eject(void)
158 audacious_remote_playlist_clear(dbus_proxy);
159 audacious_remote_stop(dbus_proxy);
162 void action_prev(void)
164 audacious_remote_playlist_prev(dbus_proxy);
167 void action_next(void)
169 audacious_remote_playlist_next(dbus_proxy);
172 void action_stop(void)
174 audacious_remote_stop(dbus_proxy);
177 gboolean inside_region(int mx, int my, int x, int y, int w, int h)
179 if ((mx >= x && mx < x + w) && (my >= y && my < y + h))
180 return TRUE;
181 return FALSE;
184 void real_draw_button(GdkWindow *w, Button *button)
187 if (button->pressed)
188 gdk_draw_pixmap(w, dock_gc, pixmap,
189 button->pressed_x, button->pressed_y,
190 button->x, button->y,
191 button->width, button->height);
192 else
193 gdk_draw_pixmap(w, dock_gc, pixmap,
194 button->normal_x, button->normal_y,
195 button->x, button->y,
196 button->width, button->height);
199 void draw_button(Button *button)
201 real_draw_button(icon_win->window, button);
204 void draw_buttons(GList *list)
206 for (; list; list = g_list_next(list))
207 draw_button(list->data);
210 void real_draw_volslider(GdkWindow *w)
212 gdk_draw_pixmap(w, dock_gc, pixmap, 112, 1, VOLSLIDER_X, VOLSLIDER_Y,
213 VOLSLIDER_WIDTH, VOLSLIDER_HEIGHT);
214 gdk_draw_pixmap(w, dock_gc, pixmap, 106,
215 1 + VOLSLIDER_HEIGHT - volslider_pos,
216 VOLSLIDER_X,
217 VOLSLIDER_Y + VOLSLIDER_HEIGHT - volslider_pos,
218 VOLSLIDER_WIDTH, volslider_pos);
221 void draw_volslider(void)
223 real_draw_volslider(icon_win->window);
226 void real_draw_seekslider(GdkWindow *w)
228 int slider_x;
230 if (seekslider_visible)
232 gdk_draw_pixmap(w, dock_gc, pixmap, 66, 54,
233 SEEKSLIDER_X, SEEKSLIDER_Y, 35, 10);
234 if (seekslider_pos < SEEKSLIDER_MAX / 3)
235 slider_x = 108;
236 else if (seekslider_pos < (SEEKSLIDER_MAX * 2) / 3)
237 slider_x = 111;
238 else
239 slider_x = 114;
240 gdk_draw_pixmap(w, dock_gc, pixmap, slider_x, 48,
241 SEEKSLIDER_X + seekslider_pos,
242 SEEKSLIDER_Y, 3, SEEKSLIDER_HEIGHT);
244 else
245 gdk_draw_pixmap(w, dock_gc, pixmap, 66, 39,
246 SEEKSLIDER_X, SEEKSLIDER_Y, 35, 10);
249 void draw_seekslider(void)
251 real_draw_seekslider(icon_win->window);
254 void real_draw_scrolltext(GdkWindow * w)
256 /* get titlestring */
257 gint pl_pos = audacious_remote_get_playlist_pos(dbus_proxy);
259 if (pl_pos != -1)
261 char *title = audacious_remote_get_playlist_title(dbus_proxy, pl_pos);
262 if (title)
264 /* render text */
265 gint i = 0, c = 0, pos = 0, dest = 0;
267 for (i=0; i<SCROLLTEXT_CHARS; i++)
269 gint x = 66, y = 73;
270 scrollpos %= (strlen(title)+16) * 6;
271 pos = i + (scrollpos / 6) -8;
272 if (pos < strlen(title) && pos >= 0)
273 c = toupper(title[pos]);
274 else
275 c = ' ';
277 dest = SCROLLTEXT_X + (i * 6 - (scrollpos % 6));
279 if (c >= 'A' && c <= 'Z')
281 x = (c-'A')*6;
282 y = 64;
284 else if (c >= '0' && c <= '9')
285 x = (c-'0')*6;
286 else
288 int i = 0;
289 for (i=0; i<NUM_CHARS; i++)
290 if (c == chartable[i].ascii)
292 x = chartable[i].x;
293 y = chartable[i].y;
294 break;
297 gdk_draw_pixmap(w, dock_gc, pixmap, x, y,
298 dest, SCROLLTEXT_Y, 7, 9);
301 scrollpos++;
302 g_free(title);
307 void draw_scrolltext(void)
309 real_draw_scrolltext(icon_win->window);
312 void redraw_window(void)
314 if (xmms_running)
316 gdk_draw_pixmap(icon_win->window, dock_gc, pixmap,
317 0, 0, 0, 0, 64, 64);
318 draw_buttons(button_list);
319 draw_volslider();
320 draw_seekslider();
321 draw_scrolltext();
323 else
325 gdk_draw_pixmap(icon_win->window, dock_gc, launch_pixmap,
326 0, 0, 0, 0, 64, 64);
330 void expose_cb(GtkWidget *w, GdkEventExpose *event, gpointer data)
332 redraw_window();
335 void wheel_scroll_cb(GtkWidget *w, GdkEventScroll *event)
337 if (xmms_running)
339 if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
341 if (event->direction == GDK_SCROLL_UP)
342 volslider_pos += 3;
343 else
344 volslider_pos -= 3;
345 if (volslider_pos < 0)
346 volslider_pos = 0;
347 if (volslider_pos > VOLSLIDER_HEIGHT)
348 volslider_pos = VOLSLIDER_HEIGHT;
349 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
350 draw_volslider();
354 void button_press_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
356 GList *node;
357 Button *btn;
358 int pos;
359 char *cmd;
361 if (xmms_running)
363 if ((event->button == 2) || (event->button == 3))
365 if(audacious_remote_is_main_win(dbus_proxy))
366 audacious_remote_main_win_toggle(dbus_proxy, FALSE);
367 else
368 audacious_remote_main_win_toggle(dbus_proxy, TRUE);
372 if (event->button != 1)
373 return;
374 if (xmms_running)
376 for (node = button_list; node; node = g_list_next(node))
378 btn = node->data;
379 if (inside_region(event->x, event->y, btn->x, btn->y, btn->width, btn->height))
381 btn->focus = TRUE;
382 btn->pressed = TRUE;
383 draw_button(btn);
386 if (inside_region(event->x, event->y, VOLSLIDER_X, VOLSLIDER_Y, VOLSLIDER_WIDTH, VOLSLIDER_HEIGHT))
388 volslider_pos = VOLSLIDER_HEIGHT - (event->y - VOLSLIDER_Y);
389 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
390 draw_volslider();
391 volslider_dragging = TRUE;
393 if (inside_region(event->x, event->y, SEEKSLIDER_X, SEEKSLIDER_Y, SEEKSLIDER_WIDTH, SEEKSLIDER_HEIGHT) && seekslider_visible)
395 pos = event->x - SEEKSLIDER_X;
397 if (pos >= seekslider_pos &&
398 pos < seekslider_pos + SEEKSLIDER_KNOB_WIDTH)
399 seekslider_drag_offset = pos - seekslider_pos;
400 else
402 seekslider_drag_offset = 1;
403 seekslider_pos = pos - seekslider_drag_offset;
404 if (seekslider_pos < 0)
405 seekslider_pos = 0;
406 if (seekslider_pos > SEEKSLIDER_MAX)
407 seekslider_pos = SEEKSLIDER_MAX;
409 draw_seekslider();
410 seekslider_dragging = TRUE;
413 else if ((!single_click && event->type == GDK_2BUTTON_PRESS) ||
414 (single_click && event->type == GDK_BUTTON_PRESS))
416 cmd = g_strconcat(xmms_cmd, " &", NULL);
417 system(cmd);
418 g_free(cmd);
422 void button_release_cb(GtkWidget *w, GdkEventButton *event, gpointer data)
424 GList *node;
425 Button *btn;
426 int len;
428 if (event->button != 1)
429 return;
431 for (node = button_list; node; node = g_list_next(node))
433 btn = node->data;
434 if (btn->pressed)
436 btn->focus = FALSE;
437 btn->pressed = FALSE;
438 draw_button(btn);
439 if (btn->callback)
440 btn->callback();
443 volslider_dragging = FALSE;
444 if (seekslider_dragging)
446 len = audacious_remote_get_playlist_time(dbus_proxy, audacious_remote_get_playlist_pos(dbus_proxy));
447 audacious_remote_jump_to_time(dbus_proxy, (seekslider_pos * len) / SEEKSLIDER_MAX);
448 seekslider_dragging = FALSE;
453 void motion_notify_cb(GtkWidget *w, GdkEventMotion *event, gpointer data)
455 GList *node;
456 Button *btn;
457 gboolean inside;
459 for (node = button_list; node; node = g_list_next(node))
461 btn = node->data;
462 if (btn->focus)
464 inside = inside_region(event->x, event->y,
465 btn->x, btn->y,
466 btn->width, btn->height);
467 if ((inside && !btn->pressed) ||
468 (!inside && btn->pressed))
470 btn->pressed = inside;
471 draw_button(btn);
475 if (volslider_dragging)
477 volslider_pos = VOLSLIDER_HEIGHT - (event->y - VOLSLIDER_Y);
478 if (volslider_pos < 0)
479 volslider_pos = 0;
480 if (volslider_pos > VOLSLIDER_HEIGHT)
481 volslider_pos = VOLSLIDER_HEIGHT;
482 audacious_remote_set_main_volume(dbus_proxy, (volslider_pos * 100) / VOLSLIDER_HEIGHT);
483 draw_volslider();
485 if (seekslider_dragging)
487 seekslider_pos =
488 event->x - SEEKSLIDER_X - seekslider_drag_offset;
489 if (seekslider_pos < 0)
490 seekslider_pos = 0;
491 if (seekslider_pos > SEEKSLIDER_MAX)
492 seekslider_pos = SEEKSLIDER_MAX;
493 draw_seekslider();
498 void destroy_cb(GtkWidget *w, gpointer data)
500 gtk_exit(0);
503 static void update_tooltip(void)
505 static int pl_pos = -1;
506 static char *filename;
507 int new_pos;
509 if (!tooltips)
510 return;
512 new_pos = audacious_remote_get_playlist_pos(dbus_proxy);
514 if (new_pos == 0)
517 * Need to do some extra checking, as we get 0 also on
518 * a empty playlist
520 char *current = audacious_remote_get_playlist_file(dbus_proxy, 0);
521 if (!filename && current)
523 filename = current;
524 new_pos = -1;
526 else if (filename && !current)
528 g_free(filename);
529 filename = NULL;
530 new_pos = -1;
532 else if (filename && current && strcmp(filename, current))
534 g_free(filename);
535 filename = current;
536 new_pos = -1;
540 if (pl_pos != new_pos)
542 char *tip = NULL;
543 char *title =
544 audacious_remote_get_playlist_title(dbus_proxy, new_pos);
545 if (title)
547 tip = g_strdup_printf("%d. %s", new_pos+1, title);
548 g_free(title);
550 gtk_tooltips_set_tip(tooltips, icon_win, tip, NULL);
551 g_free(tip);
552 pl_pos = new_pos;
556 int timeout_func(gpointer data)
558 int new_pos, pos;
559 gboolean playing, running;
561 running = audacious_remote_is_running(dbus_proxy);
563 if (running)
565 if (!xmms_running)
567 gtk_widget_shape_combine_mask(icon_win, mask, 0, 0);
568 xmms_running = running;
569 redraw_window();
571 if (!volslider_dragging)
573 new_pos = (audacious_remote_get_main_volume(dbus_proxy) * 40) / 100;
575 if (new_pos < 0)
576 new_pos = 0;
577 if (new_pos > VOLSLIDER_HEIGHT)
578 new_pos = VOLSLIDER_HEIGHT;
580 if (volslider_pos != new_pos)
582 volslider_pos = new_pos;
583 draw_volslider();
587 update_tooltip();
588 draw_scrolltext();
590 playing = audacious_remote_is_playing(dbus_proxy);
591 if (!playing && seekslider_visible)
593 seekslider_visible = FALSE;
594 seekslider_dragging = FALSE;
595 seekslider_pos = -1;
596 draw_seekslider();
598 else if (playing)
600 int len, p = audacious_remote_get_playlist_pos(dbus_proxy);
601 len = audacious_remote_get_playlist_time(dbus_proxy, p);
602 if (len == -1)
604 seekslider_visible = FALSE;
605 seekslider_dragging = FALSE;
606 seekslider_pos = -1;
607 draw_seekslider();
609 else if (!seekslider_dragging)
611 seekslider_visible = TRUE;
612 pos = audacious_remote_get_output_time(dbus_proxy);
613 if (len != 0)
614 new_pos = (pos * SEEKSLIDER_MAX) / len;
615 else
616 new_pos = 0;
617 if (new_pos < 0)
618 new_pos = 0;
619 if (new_pos > SEEKSLIDER_MAX)
620 new_pos = SEEKSLIDER_MAX;
621 if (seekslider_pos != new_pos)
623 seekslider_pos = new_pos;
624 draw_seekslider();
629 else
631 if (xmms_running)
633 if (tooltips != NULL)
634 gtk_tooltips_set_tip(tooltips, icon_win, NULL, NULL);
635 gtk_widget_shape_combine_mask(icon_win, launch_mask, 0, 0);
636 xmms_running = FALSE;
637 redraw_window();
641 return TRUE;
644 void drag_data_received(GtkWidget *widget, GdkDragContext *context,
645 int x, int y, GtkSelectionData *selection_data,
646 guint info, guint time)
648 if (selection_data->data)
650 char *url = selection_data->data;
651 audacious_remote_playlist_clear(dbus_proxy);
652 audacious_remote_playlist_add_url_string(dbus_proxy, url);
653 audacious_remote_play(dbus_proxy);
657 static gboolean dbus_init(void)
659 GError *error = NULL;
661 connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
662 if (connection == NULL)
663 return FALSE;
665 dbus_proxy = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
666 AUDACIOUS_DBUS_PATH,
667 AUDACIOUS_DBUS_INTERFACE);
668 if (dbus_proxy == NULL)
669 return FALSE;
671 return TRUE;
674 void init(void)
676 GdkWindowAttr attr;
677 GdkColor bg_color;
678 GdkWindow *leader;
679 XWMHints hints;
680 int i, w, h;
681 GdkGC *mask_gc;
683 for (i = 0; i < NUM_BUTTONS; i++)
684 button_list = g_list_append(button_list, &buttons[i]);
686 if (song_title)
688 tooltips = gtk_tooltips_new();
689 gtk_tooltips_set_delay(tooltips, 1000);
692 icon_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
693 gtk_widget_set_app_paintable(icon_win, TRUE);
694 gtk_widget_set_uposition(icon_win, 0, 0);
695 gtk_widget_set_usize(icon_win, 64, 64);
696 gtk_widget_set_events(icon_win,
697 GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
698 GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK);
699 gtk_signal_connect(GTK_OBJECT(icon_win), "expose_event",
700 GTK_SIGNAL_FUNC(expose_cb), NULL);
701 gtk_signal_connect(GTK_OBJECT(icon_win), "button_press_event",
702 GTK_SIGNAL_FUNC(button_press_cb), NULL);
703 gtk_signal_connect(GTK_OBJECT(icon_win), "scroll_event",
704 GTK_SIGNAL_FUNC(wheel_scroll_cb), NULL);
705 gtk_signal_connect(GTK_OBJECT(icon_win), "button_release_event",
706 GTK_SIGNAL_FUNC(button_release_cb), NULL);
707 gtk_signal_connect(GTK_OBJECT(icon_win), "motion_notify_event",
708 GTK_SIGNAL_FUNC(motion_notify_cb), NULL);
709 gtk_signal_connect(GTK_OBJECT(icon_win), "destroy",
710 GTK_SIGNAL_FUNC(destroy_cb), NULL);
711 gtk_drag_dest_set(icon_win, GTK_DEST_DEFAULT_ALL, drop_types, 1,
712 GDK_ACTION_COPY);
713 gtk_signal_connect(GTK_OBJECT(icon_win), "drag_data_received",
714 GTK_SIGNAL_FUNC(drag_data_received), NULL);
715 gtk_widget_realize(icon_win);
716 bg_color.red = 0;
717 bg_color.green = 0;
718 bg_color.blue = 0;
719 gdk_colormap_alloc_color(gdk_colormap_get_system(),
720 &bg_color, FALSE, TRUE);
721 gdk_window_set_background(icon_win->window, &bg_color);
722 gdk_window_clear(icon_win->window);
723 dock_gc = gdk_gc_new(icon_win->window);
725 launch_pixmap = gdk_pixmap_new(icon_win->window, 64, 64, -1);
727 launch_mask = gdk_pixmap_new(icon_win->window, 64, 64, 1);
728 mask_gc = gdk_gc_new(launch_mask);
729 bg_color.pixel = 0;
730 gdk_gc_set_foreground(mask_gc, &bg_color);
731 gdk_draw_rectangle(launch_mask, mask_gc, TRUE, 0, 0, -1, -1);
733 if (!icon_name)
734 icon_name = g_strdup_printf("%s/wmauda.xpm", DATA_DIR);
735 pixmap = gdk_pixmap_create_from_xpm(icon_win->window, &mask,
736 NULL, icon_name);
737 if (!pixmap)
739 printf("ERROR: Couldn't find %s\n", icon_name);
740 g_free(icon_name);
741 gtk_exit(1);
743 g_free(icon_name);
744 gdk_window_get_size(pixmap, &w, &h);
745 if (w > 64)
746 w = 64;
747 if (h > 64)
748 h = 64;
749 gdk_draw_pixmap(launch_pixmap, dock_gc, pixmap,
750 0, 0, 32 - (w / 2), 32 - (h / 2), w, h);
751 gdk_draw_pixmap(launch_mask, mask_gc, mask,
752 0, 0, 32 - (w / 2), 32 - (h / 2), w, h);
753 gdk_gc_unref(mask_gc);
754 gdk_pixmap_unref(pixmap);
755 gdk_bitmap_unref(mask);
757 gtk_widget_shape_combine_mask(icon_win, launch_mask, 0, 0);
759 pixmap = gdk_pixmap_create_from_xpm_d(icon_win->window,
760 &mask, NULL, dock_master_xpm);
762 attr.width = 64;
763 attr.height = 64;
764 attr.title = "wmauda";
765 attr.event_mask = GDK_BUTTON_PRESS_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_HINT_MASK;
766 attr.wclass = GDK_INPUT_OUTPUT;
767 attr.visual = gdk_visual_get_system();
768 attr.colormap = gdk_colormap_get_system();
769 attr.wmclass_name = "wmauda";
770 attr.wmclass_class = "wmauda";
771 attr.window_type = GDK_WINDOW_TOPLEVEL;
773 leader = gdk_window_new(NULL, &attr, GDK_WA_TITLE | GDK_WA_WMCLASS | GDK_WA_VISUAL | GDK_WA_COLORMAP);
775 gdk_window_set_icon(leader, icon_win->window, NULL, NULL);
776 gdk_window_reparent(icon_win->window, leader, 0, 0);
777 gdk_window_show(leader);
779 hints.initial_state = WithdrawnState;
780 hints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
781 hints.icon_window = GDK_WINDOW_XWINDOW(icon_win->window);
782 hints.icon_x = 0;
783 hints.icon_y = 0;
784 hints.window_group = GDK_WINDOW_XWINDOW(leader);
786 XSetWMHints(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(leader), &hints);
788 gtk_widget_show(icon_win);
789 timeout_tag = gtk_timeout_add(100, timeout_func, NULL);
793 void display_usage(char *cmd)
795 printf( "Usage: %s [options]\n\n"
796 "Options:\n"
797 "--------\n\n"
798 "-h, --help Display this text and exit.\n"
799 "-g, --geometry Set the geometry (for example +20+20)\n"
800 "-c, --command Command to launch Audacious (Default: audacious)\n"
801 "-i, --icon Set the icon to use when Audacious is not running\n"
802 "-n, --single Only a single click is needed to start Audacious\n"
803 "-t, --title Display song title when mouse is in window\n"
804 "-v, --version Display version information and exit\n\n",
805 cmd);
808 int main(int argc, char **argv)
810 int c, dummy;
812 static struct option lopt[] =
814 {"help", no_argument, 0, 'h'},
815 {"geometry", required_argument, 0, 'g'},
816 {"session", required_argument, 0, 's'},
817 {"command", required_argument, 0, 'c'},
818 {"icon", required_argument, 0, 'i'},
819 {"single", no_argument, 0, 'n'},
820 {"title", no_argument, 0, 't'},
821 {"version", no_argument, 0, 'v'},
822 {0, 0, 0, 0}
825 gtk_set_locale();
827 gtk_init(&argc, &argv);
829 while ((c = getopt_long(argc, argv, "hg:s:c:i:ntv", lopt, NULL)) != -1)
831 switch (c)
833 case 'h':
834 display_usage(argv[0]);
835 gtk_exit(0);
836 break;
837 case 'g':
838 XParseGeometry(optarg, &win_x, &win_y,
839 &dummy, &dummy);
840 has_geometry = TRUE;
841 break;
842 case 'c':
843 xmms_cmd = g_strdup(optarg);
844 break;
845 case 'i':
846 icon_name = g_strdup(optarg);
847 break;
848 case 'n':
849 single_click = TRUE;
850 break;
851 case 't':
852 song_title = TRUE;
853 break;
854 case 'v':
855 printf("wmauda %s\n", VERSION);
856 gtk_exit(0);
857 break;
860 if (!dbus_init())
861 return 1;
863 init();
864 gtk_main();
865 return 0;