/*  wmusic - a xmms remote-controlling DockApp
 *  Copyright (C) 2000-2001 Bastien Nocera <hadess@hadess.net>
 *  Maintained by John Chapin <john+wmusic@jtan.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#define DBL_CLICK_INTERVAL 250	/* double click interval in milliseconds */
#define ARROW_INTERVAL 100	/* arrow update interval in milliseconds */
#define SCROLL_INTERVAL 300	/* scroll update interval in milliseconds */
#define SEPARATOR " ** "	/* The separator for the scrolling title */
#define DISPLAYSIZE 6		/* width of text to display (running title) */

#include <dockapp.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <xmms/xmmsctrl.h>

#include "version.h"
#include "config.h"
#include "wmusic-master.xpm"
#include "wmusic-digits.xpm"

/*---------------------------------------------------------------------------*/
/*                             Prototypes                                    */
/*---------------------------------------------------------------------------*/

void copyNumArea(int x, int y, int sx, int sy, int dx, int dy);
void ActionPlay(int x, int y, DARect rect, void *data);
void ActionPause(int x, int y, DARect rect, void *data);
void ActionEject(int x, int y, DARect rect, void *data);
void ActionPrev(int x, int y, DARect rect, void *data);
void ActionNext(int x, int y, DARect rect, void *data);
void ActionStop(int x, int y, DARect rect, void *data);
void ActionFastr(int x, int y, DARect rect, void *data);
void ActionFastf(int x, int y, DARect rect, void *data);
void ToggleWins(int x, int y, DARect rect, void *data);
void ToggleVol(int x, int y, DARect rect, void *data);
void ChangeVol(int x, int y, DARect rect, void *data);
void ToggleTitle(int x, int y, DARect rect, void *data);
void ToggleTime(int x, int y, DARect rect, void *data);
void buttonPress(int button, int state, int x, int y);
void buttonRelease(int button, int state, int x, int y);
void DisplayRoutine();
void DrawPos (int pos);
void DrawTime(int time);
void DrawArrow(void);
void DrawChannels(int channels);
void DrawKbps(int bps);
void DrawTitle(char *title);
void ExecuteXmms(void);

/*----------------------------------------------------------------------------*/
/*                             Variables                                      */
/*----------------------------------------------------------------------------*/

/* X11 variables */
char *displayName = "";
GC gc;
XEvent ev;

/* Dockapp variables */
unsigned int xmms_session = 0;
char *xmms_cmd = "xmms";
Bool main_vis=0, pl_vis=0, eq_vis=0;
Bool xmms_running;
unsigned int volume_step = 5;
Bool run_excusive=0;

Bool t_scroll=0;
Bool t_time=0;
Bool t_volume=0;
float title_pos = 0;
unsigned int arrow_pos = 0;
Bool pause_norotate = 0;
Time click_time=0;

Pixmap pixmap, mask;	/* Pixmap that is displayed */
Pixmap pixnum, masknum;	/* Pixmap source */

int left_pressed = 0; /* for pseudo drag callback */
int motion_event = 0; /* on motion events we do not want(too fast) display update */

static DAActionRect buttonRects[] = {
	{{5, 39, 14, 9}, ActionPrev},
	{{19, 39, 14, 9}, ActionNext},
	{{33, 39, 13, 9}, ActionFastr},
	{{46, 39, 13, 9}, ActionFastf},
	{{5, 48, 11, 11}, ActionEject},
	{{16, 48, 21, 11}, ActionPlay},
	{{37, 48, 11, 11}, ActionPause},
	{{48, 48, 11, 11}, ActionStop}
};

static DAActionRect toggleRect[] = {
	{{5, 5, 54, 30}, ToggleWins}
};

static DAActionRect globRect[] = {
	{{0, 0, 64, 64}, ToggleVol}
};

static DAActionRect displayRects[] = {
	{{5, 5, 54, 12}, ToggleTime},
	{{5, 25, 54, 9}, ToggleTitle}
};

static DAActionRect volumeRects[] = {
	{{5, 17, 38, 8 }, ChangeVol}
};

