/* ===========================================================================
 * AScd: the AfterStep and WindowMaker CD player
 * ascd.c: main source
 * ===========================================================================
 * Copyright (c) 1999 Denis Bourez and Rob Malda. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by Denis Bourez & Rob Malda
 * 4. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY DENIS BOUREZ AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL DENIS BOUREZ, ROB MALDA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 * POSSIBILITY OF SUCH DAMAGE.
 * ===========================================================================
 */

#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdio.h>


#include <X11/Xlib.h>

#include <X11/xpm.h>
#include <X11/extensions/shape.h>

#include <errno.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <sys/time.h>

#include "config.h"

#include "ascd.h"
#include <workman/workman.h>

/* XPM stuff */

typedef struct _XpmIcon {
    Pixmap pixmap;
    Pixmap mask;
    XpmAttributes attributes;
} XpmIcon;

XpmIcon alphaXPM;
XpmIcon ralphaXPM;
XpmIcon backXPM;
XpmIcon barXPM;

/* Panel 1 */
XpmIcon ejectXPM;
XpmIcon fwdXPM;
XpmIcon pauseXPM;
XpmIcon playXPM;
XpmIcon pause_onXPM;
XpmIcon play_onXPM;
XpmIcon rewXPM;
XpmIcon stopXPM;

/* Panel 2 */
XpmIcon lstartXPM;
XpmIcon lendXPM;
XpmIcon lgoXPM;
XpmIcon lgo_onXPM;
XpmIcon fadeXPM;
XpmIcon introXPM;
XpmIcon intro_onXPM;
XpmIcon quitXPM;

/* Functions */

void Help(void);
void CreateWindow(int, char **);
void ParseCmdLine(int argc, char *argv[]);
void load_rc_file(int);
void save_rc_file();
void MainLoop();
void GetXPM(char *, char *);
void MaskSet();
int  FlushExpose(Window w);
void newtext (char *);
void text (char *);
void RedrawPanel();
void RedrawWindow(XpmIcon *v);
void redraw_infos();
Pixel GetColor(char *name);
void infos_cd();

/* External functions */

extern void cd_control(int);
extern char* cd_control_version();

/* These #defines control the main loop timeouts */
#define RDTIME 50000L
#define RDTIME2 75000L

/* the various switches: */

unsigned int autoplay = 0;         /* if set, play a disk when it is inserted -> see -a c.l. option  */
unsigned int intro_mode = 0;       /* play only the beginning of the tracks */
unsigned int autorepeat = FALSE;   /* zzzzzzzzzzzzz */
unsigned int blind_mode = FALSE;   /* no counter updates = no drive LED flashes */
unsigned int loop_mode = 0;        /* loop from loop_1 to loop_2 */
unsigned int loop_start_track = 0; /* track of the beggining of the loop */
unsigned int loop_end_track =0;    /* track of the end of the loop */
unsigned int loop_1 = 0;           /* pos. 1 */
unsigned int loop_2 = 0;           /* pos. 2 */
unsigned int show_db = FALSE;      /* do we have to scroll song names? */
unsigned int show_artist = FALSE;  /* if show_db, do you append artist name? */
unsigned int show_db_pos = 0;      /* internal, used for the song name scrolling */
unsigned int force_upper = FALSE;  /* all messages must be in uppercase */
int ignore_avoid = FALSE;          /* if set, we play *all* tracks, ignoring 'avoid' tags in database */
unsigned int fast_track = 0;       /* the fast track select method */
unsigned int xflaunch = FALSE;     /* do we launch xfascd when right click on the display? */
unsigned int time_mode = 0;        /* display mode for the counter. see function RedrawWindow() */
unsigned int cue_time = 10;        /* nbr of seconds for cue -> see -c command line option */

/* internals */

int lasttime = -1;
extern char *cd_device;            /* the hardware device pointing to the CD ROM player */
unsigned int datatrack = 0;        /* is the current track a data track ? */
unsigned int direct_access = 0;    /* pos. to reach with the ruler */
unsigned int direct_track = 0;     /* if we want to go directly to another track */
unsigned int wanna_play = FALSE;
unsigned int do_autorepeat = FALSE;
int wanted_track = 0;
unsigned int old_track = 0;
unsigned int anomalie = 0;         /* cd_control return value */

/* let's talk about X... */

Display *Disp;
Window Root;
Window Iconwin;
Window Win;
char *Geometry = 0;
char device[128]=DEFAULTDEVICE;
int withdrawn=FALSE;
GC WinGC;
int CarrierOn = FALSE;
int screen;

/* everything dealing with the hardware volume: */

#define MAX_VOL 255
int volume = MAX_VOL ;             /* CD volume */
int muted_volume = 0;              /* CD volume in muted mode */
int unmuted_volume = MAX_VOL;      /* CD volume to restore when leaving muted mode */
unsigned int muted = FALSE;        /* is the CD muted? */
unsigned int fade_out = FALSE;     /* do you have to start a fade in/out? */
unsigned int fade_step = 5;        /* the fading speed */
unsigned int fade_ok = 0;          /* can't remember. sorry!!!! */
extern int min_volume,max_volume;  /* from LibWorkMan */
int cur_balance = 10;              /* ? */

/* the LEDs and help texts: */

char led_color[60];                /* foreground color for LEDs */
char led_bgcolor[60];              /* back " " " " "  " " " " " */
char led_mcolor[60];               /* foreground color for LEDs in mixer mode */
char led_mbgcolor[60];             /* back " " " " "  " " " " " in mixer mode */
char led_text[9];                  /* the 'help' messages */
unsigned int text_timeout = 1;     /* messages timemout in seconds */
long text_start = 0;               /* timeout */

/* misc, have to add explanations here...! */

int redraw = TRUE;
int has_clicked = FALSE;
int info_modified = 0;
int big_spaces = 0;
int slow_down = 0;

/* 0.12 themes stuff: */

/*#define THDIR "/usr/local/share/AScd"*/
char theme[80];

unsigned int theme_select = 0;
unsigned int theme_select_nbr = 0;

/* 'no mask' is the new redraw mode used in 0.12.1: instead of
   using a big shape mask based on the background, we combine the
   background with the buttons shapes. This allows using non rect 
   buttons. Old mode is no longer supported.
*/
unsigned int no_mask = TRUE;

/* the themes level 2 globals. Not yet supported, this is just
   a draft!
*/

unsigned int panel = 0;
Atom _XA_WM_DELETE_WINDOW 	= None;

/*
#define BMAX 16
unsigned int panels = 0;
unsigned int but_nbr = 0;

char th_name[80];
char th_author[80];
char th_release[80];
char th_email[80];


XpmIcon but_xpm[BMAX];
char but_left[BMAX,20];
char but_mid[BMAX,20];
char but_right[BMAX,20];
unsigned int but_x[BMAX];
unsigned int but_x[BMAX];
unsigned int but_w[BMAX];
unsigned int but_h[BMAX];
*/

/*****************************************************************************/

#ifdef WMK
#  include "gui_wings.c"
#endif

/*****************************************************************************/

void Help() 
{
#ifdef WMK
    fprintf(stderr, "ascd %s [+WINGs module] (c) 1999 Rob Malda and Denis Bourez\n", VERSION);
#else
    fprintf(stderr, "ascd %s (c) 1999 Rob Malda and Denis Bourez\n", VERSION);
#endif
    fprintf(stderr, "Usage:  ascd [-options ...] where the options are:\n\n");

    fprintf(stderr, "-version                 Display the version numbers and exit\n");
    fprintf(stderr, "-help                    Display this help screen and exit\n");
    fprintf(stderr, "+/-withdrawn             Turn on/off withdrawn mode for WindowMaker\n");
    fprintf(stderr, "-geometry geom           Standard X Location\n");
    fprintf(stderr, "-ti time                 Texts display timeout in seconds (default = 1)\n");
    fprintf(stderr, "-cue time                Cue Time in seconds (default = 10)\n");
    fprintf(stderr, "+/-a                     Turn on/off Autoplay mode\n");
    fprintf(stderr, "+/-t                     Turn on/off Autorepeat mode\n");
    fprintf(stderr, "+/-B                     Turn on/off Blind mode (no counters updates)\n");
    fprintf(stderr, "+/-ia                    Apply/Ignore 'avoid' tags in WorkMan database\n"),
    fprintf(stderr, "+/-up                    All messages in uppercase?\n");
    fprintf(stderr, "-theme value             Select the visual theme (in %s)\n", THDIR);
    fprintf(stderr, "-xf                      Launch XfAscd with middle click on counter\n");
    fprintf(stderr, "-minvolume value         Minimum volume\n");
    fprintf(stderr, "-maxvolume value         Maximum volume\n");
    fprintf(stderr, "-volume value            CD Drive volume, from 0 to maxvolume\n");
    fprintf(stderr, "-mvolume value           CD Drive volume in mute mode, from 0 to maxvolume\n");
    fprintf(stderr, "-fadestep value          Fade in/out timing offset\n");
    fprintf(stderr, "-device device_driver    CDROM drive device\n");
    fprintf(stderr, "-showtitle               Turn on Song Title Scrolling\n");
    fprintf(stderr, "-showartist              Show artist name when scrolling song title\n");
    fprintf(stderr, "-save                    Save settings and exit. Should be *last* command.\n\n");
    exit(1);
} 

