765 lines
22 KiB
C
765 lines
22 KiB
C
/* ===========================================================================
|
|
* 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 <math.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 "config.h"
|
|
#include "ascd.h"
|
|
#include "faktory_prot.h"
|
|
#include <workman/workman.h>
|
|
|
|
XpmIcon alphaXPM;
|
|
XpmIcon ralphaXPM;
|
|
XpmIcon backXPM;
|
|
XpmIcon iconXPM;
|
|
|
|
/* External functions */
|
|
|
|
extern time();
|
|
extern open();
|
|
extern cd_control(int);
|
|
extern cd_control_version();
|
|
|
|
/* the various switches: */
|
|
|
|
int debug = FALSE; /* verbose mode */
|
|
unsigned int autoplay = 0; /* if set, play a disk when it is inserted -> see -a c.l. option */
|
|
unsigned int autoprobe = TRUE; /* probe the drive, but do not play (autoplay) */
|
|
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 show_icon_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;
|
|
char xv[128];
|
|
int withdrawn=FALSE;
|
|
GC WinGC;
|
|
int CarrierOn = FALSE;
|
|
int screen;
|
|
|
|
/* everything dealing with the hardware volume: */
|
|
|
|
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; /* ? */
|
|
|
|
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 selectors_timeout = 0;
|
|
int redraw = TRUE;
|
|
int has_clicked = FALSE;
|
|
int info_modified = 0;
|
|
int big_spaces = 0;
|
|
int slow_down = 0;
|
|
|
|
/* ====================================================================
|
|
Faktory: theme subsystem
|
|
==================================================================== */
|
|
|
|
char theme[FAK_CMAX];
|
|
char selected_theme[FAK_CMAX];
|
|
unsigned int theme_select = 0;
|
|
unsigned int theme_select_nbr = 0;
|
|
|
|
unsigned int panel = 1; /* current panel */
|
|
unsigned int panels = 0; /* how many panels? */
|
|
unsigned int but_max = 0; /* how many buttons? */
|
|
unsigned int but_msg = 0; /* which one is the message zone? */
|
|
unsigned int but_counter = 0; /* which one is the counter? */
|
|
unsigned int but_tracknbr = 0; /* which one is the track number? */
|
|
unsigned int but_db = 0; /* which one is the database zone? */
|
|
unsigned int icon_msg = 0;
|
|
unsigned int icon_counter = 0;
|
|
unsigned int icon_tracknbr = 0;
|
|
unsigned int but_current = 0; /* last selected button */
|
|
|
|
unsigned int panel_stop = 0; /* autoswitch to this panel on stop/eject */
|
|
unsigned int panel_play = 0; /* autoswitch to this panel on play */
|
|
|
|
char th_name[FAK_CMAX];
|
|
char th_author[FAK_CMAX];
|
|
char th_release[FAK_CMAX];
|
|
char th_email[FAK_CMAX];
|
|
char th_url[FAK_CMAX];
|
|
char th_comment[FAK_CMAX];
|
|
char th_alpha1[FAK_CMAX];
|
|
char th_alpha2[FAK_CMAX];
|
|
char th_background[FAK_CMAX];
|
|
char th_icon_window[FAK_CMAX];
|
|
|
|
int th_no_minus = FALSE;
|
|
int th_no_icon_window = FALSE;
|
|
|
|
struct fak_button thdata[FAK_BMAX];
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* ====================================================================
|
|
The optional modules globals:
|
|
==================================================================== */
|
|
|
|
#ifdef WMK
|
|
#include "wings_global.c"
|
|
#endif
|
|
|
|
#ifdef MIXER
|
|
#include "mixer_global.c"
|
|
#endif
|
|
|
|
/*****************************************************************************/
|
|
|
|
void mouse_events(XEvent Event)
|
|
{
|
|
int i;
|
|
int j;
|
|
int do_it = TRUE;
|
|
|
|
for (i=1 ; i <= but_max ; i++) {
|
|
if ((thdata[i].panel == panel) || (thdata[i].panel == 0)) {
|
|
if (strlen(thdata[i].xpm_file) > 0) {
|
|
if ((Event.xbutton.y >= thdata[i].y) && (Event.xbutton.y <= thdata[i].y + thdata[i].xpm.attributes.height)) {
|
|
if ((Event.xbutton.x >= thdata[i].x) && (Event.xbutton.x <= thdata[i].x + thdata[i].xpm.attributes.width)) {
|
|
if (th_no_icon_window) {
|
|
/* Special Icon Mode: we must check in which window the user clicked */
|
|
do_it = TRUE;
|
|
if (Event.xbutton.window == Iconwin) {
|
|
if (!thdata[i].icon) do_it = FALSE;
|
|
} else {
|
|
if (thdata[i].icon) do_it = FALSE;
|
|
}
|
|
}
|
|
/* no commands defined? We skip this one! */
|
|
if (((thdata[i].left != 0) || (thdata[i].mid != 0) || (thdata[i].right != 0)) && (do_it)) {
|
|
if (debug) fprintf(stderr, "** User selected button %d with mouse button %d\n", i, Event.xbutton.button);
|
|
j = 0;
|
|
switch(Event.xbutton.button) {
|
|
case 1: j = thdata[i].left; break;
|
|
case 2: j = thdata[i].mid; break;
|
|
default: j = thdata[i].right; break;
|
|
}
|
|
but_current = i;
|
|
if (debug) fprintf(stderr, "-> command = %d\n", j);
|
|
if ((j >= 1) && (j <= 49)) fak_event_handle(j, Event);
|
|
else if ((j >= 50) && (j <= 99)) cd_event_handle(j, Event);
|
|
#ifdef MIXER
|
|
else if ((j >= 100) && (j <= 199)) mixer_event_handle(j, Event);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
GUI control
|
|
------------------------------------------------------------------------ */
|
|
|
|
Pixel get_color(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 create_window(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);
|
|
ScreenHeight = DisplayHeight(Disp,screen);
|
|
ScreenWidth = DisplayWidth(Disp,screen);
|
|
|
|
/* it's time to load the visual theme! */
|
|
|
|
if (fak_load_theme(theme, FALSE)) {
|
|
if (debug) fprintf(stderr, "-> back from fak_load_theme!\n");
|
|
} else {
|
|
fprintf(stderr, "ascd: fatal error\n\n");
|
|
fprintf(stderr, "The '%s' theme definition file can't be read.\n\n", theme);
|
|
exit(1);
|
|
}
|
|
|
|
SizeHints.flags= USSize|USPosition;
|
|
SizeHints.x = 0;
|
|
SizeHints.y = 0;
|
|
back_pix = get_color("black");
|
|
fore_pix = get_color("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);
|
|
|
|
if (!th_no_icon_window) {
|
|
Iconwin = XCreateSimpleWindow(Disp,Win,
|
|
SizeHints.x,SizeHints.y,
|
|
SizeHints.width,
|
|
SizeHints.height,
|
|
borderwidth,
|
|
fore_pix,
|
|
back_pix);
|
|
} else {
|
|
Iconwin = XCreateSimpleWindow(Disp, Win,
|
|
SizeHints.x,
|
|
SizeHints.y,
|
|
iconXPM.attributes.width,
|
|
iconXPM.attributes.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);
|
|
XSetCommand(Disp, Win, argv, argc);
|
|
|
|
XMapWindow(Disp, Win);
|
|
|
|
|
|
if (debug) fprintf(stderr, "-> calling fak_maskset() from create_window()...\n");
|
|
fak_maskset();
|
|
if (debug) fprintf(stderr, "-> calling fak_redraw() from create_window()...\n");
|
|
fak_redraw();
|
|
if (debug) fprintf(stderr, "-> Leaving create_window()\n");
|
|
}
|
|
|
|
void newtext(char *txt) {
|
|
strcpy(led_text, txt);
|
|
text_start = 0;
|
|
}
|
|
|
|
void show_icon_db_f() {
|
|
/* scroll the song title */
|
|
char txt[256];
|
|
char txt2[256];
|
|
char dsp[9];
|
|
int track;
|
|
int red;
|
|
|
|
if (!th_no_icon_window) return;
|
|
if (icon_msg == 0) return;
|
|
|
|
if (theme_select == 0) {
|
|
|
|
/* there is a message to display, we'll wait for the message to
|
|
time-out before handling the track title... */
|
|
|
|
if (strlen(led_text) > 0) return;
|
|
|
|
/* if in fast track selector, we show the title of the track to reach */
|
|
|
|
if (fast_track > 0) {
|
|
track = fast_track - 1;
|
|
red = FALSE;
|
|
} else {
|
|
track = cur_track - 1;
|
|
red = TRUE;
|
|
}
|
|
|
|
if (track > cur_ntracks - 1) return;
|
|
|
|
if (cd->trk[track].songname != NULL) {
|
|
if (show_artist) {
|
|
if (cd->artist != NULL) {
|
|
sprintf(txt2, "%s: %s", cd->artist, cd->trk[track].songname);
|
|
} else {
|
|
strcpy(txt2, cd->trk[track].songname);
|
|
}
|
|
} else {
|
|
strcpy(txt2, cd->trk[track].songname);
|
|
}
|
|
fak_icon_text("", MSG_PANEL, 0, red);
|
|
if (strlen(txt2) > thdata[icon_msg].w) {
|
|
strcpy(txt, " ");
|
|
strcat(txt, txt2);
|
|
if (show_icon_db_pos > strlen(txt)) show_icon_db_pos = 0;
|
|
tes_sncpy(dsp, txt + show_icon_db_pos, thdata[icon_msg].w);
|
|
fak_icon_text(dsp, MSG_PANEL, 0, red);
|
|
show_icon_db_pos ++;
|
|
} else {
|
|
fak_icon_text(txt2, MSG_PANEL, 0, red);
|
|
}
|
|
} else {
|
|
strcpy(txt, "");
|
|
}
|
|
}
|
|
}
|
|
|
|
void show_db_f() {
|
|
/* scroll the song title */
|
|
char txt[256];
|
|
char txt2[256];
|
|
char dsp[9];
|
|
int track;
|
|
int red;
|
|
int where;
|
|
int longueur;
|
|
int i;
|
|
|
|
if (but_db > 0) {
|
|
where = DB_PANEL;
|
|
longueur = thdata[but_db].w;
|
|
} else {
|
|
where = MSG_PANEL;
|
|
longueur = thdata[but_msg].w;
|
|
}
|
|
|
|
if ((theme_select == 0) || (where == DB_PANEL)) {
|
|
|
|
/*
|
|
there is a message to display, we'll wait for the message
|
|
to time-out before handling the track title... (but only if
|
|
there is no separate areas)
|
|
*/
|
|
|
|
if ((strlen(led_text) > 0) && (where == MSG_PANEL)) return;
|
|
|
|
/* if in fast track selector, we show the title of the track to reach */
|
|
|
|
if (fast_track > 0) {
|
|
track = fast_track - 1;
|
|
red = FALSE;
|
|
} else {
|
|
track = cur_track - 1;
|
|
red = TRUE;
|
|
}
|
|
|
|
/* warning: avoid weird datas: */
|
|
|
|
if (track > cur_ntracks - 1) return;
|
|
if (track < 0) return;
|
|
|
|
if (debug > 1) fprintf(stderr, "** Show DB TRACK = %d\n", track);
|
|
|
|
if (cd->trk[track].songname != NULL) {
|
|
if (show_artist) {
|
|
if (cd->artist != NULL) {
|
|
sprintf(txt2, "%s: %s", cd->artist, cd->trk[track].songname);
|
|
} else {
|
|
strcpy(txt2, cd->trk[track].songname);
|
|
}
|
|
} else {
|
|
strcpy(txt2, cd->trk[track].songname);
|
|
}
|
|
fak_text("", where, 0, red);
|
|
if (strlen(txt2) > longueur) {
|
|
strcpy(txt, "");
|
|
for (i = 0 ; i < longueur ; i++) strcat(txt, " ");
|
|
strcat(txt, txt2);
|
|
if (show_db_pos > strlen(txt)) show_db_pos = 0;
|
|
tes_sncpy(dsp, txt + show_db_pos, longueur);
|
|
fak_text(dsp, DB_PANEL, 0, red);
|
|
show_db_pos ++;
|
|
} else {
|
|
fak_text(txt2, DB_PANEL, 0, red);
|
|
}
|
|
} else {
|
|
strcpy(txt, "");
|
|
}
|
|
}
|
|
|
|
show_icon_db_f();
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
Loooooooooooooooooping.........
|
|
------------------------------------------------------------------------ */
|
|
|
|
void main_loop()
|
|
{
|
|
unsigned int no_disk = 0;
|
|
long int dodo = RDTIME;
|
|
XEvent Event;
|
|
|
|
while(1) {
|
|
|
|
if (debug > 1) fprintf(stderr, "** [Main Loop] mode = %02d track = %02d \n", cur_cdmode, cur_track);
|
|
|
|
if (cur_cdmode == WM_CDM_EJECTED) no_disk = 1;
|
|
|
|
slow_down++;
|
|
|
|
if (slow_down > 10) {
|
|
|
|
#ifdef WMK
|
|
/* in 0.13, we no longer close WINGs windows if ejected
|
|
if ((cur_cdmode == WM_CDM_EJECTED) && (en_vue)) {
|
|
WMCloseWindow(win);
|
|
en_vue = FALSE;
|
|
}
|
|
*/
|
|
#endif
|
|
|
|
if (no_disk == 1) {
|
|
cur_ntracks = 0; /* 0.13pr6: what a hack!!!! */
|
|
|
|
if (autoplay || autoprobe) {
|
|
dodo = RDTIME2;
|
|
wm_cd_status();
|
|
}
|
|
|
|
if (cur_cdmode != WM_CDM_EJECTED) no_disk = 0;
|
|
if ( (cur_cdmode == WM_CDM_STOPPED) && (autoplay) ) {
|
|
newtext("Autoplay");
|
|
if (cd->volume > 0) {
|
|
volume=cd->volume;
|
|
cd_volume(volume, 10, max_volume);
|
|
}
|
|
cd_control(PLAY);
|
|
wm_cd_status();
|
|
dodo = RDTIME;
|
|
fak_maskset();
|
|
fak_redraw();
|
|
}
|
|
}
|
|
|
|
/* The Loop Mode : */
|
|
if ( (cur_track == loop_end_track ) && (cur_pos_rel >= loop_2) && (loop_mode) ) {
|
|
cd_control(LOOP);
|
|
fak_redraw();
|
|
}
|
|
|
|
/* The Intro Scan Mode : */
|
|
if ( (cur_pos_rel > cue_time) && (intro_mode) ) {
|
|
cd_control(INTRONEXT);
|
|
fak_redraw();
|
|
}
|
|
}
|
|
|
|
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;
|
|
fak_redraw();
|
|
} else {
|
|
if (debug > 1) fprintf(stderr, "** XEVent - expose, not handled, count = %d\n", Event.xexpose.count);
|
|
}
|
|
break;
|
|
|
|
/* ----------------------- Mouse Click ---------------------- */
|
|
|
|
case ButtonPress:
|
|
|
|
wm_cd_status();
|
|
mouse_events(Event);
|
|
break;
|
|
|
|
/* ------------------------ Destroy Window ------------------- */
|
|
|
|
case DestroyNotify:
|
|
XFreeGC(Disp, WinGC);
|
|
XDestroyWindow(Disp, Win);
|
|
XDestroyWindow(Disp, Iconwin);
|
|
XCloseDisplay(Disp);
|
|
exit(0);
|
|
break;
|
|
default:
|
|
if (debug > 1) fprintf(stderr, "** XEvent - unknown event type = %d\n", Event.type);
|
|
break;
|
|
}
|
|
|
|
#ifdef WMK
|
|
}
|
|
#endif
|
|
XFlush(Disp);
|
|
} /* check event */
|
|
|
|
usleep(dodo);
|
|
|
|
/* ----------------- now we have to redraw the screen: ---------------- */
|
|
|
|
if ((slow_down > 10) || (has_clicked)) {
|
|
fak_redraw();
|
|
slow_down = 0;
|
|
has_clicked = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------
|
|
So... let's go!
|
|
------------------------------------------------------------------------ */
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
extern char *rcfile, *dbfiles;
|
|
|
|
/*printf("AScd %s\n", VERSION);*/
|
|
|
|
/* CD device: */
|
|
|
|
#ifndef NO_D_DEVICE
|
|
cd_device = malloc(strlen(DEFAULTDEVICE) + 1);
|
|
strcpy(cd_device, DEFAULTDEVICE);
|
|
#endif
|
|
|
|
strcpy(led_text, "");
|
|
strcpy(theme, "default");
|
|
strcpy(xv, "xv");
|
|
|
|
/* 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_rc_file(FALSE);
|
|
command_line_parse(argc, argv);
|
|
|
|
#ifdef WMK
|
|
if (debug) fprintf(stderr, "** [WINGs] init app...\n");
|
|
WMInitializeApplication("AScd", &argc, argv);
|
|
#endif
|
|
|
|
#ifdef MIXER
|
|
mixer_ok = 1;
|
|
if (debug) fprintf(stderr, "** [mixer] checking mixer device...\n");
|
|
if (! check_mixer()) {
|
|
fprintf(stderr, "ascd: can't initialize mixer device. Mixing support disabled.\n");
|
|
mixer_ok = 0;
|
|
}
|
|
#endif
|
|
|
|
if (debug) fprintf(stderr, "** creating main window...\n");
|
|
create_window(argc, argv);
|
|
if (debug) fprintf(stderr, "** checking CD status...\n");
|
|
wm_cd_status();
|
|
|
|
if (cur_cdmode != WM_CDM_EJECTED) {
|
|
if (debug) fprintf(stderr, "** reading CD initial volume...\n");
|
|
volume = wm_cd_read_initial_volume(max_volume);
|
|
} else {
|
|
if (debug) fprintf(stderr, "** CD is ejected: volume ignored.\n");
|
|
}
|
|
|
|
if (debug) fprintf(stderr, "** checking autoplay...\n");
|
|
if ((autoplay) && (cur_cdmode == WM_CDM_STOPPED)) {
|
|
if (cur_track < 1) {
|
|
cur_track = 1;
|
|
wm_cd_status();
|
|
}
|
|
if (debug) fprintf(stderr, "-> autoplay: play command\n");
|
|
cd_control(PLAY);
|
|
if (debug) fprintf(stderr, "-> autoplay: checking status\n");
|
|
wm_cd_status();
|
|
if (debug) fprintf(stderr, "-> autoplay: redrawing\n");
|
|
fak_redraw();
|
|
if (debug) fprintf(stderr, "-> autoplay: done\n");
|
|
} else {
|
|
if (debug) fprintf(stderr, "-> no autoplay\n");
|
|
}
|
|
|
|
if (debug) fprintf(stderr, "** checking current CD volume in database\n");
|
|
|
|
if (((cur_cdmode == WM_CDM_PLAYING) || (cur_cdmode == WM_CDM_PAUSED)) && (cd->volume > 0)) {
|
|
volume=cd->volume;
|
|
cd_volume(volume, 10, max_volume);
|
|
}
|
|
|
|
fak_maskset();
|
|
|
|
if (debug) fprintf(stderr, "** Init passed. Entering main loop.\n");
|
|
redraw = TRUE;
|
|
main_loop();
|
|
return 0;
|
|
}
|