static DAProgramOption options[] = {
	{"-c", "--command", "Command to launch xmms", DOString, False,
		{&xmms_cmd} },
	{"-d", "--display", "Display to use", DOString, False, {&displayName} },
	{"-r", "--run", "Run xmms on startup", DONone, False, {NULL} },
	{"-s", "--session", "Xmms session to use", DONatural, False,
		{&xmms_session} },
	{"-t", "--title", "Show title instead of kbps by default", DONone,
		False, {NULL} },
	{"-u", "--hide", "Hide xmms windows on startup", DONone, False,
		{NULL} },
	{"-V", "--volume", "Stepping of the wheel volume control (in percent)",
		DONatural, False, {&volume_step} },
	{"-x", "--wmxmms", "Use wmxmms-like show and hide", DONone, False,
		{NULL} },
	{"-a", "--rotate-arrow", "Do not rotate the arrow, when paused", 
		DONone, False, {NULL} },
	{"-l", "--time-left", "Show time left instead of time remaining by default",
	 DONone, False, {NULL} },
	{"-b", "--volume-slider", "Show volume slider instead of channels", 
	 DONone, False, {NULL}},
	{"-R", "--run-excusive", "Run xmms on startup, exit when xmms exits", DONone, False, {NULL} }
};

typedef struct
{
	wchar_t c;
	int x;
	int y;
} glyphdescr;