void SHelp() 
{
    fprintf(stderr, "ascd: bad command line syntax.\n");
    fprintf(stderr, "Type 'ascd -help' for a list of command line options.\n");
    exit(-1);
} 

#define MAX_LINE_NAME 16

void ParseCmdLine(int argc, char *argv[]) {
    int i;
    char *Argument;
    int sw;

    for (i = 1 ; i < argc ; i++) {
	Argument = argv[i];

	if ((Argument[0] == '-') || (Argument[0] == '+')) {
	    if (Argument[0] == '-') {
		sw = FALSE;
	    } else if (Argument[0] == '+') {
		sw = TRUE;
	    }

	    if ((strcmp(Argument + 1, "w") == 0) || (strcmp(Argument + 1, "withdrawn") == 0)) {
		if (sw) withdrawn = TRUE;
		else withdrawn = FALSE;
	    }

	    else if ((strcmp(Argument + 1, "g") == 0) || (strcmp(Argument + 1, "geometry") == 0)) {
		if(++i >= argc) SHelp();
		Geometry = argv[i];
	    }
	    
	    else if ((strcmp(Argument + 1, "d") == 0) || (strcmp(Argument + 1, "device") == 0)) {
		if(++i >= argc) SHelp();
		cd_device = malloc(strlen(argv[i]) + 1);
		strcpy(cd_device, argv[i]);
	    }

	    else if (strcmp(Argument + 1, "theme") == 0) {
		if(++i >= argc) SHelp();
		strcpy(theme, argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "f") == 0) || (strcmp(Argument + 1, "fg") == 0)) {
		if(++i >= argc) SHelp();
		strcpy(led_color, "X c ");
		strcat(led_color, argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "b") == 0) || (strcmp(Argument + 1, "bg") == 0)) {
		if(++i >= argc) SHelp();
		strcpy(led_bgcolor, "  c ");
		strcat(led_bgcolor, argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "mfg") == 0)) {
		if(++i >= argc) SHelp();
		strcpy(led_mcolor, "  c ");
		strcat(led_mcolor, argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "mbg") == 0)) {
		if(++i >= argc) SHelp();
		strcpy(led_mbgcolor, "  c ");
		strcat(led_mbgcolor, argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "c") == 0) || (strcmp(Argument + 1, "cue") == 0)) {
		if(++i >= argc) SHelp();
		cue_time = atoi(argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "i") == 0) || (strcmp(Argument + 1, "ti") == 0)) {
		if(++i >= argc) SHelp();
		text_timeout = atoi(argv[i]);
	    }

	    else if ((strcmp(Argument + 1, "a") == 0) || (strcmp(Argument + 1, "autoplay") == 0)) {
		if (sw) autoplay = TRUE;
		else autoplay = FALSE;
	    }

	    else if (strcmp(Argument + 1, "B") == 0) {
		if (sw) blind_mode = TRUE;
		else blind_mode = FALSE;
	    }

	    else if (strcmp(Argument + 1, "ia") == 0) {
		if (sw) ignore_avoid = TRUE;
		else ignore_avoid = FALSE;
	    }

	    else if (strcmp(Argument + 1, "up") == 0) {
		if (sw) force_upper = TRUE;
		else force_upper = FALSE;
	    }

	    else if ((strcmp(Argument + 1, "t") == 0) || (strcmp(Argument + 1, "autorepeat") == 0)) {
		if (sw) autorepeat = TRUE;
		else autorepeat = FALSE;
	    }

	    else if (strcmp(Argument + 1, "showtitle") == 0) {
		show_db = TRUE;
	    }

	    else if (strcmp(Argument + 1, "showartist") == 0) {
		show_artist = TRUE;
	    }

	    else if (strcmp(Argument + 1, "mvolume") == 0) {
		if(++i >= argc) SHelp();
		muted_volume = atoi(argv[i]);
	    }

	    else if (strcmp(Argument + 1, "volume") == 0) {
		if(++i >= argc) SHelp();
		volume = atoi(argv[i]);
	    }

	    else if (strcmp(Argument + 1, "xf") == 0) {
		xflaunch = TRUE;
	    }


	    else if (strcmp(Argument + 1, "maxvolume") == 0) {
		if(++i >= argc) SHelp();
		max_volume = atoi(argv[i]);
	    }

	    else if (strcmp(Argument + 1, "minvolume") == 0) {
		if(++i >= argc) SHelp();
		min_volume = atoi(argv[i]);
	    }

	    else if (strcmp(Argument + 1, "fadestep") == 0) {
		if(++i >= argc) SHelp();
		fade_step = atoi(argv[i]);
	    }

	    else if (strcmp(Argument + 1, "save") == 0) {
		save_rc_file();
		fprintf(stderr, "Settings file saved.\n");
		exit(0);
	    }

	    else if ((strcmp(Argument + 1, "version") == 0) || (strcmp(Argument + 1, "v") == 0)) {
		fprintf(stderr, "%s %s (CDcontrol %s, %s)\n", PACKAGE, VERSION, cd_control_version(), wm_libver_string());
		exit(0);
	    }

	    else if ((strcmp(Argument + 1, "h") == 0) || (strcmp(Argument + 1, "help") == 0)) {
		Help();
	    } else {
		SHelp();
	    }
	} else {
	    SHelp();
	}

    }
    
} 

/* The rc file functions, taken from xfascd*/

void load_rc_file(int mx)
{
    FILE *in;
    struct passwd *pw;
    char st[256];

    if (NULL == (pw = getpwuid(getuid()))) {
        return;
    } else {
        sprintf(st, "%s/.ascdrc", pw->pw_dir);
        if ((in = fopen(st, "r"))) {
            while ( fgets(st, 255, in) ) {
                if (strlen(st) > 0) st[strlen(st) - 1] = 0;

		if (!mx) {
#ifndef NO_D_DEVICE
		    if (strncmp(st, "CD_DEVICE=", 10) == 0) strcpy(cd_device, st + 10);
		    else if (strncmp(st, "THEME=", 6) == 0) strcpy(theme, st + 6);
		    else if (strncmp(st, "AUTOREPEAT=", 11) == 0) autorepeat = atoi(st + 11);
#else
		    if (strncmp(st, "AUTOREPEAT=", 11) == 0) autorepeat = atoi(st + 11);
#endif
		    else if (strncmp(st, "AUTOPLAY=", 9) == 0) autoplay = atoi(st + 9);
		    else if (strncmp(st, "CUE_TIME=", 9) == 0) cue_time = atoi(st + 9);
		    else if (strncmp(st, "TI=", 3) == 0) text_timeout = atoi(st + 3);
		    else if (strncmp(st, "MAX_VOL=", 8) == 0) max_volume = atoi(st + 8);
		    else if (strncmp(st, "MIN_VOL=", 8) == 0) min_volume = atoi(st + 8);
		    else if (strncmp(st, "MUT_VOL=", 8) == 0) muted_volume = atoi(st + 8);
		    else if (strncmp(st, "VOLUME=", 7) == 0) volume = atoi(st + 7);
		    else if (strncmp(st, "FADE_STEP=", 10) == 0) fade_step = atoi(st + 10);
		    else if (strncmp(st, "BGCOLOR=", 8) == 0) strcat(led_bgcolor, st + 8);
		    else if (strncmp(st, "FGCOLOR=", 8) == 0) strcat(led_color, st + 8);
		    else if (strncmp(st, "MBGCOLOR=", 9) == 0) strcat(led_mbgcolor, st + 9);
		    else if (strncmp(st, "MFGCOLOR=", 9) == 0) strcat(led_mcolor, st + 9);
		    else if (strncmp(st, "TIMEMODE=", 9) == 0) time_mode = atoi(st + 9);
		    else if (strcmp(st, "WITHDRAWN") == 0) withdrawn = TRUE;
		    else if (strcmp(st, "SHOWDB") == 0) show_db = TRUE;
		    else if (strcmp(st, "SHOWARTIST") == 0) show_artist = TRUE;
		    else if (strcmp(st, "UPPERCASE") == 0) force_upper = TRUE;
		    else if (strncmp(st, "IGNORE_AVOID=", 13) == 0) ignore_avoid = atoi(st + 13);
		}
            }
            fclose(in);
            return;
        } else {
            return;
        }
    }
}