static glyphdescr glyphs[] = {
	{L'-', 67, 83}, {L'.', 73, 83}, {L'\x27', 79, 83},
	{L'(', 85, 83}, {L')', 91, 83}, {L'*', 97, 83}, {L'/', 103, 83},

	{L'0',  1, 83}, {L'1',  7, 83}, {L'2', 13, 83}, {L'3', 19, 83}, {L'4', 25, 83},
	{L'5', 31, 83}, {L'6', 37, 83}, {L'7', 43, 83}, {L'8', 49, 83}, {L'9', 55, 83},



	{L'A',  1, 73}, {L'a',  1, 73},
	{L'B',  7, 73}, {L'b',  7, 73},
	{L'C', 13, 73}, {L'c', 13, 73},
	{L'D', 19, 73}, {L'd', 19, 73},
	{L'E', 25, 73}, {L'e', 25, 73},

	{L'F', 31, 73}, {L'f', 31, 73},
	{L'G', 37, 73}, {L'g', 37, 73},
	{L'H', 43, 73}, {L'h', 43, 73},
	{L'I', 49, 73}, {L'i', 49, 73},
	{L'J', 55, 73}, {L'j', 55, 73},

	{L'K', 61, 73}, {L'k', 61, 73},
	{L'L', 67, 73}, {L'l', 67, 73},
	{L'M', 73, 73}, {L'm', 73, 73},
	{L'N', 79, 73}, {L'n', 79, 73},
	{L'O', 85, 73}, {L'o', 85, 73},

	{L'P', 91, 73}, {L'p', 91, 73},
	{L'Q', 97, 73}, {L'q', 97, 73},
	{L'R',103, 73}, {L'r',103, 73},
	{L'S',109, 73}, {L's',109, 73},
	{L'T',115, 73}, {L't',115, 73},

	{L'U',121, 73}, {L'u',121, 73},
	{L'V',127, 73}, {L'v',127, 73},
	{L'W',133, 73}, {L'w',133, 73},
	{L'X',139, 73}, {L'x',139, 73},
	{L'Y',145, 73}, {L'y',145, 73},

	{L'Z',151, 73}, {L'z',151, 73},


	{L'\x42e',  1, 93}, {L'\x44e',  1, 93}, /* cyrillic Yu */

	{L'\x410',  7, 93}, {L'\x430',  7, 93}, /* cyrillic A */
	{L'\x411', 13, 93}, {L'\x431', 13, 93}, /* cyrillic Be */
	{L'\x426', 19, 93}, {L'\x446', 19, 93}, /* cyrillic Ce */
	{L'\x414', 25, 93}, {L'\x434', 25, 93}, /* cyrillic De */
	{L'\x415', 31, 93}, {L'\x435', 31, 93}, /* cyrillic Ye */

	{L'\x424', 37, 93}, {L'\x444', 37, 93}, /* cyrillic eF */
	{L'\x413', 43, 93}, {L'\x433', 43, 93}, /* cyrillic Ge */
	{L'\x425', 49, 93}, {L'\x445', 49, 93}, /* cyrillic Ha */
	{L'\x418', 55, 93}, {L'\x438', 55, 93}, /* cyrillic I */
	{L'\x419', 61, 93}, {L'\x439', 61, 93}, /* cyrillic I-kratkoe */

	{L'\x41a', 67, 93}, {L'\x43a', 67, 93}, /* cyrillic Ka */
	{L'\x41b', 73, 93}, {L'\x43b', 73, 93}, /* cyrillic eL */
	{L'\x41c', 79, 93}, {L'\x43c', 79, 93}, /* cyrillic eM */
	{L'\x41d', 85, 93}, {L'\x43d', 85, 93}, /* cyrillic eN */
	{L'\x41e', 91, 93}, {L'\x43e', 91, 93}, /* cyrillic O */

	{L'\x41f', 97, 93}, {L'\x43f', 97, 93}, /* cyrillic Pe */
	{L'\x42f',103, 93}, {L'\x44f',103, 93}, /* cyrillic Ya */
	{L'\x420',109, 93}, {L'\x440',109, 93}, /* cyrillic eR */
	{L'\x421',115, 93}, {L'\x441',115, 93}, /* cyrillic eS */
	{L'\x422',121, 93}, {L'\x442',121, 93}, /* cyrillic Te */

	{L'\x423',127, 93}, {L'\x443',127, 93}, /* cyrillic U */
	{L'\x416',133, 93}, {L'\x436',133, 93}, /* cyrillic Je */
	{L'\x412',139, 93}, {L'\x432',139, 93}, /* cyrillic Ve */
	{L'\x42c',145, 93}, {L'\x44c',145, 93}, /* cyrillic MyagkijZnak */
	{L'\x42b',151, 93}, {L'\x44b',151, 93}, /* cyrillic Y */

	{L'\x417',157, 93}, {L'\x437',157, 93}, /* cyrillic Ze */
	{L'\x428',163, 93}, {L'\x448',163, 93}, /* cyrillic Sha */
	{L'\x42d',169, 93}, {L'\x44d',169, 93}, /* cyrillic E */
	{L'\x429',175, 93}, {L'\x449',175, 93}, /* cyrillic Scha */
	{L'\x427',181, 93}, {L'\x447',181, 93}, /* cyrillic Che */

	{L'\x42a',187, 93}, {L'\x44a',187, 93}, /* cyrillic TvyordyiZnak */
	{L'\x404',115, 83}, {L'\x454',115, 83}, /* ukrainian IE */
	{L'\x406', 49, 73}, {L'\x456', 49, 73}, /* ukrainian I */
	{L'\x407',109, 83}, {L'\x457',109, 83}, /* ukrainian YI */
	{L'\x491', 43, 93}, {L'\x490', 43, 93}, /* ukrainian GHE with upturn */

	{L'\x401',121, 83}, {L'\x451',121, 83}, /* cyrillic Yo */

	{L' ', 61, 83}
};

/*----------------------------------------------------------------------------*/
/*                              Functions                                     */
/*----------------------------------------------------------------------------*/

void copyNumArea(int x, int y, int sx, int sy, int dx, int dy)
{
	XCopyArea(DADisplay, pixnum, pixmap, gc, x, y, sx, sy, dx, dy);
}

void buttonDraw(DARect rect)
{
	copyNumArea((rect.x)-5, (rect.y)-8, rect.width, rect.height,
			rect.x, rect.y);
	DASetPixmap(pixmap);
}

void ActionPlay(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_play(xmms_session);
	}
}

void ActionPause(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_pause(xmms_session);
	}
}

void ActionEject(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_eject(xmms_session);
	}
}

void ActionPrev(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_playlist_prev(xmms_session);
	}
}

void ActionNext(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_playlist_next(xmms_session);
	}
}

void ActionStop(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_stop(xmms_session);
	}
}

void ActionFastr(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_jump_to_time(xmms_session,
			xmms_remote_get_output_time(xmms_session)-10000);
	}
}

void ActionFastf(int x, int y, DARect rect, void *data)
{
	if (data) {
		buttonDraw(rect);
	} else {
		xmms_remote_jump_to_time(xmms_session,
			xmms_remote_get_output_time(xmms_session)+10000);
	}
}

void ToggleWins(int x, int y, DARect rect, void *data)
{
	if (xmms_running)
	{
		if (options[7].used)
		{
			if (data)
			xmms_remote_main_win_toggle(xmms_session,
					!xmms_remote_is_main_win(xmms_session));
			if (!data)
			xmms_remote_pl_win_toggle(xmms_session,
					!xmms_remote_is_pl_win(xmms_session));
		} else {
			if (xmms_remote_is_main_win(xmms_session) || 
			    xmms_remote_is_pl_win(xmms_session) ||
			    xmms_remote_is_eq_win(xmms_session))
			{
				main_vis = xmms_remote_is_main_win(xmms_session);
				pl_vis = xmms_remote_is_pl_win(xmms_session);
				eq_vis = xmms_remote_is_eq_win(xmms_session);

				xmms_remote_main_win_toggle(xmms_session, 0);
				xmms_remote_pl_win_toggle(xmms_session, 0);
				xmms_remote_eq_win_toggle(xmms_session, 0);
			} else {
				xmms_remote_main_win_toggle(xmms_session, main_vis);
				xmms_remote_pl_win_toggle(xmms_session, pl_vis);
				xmms_remote_eq_win_toggle(xmms_session, eq_vis);
			}
		}
	} else {
		if ( (ev.xbutton.time-click_time) <= DBL_CLICK_INTERVAL )
		{
			click_time=0;
			ExecuteXmms();
		} else {
			click_time=ev.xbutton.time;
		}
	}
}

void ToggleVol(int x, int y, DARect rect, void *data)
{
	int volume;
	int factor;

	if (*(int*)data == 1)
		factor = volume_step;
	else
		factor = -volume_step;

	/* xmms seems to do the bounds checking for us */

	volume = xmms_remote_get_main_volume(xmms_session);
	xmms_remote_set_main_volume(xmms_session, volume+factor);
}

void ChangeVol(int x, int y, DARect rect, void *data)
{
	int volume = (int)100*(((float)x)/38);
	xmms_remote_set_main_volume(xmms_session, volume);
}

void ToggleTitle(int x, int y, DARect rect, void *data)
{
	if (t_scroll)
		t_scroll = 0;
	else t_scroll =1;
}

void ToggleTime(int x, int y, DARect rect, void *data)
{
	if (t_time)
		t_time = 0;
	else t_time =1;
}

void buttonPress(int button, int state, int x, int y)
{
	if (button==1)
		left_pressed=1;
	if (xmms_running)
	{
		if (button == 1)
		{
			char *tmp="1";
			DAProcessActionRects(x, y, buttonRects, sizeof(buttonRects)/sizeof(DAActionRect), tmp);
			DAProcessActionRects(x, y, displayRects, sizeof(displayRects)/sizeof(DAActionRect), tmp);
		}
		if (button == 2)
		{
			DAProcessActionRects(x, y, toggleRect, sizeof(toggleRect)/sizeof(DAActionRect), NULL);
		}
		if (button == 3)
		{
			char *tmp="1";
			DAProcessActionRects(x, y, toggleRect, sizeof(toggleRect)/sizeof(DAActionRect), tmp);
		}
		if ((button == 4) || (button == 5))
		{
			if (button == 5)
			{
				/* Wheel scrolls down */
				int tmp=2;
				DAProcessActionRects(x, y, globRect, sizeof(globRect)/sizeof(DAActionRect), &tmp);
			} else {
				/* Wheel scrolls up */
				int tmp=1;
				DAProcessActionRects(x, y, globRect, sizeof(globRect)/sizeof(DAActionRect), &tmp);
			}
		}
	}
	else
		DAProcessActionRects(x, y, toggleRect, sizeof(toggleRect)/sizeof(DAActionRect), NULL);
}

void buttonRelease(int button, int state, int x, int y)
{
	if (button==1)
		left_pressed=0;
	if (xmms_running)
	{
		if (button == 1)
		{
			copyNumArea(0,51, 54, 20, 5,39);
			DASetPixmap(pixmap);
			DAProcessActionRects(x, y, buttonRects, sizeof(buttonRects)/sizeof(DAActionRect), NULL);
		}
	}
}