void save_rc_file()
{
    FILE *out;
    struct passwd *pw;
    char st[128];

    if (NULL == (pw = getpwuid(getuid()))) {
	/* hum... big problem... */
        return;
    } else {
        sprintf(st, "%s/.ascdrc", pw->pw_dir);
        if ((out = fopen(st, "w"))) {
            fprintf(out, "#### generated by AScd version %s ####\n", VERSION);
#ifndef NO_D_DEVICE
	    fprintf(out, "CD_DEVICE=%s\n", cd_device);
#endif	   
	    fprintf(out, "THEME=%s\n", theme);
            fprintf(out, "AUTOREPEAT=%d\n", autorepeat);
            fprintf(out, "AUTOPLAY=%d\n", autoplay);
            fprintf(out, "CUE_TIME=%d\n", cue_time);
            fprintf(out, "TI=%d\n", text_timeout);
            fprintf(out, "VOLUME=%d\n", volume);
            fprintf(out, "MAX_VOL=%d\n", max_volume);
            fprintf(out, "MIN_VOL=%d\n", min_volume);
            fprintf(out, "MUT_VOL=%d\n", muted_volume);
            fprintf(out, "FADE_STEP=%d\n", fade_step);
	    fprintf(out, "BGCOLOR=%s\n", led_bgcolor + 4);
	    fprintf(out, "FGCOLOR=%s\n", led_color + 4);
	    fprintf(out, "MBGCOLOR=%s\n", led_mbgcolor + 4);
	    fprintf(out, "MFGCOLOR=%s\n", led_mcolor + 4);
	    fprintf(out, "TIMEMODE=%d\n", time_mode);
            fprintf(out, "IGNORE_AVOID=%d\n", ignore_avoid);
	    if (withdrawn) {
		fprintf(out, "WITHDRAWN\n");
	    }
	    if (show_db) {
		fprintf(out, "SHOWDB\n");
	    }
	    if (show_artist) {
		fprintf(out, "SHOWARTIST\n");
	    }
	    if (force_upper) {
		fprintf(out, "UPPERCASE\n");
	    }

            fclose(out);
            return;
        } else {
            return;
        }
    }
}

/*****************************************************************************/

void cdplayer_mouse_events(XEvent Event) 
{
    char txt[127];
    unsigned int i;
    FILE *in;

    has_clicked = TRUE;
    show_db_pos = 0;

    if ((Event.xbutton.y <= 2) || (Event.xbutton.y >= 56) ||
	(Event.xbutton.x <= 2) || (Event.xbutton.x >= 56)) {
	
	/* outside... Do nothing!!! */
	
    } else if( Event.xbutton.y <= 9) {
	
	/* the display */

	if (Event.xbutton.x < 40) {

	    /* Time display */

	    switch (Event.xbutton.button) {
	    case 2: /* Mid button: (un)mute volume */
		if (!xflaunch) {
		    if (muted) {
			muted = 0;
			newtext("Mute Off");
			cd_volume(volume, 10, 100);
		    } else {
			newtext("Mute On");
			muted = 1;
			cd_volume(muted_volume, 10, 100);
		    }
		} else {
		    sprintf(txt, "xfascd -d %s &", cd_device);
		    system(txt);
		}
		break;
	    default: /* Left: toggle display mode */
#ifdef WMK
		big_window(scr);
#else
		time_mode++ ;
		if (time_mode > 3) time_mode = 0;
#endif
		break;
	    }
	} else {

	    /* the Fast-track select */

	    if (theme_select == 0) {
		if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) {
		    switch (Event.xbutton.button) {
		    case 3: /* down */
			if (fast_track == 0) {
			    if (cur_track > 1) fast_track = cur_track - 1;
			    else fast_track = cur_ntracks;
			} else {
			    if (fast_track == 1) fast_track = cur_ntracks;
			    else fast_track--;
			}
			break;
		    case 2:
			fast_track = 0;
			break;
		    default: 
			if (fast_track == 0) {
			    if (cur_track < cur_ntracks) fast_track = cur_track + 1;
			    else fast_track = 1;

			} else {
			    if (fast_track == cur_ntracks) fast_track = 1;
			    else fast_track++;
			}
			break;
		    }
		}
	    } else { /* theme selection */
		switch (Event.xbutton.button) {
		case 3:
		    theme_select --;
		    if (theme_select == 1) theme_select = theme_select_nbr;
		    sprintf(txt, "%s/.dir", THDIR);
		    if( (in = fopen(txt, "r"))!= NULL ) {
			i = 0;
			while (fgets(txt, 255,in)) {
			    i++;
			    txt[strlen(txt) - 1] = 0;
			    if (i == theme_select) {
				break;
			    }
			}
			fclose(in);
			strcpy(theme, txt);
			(void)GetXPM(led_color, led_bgcolor);
			(void)MaskSet();
		    }
		    break;
		case 2:
		    theme_select = 0;
		    break;
		default:
		    theme_select ++;
		    if (theme_select > theme_select_nbr) theme_select = 1;
		    sprintf(txt, "%s/.dir", THDIR);
		    if ((in = fopen(txt, "r"))!=NULL) {
			i = 0;
			while (fgets(txt, 255,in)) {
			    i++;
			    txt[strlen(txt) - 1] = 0;
			    if (i == theme_select) {
				break;
			    }
			}
			fclose(in);
			strcpy(theme, txt);
			(void)GetXPM(led_color, led_bgcolor);
			(void)MaskSet();
		    }
		    break;
		}
	    }
	}
    }

    else if (Event.xbutton.y < 18) {
	/* second display line */
	if (Event.xbutton.button != 3) {
	    /* left or middle: toggle track name scrolling on/off */
	    if (show_db) show_db = FALSE;
	    else show_db = TRUE;
	} else {
	    /* right button: theme selector */
	    if (theme_select == 0) {
		theme_select = 1;

		sprintf(txt, "%s/.dir", THDIR);
		theme_select_nbr = 0;
		if( (in = fopen(txt, "r"))!= NULL ) {
		    while (fgets(txt, 255,in)) theme_select_nbr++;
		    fclose(in);
		}

		sprintf(txt, "%s/.dir", THDIR);
		if ((in = fopen(txt, "r")) != NULL ) {
		    i = 0;
		    while (fgets(txt, 255, in)) {
			i++;
			txt[strlen(txt) - 1] = 0;
			if (strcmp(txt, theme) == 0) {
			    theme_select = i;
			    break;
			}
		    }
		    fclose(in);
		}
	    } else {
		theme_select = 0;
	    }
	}
    }

    else if ((Event.xbutton.y >= 21) && (Event.xbutton.y <= 25)) {

	if (Event.xbutton.x <= 47) {
	    /* We're in the progress bar. Direct Access! */
	    
	    switch(Event.xbutton.button) {
	    case 3:
		
		/* Loc Access:
		   We move to the starting point of the loop. */
		
		cd_control(LOCACCESS);
		RedrawWindow(&backXPM);
		wm_cd_status();
		if (!anomalie) newtext("Auto Loc");
		else newtext("ERROR!");
		break;
	    default:
		
		/* Direct Access:
		   we have to compute the offset to pass it to cd_control. We also have to
		   check if we want to move inside the current track or in the whole CD */
		
		if (cur_track < 1) cur_track = 1;
		
		if ((time_mode == 2) || (time_mode == 3)) {
		    direct_access = (int)((float)(Event.xbutton.x - 2) / 46.0 * (float)cur_cdlen);
		    cd_control(GLOBALACCESS);
		} else {
		    direct_access = (int)((float)(Event.xbutton.x - 2) / 46.0 * (float)cur_tracklen);
		    cd_control(DIRECTACCESS);
		}
		wm_cd_status();
		RedrawWindow(&backXPM);
		break;
	    }
	} else {

	    /* the panel switch button */

	    if (Event.xbutton.x > 49) {
		if (cur_cdmode != WM_CDM_EJECTED) {
		    panel ++;
		    if (panel > 1) panel = 0;
		}
		(void)MaskSet();
		(void)RedrawPanel();
		(void)RedrawWindow(&backXPM);
	    }
	}
    }
    
    else if ((Event.xbutton.y >= 27) && (Event.xbutton.y <= 40)) {

	if (Event.xbutton.x <= 18) {
	    if (panel == 0) {
		/* REW */
		if (Event.xbutton.button == 1) {
		    cd_control(DNTRACK);
		} else if (Event.xbutton.button == 2) {
		    newtext("First Tk");
		    cd_control(FIRST);
		} else if (Event.xbutton.button == 3) {
		    cd_control(REV);
		}
	    } else {
		loop_1 = cur_pos_rel;
		newtext("L. Start");
		loop_start_track = cur_track;
	    }
	} else if (Event.xbutton.x <= 37) {
	    if (panel == 0) {
		/* PLAY */
		if (cur_cdmode == WM_CDM_PAUSED) {
		    newtext("Playing");
		    wanna_play = TRUE;
		    cd_control(PAUSE);
		} else if (cur_cdmode == WM_CDM_PLAYING) {
		    if (fast_track != 0) {
			direct_track = fast_track;
			fast_track = 0;
			cd_control(DIRECTTRACK);
		    } else {
			newtext("Paused");
			cd_control(PAUSE);
		    }
		} else if (cur_cdmode == WM_CDM_EJECTED) {
		    cd_control(CLOSETRAY);
		} else {
		    newtext("Play");
		    wanna_play = TRUE;
		    cd_control(PLAY);
		}
	    } else {
		if (loop_mode) {
		    loop_mode = 0;
		    newtext("Loop Off");
		} else {
		    cd_control(LOOP);
		    if (!anomalie) newtext("Loop On");
		    else newtext("ERROR!");
		}
	    }
	} else {
	    if (panel == 0) {
		/* FWD */
		if (Event.xbutton.button == 1) {
		    cd_control(UPTRACK);
		} else if (Event.xbutton.button == 2) {
		    newtext("Last Tk");
		    cd_control(LAST);
		} else if (Event.xbutton.button == 3) {
		    cd_control(CUE);
		}
	    } else {
		loop_2 = cur_pos_rel;
		loop_end_track = cur_track;
		newtext("L. End");
	    }
	}

	RedrawWindow(&backXPM);
    } else if (Event.xbutton.y > 40) {
	/* the bottow row */
	if (Event.xbutton.x <= 18) {
	    /* PAUSE or FADE */
	    if (panel == 0) {
		fast_track = 0;
		newtext("Paused");
		wanna_play = TRUE;
		cd_control(PAUSE);
		(void)MaskSet();
	    } else {
		if (cur_cdmode == WM_CDM_PLAYING) {
		    newtext("Fade Out");
		} else {
		    newtext("Fade In");
		}
		fade_out = TRUE;
	    }
	} else if (Event.xbutton.x <= 37) {
	    if (panel == 0) {
		/* STOP */
		fast_track = 0;
		if (cur_cdmode != WM_CDM_STOPPED) {
		    newtext("Stop");
		    cd_control(STOPONLY);
		    wm_cd_status();
		    cur_track = 0;
		    (void)MaskSet();
		} else {
		    newtext("Eject");
		    cd_control(EJECT);
		    (void)MaskSet();
		}
		redraw = TRUE;
	    } else {
		cd_control(INTROSCAN);
		wm_cd_status();
		newtext("Intro Sc");
		(void)MaskSet();
	    }
	} else {
	    if (panel == 0) {
		if ((cur_cdmode != WM_CDM_EJECTED) && (cur_cdmode != WM_CDM_STOPPED)) {
		    newtext("Eject");
		    cd_control(EJECT);
		    fast_track = 0;
		    (void)MaskSet();
		} else {
		    exit(0);
		}
	    } else {
		exit(0);
	    }
	}

	RedrawWindow(&backXPM);
    }
} 

/* ------------------------------------------------------------------------
   GUI control
   ------------------------------------------------------------------------ */

Pixel GetColor(char *ColorName) 
{
    XColor Color;
    XWindowAttributes Attributes;

    XGetWindowAttributes(Disp,Root,&Attributes);
    Color.pixel = 0;

    if (!XParseColor (Disp, Attributes.colormap, ColorName, &Color))
      fprintf(stderr,"ascd: can't parse %s\n", ColorName);
    else if(!XAllocColor (Disp, Attributes.colormap, &Color))
      fprintf(stderr,"ascd: can't allocate %s\n", ColorName);

    return Color.pixel;
} 

void GetXPM(char *foreground, char *background) 
{
    char txt[256];
    XWindowAttributes Attributes;
    int Ret;

    sprintf(txt, "%s/%s", THDIR, theme);
    if (access(txt, X_OK | R_OK) != 0) {
	sprintf(txt, "%s/default", THDIR);
	if (access(txt, X_OK | R_OK) != 0) {
	    fprintf(stderr, "ascd: fatal error\n\n");
	    fprintf(stderr, "The '%s' and 'default' themes folders are not \navailable in %s.\n\n", theme, THDIR);
	    fprintf(stderr, "Please check the permissions and/or redo ascd installation.\n\n");
	    exit(1);
	} else {
	    strcpy(theme, "default");
	}
    }


    XGetWindowAttributes(Disp,Root,&Attributes);

    /* background: */

    sprintf(txt, "%s/%s/background.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &backXPM.pixmap,
			      &backXPM.mask, &backXPM.attributes);

    /* buttons: */

    fwdXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/fwd.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &fwdXPM.pixmap,
			      &fwdXPM.mask, &fwdXPM.attributes);
    
    rewXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/rew.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &rewXPM.pixmap,
			      &rewXPM.mask, &rewXPM.attributes);

    playXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/play.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &playXPM.pixmap,
			      &playXPM.mask, &playXPM.attributes);

    play_onXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/play_on.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &play_onXPM.pixmap,
			      &play_onXPM.mask, &play_onXPM.attributes);

    pauseXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/pause.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &pauseXPM.pixmap,
			      &pauseXPM.mask, &pauseXPM.attributes);

    pause_onXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/pause_on.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &pause_onXPM.pixmap,
			      &pause_onXPM.mask, &pause_onXPM.attributes);

    ejectXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/eject.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &ejectXPM.pixmap,
			      &ejectXPM.mask, &ejectXPM.attributes);

    stopXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/stop.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &stopXPM.pixmap,
			      &stopXPM.mask, &stopXPM.attributes);

    lstartXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/lstart.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &lstartXPM.pixmap,
			      &lstartXPM.mask, &lstartXPM.attributes);

    lendXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/lend.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &lendXPM.pixmap,
			      &lendXPM.mask, &lendXPM.attributes);

    lgoXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/lgo.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &lgoXPM.pixmap,
			      &lgoXPM.mask, &lgoXPM.attributes);

    lgo_onXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/lgo_on.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &lgo_onXPM.pixmap,
			      &lgo_onXPM.mask, &lgo_onXPM.attributes);

    fadeXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/fade.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &fadeXPM.pixmap,
			      &fadeXPM.mask, &fadeXPM.attributes);

    introXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/intro.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &introXPM.pixmap,
			      &introXPM.mask, &introXPM.attributes);

    intro_onXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/intro_on.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &intro_onXPM.pixmap,
			      &intro_onXPM.mask, &intro_onXPM.attributes);

    quitXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/quit.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &quitXPM.pixmap,
			      &quitXPM.mask, &quitXPM.attributes);

    alphaXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/digits.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &alphaXPM.pixmap,
			      &alphaXPM.mask, &alphaXPM.attributes);

    ralphaXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/rdigits.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &ralphaXPM.pixmap,
			      &ralphaXPM.mask, &ralphaXPM.attributes);

    barXPM.attributes.valuemask |= (XpmReturnPixels | XpmReturnExtensions);
    sprintf(txt, "%s/%s/bar.xpm", THDIR, theme);
    Ret = XpmReadFileToPixmap(Disp, Root, txt, &barXPM.pixmap,
			      &barXPM.mask, &barXPM.attributes);

    if (Ret != XpmSuccess) {
	fprintf(stderr, "ascd: fatal error\n\n");
	fprintf(stderr, "Can't load the background and/or buttons pixmaps.\n");
	fprintf(stderr, "Causes can be:\n");
	fprintf(stderr, "- problem(s) in the files\n");
	fprintf(stderr, "- a non existing color in fore/background colors definition\n");
	fprintf(stderr, "- not enough free color cells\n\n");
	exit(1);
    }
} 