void buttonDrag(int x, int y) 
{
	motion_event=1;
	if (t_volume)
		if (left_pressed==1) {
			DAProcessActionRects(x,y, volumeRects, 1, NULL);
			DrawChannels(0); /* volume only update */
			DASetPixmap(pixmap);
		}
}

void DisplayRoutine()
{
	int time = 0, length = 0, position = 100;
	int rate, freq, nch;
	char *title = NULL;
	Bool do_scroll=t_scroll;

	xmms_running=xmms_remote_is_running(xmms_session);

	/* Compute diplay */
	if (!xmms_running)
	{
		if (run_excusive)
			exit(0);
		position = 100; /* Will display "00" as the current position */
		do_scroll = 0;   /* Will display channel/kbps info */
		arrow_pos = 5;
		rate = 0;
		time = 0;
		nch = 4;
		freq = 0;
		length = 0;
	} else {
	        /* check again, avoiding xmms_remote_* functions to hang,
		   if xmms was closed in the meantime */
	        if ((xmms_running = xmms_remote_is_running(xmms_session)))  
		{
		        position = xmms_remote_get_playlist_pos(xmms_session);
			xmms_remote_get_info(xmms_session, &rate, &freq, &nch);
			time = xmms_remote_get_output_time(xmms_session);
			length = xmms_remote_get_playlist_time(xmms_session, position);
			title = xmms_remote_get_playlist_title(xmms_session, position);
			if (!xmms_remote_is_playing(xmms_session) || (pause_norotate && 
								      xmms_remote_is_paused(xmms_session) ))
			    arrow_pos = 5;
		}
	}

	/*Draw everything */
	if (t_time) DrawTime(length-time);
	else DrawTime(time);
	DrawPos(position);
	DrawArrow();
	DrawChannels(nch);
	if (do_scroll && (title != NULL))
		DrawTitle(title);
	else
		DrawKbps(rate);

	DASetPixmap(pixmap);

	if (title != NULL)
		free(title);
}

void DrawPos (int pos)
{
	char posstr[16];
	char *p = posstr;
	int i=1;

	pos++;
	if (pos > 99) pos=0;
	sprintf(posstr, "%02d", pos);
	
	for (;i<3; i++)
	{
		copyNumArea((*p-'0')*6 + 1, 1, 6, 7, (i*6)+39, 7);
		p++;
	}
}

void DrawTime(int time)
{
	char timestr[16];
	char *p = timestr;
	int i=0;

	time = time / 1000;

	/* 3 cases:
	 *     up to 99 minutes and 59 seconds
	 *     up to 99 hours and 59 minutes
	 *     more
	 */
	if (time < 6000)
	{
		sprintf(timestr, "%02d%02d", time / 60, time % 60);
	} else {
		if (time < 360000)
		{
			sprintf(timestr, "%02d%02d", time / 3600,
					time % 3600 / 60);
		} else {
			sprintf(timestr, "%02d%02d", 0, 0);
		}
	}

	for (;i<4; i++)
	{
		copyNumArea((*p-'0')*7 + 2, 11, 7, 9, i<2 ?(i*7)+7:(i*7)+12, 7);
		p++;
	}
}

void DrawArrow(void)
{
	copyNumArea((arrow_pos*8)+30, 22, 8, 9, 47, 19);
	arrow_pos++;
	if (arrow_pos > 4) arrow_pos = 0;
}

void DrawChannels(int channels)
{

	if (t_volume) {
   		int volume = (int)(0.36*(float)xmms_remote_get_main_volume(xmms_session));
		if (volume > 36)
			volume = 36;
		copyNumArea(61, 0, volume, 6, 7, 18);
		copyNumArea(97, 0, 36-volume, 6, 7+volume, 18);
	} else {
		if (channels == 4)
			{
				copyNumArea(55, 32, 10, 6, 10, 18);
			} else {
				copyNumArea((channels*10), 22, 10, 6, 10, 18);
			}
	}
}