void CreateWindow(int argc, char **argv) 
{
    int i;
    unsigned int borderwidth ;
    char *display_name = NULL;
    char *wname = "ascd";
    XGCValues gcv;
    unsigned long gcm;
    XTextProperty name;
    Pixel back_pix, fore_pix;
    int x_fd;
    int d_depth;
    int ScreenWidth, ScreenHeight;
    XSizeHints SizeHints;
    XWMHints WmHints;
    XClassHint classHint;

    /* Open display */
    if (!(Disp = XOpenDisplay(display_name))) {
	fprintf(stderr,"ascd: can't open display %s\n", XDisplayName(display_name));
	exit (1);
    }

    screen = DefaultScreen(Disp);

#ifdef WMK
    scr = WMCreateScreen(Disp, DefaultScreen(Disp));
    create_big_window(scr);
    create_db_window(scr);
    create_about_window(scr);
#endif

    Root = RootWindow(Disp, screen);
    d_depth = DefaultDepth(Disp, screen);
    x_fd = XConnectionNumber(Disp);
    _XA_WM_DELETE_WINDOW = XInternAtom (Disp, "WM_DELETE_WINDOW", False);
    
    ScreenHeight = DisplayHeight(Disp,screen);
    ScreenWidth = DisplayWidth(Disp,screen);

    GetXPM(led_color, led_bgcolor);

    SizeHints.flags= USSize|USPosition;
    SizeHints.x = 0;
    SizeHints.y = 0;
    back_pix = GetColor("black");
    fore_pix = GetColor("white");

    XWMGeometry(Disp, screen, Geometry, NULL, (borderwidth = 1), &SizeHints,
		&SizeHints.x,&SizeHints.y,&SizeHints.width,
		&SizeHints.height, &i);

    SizeHints.width = backXPM.attributes.width;
    SizeHints.height= backXPM.attributes.height;

    Win = XCreateSimpleWindow(Disp,Root,SizeHints.x,SizeHints.y,
			      SizeHints.width,SizeHints.height,
			      borderwidth,fore_pix,back_pix);

    Iconwin = XCreateSimpleWindow(Disp,Win,SizeHints.x,SizeHints.y,
				  SizeHints.width,SizeHints.height,
				  borderwidth,fore_pix,back_pix);
    XSetWMNormalHints(Disp, Win, &SizeHints);

    classHint.res_name = "ascd" ;
    classHint.res_class = "AScd";

    XSetClassHint (Disp, Win, &classHint);

    XSelectInput(Disp, Win, (ExposureMask | ButtonPressMask | StructureNotifyMask));
    XSelectInput(Disp, Iconwin, (ExposureMask | ButtonPressMask |
				 StructureNotifyMask));

    if (XStringListToTextProperty(&wname, 1, &name) ==0) {
	fprintf(stderr, "ascd: can't allocate window name\n");
	exit(-1);
    }

    XSetWMName(Disp, Win, &name);

    /* Create WinGC */
    gcm = GCForeground|GCBackground|GCGraphicsExposures;
    gcv.foreground = fore_pix;
    gcv.background = back_pix;
    gcv.graphics_exposures = False;
    WinGC = XCreateGC(Disp, Root, gcm, &gcv);

    WmHints.initial_state = withdrawn ? WithdrawnState : NormalState ;
    WmHints.icon_window = Iconwin;
    WmHints.window_group = Win;
    WmHints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
    WmHints.icon_x = SizeHints.x;
    WmHints.icon_y = SizeHints.y;
    XSetWMHints(Disp, Win, &WmHints);
    XSetWMProtocols (Disp, Win, &_XA_WM_DELETE_WINDOW, 1);
    XSetCommand(Disp, Win, argv, argc);
    
    XMapWindow(Disp, Win);
    
    if (no_mask) {
	(void)MaskSet();
    }
    RedrawWindow(&backXPM);
} 

int FlushExpose(Window w) 
{
    XEvent dummy;
    int i=0;

    while (XCheckTypedWindowEvent (Disp, w, Expose, &dummy))i++;
    return i;
} 

void minus(void) {
    if (time_mode == 1) {
	XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC,
		  6 * (45 - 32), 0, 6, 7, 1, 2);
	XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC,
		  6 * (45 - 32), 0, 6, 7, 1, 2);
    } else if (time_mode == 3) {
	XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC,
		  588, 0, 4, 7, 1, 2);
	XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC,
		  588, 0, 4, 7, 1, 2);
    }

    /* if displaying CD times, we display a little 'cd' */

    if (time_mode >= 2) {
	XCopyArea(Disp, ralphaXPM.pixmap, Win, WinGC,
		  582, 0, 4, 4, 1, 2);
	XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC,
		  582, 0, 4, 4, 1, 2);
    }

}

/*#define ACCTABLE "éÉèÈêÊàÀâÂùÙûÛîÎôÔçÇ**"*/
#define ACCTABLE "éeèeêeàaâaùuûuîiôoçc**"
#define UPACCTABLE "éEèEêEàAâAùUûUîIôOçC**"

void tes_sncpy(char *out, char *in, int n)
{
   register int i;
   for (i=0; i<=n-1; i++) out[i] = in[i];
   out[i] = '\0';
}

void Text_Draw(char *string, unsigned int row, unsigned int col, unsigned int red) {
    unsigned int x = 0;
    unsigned int offset = 0;
    unsigned hoffset = 6;
    unsigned char txt[128];
    unsigned int j;

    strcpy(txt, string);
    for(x = 0; x < strlen(txt); x++) {

	/* lookup in the accents table to remove them */
	if (! force_upper) {
	    for (j = 0 ; j <= strlen(ACCTABLE) - 2 ; j = j + 2) {
		if ( txt[x] == (unsigned char)ACCTABLE[j] ) {
		    txt[x] = ACCTABLE[j + 1];
		    break;
		}
	    }
	} else {
	    /* force upper case */
	    for (j = 0 ; j <= strlen(UPACCTABLE) - 2 ; j = j + 2) {
		if ( txt[x] == (unsigned char)UPACCTABLE[j] ) {
		    txt[x] = UPACCTABLE[j + 1];
		    break;
		}
	    }
	    txt[x] = toupper(txt[x]);
	}

	if ((txt[x] >= 32) && (txt[x] <= 131)) offset = txt[x] - 32;
	else offset = 0;

	if (red) {
	    XCopyArea(Disp, ralphaXPM.pixmap, Win, WinGC,
		      6 * offset, 0, 6, 9, hoffset + ((row * 6) + (x * 6)), 2 + (col * 8));
	    XCopyArea(Disp, ralphaXPM.pixmap, Iconwin, WinGC,
		      6 * offset, 0, 6, 9, hoffset + ((row * 6) + (x * 6)), 2 + (col * 8));
	} else {
	    XCopyArea(Disp, alphaXPM.pixmap, Win, WinGC,
		      6 * offset, 0, 6, 9, hoffset + ((row * 6) + (x * 6)), 2 + (col * 8));
	    XCopyArea(Disp, alphaXPM.pixmap, Iconwin, WinGC,
		      6 * offset, 0, 6, 9, hoffset + ((row * 6) + (x * 6)), 2 + (col * 8));
	}
	
    }
}

void newtext(char *txt) { 
    strcpy(led_text, txt);
    text_start = 0;
} 


void show_db_f() {
    /* scroll the song title */
    char txt[256];
    char txt2[256];
    char dsp[9];
    if (theme_select == 0) {
	if (cd->trk[cur_track - 1].songname != NULL) {
	    if (show_artist) {
		if (cd->artist != NULL) {
		    sprintf(txt2, "%s: %s", cd->artist, cd->trk[cur_track - 1].songname);
		} else {
		    strcpy(txt2, cd->trk[cur_track - 1].songname);
		}
	    } else {
		strcpy(txt2, cd->trk[cur_track - 1].songname);
	    }
	    Text_Draw("        ", 0, 1, TRUE);
	    if (strlen(txt2) > 8) {
		strcpy(txt, "       ");
		strcat(txt, txt2);
		if (show_db_pos > strlen(txt)) show_db_pos = 0;
		tes_sncpy(dsp, txt + show_db_pos, 8);
		Text_Draw(dsp, 0, 1, TRUE);
		show_db_pos ++;
	    } else {
		Text_Draw(txt2, 0, 1, TRUE);
	    }
	} else {
	    *txt = '\0';
	}
    }
}