void DrawKbps(int bps)
{
	char kbpstr[16];
	char *p = kbpstr;
	int i=1;

	if (bps > 999000) bps=0;
	sprintf(kbpstr, "%03d", bps / 1000);

	for (;i<4; i++)
	{
		copyNumArea((*p-'0')*6 + 1, 1, 6, 7, (i*6)+1, 26);
		p++;
	}
	copyNumArea(55, 39, 18, 8, 25, 26);
}

void DrawChar(wchar_t wc, int x, int y)
{
	int i;
	for(i = 0; i < sizeof(glyphs)/sizeof(glyphdescr) - 1; ++i)
	{
		if(wc == glyphs[i].c)
			break;
	}
	copyNumArea(glyphs[i].x, glyphs[i].y, 6, 8, x, y);
}

int DrawChars(char *title, int tpos, int pos)
{
	wchar_t wc;

	mbtowc(NULL, NULL, 0);
	while(*title && (pos <= (tpos + DISPLAYSIZE)))
	{
		int len = mbtowc(&wc, title, MB_CUR_MAX);
		title += len;
		if(pos > tpos)
			DrawChar(wc, (pos - tpos)*6 + 1, 26);
		++pos;
	}
	return pos;
}

void DrawTitle(char *name)
{
	int len, pos, tpos = title_pos;

	if (name == NULL)
		return;
#ifdef DEBUG
	printf("name: %s\n", name);
#endif
	len = pos = DrawChars(name, tpos, 0);
	if(pos < 6)
	{
		DrawChars("      ", tpos, pos);
		return;
	}

	if(pos <= tpos + DISPLAYSIZE)
		pos = DrawChars(SEPARATOR, tpos, pos);

	if(pos <= tpos + DISPLAYSIZE)
		DrawChars(name, tpos, pos);

	if(tpos >= len + strlen(SEPARATOR))
		title_pos = 0;

	title_pos = title_pos + 0.5;
}

void ExecuteXmms(void)
{
	char *command;
	int status;

	command=malloc(strlen(xmms_cmd)+5);
	sprintf(command, "%s &", xmms_cmd);
	status = system(command);
	if (status)
	{
		fprintf(stderr, "XMMS can't be launched, exiting...");
		exit(1);
	}
	while (!xmms_remote_is_running(xmms_session))
		usleep(10000L);
	free(command);
}
/*----------------------------------------------------------------------------*/
/*                                   Main                                     */
/*----------------------------------------------------------------------------*/

int main(int argc, char **argv)
{
	unsigned height, width;
	DACallbacks callbacks={NULL, buttonPress, buttonRelease, buttonDrag,
		NULL, NULL, NULL};

	/* Initialization */
	DAParseArguments(argc, argv, options,
		sizeof(options)/sizeof(DAProgramOption),
		"XMMS remote control by Bastien Nocera <hadess@hadess.net>",
		VERSION);

	setlocale(LC_ALL, "");
	DAInitialize(displayName, "wmusic", 64, 64, argc, argv);
	DASetCallbacks(&callbacks);
	DASetTimeout(100);

	DAMakePixmapFromData(wmusic_master_xpm, &pixmap,
			&mask, &height, &width);
	DAMakePixmapFromData(wmusic_digits_xpm, &pixnum,
			&masknum, &height, &width);
	gc = DefaultGC(DADisplay, DefaultScreen(DADisplay));
	DASetShapeWithOffset(mask, 0, 0);

	DASetPixmap(pixmap);
	DAShow();

	/* End of initialization */

	if (options[4].used) t_scroll=1;
	if (options[8].used) pause_norotate=1;
	if (options[9].used) t_time=1;
	if (options[10].used) t_volume=1;
	if (options[11].used) run_excusive=1;

	/* Launch xmms if it's not running and -r or -R was used */
	xmms_running=xmms_remote_is_running(xmms_session);
	if ((!xmms_running) && (options[2].used || run_excusive))
	{
		ExecuteXmms();
		xmms_running=1;
	}

	if(xmms_remote_is_main_win(xmms_session) && (options[6].used))
		ToggleWins(0, 0, DANoRect, NULL);

	/* Update the display */
	DisplayRoutine();

	while (1) {
		if (DANextEventOrTimeout(&ev, 100))
				DAProcessEvent(&ev);
		if (!motion_event)
			DisplayRoutine();
		else
			motion_event=0;
	}
	return 0;
}