void RedrawPanel() {
    if (panel == 0) {
	XCopyArea(Disp, rewXPM.pixmap, Win, WinGC,
		  0, 0, rewXPM.attributes.width, rewXPM.attributes.height, 0, 27);
	
	XCopyArea(Disp, rewXPM.pixmap, Iconwin, WinGC,
		  0, 0, rewXPM.attributes.width, rewXPM.attributes.height, 0, 27);
	
	XCopyArea(Disp, fwdXPM.pixmap, Win, WinGC,
		  0, 0, fwdXPM.attributes.width, fwdXPM.attributes.height, 38, 27);
	
	XCopyArea(Disp, fwdXPM.pixmap, Iconwin, WinGC,
		  0, 0, fwdXPM.attributes.width, fwdXPM.attributes.height, 38, 27);
	
	if (cur_cdmode == WM_CDM_PLAYING) {
	    XCopyArea(Disp, play_onXPM.pixmap, Win, WinGC,
		      0, 0, play_onXPM.attributes.width, play_onXPM.attributes.height, 19, 27);
	    XCopyArea(Disp, play_onXPM.pixmap, Iconwin, WinGC,
		      0, 0, play_onXPM.attributes.width, play_onXPM.attributes.height, 19, 27);
	} else {
	    XCopyArea(Disp, playXPM.pixmap, Win, WinGC,
		      0, 0, playXPM.attributes.width, playXPM.attributes.height, 19, 27);
	    XCopyArea(Disp, playXPM.pixmap, Iconwin, WinGC,
		      0, 0, playXPM.attributes.width, playXPM.attributes.height, 19, 27);
	}
	
	if (cur_cdmode == WM_CDM_PAUSED) {
	    XCopyArea(Disp, pause_onXPM.pixmap, Win, WinGC,
		      0, 0, pause_onXPM.attributes.width, pause_onXPM.attributes.height, 0, 42);
	    XCopyArea(Disp, pause_onXPM.pixmap, Iconwin, WinGC,
		      0, 0, pause_onXPM.attributes.width, pause_onXPM.attributes.height, 0, 42);
	} else {
	    XCopyArea(Disp, pauseXPM.pixmap, Win, WinGC,
		      0, 0, pauseXPM.attributes.width, pauseXPM.attributes.height, 0, 42);
	    XCopyArea(Disp, pauseXPM.pixmap, Iconwin, WinGC,
		      0, 0, pauseXPM.attributes.width, pauseXPM.attributes.height, 0, 42);
	}

	if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED)) {
	    XCopyArea(Disp, stopXPM.pixmap, Win, WinGC,
		      0, 0, stopXPM.attributes.width, stopXPM.attributes.height, 19, 42);
	    XCopyArea(Disp, stopXPM.pixmap, Iconwin, WinGC,
		      0, 0, stopXPM.attributes.width, stopXPM.attributes.height, 19, 42);
	} else {
	    XCopyArea(Disp, ejectXPM.pixmap, Win, WinGC,
		      0, 0, ejectXPM.attributes.width, ejectXPM.attributes.height, 19, 42);
	    XCopyArea(Disp, ejectXPM.pixmap, Iconwin, WinGC,
		      0, 0, ejectXPM.attributes.width, ejectXPM.attributes.height, 19, 42);
	}

	if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED)) {
	    XCopyArea(Disp, ejectXPM.pixmap, Win, WinGC,
		      0, 0, ejectXPM.attributes.width, ejectXPM.attributes.height, 38, 42);
	    XCopyArea(Disp, ejectXPM.pixmap, Iconwin, WinGC,
		      0, 0, ejectXPM.attributes.width, ejectXPM.attributes.height, 38, 42);
	} else {
	    XCopyArea(Disp, quitXPM.pixmap, Win, WinGC,
		      0, 0, quitXPM.attributes.width, quitXPM.attributes.height, 38, 42);
	    XCopyArea(Disp, quitXPM.pixmap, Iconwin, WinGC,
		      0, 0, quitXPM.attributes.width, quitXPM.attributes.height, 38, 42);
	}
    } else {
	XCopyArea(Disp, lstartXPM.pixmap, Win, WinGC,
		  0, 0, lstartXPM.attributes.width, lstartXPM.attributes.height, 0, 27);
	XCopyArea(Disp, lstartXPM.pixmap, Iconwin, WinGC,
		  0, 0, lstartXPM.attributes.width, lstartXPM.attributes.height, 0, 27);
	
	XCopyArea(Disp, lendXPM.pixmap, Win, WinGC,
		  0, 0, lendXPM.attributes.width, lendXPM.attributes.height, 38, 27);
	XCopyArea(Disp, lendXPM.pixmap, Iconwin, WinGC,
		  0, 0, lendXPM.attributes.width, lendXPM.attributes.height, 38, 27);

	if (loop_mode) {
	    XCopyArea(Disp, lgo_onXPM.pixmap, Win, WinGC,
		      0, 0, lgo_onXPM.attributes.width, lgo_onXPM.attributes.height, 19, 27);
	    XCopyArea(Disp, lgo_onXPM.pixmap, Iconwin, WinGC,
		      0, 0, lgo_onXPM.attributes.width, lgo_onXPM.attributes.height, 19, 27);
	} else {
	    XCopyArea(Disp, lgoXPM.pixmap, Win, WinGC,
		      0, 0, lgoXPM.attributes.width, lgoXPM.attributes.height, 19, 27);
	    XCopyArea(Disp, lgoXPM.pixmap, Iconwin, WinGC,
		      0, 0, lgoXPM.attributes.width, lgoXPM.attributes.height, 19, 27);
	}

	XCopyArea(Disp, fadeXPM.pixmap, Win, WinGC,
		  0, 0, fadeXPM.attributes.width, fadeXPM.attributes.height, 0, 42);
	XCopyArea(Disp, fadeXPM.pixmap, Iconwin, WinGC,
		  0, 0, fadeXPM.attributes.width, fadeXPM.attributes.height, 0, 42);

	if (intro_mode) {
	    XCopyArea(Disp, intro_onXPM.pixmap, Win, WinGC,
		      0, 0, intro_onXPM.attributes.width, intro_onXPM.attributes.height, 19, 42);	
	    XCopyArea(Disp, intro_onXPM.pixmap, Iconwin, WinGC,
		      0, 0, intro_onXPM.attributes.width, intro_onXPM.attributes.height, 19, 42);
	} else {
	    XCopyArea(Disp, introXPM.pixmap, Win, WinGC,
		      0, 0, introXPM.attributes.width, introXPM.attributes.height, 19, 42);	
	    XCopyArea(Disp, introXPM.pixmap, Iconwin, WinGC,
		      0, 0, introXPM.attributes.width, introXPM.attributes.height, 19, 42);
	}

	XCopyArea(Disp, quitXPM.pixmap, Win, WinGC,
		  0, 0, quitXPM.attributes.width, quitXPM.attributes.height, 38, 42);
	XCopyArea(Disp, quitXPM.pixmap, Iconwin, WinGC,
		  0, 0, quitXPM.attributes.width, quitXPM.attributes.height, 38, 42);
    }
}

void MaskSet() {

    XShapeCombineMask(Disp, Win, ShapeBounding, 0, 0, backXPM.mask, ShapeSet);
    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0, backXPM.mask, ShapeSet);

    if (panel == 0) {

	XShapeCombineMask(Disp, Win, ShapeBounding,      0, 27, rewXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding,  0, 27, rewXPM.mask, ShapeUnion);

	XShapeCombineMask(Disp, Win, ShapeBounding,     38, 27, fwdXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding, 38, 27, fwdXPM.mask, ShapeUnion);
	
	if (cur_cdmode == WM_CDM_PLAYING) {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 27, play_onXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 27, play_onXPM.mask, ShapeUnion);
	} else {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 27, playXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 27, playXPM.mask, ShapeUnion);
	}
	
	if (cur_cdmode == WM_CDM_PAUSED) {
	    XShapeCombineMask(Disp, Win, ShapeBounding,      0, 42, pause_onXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding,  0, 42, pause_onXPM.mask, ShapeUnion);
	} else {
	    XShapeCombineMask(Disp, Win, ShapeBounding,      0, 42, pauseXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding,  0, 42, pauseXPM.mask, ShapeUnion);
	}

	if ((cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED)) {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 42, stopXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 42, stopXPM.mask, ShapeUnion);

	    XShapeCombineMask(Disp, Win, ShapeBounding,     38, 42, ejectXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 38, 42, ejectXPM.mask, ShapeUnion);
	} else {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 42, ejectXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 42, ejectXPM.mask, ShapeUnion);

	    XShapeCombineMask(Disp, Win, ShapeBounding,     38, 42, quitXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 38, 42, quitXPM.mask, ShapeUnion);
	}
    } else {
	XShapeCombineMask(Disp, Win, ShapeBounding,      0, 27, lstartXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding,  0, 27, lstartXPM.mask, ShapeUnion);

	XShapeCombineMask(Disp, Win, ShapeBounding,     38, 27, lendXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding, 38, 27, lendXPM.mask, ShapeUnion);

	if (loop_mode) {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 27, lgo_onXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 27, lgo_onXPM.mask, ShapeUnion);
	} else {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 27, lgoXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 27, lgoXPM.mask, ShapeUnion);
	}

	
	XShapeCombineMask(Disp, Win, ShapeBounding,      0, 42, fadeXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding,  0, 42, fadeXPM.mask, ShapeUnion);

	if (intro_mode) {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 42, intro_onXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 42, intro_onXPM.mask, ShapeUnion);
	} else {
	    XShapeCombineMask(Disp, Win, ShapeBounding,     19, 42, introXPM.mask, ShapeUnion);
	    XShapeCombineMask(Disp, Iconwin, ShapeBounding, 19, 42, introXPM.mask, ShapeUnion);
	}

	XShapeCombineMask(Disp, Win, ShapeBounding,     38, 42, quitXPM.mask, ShapeUnion);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding, 38, 42, quitXPM.mask, ShapeUnion);
    }
}

/* ------------------------------------------------------------------------
   The big deal: We have to redraw the pixmaps, and update all leds. But
   there a few cd_control() calls also.
   ------------------------------------------------------------------------ */

void RedrawWindow(XpmIcon *Icon) {
    int disp_time;
    static time_t last_flash_time = 0;
    static int flash=0;
    long dodo = 300000;
    char cdtime[6];
    char txt[40];
    int i;
    FILE *in;

    if (strlen(led_text) > 0) {
	if (text_start == 0) {
	    text_start = time(NULL);
	    (void)RedrawPanel();
	    Text_Draw("        ", 0, 1, FALSE);
	    Text_Draw(led_text, 0, 1, FALSE);
	}
	
	if (time(NULL) - text_start > text_timeout) {
	    text_start = 0;
	    redraw = TRUE;
	    strcpy(led_text, "");
	    Text_Draw("        ", 0, 1, FALSE);
	} else { 
	    if (!fade_out) return;
	}
    }

#ifdef WMK
    if (cur_track != old_track) {
	update_track();
	old_track = cur_track;
    }
#endif

    if (!blind_mode) {
	if ((cur_cdmode == WM_CDM_PLAYING) || (wanna_play)) wm_cd_status();
    }

    if ((cur_track == cur_ntracks) && (cur_cdmode != WM_CDM_PAUSED) && (cur_cdmode != WM_CDM_PLAYING)) {
	/*if (wanna_play) {*/
	    if (autorepeat) {
		newtext("A.Repeat");
		do_autorepeat = TRUE;
		cd_control(PLAY);
	    } else {
		cur_cdmode = WM_CDM_STOPPED;
		wm_cd_status();
		cur_track = 0;
		redraw = TRUE;
		RedrawPanel();
	    } 
	    /*} else RedrawPanel();*/
    } else {
	/* 
	   no redraw needed? In this case, we leave the function here,
	   to avoid a flashy screen
	*/
	if(((cur_cdmode != WM_CDM_PAUSED) && lasttime == cur_pos_rel) && (!redraw) && (text_start == 0)) return;
    }
    

    /* ---------------------------------------------------------------- 
       The FADE IN/OUT
       ---------------------------------------------------------------- */

    if ((cur_cdmode == WM_CDM_PLAYING) && (fade_out)) {
	if (!fade_ok) {
	    fade_ok = 1;
	    return;
	} else {
	    unmuted_volume = volume ;
	    while (volume > min_volume) {
		volume = volume - fade_step;
		cd_volume(volume, 10, max_volume);
		usleep(dodo);
	    }
	    fade_out = 0;
	    fade_ok = 0;
	    cd_control(PAUSE);
	    old_track = 0;
	    volume = unmuted_volume;
	    cd_volume(volume, 10, max_volume);
	}
    }

    /* The auto fade in: */

    if ((cur_cdmode == WM_CDM_PAUSED) && (fade_out)){
	if (!fade_ok) {
	    fade_ok = 1;
	    return;
	} else {
	    unmuted_volume = volume;
	    volume = min_volume;
	    cd_volume(volume, 10, max_volume);
	    wm_cd_status();
	    usleep(dodo * 5);
	    cd_control(PAUSE);
	    usleep(dodo * 5);
	    while (volume < max_volume) {
		volume = volume + fade_step;
		cd_volume(volume, 10, max_volume);
		usleep(dodo);
	    }
	    fade_out = 0;
	    fade_ok = 0;
	    volume = unmuted_volume;
	    cd_volume(volume, 10, max_volume);
	}
    }


    /* ======================================================= */
    /* the next track handling. We have to skip 'avoid' tracks */
    /* ======================================================= */

    if ((cur_cdmode != WM_CDM_EJECTED) && (! ignore_avoid)) {
	if (cur_ntracks > 1) { /* only if there are more than ONE track */
	    if (cur_track != old_track) {
		i = cur_track - 1;
		while ((i <= cur_ntracks) && (cd->trk[i].avoid == 1)) {
		    i ++;
		}

		/* go to the next valid track, only if it is now the
		   current track... */

		if (i != cur_track - 1) {
		    direct_track = i + 1;
		    cd_control(DIRECTTRACK);
		}
	    }
	}
    }
    
    

    /* ---------------------------------------------------------------- */


    if (redraw) redraw = FALSE;

    if (cur_cdmode == WM_CDM_PAUSED) {
	time_t flash_time = time(NULL);
	if (flash_time == last_flash_time) return;
	last_flash_time = flash_time;
	flash = !flash;
    } else {
	/* reset these if not paused, so next pause goes smoothly */
	last_flash_time = 0;
	flash = 1;
    }
    
    lasttime = cur_pos_rel;


    
    /* =======================================================================
       Background
       ======================================================================= */

    FlushExpose(Win);
    FlushExpose(Iconwin);

    if (! no_mask) {
	XShapeCombineMask(Disp, Win, ShapeBounding, 0, 0,
			  backXPM.mask, ShapeSet);
	XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0,
			  backXPM.mask, ShapeSet);
    }

    XCopyArea(Disp,backXPM.pixmap,Win,WinGC,
	      0,0,backXPM.attributes.width, backXPM.attributes.height,0,0);

    XCopyArea(Disp,backXPM.pixmap,Iconwin,WinGC,
	      0,0,backXPM.attributes.width, backXPM.attributes.height,0,0);

    /* =======================================================================
       The buttons
       ======================================================================= */
    
    (void)RedrawPanel();

    /* =======================================================================
       The leds
       ======================================================================= */

    /* The Track number */

    /* if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) { */
    Text_Draw("        ", 0, 0, FALSE);

    /* no CD? no counters! */

    if (cur_cdmode == WM_CDM_EJECTED) {
	Text_Draw("AScd", 0, 0, FALSE);
	Text_Draw("NO CD", 0, 1, TRUE);
	return;
    }

    /* Theme select
       ============
    */

    if (theme_select > 0) {
	Text_Draw("THEME", 0, 0, TRUE);
	sprintf(cdtime, "%02d", theme_select);
	Text_Draw(cdtime, 6, 0, TRUE);
	strcpy(cdtime, " ");
	cdtime[0] = 127;
	Text_Draw(cdtime, 5, 0, FALSE);
	
	i = 0;
	sprintf(txt, "%s/.dir", THDIR);
	if( (in = fopen(txt, "r"))!= NULL ) {
	    while (fgets(txt, 255,in)!=NULL) {
		i++;
		txt[strlen(txt) - 1] = 0;
		if (i == theme_select) {
		    Text_Draw(txt, 0, 1, FALSE);
		    break;
		}
	    }
	    fclose(in);
	}
	return;
    }

    /* Fast Track select
       =================
    */

    if (fast_track == 0) {
	if (cur_track > 0) {
	    if (time_mode != 3) {
		sprintf(cdtime, "%02d", cur_track);
	    } else {
		sprintf(cdtime, "%02d", cur_ntracks - cur_track);
	    }
	} else {
	    sprintf(cdtime, "%02d", cur_ntracks);
	}
	Text_Draw(cdtime, 6, 0, TRUE);
    } else {
	sprintf(cdtime, "%02d", fast_track);
	Text_Draw(cdtime, 6, 0, FALSE);
	strcpy(cdtime, " ");
	cdtime[0] = 127;
	Text_Draw(cdtime, 5, 0, TRUE);
    }

    /* The counter */

    switch(time_mode) {
    case 0:
	minus();
	disp_time = cur_pos_rel;
	break;
    case 1:
	minus();
	disp_time = cur_tracklen - cur_pos_rel ;
	break;
    case 2:
	minus();
	disp_time = cur_pos_abs;
	break;
    default:
	minus();
	disp_time = cur_cdlen - cur_pos_abs;
	break;
    }

    strcpy(cdtime, "00:00");
    if ((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) {
	cdtime[0] = 0 ;
	cdtime[1] = (disp_time / 60);
	if (cdtime[1] >= 10) {
	    cdtime[0] = (cdtime[1] / 10);
	    cdtime[1] = (cdtime[1] % 10);
	}
	cdtime[3] = ((disp_time % 60) / 10);
	cdtime[4] = (disp_time % 10);
    } else {
	cdtime[0] = 0;
	cdtime[1] = (cur_cdlen / 60);
	if (cdtime[1] >= 10) {
	    cdtime[0] = (cdtime[1] / 10);
	    cdtime[1] = (cdtime[1] % 10);
	}
	cdtime[3] = ((cur_cdlen % 60) / 10);
	cdtime[4] = (cur_cdlen % 10);
    }

    cdtime[0] = cdtime[0] + 48;
    cdtime[1] = cdtime[1] + 48;
    cdtime[3] = cdtime[3] + 48;
    cdtime[4] = cdtime[4] + 48;

    Text_Draw(cdtime, 0, 0, FALSE);

    /* =======================================================================
       The Progress Bar
       ======================================================================= */

    if ( (cur_cdmode != WM_CDM_STOPPED) && (cur_cdmode != WM_CDM_EJECTED) ) {
	if ((time_mode == 2) || (time_mode == 3)) {
	    XCopyArea(Disp, barXPM.pixmap, Win, WinGC,
		      0, 0, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * 46.0), 3, 1, 22);
	    XCopyArea(Disp, barXPM.pixmap, Iconwin, WinGC,
		      0, 0, 0 + (int)((float)cur_pos_abs / (float)cur_cdlen * 46.0), 3, 1, 22);
	} else {
	    XCopyArea(Disp, barXPM.pixmap, Win, WinGC,
		      0, 0, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * 46.0), 3, 1, 22);
	    XCopyArea(Disp, barXPM.pixmap, Iconwin, WinGC,
		      0, 0, 0 + (int)((float)cur_pos_rel / (float)cur_tracklen * 46.0), 3, 1, 22);
	}
    }

} 

/* ------------------------------------------------------------------------
   The CD player main loop
   ------------------------------------------------------------------------ */

void MainLoop() 
{
    unsigned int no_disk = 0;
    long int dodo = RDTIME;
    XEvent Event;

    while(1) {
	if (cur_cdmode == WM_CDM_EJECTED) no_disk = 1;

	slow_down++;
	
	if (slow_down > 10) {

#ifdef WMK
	    if ((cur_cdmode == WM_CDM_EJECTED) && (en_vue)) {
		WMCloseWindow(win);
		en_vue = FALSE;
	    }
#endif

	    if (no_disk == 1) {
		if (autoplay) {
		    dodo = RDTIME2;
		    wm_cd_status();
		}
		if (cur_cdmode != WM_CDM_EJECTED) no_disk = 0;
		if ( (cur_cdmode == WM_CDM_STOPPED) && (autoplay) )  {
		    newtext("AUTOPLAY");
		    volume = read_initial_volume(max_volume);
		    cd_control(PLAY);
		    wm_cd_status();
		    dodo = RDTIME;
		    (void)MaskSet();
		    RedrawWindow(&backXPM);
		}
	    }
	    
	    /* The Loop Mode : */
	    if ( (cur_track == loop_end_track ) && (cur_pos_rel >= loop_2) && (loop_mode) ) {
		cd_control(LOOP);
		RedrawWindow(&backXPM);
	    }
	    
	    /* The Intro Scan Mode : */
	    if ( (cur_pos_rel > cue_time) && (intro_mode) ) {
		cd_control(INTRONEXT);
		RedrawWindow(&backXPM);
	    }
	}

	if ((slow_down == 1) || (slow_down == 6)) {
	    if ((show_db) && (cur_cdmode == WM_CDM_PLAYING)) show_db_f();
	}

	/* Check events */
	
	while (XPending(Disp))
	    {
		
		XNextEvent(Disp, &Event);
		
#ifdef WMK		
		if (!WMHandleEvent(&Event)) {
#endif
		switch(Event.type) {
		    
		    /* ---------------------- Redraw Window --------------------- */
		    
		case Expose:
		    if(Event.xexpose.count == 0) {
			lasttime=01;
			redraw = TRUE;
			RedrawWindow(&backXPM);
		    }
		    break;
		    
		    /* ----------------------- Mouse Click ---------------------- */
		    
		case ButtonPress:
		    
		    wm_cd_status();
		    cdplayer_mouse_events(Event);
		    break;
		    
		    /* ------------------------ Destroy Window ------------------- */
	        case ClientMessage:
    		  if ((Event.xclient.format != 32) ||
		      (Event.xclient.data.l[0] != _XA_WM_DELETE_WINDOW))
		      break;
		case DestroyNotify:
		    XFreeGC(Disp, WinGC);
		    XDestroyWindow(Disp, Iconwin);
		    XDestroyWindow(Disp, Win);
		    XCloseDisplay(Disp);
		    exit(0);
		    break;
		}

#ifdef WMK		
		}
#endif
		XFlush(Disp);
	    } /* check event */
	
	usleep(dodo);
	
	/* ----------------- now we have to redraw the screen: ---------------- */
	
	if ((slow_down > 10) || (has_clicked)) {
	    RedrawWindow(&backXPM);
	    slow_down = 0;
	    has_clicked = FALSE;
	}
    }
} 

/* ------------------------------------------------------------------------
   dumb functions: do nothing, but they need to be present if we don't
   wanna change anything in the WorkMan code...
   ------------------------------------------------------------------------ */

void disable_save() { }
int get_playnew() { return autoplay; }
void set_abtimer(int a, int b) { }
void about_set_drivetype(char *vendor, char *model, char *rev) 
{ 
}

/* ------------------------------------------------------------------------
   So... let's go!
   ------------------------------------------------------------------------ */

int main(int argc, char *argv[]) 
{
    extern char *rcfile, *dbfiles;  
    
    /* CD device: */

#ifndef NO_D_DEVICE
    cd_device = malloc(strlen(DEFAULTDEVICE) + 1);
    strcpy(cd_device, DEFAULTDEVICE);
#endif

    strcpy(led_text, "");
    strcpy(theme, "default");
    
    /* prepares the LED colors variables: */
    
    strcpy(led_color, "X c ");
    strcpy(led_bgcolor, "  c ");

    /* the WorkMan database. It's still not used in ascd, but we need this
       to start the WorkMan code
    */

    rcfile = getenv("WORKMANRC");
    if (rcfile) rcfile = (char *)wm_strdup(rcfile);
    dbfiles = getenv("WORKMANDB");
    if (dbfiles) dbfiles = (char *)wm_strdup(dbfiles);

    split_workmandb();

    /* load .ascdrc file: */
    load_rc_file(FALSE);

    /* load the command line options */
    ParseCmdLine(argc, argv);

    /* if none specified, default colours for LEDs */

    if (strlen(led_color) == 4) strcat(led_color, DEFAULT_COLOR);
    if (strlen(led_bgcolor) == 4) strcat(led_bgcolor, DEFAULT_BGCOLOR);

#ifdef WMK
    WMInitializeApplication("AScd", &argc, argv);
#endif
    CreateWindow(argc, argv);

    wm_cd_status();
    
    if (cur_cdmode != WM_CDM_EJECTED) {
	volume = read_initial_volume(max_volume);
	/*cd_volume(volume, 10, max_volume);*/
    }

    if ((autoplay) && (cur_cdmode == WM_CDM_STOPPED)) {
	if (cur_track < 1) {
	    cur_track = 1;
	    wm_cd_status();
	}
	cd_control(PLAY);
	wm_cd_status();
	RedrawWindow(&backXPM);
    }

    (void)MaskSet();
    (void)MainLoop();
    return 0;
}
