[Pkg-wmaker-commits] [wmrack] 01/97: Original Oliver Graf version as checked into CVS by Xtifr

Doug Torrance dtorrance-guest at moszumanska.debian.org
Sat Aug 22 02:41:57 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository wmrack.

commit fc290ff68b669807cb750e0d899647824f71ade1
Author: Chris Waters <xtifr.w at gmail.com>
Date:   Thu Mar 8 16:36:05 2012 -0800

    Original Oliver Graf version as checked into CVS by Xtifr
---
 .cvsignore             |   11 +
 CHANGES                |   49 ++
 LICENSE                |  339 +++++++++++
 Makefile.in            |   77 +++
 README                 |   72 +++
 README.ctrl            |   10 +
 TODO                   |   12 +
 WARRANTY               |   21 +
 XPM/.cvsignore         |    3 +
 XPM/Makefile.in        |   21 +
 XPM/README             |   27 +
 XPM/cd-mask.xpm        |   57 ++
 XPM/clean.style        |  374 ++++++++++++
 XPM/grey.style         |  388 +++++++++++++
 XPM/grey/alphaled.xpm  |   18 +
 XPM/grey/cdnodisc.xpm  |   59 ++
 XPM/grey/cdpaused.xpm  |   59 ++
 XPM/grey/cdplaying.xpm |   59 ++
 XPM/grey/cdstopped.xpm |   59 ++
 XPM/grey/led.xpm       |   18 +
 XPM/grey/mixer.xpm     |   59 ++
 XPM/grey/mixled.xpm    |   52 ++
 XPM/led.xpm            |   18 +
 XPM/mixer-mask.xpm     |   54 ++
 cdctrl.c               |  188 ++++++
 cdrom.c                | 1047 +++++++++++++++++++++++++++++++++
 cdrom.h                |  147 +++++
 config.h.in            |    7 +
 configure.in           |  118 ++++
 install-sh             |  250 ++++++++
 library.c              |  163 ++++++
 library.h              |   33 ++
 mixctrl.c              |  141 +++++
 mixer.c                |  511 ++++++++++++++++
 mixer.h                |   59 ++
 wmrack.c               | 1503 ++++++++++++++++++++++++++++++++++++++++++++++++
 wmrack.man             |  235 ++++++++
 xpmicon.c              |  338 +++++++++++
 xpmicon.h              |   46 ++
 39 files changed, 6702 insertions(+)

diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..cccad1d
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,11 @@
+wmrack
+cdctrl
+mixctrl
+Makefile
+config.log
+config.cache
+config.status
+config.h
+confdefs.*
+configure
+.depend
diff --git a/CHANGES b/CHANGES
new file mode 100644
index 0000000..c19f80c
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,49 @@
+1.0b4 -> 1.0b5
+--------------
+- use of stafs in cd_doEject regargdless of libc version
+
+1.0b3 -> 1.0b4
+--------------
+- fixed the ustat problem with redhat 5
+- fixed the -X11 stuff in configure.in
+- changed a ifdef 0 in wmrack.c
+- fixed a segfault in lib_open/loadMixerRC
+
+1.0b2 -> 1.0b3
+--------------
+- tested repeat behaviour of play-lists -> all ok (at least for me)
+- fixed segfaults when no mixer file is present
+- my new Toshiba cdrom returnes AUDIO_INVALID on new disc
+  added code to handle this behaviour to cdrom.c
+- some stop changes (by dledford at dialnet.net)
+- mainLoop uwait upgraded to 5000ms to reduce polling (this is not the
+  right solution -- I want a sort of select....)
+- cd_getStatus will now only update after at least 5000ms passed
+  to prevent constant cdrom polling
+
+1.0b1 -> 1.0b2
+--------------
+- play sequence corrected after some tests
+- corrected GNUstep path autodetection and library creation
+- enabled GNUstep/Library path searchs for mixer and styles
+- fixed some play-opt leaks
+- added automatic play optimization (longest-sequence play)
+- another starttrack typo
+- missing led color symbols added
+- fixed starttrack set to curtrack when STOP is pressed
+- fixed missing mode & cur_track in cd_reopen
+- fixed track-display bug at end of disc
+- cd_doPlay only plays ONE track getStatus switches to next
+- changed CDPlayInfo start/end handling to just current
+
+0.9 -> 1.0b1
+------------
+- added a DATA notice for data-only discs
+- finished playlist stuff (automatic play of list, programing)
+- added exit function (Ctrl-Button-3 click on the mode changer)
+- added randomize to playlist
+- added playlist support
+- changed load/eject behaviour: button-3 click will always open the tray
+- added mixer library file
+- added mixer support (linux)
+- changed configuration from Imake to autoconf
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..d60cc11
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,77 @@
+
+# WMRack Makefile.in for autoconf
+#
+# Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+
+CC		= @CC@
+CFLAGS		= @CFLAGS@
+LIBS		= @LIBS@
+INSTALL		= @INSTALL@
+INSTALL_DATA	= @INSTALL_DATA@
+RM		= rm -f
+
+SOURCES		= xpmicon.c library.c cdrom.c mixer.c wmrack.c \
+		  cdctrl.c mixctrl.c
+OBJECTS		= xpmicon.o library.o cdrom.o mixer.o wmrack.o
+CD_CTRL_OBJS	= cdrom.o cdctrl.o
+MIXER_CTRL_OBJS	= mixer.o mixctrl.o
+
+TARGETS		= wmrack @CTRL@
+
+MANPAGES	= wmrack.man
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+BINDIR = @bindir@
+MANDIR = @mandir@
+LIBDIR = @libdir@/WMRack
+
+MAN1DIR = $(MANDIR)/man1
+
+all: depend standart.style $(TARGETS)
+
+standart.style:
+	(cd XPM; make standart.style)
+
+wmrack: $(OBJECTS)
+	$(CC) $(OBJECTS) -o $@ $(LIBS)
+
+cdctrl: $(CD_CTRL_OBJS)
+	$(CC) $(CD_CTRL_OBJS) -o $@ $(LIBS)
+
+mixctrl: $(MIXER_CTRL_OBJS)
+	$(CC) $(MIXER_CTRL_OBJS) -o $@ $(LIBS)
+
+install: $(TARGETS) install-bin install-man install-lib
+
+install-bin:
+	mkdir -p $(BINDIR)
+	for prog in $(TARGETS); do \
+		$(INSTALL) $${prog} $(BINDIR) ; \
+	done
+
+install-man:
+	mkdir -p $(MAN1DIR)
+	for man in $(MANPAGES); do \
+		$(INSTALL_DATA) $${man} $(MAN1DIR)/`basename $${man} .man`.1x ; \
+	done
+
+install-lib:
+	(cd XPM; make install)
+
+clean:
+	$(RM) *.o core
+
+binclean: clean
+	$(RM) wmrack cdctrl mixctrl
+
+distclean: binclean
+	$(RM) Makefile XPM/Makefile config.h .depend \
+		config.status config.log config.cache XPM/standart.style
+
+depend: standart.style .depend
+
+.depend:
+	gcc -M $(SOURCES) >> Makefile
+	echo "Done" > .depend
+
diff --git a/README b/README
new file mode 100644
index 0000000..aaf8d76
--- /dev/null
+++ b/README
@@ -0,0 +1,72 @@
+				  wmrack 1.0
+				  ==========
+
+		     The WindowMaker Sound Control Panel
+				      by
+			  Oliver Graf <ograf at fga.de>
+
+
+DESCRIPTION:
+------------
+WMRack is a Dock/Wharf applet which gives you complete control over
+your CDROM, the Mixer and hopefully in the future to other sound related
+stuff (feel free to send suggestions).
+
+It's main advantage is the high configurability, which will let you specify
+different looks for the window at startup.
+
+CD-Functions:
+ * Display Track and Time (remaining/to-go, track/total)
+ * Play, Pause, Stop, Eject, Load, Track +/-, Fast Fore-/Back-ward
+ * Display of total tracks and length when a new CD is loaded
+ * random play, skip data tracks, play lists
+
+Mixer Functions:
+ * startup options for initial volume
+ * control all your mixer devices
+ * control balance
+ * change record sources
+
+INSTALLATION:
+-------------
+First you need to configure the whole package with:
+
+./configure (see './configure --help' for options)
+
+Now you can make a link in XPM to the style you want compiled into
+WMRack using 'ln -s A.style standart.style' or do nothing for the
+default.
+
+After this a 'make' will compile WMRack and a 'make install' will
+install it.
+
+
+USAGE:
+------
+Look into the manpage for supported options and functions.
+
+Easily swallowed by dock (use the --withdrawn option).
+
+Putting wmrack into AfterStep Wharf:
+*Wharf WMRack nil Swallow "wmrack" wmrack &
+
+
+BUGS & CONTACT:
+---------------
+Please send bug reports or suggestions to ograf at fga.de. Include
+a description how the bug can be reproduced plus the vendor and
+model of your cdrom and/or soundcard. Also include a debug log
+(configure with --with-debug -- this is the default for beta
+versions) created with your bug-reproduction-recipe.
+
+Send new styles or style questions to ograf at fga.de
+
+
+HISTORY:
+--------
+Basically this thing borrowed much from WorkBone, ascd and asmixer. But in
+the progress of work, almost any part that was stolen, has been rewritten,
+restructured, and overworked.
+
+-----
+$Id: README,v 1.1.1.1 2001/02/12 22:25:31 xtifr Exp $
diff --git a/README.ctrl b/README.ctrl
new file mode 100644
index 0000000..2e5bef4
--- /dev/null
+++ b/README.ctrl
@@ -0,0 +1,10 @@
+cdctrl and mixctrl are test programs for the cdrom.* and mixer.*
+stuff.
+
+To compile it you must give configure the --with-ctrl switch.
+
+Without the DEBUG and gdb stuff it also gives a useful command-line
+interface to your cdrom and mixer.
+
+-----
+$Id: README.ctrl,v 1.1.1.1 2001/02/12 22:25:31 xtifr Exp $
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..ce162d2
--- /dev/null
+++ b/TODO
@@ -0,0 +1,12 @@
+
+ - WindowMaker Application Menu integration (if I get the test app to
+   run ;-) )
+ - integration of X-Resources for configuration purposes (that will take some
+   time -- I will first need to buy some X-Programming-Manual ;-) )
+ - better configurability of the display (via XPM-extensions -- until now you
+   can only change the look of the thing, but the positions and sizes must
+   stay fixed).
+ - cddb lookups + scroll text display
+ - cd-changer (I can't test this because I don't have such a thing)
+ - sound-file-player
+ - spectrum analyzer
diff --git a/WARRANTY b/WARRANTY
new file mode 100644
index 0000000..741fbcb
--- /dev/null
+++ b/WARRANTY
@@ -0,0 +1,21 @@
+                            NO WARRANTY
+
+      BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+      IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
diff --git a/XPM/.cvsignore b/XPM/.cvsignore
new file mode 100644
index 0000000..05b6a52
--- /dev/null
+++ b/XPM/.cvsignore
@@ -0,0 +1,3 @@
+tmp
+standart.style
+Makefile
diff --git a/XPM/Makefile.in b/XPM/Makefile.in
new file mode 100644
index 0000000..41de47a
--- /dev/null
+++ b/XPM/Makefile.in
@@ -0,0 +1,21 @@
+
+INSTALL		= @INSTALL@
+INSTALL_DATA	= @INSTALL_DATA@
+LN		= @LN_S@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+BINDIR = @bindir@
+MANDIR = @mandir@
+LIBDIR = @libdir@/WMRack
+
+standart.style: grey.style
+	$(LN) grey.style standart.style
+
+install:
+	mkdir -p $(LIBDIR)
+	for style in *.style; do \
+	  if test "$${style}" != "standart.style"; then \
+	     $(INSTALL_DATA) $${style} $(LIBDIR); \
+	  fi \
+	done
diff --git a/XPM/README b/XPM/README
new file mode 100644
index 0000000..45143c2
--- /dev/null
+++ b/XPM/README
@@ -0,0 +1,27 @@
+*.style files can be loaded using the -style option of wmrack
+
+You can define your standart style by linking standart.style to
+the style of your choice before compilation using:
+ln -sf <yourchoice>.style standart.style
+
+cd_mask.xpm    is the standart mask of on of the window faces.
+mixer_mask.xpm is the standart mask of the mixer window face.
+led.xpm        are the digits and signs for the cdplayer.
+mixled.xpm     these are the scales and source buttons of the mixer.
+alphaled.xpm   this is a Dot-LED style characterset (uppercase + digits).
+
+you need for pixmaps (the names must be the name of the XPM):
+  cdnodisc  (do not include any track +/- buttons)
+  cdpaused
+  cdplaying
+  cdstopped
+  mixer
+  mixled    (this must be changed because of the recsrc button)
+plus (until now not really needed, the compiletime default will do):
+  led
+  alphaled
+cat all eight into one file using for example:
+  'cat no.xpm pl.xpm pau.xpm sto.xpm mix.xpm led.xpm mixled.xpm alpha.xpm >a.style'
+
+If you want to submit new styles to the WMRack distribution, send
+them to Oliver Graf <ograf at fga.de>.
diff --git a/XPM/cd-mask.xpm b/XPM/cd-mask.xpm
new file mode 100644
index 0000000..163d703
--- /dev/null
+++ b/XPM/cd-mask.xpm
@@ -0,0 +1,57 @@
+/* XPM */
+static char *sample_mask[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 3 1",
+"  c Black",
+". c Gray50",
+"X c None",
+/* pixels */
+"................................................",
+"................................................",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"..                                            ..",
+"................................................",
+"................................................",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+".............XXXX..............XXXX.............",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+"XXXXXXXXXXXXXX....................XXXXXXXXXXXXXX",
+".............X....................X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X..                ..X.............",
+".............X....................X.............",
+"XXXXXXXXXXXXXX....................XXXXXXXXXXXXXX"
+};
diff --git a/XPM/clean.style b/XPM/clean.style
new file mode 100644
index 0000000..6519d73
--- /dev/null
+++ b/XPM/clean.style
@@ -0,0 +1,374 @@
+/*
+ * 'clean' style created by <ulho at uni-paderborn.de>
+ *
+ * named after the schumacher-clean font
+ *
+ */
+/* XPM */
+static char * alphaled[] = {
+"296 11 2 1",
+" 	s led_color_back	c black",
+".	s led_color_high	c green",
+"                                                                                                                                                                                                                  ....      .     ....    ....      ..   ......    ...   ......   ....    ....          ",
+"    .    ......    ....  .....   ....... .......   ....  .     .  .....     ...  .    .  .       .     . .     .   ...   ......    ...   ......   .....  ....... .     . .     . .     . .     . .     . ....... .    .    ..    .    .  .    .     ..   .        .      .    .  .    .  .    .         ",
+"    .    .     .  .    . .    .  .       .        .    . .     .    .         .  .   .   .       .     . .     .  .   .  .     .  .   .  .     . .     .    .    .     . .     . .     . .     . .     .       . .    .     .         .       .    . .   .       .            .  .    .  .    .         ",
+"   ...   .     . .       .     . .       .       .       .     .    .         .  .  .    .       ..   .. ..    . .     . .     . .     . .     . .          .    .     . .     . .  .  .  .   .   .   .       .  .    .     .         .       .    . .   .       .           .   .    .  .    .         ",
+"   . .   .     . .       .     . .       .       .       .     .    .         .  . .     .       ..   .. . .   . .     . .     . .     . .     . .          .    .     .  .   .  .  .  .   . .     . .       .   .    .     .        .     ...    .  .   .....   .....       .    ....   .    .         ",
+"   . .   ......  .       .     . .....   .....   .       .......    .         .  ..      .       . . . . .  .  . .     . ......  .     . ......   .....     .    .     .  .   .  . . . .    .       .       .    .    .     .       .         .   .  .        .  .    .     .    .    .   .....         ",
+"  .....  .     . .       .     . .       .       .   ... .     .    .         .  . .     .       . . . . .   . . .     . .       .     . .  .          .    .    .     .   . .   . . . .   . .      .      .     .    .     .      .          .  .   .        .  .    .     .    .    .       .         ",
+"  .   .  .     . .       .     . .       .       .     . .     .    .    .    .  .  .    .       .  .  . .    .. .     . .       .     . .   .         .    .    .     .   . .   ..   ..  .   .     .     .      .    .     .     .           .  ......       .  .    .    .     .    .       .         ",
+"  .   .  .     .  .    . .    .  .       .        .    . .     .    .    .    .  .   .   .       .  .  . .     .  .   .  .        .   .  .    .  .     .    .    .     .    .    ..   .. .     .    .    .       .    .     .    .       .    .      .   .    .  .    .    .     .    .      .          ",
+" ..   .. ......    ....  .....   ....... .         ..... .     .  .....   ....   .    .  ......  .     . .     .   ...   .         ...   .     .  .....     .     .....     .    .     . .     .    .    .......  ....      .    ......   ....      ...   ....    ....     .      ....    ...           ",
+"                                                                                                                                                                                                                                                                                                        "};
+/* XPM */
+static char * cdnodisc[] = {
+"48 48 6 1",
+" 	c #318C318C318C",
+".	c #631863186318",
+"X	s led_color_back	c black",
+"o	c #CE72CE72CE72",
+"O	c none",
+"+	s led_color_high	c green",
+"                                               .",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+".ooooooooooooooooooooooooooooooooooooooooooooooo",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"oooooooooooo.OOOOooooooooooooo.OOOOoooooooooooo.",
+"oXXXXXXXXXXX OOOOoXXXXXXXXXXXX OOOOoXXXXXXXXXXX ",
+"oXXXXXXXXXXX OOOOoXXXXXX++XXXX OOOOoXXXXX+XXXXX ",
+"oXX+++XXXXXX OOOOoXXXXX+++X+XX OOOOoXXXX+++XXXX ",
+"oXX+X++XXXXX OOOOoXX++++X+XXXX OOOOoXXX++X++XXX ",
+"oXX+XX++XXXX OOOOoXX+X+XX+XXXX OOOOoXX++XXX++XX ",
+"oXX+XXX++XXX OOOOoXX+X+XX+XX+X OOOOoXX+XXXXX+XX ",
+"oXX+XX++XXXX OOOOoXX+X+XX+XXXX OOOOoXX+++++++XX ",
+"oXX+X++XXXXX OOOOoXX++++X+XXXX OOOOoXXXXXXXXXXX ",
+"oXX+++XXXXXX OOOOoXXXXX+++X+XX OOOOoXX+++++++XX ",
+"oXXXXXXXXXXX OOOOoXXXXXX++XXXX OOOOoXXXXXXXXXXX ",
+"oXXXXXXXXXXX OOOOoXXXXXXXXXXXX OOOOoXXXXXXXXXXX ",
+".            OOOO.             OOOO.            ",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"OOOOOOOOOOOOOOO                 .OOOOOOOOOOOOOOO",
+"oooooooooooo.OO XOXOXOXOXOXOXOXOoOOoooooooooooo.",
+"oXOXOXOXOXOX OO OXOXOXOXOXOXOXOXoOOoXOXOXOXOXOX ",
+"oOXOXOXOXOXO OO XOXOXOXOXOXOXOXOoOOoOXOXOXOXOXO ",
+"oXO+OXO+O+OX OO OXOXOXOXOXOXOXOXoOOoXO+O+OXO+OX ",
+"oOXOXO+OXOXO OO XOXOXOXOXOXOXOXOoOOoOXOXO+OXOXO ",
+"oXO+O+OXO+OX OO OXOXOXOXOXOXOXOXoOOoXO+OXO+O+OX ",
+"oOXO+OXOXOXO OO XOXOXOXOXOXOXOXOoOOoOXOXOXO+OXO ",
+"oXO+O+OXO+OX OO OXOXOXOXOXOXOXOXoOOoXO+OXO+O+OX ",
+"oOXOXO+OXOXO OO XOXOXOXOXOXOXOXOoOOoOXOXO+OXOXO ",
+"oXO+OXO+O+OX OO OXOXOXOXOXOXOXOXoOOoXO+O+OXO+OX ",
+"oOXOXOXOXOXO OO XOXOXOXOXOXOXOXOoOOoOXOXOXOXOXO ",
+"oXOXOXOXOXOX OO OXOXOXOXOXOXOXOXoOOoXOXOXOXOXOX ",
+"..           OO XOXOXOXOXOXOXOXXoOO.            ",
+"OOOOOOOOOOOOOOO.oooooooooooooooooOOOOOOOOOOOOOOO"};
+/* XPM */
+static char * cdpaused[] = {
+"48 48 7 1",
+" 	c #318C318C318C",
+".	c #631863186318",
+"X	s led_color_back	c black",
+"o	c #CE72CE72CE72",
+"O	c #9CE69CE69CE6",
+"+	c none",
+"@	s led_color_high	c green",
+"                                               .",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+"Oooooooooooooooooooooooooooooooooooooooooooooooo",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"ooooooooooooO++++oooooooooooooO++++ooooooooooooO",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXXXXXXXX ",
+"oXX@@@XXXXXX ++++oXXXXX@@@XXXX ++++oXX@@@@@@@XX ",
+"oXX at X@@XXXXX ++++oXX@@@@X at X@XX ++++oXX at XXXXX@XX ",
+"oXX at XX@@XXXX ++++oXX at X@XX at XXXX ++++oXX at XXXXX@XX ",
+"oXX at XXX@@XXX ++++oXX at X@XX at XX@X ++++oXX at XXXXX@XX ",
+"oXX at XX@@XXXX ++++oXX at X@XX at XXXX ++++oXX at XXXXX@XX ",
+"oXX at X@@XXXXX ++++oXX@@@@X at X@XX ++++oXX at XXXXX@XX ",
+"oXX@@@XXXXXX ++++oXXXXX@@@XXXX ++++oXX@@@@@@@XX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"O            ++++O             ++++O            ",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"+++++++++++++++                 O+++++++++++++++",
+"ooooooooooooO++ XXXXXXXXXXXXXXXXo++ooooooooooooO",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX@@@XXX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XXX@@@XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"O            ++ XXXXXXXXXXXXXXXXo++O            ",
+"+++++++++++++++Oooooooooooooooooo+++++++++++++++"};
+/* XPM */
+static char * cdplaying[] = {
+"48 48 7 1",
+" 	c #318C318C318C",
+".	c #631863186318",
+"X	s led_color_back	c black",
+"o	c #CE72CE72CE72",
+"O	c #9CE69CE69CE6",
+"+	c none",
+"@	s led_color_high	c green",
+"                                               .",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+"Oooooooooooooooooooooooooooooooooooooooooooooooo",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"ooooooooooooO++++oooooooooooooO++++ooooooooooooO",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXXXXXXXX ",
+"oXX@@@X@@@XX ++++oXXXXX@@@XXXX ++++oXX@@@@@@@XX ",
+"oXX at X@X at X@XX ++++oXX@@@@X at X@XX ++++oXX at XXXXX@XX ",
+"oXX at X@X at X@XX ++++oXX at X@XX at XXXX ++++oXX at XXXXX@XX ",
+"oXX at X@X at X@XX ++++oXX at X@XX at XX@X ++++oXX at XXXXX@XX ",
+"oXX at X@X at X@XX ++++oXX at X@XX at XXXX ++++oXX at XXXXX@XX ",
+"oXX at X@X at X@XX ++++oXX@@@@X at X@XX ++++oXX at XXXXX@XX ",
+"oXX@@@X@@@XX ++++oXXXXX@@@XXXX ++++oXX@@@@@@@XX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"O            ++++O             ++++O            ",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"+++++++++++++++                 O+++++++++++++++",
+"ooooooooooooO++ XXXXXXXXXXXXXXXXo++ooooooooooooO",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX@@@XXX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XXX@@@XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"O            ++ XXXXXXXXXXXXXXXXo++O            ",
+"+++++++++++++++Oooooooooooooooooo+++++++++++++++"};
+/* XPM */
+static char * cdstopped[] = {
+"48 48 7 1",
+" 	c #318C318C318C",
+".	c #631863186318",
+"X	s led_color_back	c black",
+"o	c #CE72CE72CE72",
+"O	c #9CE69CE69CE6",
+"+	c none",
+"@	s led_color_high	c green",
+"                                               .",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXo",
+"Oooooooooooooooooooooooooooooooooooooooooooooooo",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"ooooooooooooO++++oooooooooooooO++++ooooooooooooO",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXX at XXXXX ",
+"oXX@@@XXXXXX ++++oXXXXX@@@XXXX ++++oXXXX@@@XXXX ",
+"oXX at X@@XXXXX ++++oXX@@@@X at X@XX ++++oXXX@@X@@XXX ",
+"oXX at XX@@XXXX ++++oXX at X@XX at XXXX ++++oXX@@XXX@@XX ",
+"oXX at XXX@@XXX ++++oXX at X@XX at XX@X ++++oXX at XXXXX@XX ",
+"oXX at XX@@XXXX ++++oXX at X@XX at XXXX ++++oXX@@@@@@@XX ",
+"oXX at X@@XXXXX ++++oXX@@@@X at X@XX ++++oXXXXXXXXXXX ",
+"oXX@@@XXXXXX ++++oXXXXX@@@XXXX ++++oXX@@@@@@@XX ",
+"oXXXXXXXXXXX ++++oXXXXXX@@XXXX ++++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++++oXXXXXXXXXXXX ++++oXXXXXXXXXXX ",
+"O            ++++O             ++++O            ",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"+++++++++++++++                 O+++++++++++++++",
+"ooooooooooooO++ XXXXXXXXXXXXXXXXo++ooooooooooooO",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX@@@XXX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XXX@@@XX ",
+"oXX at X@@XX at XX ++ XXXXXXXXXXXXXXXXo++oXX at XX@@X at XX ",
+"oXX at XX@@X at XX ++ XXXXXXXXXXXXXXXXo++oXX at X@@XX at XX ",
+"oXX at XXX@@@XX ++ XXXXXXXXXXXXXXXXo++oXX@@@XXX at XX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"oXXXXXXXXXXX ++ XXXXXXXXXXXXXXXXo++oXXXXXXXXXXX ",
+"O            ++ XXXXXXXXXXXXXXXXo++O            ",
+"+++++++++++++++Oooooooooooooooooo+++++++++++++++"};
+/* XPM */
+static char * cdled[] = {
+"110 11 2 1",
+" 	s led_color_back	c black",
+".	s led_color_high	c green",
+" ....      .     ....    ....      ..   ......    ...   ......   ....    ....                 ...     ..      ",
+".    .    ..    .    .  .    .     ..   .        .      .    .  .    .  .    .                 .      . .     ",
+".    .     .         .       .    . .   .       .            .  .    .  .    .          .      .      ..      ",
+".    .     .         .       .    . .   .       .           .   .    .  .    .                 .      . .     ",
+".    .     .        .     ...    .  .   .....   .....       .    ....   .    .                        . .     ",
+".    .     .       .         .   .  .        .  .    .     .    .    .   .....                ...             ",
+".    .     .      .          .  .   .        .  .    .     .    .    .       .                         .      ",
+".    .     .     .           .  ......       .  .    .    .     .    .       .          .     . .     ..      ",
+".    .     .    .       .    .      .   .    .  .    .    .     .    .      .                 ...      .      ",
+" ....      .    ......   ....      ...   ....    ....     .      ....    ...                  . .      .      ",
+"                                                                                              . .      .      "};
+/* XPM */
+static char * mixer[] = {
+"48 48 6 1",
+" 	c #318C318C318C",
+".	c #631863186318",
+"X	c none",
+"o	s led_color_back	c black",
+"O	c #CE72CE72CE72",
+"+	s led_color_high	c green",
+"          .XXX                   .XXX          .",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX ooooooooooooooooooOXXX oooooooooO",
+" oooooooooOXXX.OOOOOOOOOOOOOOOOOOOXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXXOOOOOOOOOOOOO.XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooooooooooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooooooooooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooo++++oooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOooo++oo++ooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoo++oooo++oo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoo+oo++oo+oo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoo++oooo++oo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOooo++oo++ooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooo++++oooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooooooooooo XXXXXX oooooooooO",
+" oooooooooOXXXXXXOoooooooooooo XXXXXX oooooooooO",
+" oooooooooOXXXXXX.             XXXXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXXXXXXXXXXXXXXXXXXXXXX oooooooooO",
+" oooooooooOXXXXXX..............XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+" oooooooooOXXXXXX.oooooooooooo.XXXXXX oooooooooO",
+".OOOOOOOOOOXXXXXX..............XXXXXX.OOOOOOOOOO",
+"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"};
+/* XPM */
+static char * mixled[] = {
+"58 39 6 1",
+" 	s led_color_back	c black",
+".	c red",
+"X	s led_color_high	c green",
+"o	c #CE72CE72CE72",
+"O	c #631863186318",
+"+	c #318C318C318C",
+"   .   .   .   .   .   .   .   .   .   . X .oooooooooooooO",
+"   .   .   .   .   .   .   .   .   .   . X .o            +",
+"   .   .   .   .   .   .   .   .   .   . X .o       X    +",
+"X X.X X.X X.X X.X X.X X.X X.X X.X X.XXX.XXX.o      XX X  +",
+"   .   .   .   .   .   .   .   .   . X . X .o  XX X X    +",
+"   .   .   .   .   .   .   .   .   . X . X .o  X X  X    +",
+"   .   .   .   .   .   .   .   .   . X . X .o  X X  X  X +",
+"X X.X X.X X.X X.X X.X X.X X.X X.XXX.XXX.XXX.o  X X  X    +",
+"   .   .   .   .   .   .   .   . X . X . X .o  XX X X    +",
+"   .   .   .   .   .   .   .   . X . X . X .o      XX X  +",
+"   .   .   .   .   .   .   .   . X . X . X .o       X    +",
+"X X.X X.X X.X X.X X.X X.X X.XXX.XXX.XXX.XXX.o            +",
+"   .   .   .   .   .   .   . X . X . X . X .O+++++++++++++",
+"   .   .   .   .   .   .   . X . X . X . X .+++++++++++++O",
+"   .   .   .   .   .   .   . X . X . X . X .+            o",
+"X X.X X.X X.X X.X X.X X.XXX.XXX.XXX.XXX.XXX.+         X  o",
+"   .   .   .   .   .   . X . X . X . X . X .+    XXX  X  o",
+"   .   .   .   .   .   . X . X . X . X . X .+   X   X X  o",
+"   .   .   .   .   .   . X . X . X . X . X .+  X     XX  o",
+"X X.X X.X X.X X.X X.XXX.XXX.XXX.XXX.XXX.XXX.+  X     XX  o",
+"   .   .   .   .   . X . X . X . X . X . X .+  X     XX  o",
+"   .   .   .   .   . X . X . X . X . X . X .+   X   X X  o",
+"   .   .   .   .   . X . X . X . X . X . X .+    XXX  X  o",
+"X X.X X.X X.X X.XXX.XXX.XXX.XXX.XXX.XXX.XXX.+         X  o",
+"   .   .   .   . X . X . X . X . X . X . X .+            o",
+"   .   .   .   . X . X . X . X . X . X . X .Oooooooooooooo",
+"   .   .   .   . X . X . X . X . X . X . X .              ",
+"X X.X X.X X.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.              ",
+"   .   .   . X . X . X . X . X . X . X . X .              ",
+"   .   .   . X . X . X . X . X . X . X . X .              ",
+"   .   .   . X . X . X . X . X . X . X . X .              ",
+"X X.X X.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.              ",
+"   .   . X . X . X . X . X . X . X . X . X .              ",
+"   .   . X . X . X . X . X . X . X . X . X .              ",
+"   .   . X . X . X . X . X . X . X . X . X .              ",
+"X X.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.XXX.              ",
+"   . X . X . X . X . X . X . X . X . X . X .              ",
+"   . X . X . X . X . X . X . X . X . X . X .              ",
+"   . X . X . X . X . X . X . X . X . X . X .              "};
diff --git a/XPM/grey.style b/XPM/grey.style
new file mode 100644
index 0000000..f3d678e
--- /dev/null
+++ b/XPM/grey.style
@@ -0,0 +1,388 @@
+/*
+ * This is a WMRack style
+ *
+ * Copyright 1997 by Oliver Graf <ograf at fga.de>
+ */
+/* XPM */
+static char * alphaled[] = {
+"296 11 4 1",
+" 	c #000063180000 s led_color_low",
+".	c #000000000000 s led_color_back",
+"X	c #0000FFFF0000 s led_color_high",
+"o	c #00009CE60000 s led_color_med",
+" .XoX. .XoXoX. . .XoX. .XoXoX. .XoXoXoX.XoXoXoX. .XoX. .X. . .X. oXoXo .XoXoXoX.X. . .X.X. . . .X. . .X.X. . .X. .XoX. .XoXoX. . .XoX. .XoXoX. . .XoX. .XoXoXoX.X. . .X.X. . .X.X. . .X.X. . .X.X. . .X.XoXoXoX. .XoX. . . . .X. .XoX. . .XoX. .X. . . .XoXoXoX. . .XoX.XoXoXoX. .XoX. . .XoX. . . . . .",
+".o...o..o....o...o...o..o....o..o.......o........o...o..o.....o....X..........o.o....o..o.......oX...Xo.oo....o..o...o..o....o...o...o..o....o...o...o.....X....o.....o.o.....o.o.....o.o.....o.o.....o.......o..o...o.......oo..o...o...o...o..o.......o..........o..........o..o...o...o...o.... .....",
+"X. . .X.X. . .X.X. . .X.X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . . . . .X.X. .X. .X. . . .X.X.X.X.X.X. .X.X. . .X.X. . .X.X. . .X.X. . .X.X. . .X. . o . .X. . .X.X. . .X.X. . .X.X. . .X.X. . .X. . . .X.X. .X.X. . .X.X.X. . .X.X. . .X.X. . . .X. . . . .X. . . . . .X.X. . .X.X. . .X. . . . .",
+"o.....o.o.....o.o.......o.....o.o.......o.......o.......o.....o....X..........o.o..o....o.......o..X..o.o.o...o.o.....o.o.....o.o.....o.o.....o.o..........X....o.....o.o.....o.o.....o..o...o...o...o.......o..o...o.o....o..o.......o.......o.o.......o........o...........o...o...o..o.....o.........",
+"X. . .X.X. . .X.X. . . .X. . .X.X. . . .X. . . .X. . . .X. . .X. . o . . . . .X.X.X. . .X. . . .X. . .X.X.X. .X.X. . .X.X. . .X.X. . .X.X. . .X. X . . . . o . .X. . .X.X. . .X.X. X .X. .X.X. . .X.X. . . .X. .X. .X.X. .X. .X. . . .X. . . .X.X. .X. .XoXoXo .X.XoX. . . .X. . .XoX. .X. . .X. . . . .",
+"oXoXoXo.oXoXoX..o.......o.....o.oXoXoX..oXoXoX..o..XoXo.oXoXoXo....X..........o.oo......o.......o.....o.o..o..o.o.....o.o....o..o.....o.o....o....XoX......X....o.....o..o...o..o..o..o....o.......o.......o....o..o..o.......o......o....oXoX..o...o.........o.oo...o......o....o...o...o...oo.........",
+"X. . .X.X. . .X.X. . . .X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . . . . .X.X.X. . .X. . . .X. . .X.X. .X.X.X. . .X.XoXoX. .X.X. .X.XoXoX. . . . X . . o . .X. . .X. X . X .X. X .X. .X.X. . . X . . .X. . .X.X. .X. . . .X. . .X. . . . .X.XoXoXoX. . . .X.X. . .X. . .X. .X. . .X. .XoX.X. . . . .",
+"o.....o.o.....o.o.......o.....o.o.......o.......o.....o.o.....o....X..........o.o..o....o.......o.....o.o...o.o.o.....o.o.......o..o..o.o..o..........o....X....o.....o...o.o....o.o.o...o...o.....o.....o......o.o...o.......o....o..........o.....o.........o.o.....o....o....o.....o......o..........",
+"X. . .X.X. . .X.X. . .X.X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . .X. . .X.X. .X. .X. . . .X. . .X.X. .X.X.X. . .X.X. . . .X. .X.X.X. .X. .X. . .X. . o . .X. . .X. .X.X. . X X X .X. . .X. . X . .X. . . .X.X. .X. . . .X. .X. . .X. . .X. . .X. .X. . .X.X. . .X. .X. . .X. . .X. . .X. . . . . .",
+"o.....o.o....o...o...o..o....o..o.......o........o...o..o.....o....X.....o...o..o....o..o.......o.....o.o....oo..o...o..o........o...o..o....o...o...o.....X.....o...o.....o......o.o...o.....o....o....o........o...o........o..o.......o...o......o....o...o...o...o....o......o...o.....o............",
+"X. . .X.XoXoX. . .XoX. .XoXoX. .XoXoXoX.X. . . . .XoX. .X. . .X. oXoXo . .XoX. .X. . .X.XoXoXoX.X. . .X.X. . .X. .XoX. .X. . . . .XoX.X.X. . .X. .XoX. . . o . . .XoX. . . X . . .X.X. .X. . .X. . X . .XoXoXoX. .XoX. . . . .X.XoXoXoX. .XoX. . . .X. . .XoX. . .XoX. . .X. . . .XoX. .XoX. . . . . . ."};
+/* XPM */
+static char * cdnodisc[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX    @    .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX    @    .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX   @@@   .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX   @@@   .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"++++++++++++++ ..................O++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .XXXXXXXXXXXXXXXXXO++++++++++++++",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
+/* XPM */
+static char * cdpaused[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
+/* XPM */
+static char * cdplaying[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @@ @@  .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@  @   .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
+/* XPM */
+static char * cdstopped[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX   @@@   .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX   @@@   .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX    @    .a",
+"OX  @      .a++++OX  @@ @    .a++++OX    @    .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
+/* XPM */
+static char * cdled[] = {
+"110 11 4 1",
+" 	c #000000000000 s led_color_back",
+".	c #0000FFFF0000 s led_color_high",
+"X	c #00009E790000 s led_color_med",
+"o	c #000061850000 s led_color_low",
+" .....   X X X   .....   .....   X o X   .....   .....   .....   .....   .....   X X X        ... XoX ..  Xo  ",
+". oXo . o     . X oXo . X oXo . .     . . oXo X . oXo X o XoX . . oXo . . oXo . o     X        .   X  . . o o ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         X. oX  .   o  ..  Xo  ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         .X Xo  .   X  . . o o ",
+".     . X     . X XoX . o XoX . . oXo . . oXo X . oXo X o     . . oXo . . oXo . X     o               . . X X ",
+" X o X   o X o   .....   .....   .....   .....   .....   X X X   .....   .....   o X X        ... oXo         ",
+".     . X     . . oXo X X oXo . X oXo . o XoX . . oXo . X     . . oXo . o XoX . X     o                 .   X ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         X. oX . . X X  ..  Xo ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         .X Xo ... ooo . . o X ",
+". oXo . X     . . oXo X o XoX . X     . o XoX . . oXo . X     . . oXo . o XoX . X     X       . . X X   .   o ",
+" .....   o X o   .....   .....   o X o   .....   .....   X X X   .....   .....   X X o        . . o o   .   X "};
+/* XPM */
+static char * mixer[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c none",
+"X	c #318C318C318C",
+"o	c #9CE69CE69CE6",
+"O	c #000000000000 s led_color_back",
+"+	c #CE72CE72CE72",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"           ...                    ...           ",
+" XXXXXXXXX+... XXXXXXXXXXXXXXXXXX+... XXXXXXXXX+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... Xooooooooooooooooo+... XOOOOOOOo+",
+" XOOOOOOOo+... +++++++++++++++++++... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+......++++++++++++++...... XOOOOOOOo+",
+" XOOOOOOOo+......+ooooooooooooa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    @@@   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   @@@@@  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@@ @@@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@   @@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@@ @@@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   @@@@@  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    @@@   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+oXXXXXXXXXXXa...... XOOOOOOOo+",
+" XOOOOOOOo+......+aaaaaaaaaaaaa...... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+......++++++++++++++...... XOOOOOOOo+",
+" XOOOOOOOo+......+ooooooooooooa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  O     O Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  oO   Oo Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   oO Oo  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    oOo   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    OoO   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   Oo oO  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  Oo   oO Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" Xoooooooo+......+oXXXXXXXXXXXa...... Xoooooooo+",
+" ++++++++++......+aaaaaaaaaaaaa...... ++++++++++",
+"................................................"};
+/* XPM */
+static char * mixled[] = {
+"58 39 10 1",
+" 	c #000063180000 s led_color_low",
+".	c #00009CE60000 s led_color_med",
+"X	c #FFFF00000000",
+"o	c #0000FFFF0000 s led_color_high",
+"O	c #CE72CE72CE72",
+"+	c #9CE69CE69CE6",
+"@	c #000000000000 s led_color_back",
+"#	c #631863186318",
+"$	c #318C318C318C",
+"a	c #000000000000",
+" . X . X . X . X . X . X . X . X . X . XoooXOOOOOOOOOOOOOO",
+". .X. .X. .X. .X. .X. .X. .X. .X. .X. .XoooXO++++++++++++a",
+" . X . X . X . X . X . X . X . X . X . XoooXO+######o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+###o###o##$a",
+" . X . X . X . X . X . X . X . X . XoooXoooXO+##oo#o####$a",
+". .X. .X. .X. .X. .X. .X. .X. .X. .XoooXoooXO+#ooo####o#$a",
+" . X . X . X . X . X . X . X . X . XoooXoooXO+#ooo##o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+#ooo####o#$a",
+" . X . X . X . X . X . X . X . XoooXoooXoooXO+##oo#o####$a",
+". .X. .X. .X. .X. .X. .X. .X. .XoooXoooXoooXO+###o###o##$a",
+" . X . X . X . X . X . X . X . XoooXoooXoooXO+######o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+$$$$$$$$$$$a",
+" . X . X . X . X . X . X . XoooXoooXoooXoooXOaaaaaaaaaaaaa",
+". .X. .X. .X. .X. .X. .X. .XoooXoooXoooXoooXaaaaaaaaaaaaaa",
+" . X . X . X . X . X . X . XoooXoooXoooXoooXa$$$$$$$$$$$$O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#######o##+O",
+" . X . X . X . X . X . XoooXoooXoooXoooXoooXa$###ooo#o##+O",
+". .X. .X. .X. .X. .X. .XoooXoooXoooXoooXoooXa$##o###oo##+O",
+" . X . X . X . X . X . XoooXoooXoooXoooXoooXa$#o#####o##+O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#o#####o##+O",
+" . X . X . X . X . XoooXoooXoooXoooXoooXoooXa$#o#####o##+O",
+". .X. .X. .X. .X. .XoooXoooXoooXoooXoooXoooXa$##o###oo##+O",
+" . X . X . X . X . XoooXoooXoooXoooXoooXoooXa$###ooo#o##+O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#######o##+O",
+" . X . X . X . XoooXoooXoooXoooXoooXoooXoooXa$+++++++++++O",
+". .X. .X. .X. .XoooXoooXoooXoooXoooXoooXoooXaOOOOOOOOOOOOO",
+" . X . X . X . XoooXoooXoooXoooXoooXoooXoooXOOOOOOOOOOOOOO",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO++++++++++++a",
+" . X . X . XoooXoooXoooXoooXoooXoooXoooXoooXO+##########$a",
+". .X. .X. .XoooXoooXoooXoooXoooXoooXoooXoooXO+##@#####@#$a",
+" . X . X . XoooXoooXoooXoooXoooXoooXoooXoooXO+##+@###@+#$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+###+@#@+##$a",
+" . X . XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+####+ at +###$a",
+". .X. .XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+####@+@###$a",
+" . X . XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+###@+#+@##$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+##@+###+@#$a",
+" . XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXO+##########$a",
+". .XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXO+$$$$$$$$$$$a",
+" . XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXOaaaaaaaaaaaaa"};
diff --git a/XPM/grey/alphaled.xpm b/XPM/grey/alphaled.xpm
new file mode 100644
index 0000000..d5d63fb
--- /dev/null
+++ b/XPM/grey/alphaled.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char * alphaled[] = {
+"296 11 4 1",
+" 	c #000063180000 s led_color_low",
+".	c #000000000000 s led_color_back",
+"X	c #0000FFFF0000 s led_color_high",
+"o	c #00009CE60000 s led_color_med",
+" .XoX. .XoXoX. . .XoX. .XoXoX. .XoXoXoX.XoXoXoX. .XoX. .X. . .X. oXoXo .XoXoXoX.X. . .X.X. . . .X. . .X.X. . .X. .XoX. .XoXoX. . .XoX. .XoXoX. . .XoX. .XoXoXoX.X. . .X.X. . .X.X. . .X.X. . .X.X. . .X.XoXoXoX. .XoX. . . . .X. .XoX. . .XoX. .X. . . .XoXoXoX. . .XoX.XoXoXoX. .XoX. . .XoX. . . . . .",
+".o...o..o....o...o...o..o....o..o.......o........o...o..o.....o....X..........o.o....o..o.......oX...Xo.oo....o..o...o..o....o...o...o..o....o...o...o.....X....o.....o.o.....o.o.....o.o.....o.o.....o.......o..o...o.......oo..o...o...o...o..o.......o..........o..........o..o...o...o...o.... .....",
+"X. . .X.X. . .X.X. . .X.X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . . . . .X.X. .X. .X. . . .X.X.X.X.X.X. .X.X. . .X.X. . .X.X. . .X.X. . .X.X. . .X. . o . .X. . .X.X. . .X.X. . .X.X. . .X.X. . .X. . . .X.X. .X.X. . .X.X.X. . .X.X. . .X.X. . . .X. . . . .X. . . . . .X.X. . .X.X. . .X. . . . .",
+"o.....o.o.....o.o.......o.....o.o.......o.......o.......o.....o....X..........o.o..o....o.......o..X..o.o.o...o.o.....o.o.....o.o.....o.o.....o.o..........X....o.....o.o.....o.o.....o..o...o...o...o.......o..o...o.o....o..o.......o.......o.o.......o........o...........o...o...o..o.....o.........",
+"X. . .X.X. . .X.X. . . .X. . .X.X. . . .X. . . .X. . . .X. . .X. . o . . . . .X.X.X. . .X. . . .X. . .X.X.X. .X.X. . .X.X. . .X.X. . .X.X. . .X. X . . . . o . .X. . .X.X. . .X.X. X .X. .X.X. . .X.X. . . .X. .X. .X.X. .X. .X. . . .X. . . .X.X. .X. .XoXoXo .X.XoX. . . .X. . .XoX. .X. . .X. . . . .",
+"oXoXoXo.oXoXoX..o.......o.....o.oXoXoX..oXoXoX..o..XoXo.oXoXoXo....X..........o.oo......o.......o.....o.o..o..o.o.....o.o....o..o.....o.o....o....XoX......X....o.....o..o...o..o..o..o....o.......o.......o....o..o..o.......o......o....oXoX..o...o.........o.oo...o......o....o...o...o...oo.........",
+"X. . .X.X. . .X.X. . . .X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . . . . .X.X.X. . .X. . . .X. . .X.X. .X.X.X. . .X.XoXoX. .X.X. .X.XoXoX. . . . X . . o . .X. . .X. X . X .X. X .X. .X.X. . . X . . .X. . .X.X. .X. . . .X. . .X. . . . .X.XoXoXoX. . . .X.X. . .X. . .X. .X. . .X. .XoX.X. . . . .",
+"o.....o.o.....o.o.......o.....o.o.......o.......o.....o.o.....o....X..........o.o..o....o.......o.....o.o...o.o.o.....o.o.......o..o..o.o..o..........o....X....o.....o...o.o....o.o.o...o...o.....o.....o......o.o...o.......o....o..........o.....o.........o.o.....o....o....o.....o......o..........",
+"X. . .X.X. . .X.X. . .X.X. . .X.X. . . .X. . . .X. . .X.X. . .X. . o . .X. . .X.X. .X. .X. . . .X. . .X.X. .X.X.X. . .X.X. . . .X. .X.X.X. .X. .X. . .X. . o . .X. . .X. .X.X. . X X X .X. . .X. . X . .X. . . .X.X. .X. . . .X. .X. . .X. . .X. . .X. .X. . .X.X. . .X. .X. . .X. . .X. . .X. . . . . .",
+"o.....o.o....o...o...o..o....o..o.......o........o...o..o.....o....X.....o...o..o....o..o.......o.....o.o....oo..o...o..o........o...o..o....o...o...o.....X.....o...o.....o......o.o...o.....o....o....o........o...o........o..o.......o...o......o....o...o...o...o....o......o...o.....o............",
+"X. . .X.XoXoX. . .XoX. .XoXoX. .XoXoXoX.X. . . . .XoX. .X. . .X. oXoXo . .XoX. .X. . .X.XoXoXoX.X. . .X.X. . .X. .XoX. .X. . . . .XoX.X.X. . .X. .XoX. . . o . . .XoX. . . X . . .X.X. .X. . .X. . X . .XoXoXoX. .XoX. . . . .X.XoXoXoX. .XoX. . . .X. . .XoX. . .XoX. . .X. . . .XoX. .XoX. . . . . . ."};
diff --git a/XPM/grey/cdnodisc.xpm b/XPM/grey/cdnodisc.xpm
new file mode 100644
index 0000000..e54646e
--- /dev/null
+++ b/XPM/grey/cdnodisc.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * cdnodisc[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX    @    .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX    @    .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX   @@@   .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX   @@@   .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"++++++++++++++ ..................O++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .ooooooooooooooooXO++++++++++++++",
+"++++++++++++++ .XXXXXXXXXXXXXXXXXO++++++++++++++",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
diff --git a/XPM/grey/cdpaused.xpm b/XPM/grey/cdpaused.xpm
new file mode 100644
index 0000000..6141ef1
--- /dev/null
+++ b/XPM/grey/cdpaused.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * cdpaused[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
diff --git a/XPM/grey/cdplaying.xpm b/XPM/grey/cdplaying.xpm
new file mode 100644
index 0000000..824d0f3
--- /dev/null
+++ b/XPM/grey/cdplaying.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * cdplaying[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @@ @@  .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@  @   .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX @@@    @ .a++++OX  @@@@@  .a",
+"OX  @@ @@  .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
diff --git a/XPM/grey/cdstopped.xpm b/XPM/grey/cdstopped.xpm
new file mode 100644
index 0000000..7353cbc
--- /dev/null
+++ b/XPM/grey/cdstopped.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * cdstopped[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c #318C318C318C",
+"X	c #9CE69CE69CE6",
+"o	c #000000000000 s led_color_back",
+"O	c #CE72CE72CE72",
+"+	c none",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"                                                ",
+" ..............................................O",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .ooooooooooooooooooooooooooooooooooooooooooooXO",
+" .XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXO",
+" OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"OOOOOOOOOOOOO++++OOOOOOOOOOOOOO++++OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa++++OXXXXXXXXXXXXa++++OXXXXXXXXXXXa",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX  @      .a++++OX  @@ @    .a++++OX  @@@@@  .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX   @@@   .a",
+"OX  @@@@@  .a++++OX @@@  @   .a++++OX   @@@   .a",
+"OX  @@@    .a++++OX @@@    @ .a++++OX    @    .a",
+"OX  @      .a++++OX  @@ @    .a++++OX    @    .a",
+"OX         .a++++OX   @   @  .a++++OX         .a",
+"OX         .a++++OX      @   .a++++OX         .a",
+"OX..........a++++OX...........a++++OX..........a",
+"Oaaaaaaaaaaaa++++Oaaaaaaaaaaaaa++++Oaaaaaaaaaaaa",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++++++++++++++++++",
+"++++++++++++++                    ++++++++++++++",
+"OOOOOOOOOOOOO+ ..................O+OOOOOOOOOOOOO",
+"OXXXXXXXXXXXa+ .ooooooooooooooooXO+OXXXXXXXXXXXa",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @@@@@  .a+ .ooooooooooooooooXO+OX  @@@@@  .a",
+"OX  @ @@@  .a+ .ooooooooooooooooXO+OX  @@@ @  .a",
+"OX  @   @  .a+ .ooooooooooooooooXO+OX  @   @  .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX         .a+ .ooooooooooooooooXO+OX         .a",
+"OX..........a+ .ooooooooooooooooXO+OX..........a",
+"Oaaaaaaaaaaaa+ .XXXXXXXXXXXXXXXXXO+Oaaaaaaaaaaaa",
+"++++++++++++++ OOOOOOOOOOOOOOOOOOO++++++++++++++"};
diff --git a/XPM/grey/led.xpm b/XPM/grey/led.xpm
new file mode 100644
index 0000000..39b293b
--- /dev/null
+++ b/XPM/grey/led.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char * cdled[] = {
+"110 11 4 1",
+" 	c #000000000000 s led_color_back",
+".	c #0000FFFF0000 s led_color_high",
+"X	c #00009E790000 s led_color_med",
+"o	c #000061850000 s led_color_low",
+" .....   X X X   .....   .....   X o X   .....   .....   .....   .....   .....   X X X        ... XoX ..  Xo  ",
+". oXo . o     . X oXo . X oXo . .     . . oXo X . oXo X o XoX . . oXo . . oXo . o     X        .   X  . . o o ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         X. oX  .   o  ..  Xo  ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         .X Xo  .   X  . . o o ",
+".     . X     . X XoX . o XoX . . oXo . . oXo X . oXo X o     . . oXo . . oXo . X     o               . . X X ",
+" X o X   o X o   .....   .....   .....   .....   .....   X X X   .....   .....   o X X        ... oXo         ",
+".     . X     . . oXo X X oXo . X oXo . o XoX . . oXo . X     . . oXo . o XoX . X     o                 .   X ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         X. oX . . X X  ..  Xo ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         .X Xo ... ooo . . o X ",
+". oXo . X     . . oXo X o XoX . X     . o XoX . . oXo . X     . . oXo . o XoX . X     X       . . X X   .   o ",
+" .....   o X o   .....   .....   o X o   .....   .....   X X X   .....   .....   X X o        . . o o   .   X "};
diff --git a/XPM/grey/mixer.xpm b/XPM/grey/mixer.xpm
new file mode 100644
index 0000000..8bdb2cb
--- /dev/null
+++ b/XPM/grey/mixer.xpm
@@ -0,0 +1,59 @@
+/* XPM */
+static char * mixer[] = {
+"48 48 8 1",
+" 	c #631863186318",
+".	c none",
+"X	c #318C318C318C",
+"o	c #9CE69CE69CE6",
+"O	c #000000000000 s led_color_back",
+"+	c #CE72CE72CE72",
+"@	c #0000FFFF0000 s led_color_high",
+"a	c #000000000000",
+"           ...                    ...           ",
+" XXXXXXXXX+... XXXXXXXXXXXXXXXXXX+... XXXXXXXXX+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... XOOOOOOOOOOOOOOOOo+... XOOOOOOOo+",
+" XOOOOOOOo+... Xooooooooooooooooo+... XOOOOOOOo+",
+" XOOOOOOOo+... +++++++++++++++++++... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+......++++++++++++++...... XOOOOOOOo+",
+" XOOOOOOOo+......+ooooooooooooa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    @@@   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   @@@@@  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@@ @@@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@   @@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  @@@ @@@ Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   @@@@@  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    @@@   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+oXXXXXXXXXXXa...... XOOOOOOOo+",
+" XOOOOOOOo+......+aaaaaaaaaaaaa...... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+.......................... XOOOOOOOo+",
+" XOOOOOOOo+......++++++++++++++...... XOOOOOOOo+",
+" XOOOOOOOo+......+ooooooooooooa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  O     O Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  oO   Oo Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   oO Oo  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    oOo   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o    OoO   Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o   Oo oO  Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o  Oo   oO Xa...... XOOOOOOOo+",
+" XOOOOOOOo+......+o          Xa...... XOOOOOOOo+",
+" Xoooooooo+......+oXXXXXXXXXXXa...... Xoooooooo+",
+" ++++++++++......+aaaaaaaaaaaaa...... ++++++++++",
+"................................................"};
diff --git a/XPM/grey/mixled.xpm b/XPM/grey/mixled.xpm
new file mode 100644
index 0000000..526439b
--- /dev/null
+++ b/XPM/grey/mixled.xpm
@@ -0,0 +1,52 @@
+/* XPM */
+static char * mixled[] = {
+"58 39 10 1",
+" 	c #000063180000 s led_color_low",
+".	c #00009CE60000 s led_color_med",
+"X	c #FFFF00000000",
+"o	c #0000FFFF0000 s led_color_high",
+"O	c #CE72CE72CE72",
+"+	c #9CE69CE69CE6",
+"@	c #000000000000 s led_color_back",
+"#	c #631863186318",
+"$	c #318C318C318C",
+"a	c #000000000000",
+" . X . X . X . X . X . X . X . X . X . XoooXOOOOOOOOOOOOOO",
+". .X. .X. .X. .X. .X. .X. .X. .X. .X. .XoooXO++++++++++++a",
+" . X . X . X . X . X . X . X . X . X . XoooXO+######o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+###o###o##$a",
+" . X . X . X . X . X . X . X . X . XoooXoooXO+##oo#o####$a",
+". .X. .X. .X. .X. .X. .X. .X. .X. .XoooXoooXO+#ooo####o#$a",
+" . X . X . X . X . X . X . X . X . XoooXoooXO+#ooo##o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+#ooo####o#$a",
+" . X . X . X . X . X . X . X . XoooXoooXoooXO+##oo#o####$a",
+". .X. .X. .X. .X. .X. .X. .X. .XoooXoooXoooXO+###o###o##$a",
+" . X . X . X . X . X . X . X . XoooXoooXoooXO+######o###$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+$$$$$$$$$$$a",
+" . X . X . X . X . X . X . XoooXoooXoooXoooXOaaaaaaaaaaaaa",
+". .X. .X. .X. .X. .X. .X. .XoooXoooXoooXoooXaaaaaaaaaaaaaa",
+" . X . X . X . X . X . X . XoooXoooXoooXoooXa$$$$$$$$$$$$O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#######o##+O",
+" . X . X . X . X . X . XoooXoooXoooXoooXoooXa$###ooo#o##+O",
+". .X. .X. .X. .X. .X. .XoooXoooXoooXoooXoooXa$##o###oo##+O",
+" . X . X . X . X . X . XoooXoooXoooXoooXoooXa$#o#####o##+O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#o#####o##+O",
+" . X . X . X . X . XoooXoooXoooXoooXoooXoooXa$#o#####o##+O",
+". .X. .X. .X. .X. .XoooXoooXoooXoooXoooXoooXa$##o###oo##+O",
+" . X . X . X . X . XoooXoooXoooXoooXoooXoooXa$###ooo#o##+O",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@Xa$#######o##+O",
+" . X . X . X . XoooXoooXoooXoooXoooXoooXoooXa$+++++++++++O",
+". .X. .X. .X. .XoooXoooXoooXoooXoooXoooXoooXaOOOOOOOOOOOOO",
+" . X . X . X . XoooXoooXoooXoooXoooXoooXoooXOOOOOOOOOOOOOO",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO++++++++++++a",
+" . X . X . XoooXoooXoooXoooXoooXoooXoooXoooXO+##########$a",
+". .X. .X. .XoooXoooXoooXoooXoooXoooXoooXoooXO+##@#####@#$a",
+" . X . X . XoooXoooXoooXoooXoooXoooXoooXoooXO+##+@###@+#$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+###+@#@+##$a",
+" . X . XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+####+ at +###$a",
+". .X. .XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+####@+@###$a",
+" . X . XoooXoooXoooXoooXoooXoooXoooXoooXoooXO+###@+#+@##$a",
+"@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@X@@@XO+##@+###+@#$a",
+" . XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXO+##########$a",
+". .XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXO+$$$$$$$$$$$a",
+" . XoooXoooXoooXoooXoooXoooXoooXoooXoooXoooXOaaaaaaaaaaaaa"};
diff --git a/XPM/led.xpm b/XPM/led.xpm
new file mode 100644
index 0000000..39b293b
--- /dev/null
+++ b/XPM/led.xpm
@@ -0,0 +1,18 @@
+/* XPM */
+static char * cdled[] = {
+"110 11 4 1",
+" 	c #000000000000 s led_color_back",
+".	c #0000FFFF0000 s led_color_high",
+"X	c #00009E790000 s led_color_med",
+"o	c #000061850000 s led_color_low",
+" .....   X X X   .....   .....   X o X   .....   .....   .....   .....   .....   X X X        ... XoX ..  Xo  ",
+". oXo . o     . X oXo . X oXo . .     . . oXo X . oXo X o XoX . . oXo . . oXo . o     X        .   X  . . o o ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         X. oX  .   o  ..  Xo  ",
+".X   X.      X.      X.      X. .X   X. .X      .X           o. .X   X. .X   X.         .X Xo  .   X  . . o o ",
+".     . X     . X XoX . o XoX . . oXo . . oXo X . oXo X o     . . oXo . . oXo . X     o               . . X X ",
+" X o X   o X o   .....   .....   .....   .....   .....   X X X   .....   .....   o X X        ... oXo         ",
+".     . X     . . oXo X X oXo . X oXo . o XoX . . oXo . X     . . oXo . o XoX . X     o                 .   X ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         X. oX . . X X  ..  Xo ",
+".X   X.      X. .X           X.      X.      o. .X   X.      o. .X   X.      o.         .X Xo ... ooo . . o X ",
+". oXo . X     . . oXo X o XoX . X     . o XoX . . oXo . X     . . oXo . o XoX . X     X       . . X X   .   o ",
+" .....   o X o   .....   .....   o X o   .....   .....   X X X   .....   .....   X X o        . . o o   .   X "};
diff --git a/XPM/mixer-mask.xpm b/XPM/mixer-mask.xpm
new file mode 100644
index 0000000..95a1e98
--- /dev/null
+++ b/XPM/mixer-mask.xpm
@@ -0,0 +1,54 @@
+/* XPM */
+static char * mixer_mask_xpm[] = {
+"48 48 3 1",
+" 	c None",
+".	c #79E77DF779E7",
+"X	c #000000000000",
+"...........   ....................   ...........",
+"...........   ....................   ...........",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ..XXXXXXXXXXXXXXXX..   ..XXXXXXX..",
+"..XXXXXXX..   ....................   ..XXXXXXX..",
+"..XXXXXXX..   ....................   ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..                          ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"..XXXXXXX..      ..............      ..XXXXXXX..",
+"...........      ..............      ...........",
+"...........      ..............      ...........",
+"                                                "};
diff --git a/cdctrl.c b/cdctrl.c
new file mode 100644
index 0000000..a8e30ed
--- /dev/null
+++ b/cdctrl.c
@@ -0,0 +1,188 @@
+/*
+ * $Id: cdctrl.c,v 1.1.1.1 2001/02/12 22:25:33 xtifr Exp $
+ *
+ * Part of WMRack
+ *
+ * command line tool to control the cdrom
+ * created to test the cdrom control stuff
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "cdrom.h"
+
+char *commands[]={"info", "status", "play", "pause", "skip", "stop", "eject", "playlist"};
+#define NUM_CMD 8
+
+void usage()
+{
+  fprintf(stderr,"Usage: cdctrl [-d DEVICE] [info|status|play|pause|skip|stop|eject|playlist] PARAMS\n");
+}
+
+int main(int argc, char **argv)
+{
+  CD *cd;
+  int fa=1, i, s=0, e=0xaa, status;
+  char *device="/dev/cdrom";
+  struct timeval tm;
+  
+  gettimeofday(&tm,NULL);
+  srandom(tm.tv_usec^tm.tv_sec);
+
+  if (argc<2)
+    {
+      usage();
+      exit(EXIT_FAILURE);
+    }
+
+  if (strcmp(argv[1],"-d")==0)
+    {
+      device=argv[2];
+      fa=3;
+      argc-=2;
+    }
+
+  if (argc<2)
+    {
+      usage();
+      exit(EXIT_FAILURE);
+    }
+
+  for (i=0; i<NUM_CMD; i++)
+    if (strcmp(argv[fa],commands[i])==0)
+      break;
+  if (i==NUM_CMD)
+    {
+      usage();
+      exit(EXIT_FAILURE);
+    }
+
+  cd=cd_open(device,0);
+  if (cd->status==-1)
+    printf("No CDROM in drive\n");
+  else
+    status=cd_getStatus(cd,0,1);
+
+  switch (i)
+    {
+    case 0:
+      printf("discid: %08lX\n",cd_info(cd,discid));
+      printf("Tracks: %d\n",cd_info(cd,tracks));
+      for (i=0; i<cd_info(cd,tracks); i++)
+	{
+	  printf("%2d[%2d]: start(%02d:%02d:%02d) end(%02d:%02d:%02d) len(%02d:%02d:%02d) %s\n",i,
+		 cd_info(cd,track)[i].num,
+		 cd_info(cd,track)[i].start.minute,
+		 cd_info(cd,track)[i].start.second,
+		 cd_info(cd,track)[i].start.frame,
+		 cd_info(cd,track)[i].end.minute,
+		 cd_info(cd,track)[i].end.second,
+		 cd_info(cd,track)[i].end.frame,
+		 cd_info(cd,track)[i].length.minute,
+		 cd_info(cd,track)[i].length.second,
+		 cd_info(cd,track)[i].length.frame,
+		 cd_info(cd,track)[i].data?"DATA":"");
+	}
+    showlist:
+      printf("PlayList: %d length(%02d:%02d:%02d)\n",
+	     cd_list(cd,tracks),
+	     cd_list(cd,length).minute,
+	     cd_list(cd,length).second,
+	     cd_list(cd,length).frame);
+      for (i=0; i<cd_list(cd,tracks); i++)
+	{
+	  printf("%2d[%2d]: start(%02d:%02d:%02d) end(%02d:%02d:%02d) len(%02d:%02d:%02d) %s\n",i,
+		 cd_list(cd,track)[i].num,
+		 cd_list(cd,track)[i].start.minute,
+		 cd_list(cd,track)[i].start.second,
+		 cd_list(cd,track)[i].start.frame,
+		 cd_list(cd,track)[i].end.minute,
+		 cd_list(cd,track)[i].end.second,
+		 cd_list(cd,track)[i].end.frame,
+		 cd_list(cd,track)[i].length.minute,
+		 cd_list(cd,track)[i].length.second,
+		 cd_list(cd,track)[i].length.frame,
+		 cd_list(cd,track)[i].data?"DATA":"");
+	}
+      break;
+    case 1:
+      printf("status is %d\n",status);
+      printf("mode %d track %d\n",
+	     cd_cur(cd,mode),cd_cur(cd,track));
+      if (cd_cur(cd,track)!=-1)
+	printf("%d[%d]: %02d:%02d:%02d->%02d:%02d:%02d len(%02d:%02d:%02d) d%d\n",
+	       cd_cur(cd,track),
+	       cd_list(cd,track)[cd_cur(cd,track)].num,
+	       cd_list(cd,track)[cd_cur(cd,track)].start.minute,
+	       cd_list(cd,track)[cd_cur(cd,track)].start.second,
+	       cd_list(cd,track)[cd_cur(cd,track)].start.frame,
+	       cd_list(cd,track)[cd_cur(cd,track)].end.minute,
+	       cd_list(cd,track)[cd_cur(cd,track)].end.second,
+	       cd_list(cd,track)[cd_cur(cd,track)].end.frame,
+	       cd_list(cd,track)[cd_cur(cd,track)].length.minute,
+	       cd_list(cd,track)[cd_cur(cd,track)].length.second,
+	       cd_list(cd,track)[cd_cur(cd,track)].length.frame,
+	       cd_list(cd,track)[cd_cur(cd,track)].data);
+      else
+	printf("no current track\n");
+      printf("rel %02d:%02d:%02d abs %02d:%02d:%02d\n",
+	     cd_cur(cd,relmsf.minute),
+	     cd_cur(cd,relmsf.second),
+	     cd_cur(cd,relmsf.frame),
+	     cd_cur(cd,absmsf.minute),
+	     cd_cur(cd,absmsf.second),
+	     cd_cur(cd,absmsf.frame));
+      break;
+    case 2:
+      if (argc>2)
+	s=atoi(argv[fa+1]);
+      cd_doPlay(cd,s);
+      break;
+    case 3:
+      cd_doPause(cd);
+      break;
+    case 4:
+      if (argc!=3)
+	{
+	  fprintf(stderr,"skip needs only one arg (seconds)\n");
+	  exit(EXIT_FAILURE);
+	}
+      s=atoi(argv[fa+1]);
+      cd_doSkip(cd,s);
+      break;
+    case 5:
+      cd_doStop(cd);
+      break;
+    case 6:
+      cd_doEject(cd);
+      break;
+    case 7:
+      if (argc==2)
+	cd_randomize(cd);
+      else
+	{
+	  CDPlayList *list=cdpl_new();
+	  int t;
+	  for (i=fa+1; i<argc+fa-1; i++)
+	    {
+	      t=cd_findtrack(cd,atoi(argv[i]));
+	      if (t>=0)
+		cdpl_add(list,cd,t);
+	    }
+	  cd_setpl(cd,list);
+	}
+      cd_doPlay(cd,0);
+      fprintf(stderr,"\nWARNING: cdctrl CAN ONLY SET PLAYLIST, BUT PLAYING IS LINEAR\n\n");
+      goto showlist;
+    default:
+      usage();
+      exit(EXIT_FAILURE);
+    }
+  cd_close(cd);
+  return EXIT_SUCCESS;
+}
diff --git a/cdrom.c b/cdrom.c
new file mode 100644
index 0000000..c3ca76c
--- /dev/null
+++ b/cdrom.c
@@ -0,0 +1,1047 @@
+/*
+ * $Id: cdrom.c,v 1.1.1.1 2001/02/12 22:25:42 xtifr Exp $
+ *
+ * cdrom utility functions for WMRack
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ *
+ * some hints taken from WorkBone
+ *
+ * this is very linux specific !!!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <sys/vfs.h>
+
+#ifdef linux
+#  include <linux/cdrom.h>
+#else
+#  include <sundev/srreg.h>
+#endif /* linux */
+
+#include "cdrom.h"
+
+/* workaround -- used ints in MSF, linux uses u_char, what use other systems? */
+#define msftoMSF(d,s) d.minute=s.minute; d.second=s.second; d.frame=s.frame;
+#define MSFtocdmsf(d,s,e) d.cdmsf_min0=s.minute; d.cdmsf_sec0=s.second; d.cdmsf_frame0=s.frame; d.cdmsf_min1=e.minute; d.cdmsf_sec1=e.second; d.cdmsf_frame1=e.frame;
+
+/*
+ * cddb_sum(num)
+ *
+ * utility function to cddb_discid
+ */
+int cddb_sum(int n)
+{
+  char buf[12], *p;
+  int  ret = 0;
+
+  /* For backward compatibility this algorithm must not change */
+  sprintf(buf,"%u",n);
+  for (p=buf; *p!='\0'; p++)
+    ret+=(*p-'0');
+  return (ret);
+}
+
+/*
+ * cddb_discid(cdinfo)
+ *
+ * calculates the id for a given cdinfo structure
+ */
+unsigned long cddb_discid(CDInfo *cdinfo)
+{
+  int i, t=0, n=0;
+
+  /* For backward compatibility this algorithm must not change */
+  for (i=0; i<cdinfo->tracks; i++) {
+    n+=cddb_sum((cdinfo->track[i].start.minute*60) + cdinfo->track[i].start.second);
+    t+=((cdinfo->track[i+1].start.minute*60) + cdinfo->track[i+1].start.second) -
+      ((cdinfo->track[i].start.minute*60) + cdinfo->track[i].start.second);
+  }
+  cdinfo->discid=((n % 0xff) << 24 | t << 8 | cdinfo->tracks);
+  return cdinfo->discid;
+}
+
+/*
+ * cd_readTOC(CD)
+ *
+ * Read the table of contents from the CD.
+ * returns 0 on success
+ */
+int cd_readTOC(CD *cd)
+{
+  struct cdrom_tochdr   hdr;
+  struct cdrom_tocentry entry;
+  int                   i, j;
+  MSF                   tmp;
+
+  if (cd->fd<0)
+    return 1;
+
+  if (ioctl(cd->fd, CDROMREADTOCHDR, &hdr))
+    {
+      perror("cd_readTOC[readtochdr]");
+      return 1;
+    }
+
+  cd->info.start=hdr.cdth_trk0;
+  cd->info.end=hdr.cdth_trk1;
+  cd->info.tracks=hdr.cdth_trk1-hdr.cdth_trk0+1;
+#ifdef DEBUG
+  fprintf(stderr,"cd_readTOC[DEBUG]: read header with %d tracks\n",
+	  cd->info.tracks);
+#endif
+
+  cd->info.track=malloc(cd->info.tracks*sizeof(TrackInfo));
+  if (cd->info.track==NULL)
+    {
+      perror("cd_readTOC[malloc]");
+      return 1;
+    }
+  for (i=0; i<=cd->info.tracks; i++)
+    {
+      if (i==cd->info.tracks)
+	entry.cdte_track=CDROM_LEADOUT;
+      else
+	entry.cdte_track=cd->info.start+i;
+      entry.cdte_format=CDROM_MSF;
+      if (ioctl(cd->fd, CDROMREADTOCENTRY, &entry))
+	{
+	  perror("cd_readTOC[tocentry read]");
+	  free(cd->info.track);
+	  return 1;
+	}
+
+      if (entry.cdte_track!=CDROM_LEADOUT)
+	{
+	  cd->info.track[i].num=i+1;
+	  msftoMSF(cd->info.track[i].start,entry.cdte_addr.msf);
+	  cd->info.track[i].end.minute=-1;
+	  cd->info.track[i].end.second=-1;
+	  cd->info.track[i].end.frame=-1;
+	  cd->info.track[i].data=entry.cdte_ctrl&CDROM_DATA_TRACK?1:0;
+	  if (i>0)
+	    {
+	      cd->info.track[i-1].end=cd->info.track[i].start;
+	      cd->info.track[i-1].length=subMSF(cd->info.track[i-1].end,
+						cd->info.track[i-1].start);
+	    }
+	}
+      else
+	{
+	  msftoMSF(cd->info.track[i-1].end,entry.cdte_addr.msf);
+	  cd->info.track[i-1].length=subMSF(cd->info.track[i-1].end,
+					    cd->info.track[i-1].start);
+	}
+    }
+
+  cddb_discid(&cd->info);
+
+  return 0;
+}
+
+/*
+ * cd_playMSF(cd,start,end)
+ *
+ * sends the actual play to the cdrom.
+ */
+int cd_playMSF(CD *cd, MSF start, MSF end)
+{
+  struct cdrom_msf msf;
+
+  if (cd==NULL || cd->fd<0)
+    return 1;
+
+  MSFtocdmsf(msf,start,end);
+
+  if (cd->info.current.mode==CDM_STOP)
+    if (ioctl(cd->fd, CDROMSTART))
+      {
+	perror("cd_playMSF[CDROMSTART]");
+	return 1;
+      }
+
+  if (ioctl(cd->fd, CDROMPLAYMSF, &msf))
+    {
+      printf("cd_playMSF[playmsf]\n");
+      printf("  msf = %02d:%02d:%02d %02d:%02d:%02d\n",
+	     msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0,
+	     msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1);
+      perror("cd_playMSF[CDROMPLAYMSF]");
+      return 1;
+    }
+  return 0;
+}
+
+/*
+ * cd_freeinfo(cd)
+ *
+ * frees a allocate CDInfo
+ */
+void cd_freeinfo(CD *cd)
+{
+  if (cd->info.track)
+    free(cd->info.track);
+  if (cd->info.list.track)
+    free(cd->info.list.track);
+  memset(&cd->info,0x0,sizeof(CDInfo));
+  memset(&cd->info.current,0xff,sizeof(CDPosition));
+  /* paranoia */
+  cd->info.track=NULL;
+  cd->info.list.track=NULL;
+}
+
+/*
+ * cd_close(cd)
+ *
+ * closes the cd device and frees all data structures inside
+ */
+void cd_close(CD *cd)
+{
+  if (cd==NULL)
+    return;
+
+  cd_freeinfo(cd);
+  free(cd->device);
+  close(cd->fd);
+  free(cd);
+}
+
+/*
+ * cd_open(device)
+ *
+ * sets the device for further cd-access
+ * set force to TRUE for immidiate change
+ */
+CD *cd_open(char *device, int noopen)
+{
+  struct stat st;
+  CD *cd;
+
+  if (stat(device,&st))
+    {
+      perror("cd_open[stat]");
+      return NULL;
+    }
+
+  cd=(CD *)malloc(sizeof(CD));
+  if (cd==NULL)
+    {
+      perror("cd_open[malloc]");
+      return NULL;
+    }
+
+  cd->device=strdup(device);
+  cd->fd=-1;
+  cd->status=-1;
+  memset(&cd->info,0x0,sizeof(CDInfo));
+  memset(&cd->info.current,0xff,sizeof(CDPosition));
+
+  if (!noopen)
+    cd_reopen(cd);
+
+  return cd;
+}
+
+/*
+ * cd_suspend(cd)
+ *
+ * closes the cd device, but leaves all structures intact
+ */
+int cd_suspend(CD *cd)
+{
+  if (cd==NULL)
+    return -1;
+
+  close(cd->fd);
+  cd->fd=-1;
+  cd->status=-1;
+  cd_freeinfo(cd);
+
+  return 0;
+}
+
+/*
+ * cd_reopen(cd)
+ *
+ * reopens a suspended cd device, and reads the new TOC if cd is changed
+ */
+int cd_reopen(CD *cd)
+{
+  int start, end, track;
+  
+  if (cd==NULL)
+    return 1;
+
+  if ((cd->fd=open(cd->device,0))<0)
+    {
+      perror("cd_reopen[open]");
+      return 1;
+    }
+
+  cd_freeinfo(cd);
+
+  if (!cd_readTOC(cd))
+    {
+      cd_resetpl(cd);
+      cd->status=cd_getStatus(cd,0,1);
+      switch (cd_cur(cd,mode))
+	{
+	case CDM_PLAY:
+	  cd->info.play.last_action=CDA_PLAY;
+	  break;
+	case CDM_PAUSE:
+	  cd->info.play.last_action=CDA_PAUSE;
+	  break;
+	case CDM_STOP:
+	  cd->info.play.last_action=CDA_STOP;
+	  break;
+	case CDM_COMP:
+	case CDM_EJECT:
+	  cd->info.play.last_action=CDA_NONE;
+	  break;
+	}
+      start=cd->info.play.cur_track=cd_findtrack(cd,cd_cur(cd,track));
+
+      /* do play list optimization:
+       * find the longest possible track sequence without jumps
+       */
+      for (track=cd_list(cd,track)[start].num, end=start+1;
+	   end<cd_list(cd,tracks) && track==cd_list(cd,track)[end].num-1;
+	   track=cd_list(cd,track)[end].num, end++);
+      end--;
+
+      cd->info.play.cur_end=end;
+      cd->info.play.repeat_mode=CDR_NONE;
+      cd->info.play.play_type=CDP_NORMAL;
+    }
+  else
+    {
+      cd_freeinfo(cd);
+      cd->status=-1;
+      close(cd->fd);
+      cd->fd=-1;
+    }
+
+  return 0;
+}
+
+static struct timeval last_upd={0,0};
+
+/*
+ * cd_getStatus(cd,reopen,force)
+ *
+ * Return values:
+ *  -1 error
+ *   0 No CD in drive.
+ *   1 CD in drive.
+ *   2 CD has just been inserted (TOC has been read)
+ *
+ * Updates the CDPosition struct of the cd.
+ * If reopen is not 0, the device is automatically reopened if needed.
+ * This will query the cdrom only one time within 1/2 second to reduce
+ * overhead. Force will overide this behaviour.
+ */
+int cd_getStatus(CD *cd, int reopen, int force)
+{
+  struct cdrom_subchnl sc;
+  int                  ret=1, newcd=0, im_stop=0;
+  CDPosition           *cur;
+  struct timeval       now;
+
+  if (cd==NULL)
+    return -1;
+
+  if (cd->fd<0)
+    {
+      if (!reopen)
+	{
+	  cd->status=0;
+	  return 0;
+	}
+      if (cd_reopen(cd))
+	return -1;
+      newcd=1;
+    }
+
+  gettimeofday(&now,NULL);
+  if (force
+      || ((now.tv_sec-last_upd.tv_sec)*1000000L+(now.tv_usec-last_upd.tv_usec))>500000L)
+    {
+      cur=&cd->info.current;
+      
+      sc.cdsc_format=CDROM_MSF;
+      
+      if (ioctl(cd->fd, CDROMSUBCHNL, &sc))
+	{
+	  memset(cur,0xff,sizeof(CDPosition));
+	  cur->mode=CDM_EJECT;
+	  cd->status=0;
+	  return 0;
+	}
+
+      /* only set update time if ioctl was successful */
+      last_upd=now;
+
+      if (newcd)
+	{
+	  memset(cur,0xff,sizeof(CDPosition));
+	  cur->mode=CDM_STOP;
+	  ret=2;
+	}
+      
+      switch (sc.cdsc_audiostatus)
+	{
+	case CDROM_AUDIO_PLAY:
+	  cur->mode=CDM_PLAY;
+	  
+	setpos:
+	  cur->track=cd_findtrack(cd,sc.cdsc_trk);
+	  
+	  msftoMSF(cur->relmsf,sc.cdsc_reladdr.msf);
+	  msftoMSF(cur->absmsf,sc.cdsc_absaddr.msf);
+	  
+	  break;
+	  
+	case CDROM_AUDIO_PAUSED:
+	  if (cd_play(cd,last_action)!=CDA_STOP)
+	    {
+	      cur->mode=CDM_PAUSE;
+	      goto setpos;
+	    }
+	  memset(cur,0xff,sizeof(CDPosition));
+	  cur->mode=CDM_STOP;
+	  break;
+	  
+	case CDROM_AUDIO_COMPLETED:
+	  cur->mode=CDM_COMP;
+	  break;
+	  
+	case CDROM_AUDIO_NO_STATUS:
+	case CDROM_AUDIO_INVALID: /* my TOSHIBA CD-ROM XM-5602B wants this */
+	  memset(cur,0xff,sizeof(CDPosition));
+	  cur->mode=CDM_STOP;
+	  break;
+	}
+      cd->status=ret;
+      
+      /*
+	if (ret>0 && cur->track>cd_info(cd,tracks) && cur->mode!=CDM_EJECT)
+	{
+	cd_doStop(cd);
+	im_stop=1;
+	}
+      */
+      
+      switch (cd_play(cd,repeat_mode))
+	{
+	case CDR_NONE:
+	  if ((cd_play(cd,last_action)==CDA_PLAY && cur->mode!=CDM_PLAY)
+	      /* this means: the user wants the cdrom to play,
+	       * but the cdrom does not play */
+	      || cur->mode==CDM_COMP || im_stop)
+	    {
+#ifdef DEBUG
+	      fprintf(stderr,"cd_getStatus[DEBUG]: switching to next track\n");
+#endif
+	      cd_play(cd,cur_track)=cd_play(cd,cur_end)+1;
+	      if (cd_play(cd,cur_track)<cd_list(cd,tracks))
+		cd_doPlay(cd,cd_play(cd,cur_track));
+	      else
+		cd_doStop(cd);
+	    }
+	  break;
+	case CDR_ALL:
+	  if ((cd_play(cd,last_action)==CDA_PLAY && cur->mode!=CDM_PLAY)
+	      || cur->mode==CDM_COMP || im_stop)
+	    {
+	      cd_play(cd,cur_track)++;
+	      if (cd_play(cd,cur_track)>=cd_list(cd,tracks))
+		{
+#ifdef DEBUG
+		  fprintf(stderr,"cd_getStatus[DEBUG]: repeating list\n");
+#endif
+		  if (cd_play(cd,play_type)==CDP_RANDOM)
+		    cd_randomize(cd);
+		  cd_doPlay(cd,0);
+		}
+	      else
+		{
+#ifdef DEBUG
+		  fprintf(stderr,"cd_getStatus[DEBUG]: switching to next track\n");
+#endif
+		  cd_doPlay(cd,cd_play(cd,cur_track));
+		}
+	    }
+	  break;
+	case CDR_ONE:
+	  if ((cd_play(cd,last_action)==CDA_PLAY && cur->mode!=CDM_PLAY)
+	      || cur->mode==CDM_COMP || im_stop)
+	    {
+#ifdef DEBUG
+	      fprintf(stderr,"cd_getStatus[DEBUG]: repeating track\n");
+#endif
+	      cd_doPlay(cd,cd_play(cd,cur_track));
+	    }
+	  break;
+	}
+    }
+
+  return ret;
+}
+
+/*
+ * cd_doPlay(cd,start);
+ *
+ * start playing the cd. cd must be opened. play starts at track start goes
+ * until end of track end.
+ * 0 is the first track of the play list.
+ */
+int cd_doPlay(CD *cd, int start)
+{
+  int end, track;
+
+  if (cd==NULL || cd->fd<0)
+    return 1;
+  if (start<0)
+    start=0;
+  if (start>=cd->info.list.tracks)
+    start=cd->info.list.tracks-1;
+
+  /* do play list optimization:
+   * find the longest possible track sequence without jumps
+   */
+  for (track=cd_list(cd,track)[start].num, end=start+1;
+       end<cd_list(cd,tracks) && track==cd_list(cd,track)[end].num-1;
+       track=cd_list(cd,track)[end].num, end++);
+  end--;
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_doPlay[DEBUG]: play from [%d]%02d:%02d:%02d to end of [%d]%02d:%02d:%02d\n",
+	  start,
+	  cd->info.list.track[start].start.minute,
+	  cd->info.list.track[start].start.second,
+	  cd->info.list.track[start].start.frame,
+	  end,
+	  cd->info.list.track[end].end.minute,
+	  cd->info.list.track[end].end.second,
+	  cd->info.list.track[end].end.frame);
+#endif
+  cd->info.play.last_action=CDA_PLAY;
+  cd->info.play.cur_track=start;
+  cd->info.play.cur_end=end;
+  return cd_playMSF(cd,
+		    cd->info.list.track[start].start,
+		    cd->info.list.track[end].end);
+}
+
+/*
+ * cd_doPause(cd)
+ *
+ * Pause the CD, if it's in play mode.
+ * Resume the CD, If it's already paused.
+ */
+int cd_doPause(CD *cd)
+{
+  if (cd==NULL || cd->fd<0)
+    return 1;
+
+  switch (cd->info.current.mode) {
+  case CDM_PLAY:
+    cd->info.current.mode=CDM_PAUSE;
+#ifdef DEBUG
+    fprintf(stderr,"cd_doPause[DEBUG]: pausing cdrom\n");
+#endif
+    ioctl(cd->fd, CDROMPAUSE);
+    cd->info.play.last_action=CDA_PAUSE;
+    break;
+  case CDM_PAUSE:
+    cd->info.current.mode=CDM_PLAY;
+#ifdef DEBUG
+    fprintf(stderr,"cd_doPause[DEBUG]: resuming cdrom\n");
+#endif
+    ioctl(cd->fd, CDROMRESUME);
+    cd->info.play.last_action=CDA_PLAY;
+    break;
+#ifdef DEBUG
+  default:
+    fprintf(stderr,"cd_doPause[DEBUG]: not playing or pausing\n");
+#endif
+  }
+  return 0;
+}
+
+/*
+ * cd_doStop(cd)
+ *
+ * Stop the CD if it's not already stopped.
+ */
+int cd_doStop(CD *cd)
+{
+  if (cd==NULL || cd->fd<0)
+    return 1;
+
+  if (cd->info.current.mode!=CDM_STOP)
+    {
+      /* olis cdrom needs this */
+      if (cd->info.current.mode==CDM_PLAY)
+	cd_doPause(cd);
+#ifdef DEBUG
+      fprintf(stderr,"cd_doStop[DEBUG]: stopping cdrom\n");
+#endif
+      if (ioctl(cd->fd, CDROMSTOP))
+	{
+	  perror("cd_doStop[CDROMSTOP]");
+	  return 1;
+	}
+      cd->info.play.last_action=CDA_STOP;
+      if (cd->info.current.track>=cd->info.list.tracks)
+	cd->info.play.cur_track=0;
+      else
+	cd->info.play.cur_track=cd->info.current.track;
+      memset(&cd->info.current,0xff,sizeof(CDPosition));
+      cd->info.current.mode=CDM_STOP;
+    }
+  return 0;
+}
+
+/*
+ * cd_doEject(CD *cd)
+ *
+ * Eject the current CD, if there is one.
+ * Returns 0 on success, 1 if the CD couldn't be ejected, or 2 if the
+ * CD contains a mounted filesystem.
+ */
+int cd_doEject(CD *cd)
+{
+  struct statfs ust;
+
+  if (cd==NULL)
+    return 0;
+
+  if (cd->fd<0) /* reopen a closed device */ 
+    {
+      if ((cd->fd=open(cd->device,0))<0)
+      {
+	perror("cd_doEject[(re)open]");
+	return 1;
+      }
+    }
+
+  if (statfs(cd->device, &ust))
+    {
+      perror("cd_doEject[is_mounted]");
+      cd_suspend(cd);
+      return 2;
+    }
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_doEject[DEBUG]: stopping cdrom\n");
+#endif
+  ioctl(cd->fd, CDROMSTOP);
+  cd->info.play.last_action=CDA_STOP;
+#ifdef DEBUG
+  fprintf(stderr,"cd_doEject[DEBUG]: ejecting cdrom\n");
+#endif
+  if (ioctl(cd->fd, CDROMEJECT))
+    {
+      perror("cd_doEject[CDROMEJECT]");
+      cd_suspend(cd);
+      return 1;
+    }
+
+  cd_suspend(cd);
+
+  return 0;
+}
+
+/*
+ * cd_doSkip(cd,seconds)
+ *
+ * Skip some seconds from current position
+ */
+int cd_doSkip(CD *cd, int secs)
+{
+  MSF start, end;
+
+  if (cd==NULL || cd->fd<0)
+    return 1;
+
+  end=cd_list(cd,track)[cd_play(cd,cur_end)].end;
+  start=cd->info.current.absmsf;
+  start.second+=secs;
+  start=normMSF(start);
+#ifdef DEBUG
+  fprintf(stderr,"cd_doSkip[DEBUG]: skipping %d seconds\n",secs);
+#endif
+  if (cmpMSF(start,cd->info.list.track[0].start)<0)
+    {
+      start=cd->info.list.track[0].start;
+#ifdef DEBUG
+      fprintf(stderr,"cd_doSkip[DEBUG]: can't skip before first track\n");
+#endif
+    }
+
+  if (cmpMSF(start,end)>0)
+    {
+#ifdef DEBUG
+      fprintf(stderr,"cd_doSkip[DEBUG]: at end of track ... waiting\n");
+      return 0;
+#endif
+    }
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_doSkip[DEBUG]: play from %02d:%02d:%02d to %02d:%02d:%02d\n",
+	  start.minute, start.second, start.frame,
+	  end.minute, end.second, end.frame);
+#endif
+  return cd_playMSF(cd,start,end);
+}
+
+/*
+ * cmpMSF(a,b)
+ *
+ * compares two MSF structs
+ */
+int cmpMSF(MSF a, MSF b)
+{
+  int fa=msfFrames(a), fb=msfFrames(b);
+  if (fa<fb)
+    return -1;
+  else if (fa>fb)
+    return 1;
+  return 0;
+}
+
+/*
+ * subMSF(a,b)
+ *
+ * subtract b from a
+ */
+MSF subMSF(MSF a, MSF b)
+{
+  MSF c;
+  c.minute=a.minute-b.minute;
+  c.second=a.second-b.second;
+  c.frame =a.frame -b.frame;
+  return normMSF(c);
+}
+
+/*
+ * addMSF(a,b)
+ *
+ * add a to b
+ */
+MSF addMSF(MSF a, MSF b)
+{
+  MSF c;
+  c.minute=a.minute+b.minute;
+  c.second=a.second+b.second;
+  c.frame =a.frame +b.frame;
+  return normMSF(c);
+}
+
+/*
+ * normMSF(msf)
+ *
+ * normalize msf to limits
+ */
+MSF normMSF(MSF msf)
+{
+  while (msf.frame<0) {msf.frame+=FRAMES; msf.second--;}
+  while (msf.second<0) {msf.second+=SECONDS; msf.minute--;}
+  if (msf.minute<0) msf.minute=0;
+  while (msf.frame>FRAMES) {msf.frame-=FRAMES; msf.second++;}
+  while (msf.second>SECONDS) {msf.second-=SECONDS; msf.minute++;}
+  return msf;
+}
+
+/*
+ * cd_resetpl(cd,all)
+ *
+ * reset the play list to all non-data tracks (or all tracks if all is true)
+ */
+int cd_resetpl(CD *cd)
+{
+  int i;
+
+  if (cd==NULL)
+    return 1;
+
+  if (cd->info.list.track)
+    free(cd->info.list.track);
+
+  cd->info.list.tracks=0;
+  MSFzero(cd->info.list.length);
+  
+  if (cd->info.tracks==0)
+    return 0;
+
+  cd->info.list.track=(TrackInfo *)malloc(cd->info.tracks*sizeof(TrackInfo));
+  if (cd->info.list.track==NULL)
+    {
+      perror("cd_resetpl[malloc]");
+      return 1;
+    }
+
+  cd->info.list.allocated=cd->info.tracks;
+  for (i=0; i<cd->info.tracks; i++)
+    if (!cd->info.track[i].data)
+      {
+	cd->info.list.track[cd->info.list.tracks++]=cd->info.track[i];
+	cd->info.list.length=addMSF(cd->info.list.length,
+				    cd->info.list.track[cd->info.list.tracks-1].length);
+      }
+
+  cd_play(cd,play_type)=CDP_NORMAL;
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_resetpl[DEBUG]: cd playlist reseted\n");
+#endif
+
+  return 0;
+}
+
+/*
+ * cd_findtrack(cd,number)
+ *
+ * find the track with number in the play list and return it's index
+ * returns -1 if not found
+ */
+int cd_findtrack(CD *cd, int num)
+{
+  int i;
+  
+  if (cd==NULL || cd->info.track==NULL)
+    return -1;
+
+  for (i=0; i<cd->info.list.tracks; i++)
+    if (cd->info.list.track[i].num==num)
+      return i;
+
+  return -1;
+}
+
+/*
+ * cd_randomize(cd)
+ *
+ * create a random, non-repeating play list from all non-data tracks
+ */
+int cd_randomize(CD *cd)
+{
+  int i, *wech, r, j;
+
+  if (cd==NULL)
+    return 1;
+
+  if (cd->info.list.track)
+    free(cd->info.list.track);
+
+  cd->info.list.tracks=0;
+  MSFzero(cd->info.list.length);
+  
+  if (cd->info.tracks==0)
+    return 0;
+
+  cd->info.list.track=(TrackInfo *)malloc(cd->info.tracks*sizeof(TrackInfo));
+  if (cd->info.list.track==NULL)
+    {
+      perror("cd_randomize[malloc]");
+      return 1;
+    }
+
+  wech=(int *)malloc(sizeof(int)*cd->info.tracks);
+  if (wech==NULL)
+    {
+      perror("cd_randomize[tmp-malloc]");
+      free(wech);
+      return 1;
+    }
+
+  r=cd->info.tracks;
+  for (i=0; i<cd->info.tracks; i++)
+    {
+      if (!cd->info.track[i].data)
+	wech[i]=0;
+      else
+	{
+	  wech[i]=1;
+	  r--;
+	}
+    }
+  
+
+  while (r)
+    {
+      i=random()%r;
+      for (j=0; j<cd->info.tracks; j++)
+	{
+	  if (i)
+	    i--;
+	  else if (!i && !wech[j])
+	    {
+	      cd->info.list.track[cd->info.list.tracks++]=cd->info.track[j];
+	      cd->info.list.length=addMSF(cd->info.list.length,
+					  cd->info.list.track[cd->info.list.tracks-1].length);
+	      wech[j]++;
+	      r--;
+	      break;
+	    }
+	}
+    }
+
+  cd_play(cd,play_type)=CDP_RANDOM;
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_randomize[DEBUG]: cd playlist randomized\n");
+#endif
+
+  return 0;
+}
+
+/*
+ * cd_setpl(cd,list)
+ *
+ * set the playlist of cd to list
+ */
+int cd_setpl(CD *cd, CDPlayList *list)
+{
+  if (cd==NULL || list==NULL)
+    return 1;
+
+  if (cd->info.list.track!=NULL)
+    free(cd->info.list.track);
+
+  cd->info.list.track=(TrackInfo *)malloc(list->allocated*sizeof(TrackInfo));
+  if (cd->info.list.track==NULL)
+    {
+      perror("cd_setpl[malloc]");
+      return 2;
+    }
+
+  cd->info.list.length=list->length;
+  cd->info.list.allocated=list->allocated;
+  cd->info.list.tracks=list->tracks;
+  memcpy(cd->info.list.track,list->track,list->allocated*sizeof(TrackInfo));
+
+#ifdef DEBUG
+  fprintf(stderr,"cd_setpl[DEBUG]: cd playlist set to playlist 0x%08x\n",list);
+#endif
+
+  return 0;
+}
+
+/*
+ * cdpl_new()
+ *
+ * create a new empty playlist structure
+ */
+CDPlayList *cdpl_new()
+{
+  CDPlayList *new;
+
+  new=(CDPlayList *)malloc(sizeof(CDPlayList));
+  if (new==NULL)
+    {
+      perror("cdpl_new[malloc]");
+      return NULL;
+    }
+  memset(new,0,sizeof(CDPlayList));
+
+#ifdef DEBUG
+  fprintf(stderr,"cdpl_new[DEBUG]: new playlist created (0x%08x)\n",new);
+#endif
+
+  return new;
+}
+
+/*
+ * cdpl_free(list)
+ *
+ * free the memory occupied by a playlist
+ */
+int cdpl_free(CDPlayList *list)
+{
+  if (list)
+    {
+#ifdef DEBUG
+      fprintf(stderr,"cdpl_free[DEBUG]: free playlist 0x%08x\n",list);
+#endif
+      if (list->track)
+	free(list->track);
+      free(list);
+    }
+  return 0;
+}
+
+/*
+ * cdpl_add(cd,track)
+ *
+ * add track to list
+ */
+int cdpl_add(CDPlayList *list, CD *cd, int track)
+{
+  if (list==NULL || track>=cd->info.tracks || track<0)
+    return 1;
+
+  if (list->track==NULL)
+    {
+      list->track=(TrackInfo *)malloc(10*sizeof(TrackInfo));
+      list->allocated=10;
+      list->tracks=0;
+    }
+  else if (list->allocated==list->tracks)
+    {
+      TrackInfo *new;
+      list->allocated+=10;
+      new=realloc(list->track,list->allocated*sizeof(TrackInfo));
+      if (new==NULL)
+	{
+	  perror("cdpl_add[realloc]");
+	  return 2;
+	}
+      list->track=new;
+    }
+
+  list->track[list->tracks++]=cd->info.track[track];
+  list->length=addMSF(list->length,cd->info.track[track].length);
+
+#ifdef DEBUG
+  fprintf(stderr,"cdpl_add[DEBUG]: track %d added to playlist 0x%08x (size %d)\n",
+	  cd->info.track[track].num,list,list->tracks);
+#endif
+
+  return 0;
+}
+
+/*
+ * cdpl_reset(list)
+ *
+ * set the playlist to zero tracks
+ */
+int cdpl_reset(CDPlayList *list)
+{
+  if (list==NULL)
+    return 1;
+
+  if (list->track)
+    free(list->track);
+
+  memset(list,0,sizeof(CDPlayList));
+
+#ifdef DEBUG
+  fprintf(stderr,"cdpl_reset[DEBUG]: playlist 0x%08x reseted\n",list);
+#endif
+
+  return 0;
+}
diff --git a/cdrom.h b/cdrom.h
new file mode 100644
index 0000000..d797d05
--- /dev/null
+++ b/cdrom.h
@@ -0,0 +1,147 @@
+/*
+ * $Id: cdrom.h,v 1.1.1.1 2001/02/12 22:25:42 xtifr Exp $
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+
+#ifndef _MY_CDROM_H
+#define _MY_CDROM_H
+
+/* cd status modes */
+#define CDM_CLOSED -1
+#define CDM_COMP    0
+#define CDM_PLAY    1
+#define CDM_PAUSE   2
+#define CDM_STOP    3
+#define CDM_EJECT   CDM_CLOSED
+
+/* cd actions */
+#define CDA_NONE    0
+#define CDA_STOP    1
+#define CDA_PLAY    2
+#define CDA_PAUSE   3
+
+/* repeatmode */
+#define CDR_NONE    0
+#define CDR_ONE     1
+#define CDR_ALL     2
+
+/* playtype */
+#define CDP_NORMAL  0
+#define CDP_RANDOM  1
+
+typedef struct {
+  int minute;
+  int second;
+  int frame;
+} MSF;
+
+#define FRAMES 75
+#define SECONDS 60
+
+#define fSecs(f) (int)(f/FRAMES)
+#define fMins(f) (int)(f/FRAMES/SECONDS)
+
+#define msfFrames(msf) (((msf.minute*SECONDS)+msf.second)*FRAMES+msf.frame)
+#define msfSecs(msf)   (((msf.minute*SECONDS)+msf.second)
+
+#define MSFnone(msf)   msf.minute=msf.second=msf.frame=-1
+#define MSFzero(msf)   msf.minute=msf.second=msf.frame=0
+
+typedef struct {
+  int num;
+  MSF start;  /* real start */
+  MSF end;    /* start of the next track == end */
+  MSF length; /* length of the track in MSF */
+  int data;   /* datatrack? */
+} TrackInfo;
+
+typedef struct {
+  int mode;
+  int track;
+  MSF relmsf;
+  MSF absmsf;
+} CDPosition;
+
+typedef struct {    /* stores information about the last play action */
+  int last_action;  /* last action, needed for auto-play-next-in-list */
+  int cur_track;    /* this is the automatical up-counted track within the list */
+  int cur_end;      /* this is the calculated end of an uninterupted sequence */
+  int repeat_mode;  /* repeat some or all or none */
+  int play_type;    /* normal or random */
+} CDPlayInfo;
+
+typedef struct {    /* stores a array of tracks to play */
+  MSF length;       /* length of the play list */
+  int allocated;    /* tracks allacated in track entry */
+  int tracks;       /* number of tracks in the play list */
+  TrackInfo *track; /* the tracks */
+} CDPlayList;
+
+typedef struct {
+  CDPosition    current;
+  CDPlayInfo    play;
+  CDPlayList    list;    /* is initialized with all non-data tracks */
+  unsigned long discid;
+  int           start;   /* first track of the cd */
+  int           end;     /* last track of the cd */
+  int           tracks;  /* number of tracks (end-start)+1 */
+  TrackInfo     *track;
+} CDInfo;
+
+typedef struct {
+  int    fd;
+  char   *device;
+  int    status;   /* this keeps the return value of cd_getStatus() */
+  CDInfo info;     /* only one cd per device, anything else is stupid */
+} CD;
+
+CD *cd_open(char *device, int noopen);
+int cd_reopen(CD *cd);
+int cd_suspend(CD *cd);
+void cd_close(CD *cd);
+
+void cd_freeinfo(CD *cd);
+
+int cd_getStatus(CD *cd, int reopen, int force);
+
+/*
+ * all cd_do* commands assume that prior to their call a cd_getStatus
+ * is done to update the CDPosition struct of the cd
+ */
+int cd_playMSF(CD *cd, MSF start, MSF end);
+int cd_doPlay(CD *cd, int start);
+int cd_doSkip(CD *cd, int secs);
+int cd_doPause(CD *cd);
+int cd_doStop(CD *cd);
+int cd_doEject(CD *cd);
+
+int cmpMSF(MSF a, MSF b);
+MSF subMSF(MSF a, MSF b);
+MSF addMSF(MSF a, MSF b);
+MSF normMSF(MSF msf);
+
+/*
+ * play list functions
+ *
+ * first the CD internal stuff
+ */
+int cd_resetpl(CD *cd);
+int cd_findtrack(CD *cd, int num);
+int cd_randomize(CD *cd);
+int cd_setpl(CD *cd, CDPlayList *list);
+
+/*
+ * now extra play lists
+ */
+CDPlayList *cdpl_new();
+int cdpl_free(CDPlayList *list);
+int cdpl_add(CDPlayList *list, CD *cd, int track);
+int cdpl_reset(CDPlayList *list);
+
+#define cd_info(c,w) (c->info.##w)
+#define cd_cur(c,w)  (c->info.current.##w)
+#define cd_play(c,w) (c->info.play.##w)
+#define cd_list(c,w) (c->info.list.##w)
+
+#endif
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..f6dc4ce
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,7 @@
+/* config.h.in.  Generated automatically from configure.in by autoheader.  */
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if you want GNUstep compilant paths.  */
+#undef HAVE_GNUSTEP
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..1dc5fa1
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,118 @@
+dnl
+dnl WMRack autoconf stuff
+dnl
+dnl Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+dnl
+
+AC_INIT(wmrack.c)
+AC_CONFIG_HEADER(config.h)
+
+dnl package switches
+dnl
+dnl AC_ARG_WITH(cdplayer,[  --with-cdplayer	Include cdplayer support.])
+dnl AC_ARG_WITH(mixer,   [  --with-mixer	Include mixer support.])
+AC_ARG_WITH(ctrl, \
+[  --without-ctrl          Compile without command line tools.],[],[with_ctrl="yes"])
+AC_ARG_WITH(debug, \
+[  --without-debug         Compile without extra debug messages.],[],[with_debug="yes"])
+AC_ARG_WITH(gnustep, \
+[  --without-gnustep       Don't use GNUstep style library paths.])
+
+dnl check for standart compile && install stuff
+dnl
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+
+AC_SUBST(INSTALL)
+
+dnl check for needed headers
+dnl
+AC_HEADER_STDC
+AC_CHECK_HEADER(unistd.h)
+
+dnl Check for Linux CDROM support
+dnl
+dnl if test "x${enable_cdplayer}" = "xno"; then
+dnl   AC_MSG_WARN([cdplayer feature disabled])
+dnl else
+dnl   AC_MSG_CHECKING([for cdplayer support])
+dnl   AC_EGREP_HEADER([struct cdrom_msf],linux/cdrom.h,[echo yes
+dnl AC_DEFINE(WITH_CDPLAYER,linux)],[echo no])
+dnl fi
+
+dnl Check for Linux MIXER support
+dnl
+dnl if test "x${enable_mixer}" = "xno"; then
+dnl   AC_MSG_WARN([mixer feature disabled])
+dnl else
+dnl   AC_MSG_CHECKING([for mixer support])
+dnl   AC_EGREP_HEADER([typedef struct mixer_info],linux/soundcard.h,[echo yes
+dnl AC_DEFINE(WITH_MIXER,linux)],[echo no])
+dnl fi
+
+dnl check for X11
+dnl
+AC_PATH_X
+if test "x$no_x" = "xyes"; then
+  AC_MSG_ERROR([WMRack needs X Windows!!!])
+else
+  CFLAGS="$CFLAGS -I${x_includes}"
+  LIBS="$LIBS -L${x_libraries} -lX11"
+fi
+
+dnl check for Xpm
+dnl
+AC_CHECK_LIB(Xpm,XpmCreatePixmapFromBuffer,\
+	[LIBS="$LIBS -lXpm"],\
+	AC_MSG_ERROR([WMRack needs XPM support!!!]),\
+	-lX11)
+
+dnl check for Shape extensions
+dnl
+AC_CHECK_HEADER(X11/extensions/shape.h,[],\
+	[AC_MSG_ERROR([WMRack needs X11 Shape extensions!!!])])
+AC_CHECK_LIB(Xext,XShapeCombineMask,\
+	[LIBS="$LIBS -lXext"],\
+	AC_MSG_ERROR([WMRack needs the X11 extension library!!!]),\
+	-lX11)
+
+dnl check for extra package options
+dnl
+echo
+
+dnl command line tools
+if test "x${with_ctrl}" = "xyes"; then
+  echo "compiling the extra command line tools"
+  CTRL="cdctrl mixctrl"
+else
+  CTRL=""
+fi
+AC_SUBST(CTRL)
+
+dnl DEBUG
+if test "x${with_debug}" = "xyes"; then
+  echo "adding extra DEBUG output"
+  CFLAGS="-ggdb -DDEBUG $CFLAGS"
+fi
+
+dnl GNUstep paths
+if test "x${with_gnustep}" = "xno"; then
+  echo "GNUstep path standarts disabled"
+else
+  echo -n "Trying to detect GNUstep paths..."
+  if test -d "$prefix/GNUstep" -o -d "$ac_default_prefix/GNUstep"; then
+    libdir=[\${prefix}/GNUstep/Library]
+    echo " $libdir"
+    AC_DEFINE(HAVE_GNUSTEP)
+  else
+    echo " NOT FOUND -- DISABLED"
+  fi
+fi
+
+echo
+
+dnl All done
+dnl create output
+dnl
+AC_OUTPUT(Makefile XPM/Makefile)
diff --git a/install-sh b/install-sh
new file mode 100644
index 0000000..ebc6691
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/library.c b/library.c
new file mode 100644
index 0000000..64e1e91
--- /dev/null
+++ b/library.c
@@ -0,0 +1,163 @@
+/*
+ * $Id: library.c,v 1.1.1.1 2001/02/12 22:25:47 xtifr Exp $
+ *
+ * part of wmrack
+ *
+ * handles the library path searchs
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "config.h"
+#include "library.h"
+
+static char *lib_mode[]={"", "r", "w", "a"};
+
+#ifdef HAVE_GNUSTEP
+static char *lib_global_path[]={"/usr/local/GNUstep/Library/WMRack/",
+				"/usr/GNUstep/Library/WMRack/",
+				NULL};
+
+static char *lib_personal_path[]={"/GNUstep/Library/WMRack/",
+				  NULL};
+#else
+static char *lib_global_path[]={"/usr/X11R6/lib/X11/WMRack/",
+				NULL};
+
+static char *lib_personal_path[]={"/.wmrack/",
+				  NULL};
+#endif /* HAVE_GNUSTEP */
+
+static char lib_stat_path[4096]="";
+
+char *lib_findfile(char *name, int here)
+{
+  char path[4096]="";
+  int i;
+  struct stat st;
+
+  if (here)
+    {
+      strcpy(path,name);
+      if (stat(path,&st)!=0)
+	*path=0;
+    }
+
+  if (*path==0)
+    for (i=0; lib_personal_path[i]; i++)
+      {
+	strcpy(path,getenv("HOME"));
+	strcat(path,lib_personal_path[i]);
+	if (here)
+	  {
+	    strcat(path,name);
+	    if (stat(path,&st)==0)
+	      break;
+	  }
+	else
+	  if (stat(path,&st)==0)
+	    {
+	      strcat(path,name);
+	      break;
+	    }
+	*path=0;
+      }
+
+  if (*path==0)
+    {
+      for (i=0; lib_global_path[i]; i++)
+	{
+	  strcpy(path,lib_global_path[i]);
+	  strcat(path,name);
+	  if (stat(path,&st)==0)
+	    break;
+	  *path=0;
+	}
+      if (*path==0)
+	{
+	  strcpy(path,getenv("HOME"));
+	  strcat(path,lib_personal_path[0]);
+	  if (mkdir(path,0755))
+	    return NULL;
+	  strcat(path,name);
+	}
+    }
+
+  strcpy(lib_stat_path,path);
+
+  return lib_stat_path;
+}
+
+LIBRARY *lib_open(char *name, int mode)
+{
+  char *p=NULL;
+  LIBRARY *lib=NULL;
+  FILE *f=NULL;
+
+  p=lib_findfile(name,0);
+  if (p==NULL)
+    return NULL;
+
+  f=fopen(p,lib_mode[mode]);
+  if (f!=NULL)
+    {
+      lib=(LIBRARY *)malloc(sizeof(LIBRARY));
+      lib->name=strdup(p);
+      lib->f=fopen(lib->name,lib_mode[mode]);
+      lib->mode=mode;
+    }
+  return lib;
+}
+
+int lib_close(LIBRARY *lib)
+{
+  fclose(lib->f);
+  lib->f=NULL;
+  lib->mode=LIB_CLOSED;
+  return 0;
+}
+
+int lib_free(LIBRARY *lib)
+{
+  lib_close(lib);
+  free(lib->name);
+  free(lib);
+  return 0;
+}
+
+int lib_reopen(LIBRARY *lib, int mode)
+{
+  lib_close(lib);
+  lib->f=fopen(lib->name,lib_mode[mode]);
+  if (lib->f==NULL)
+    return -1;
+  return 0;
+}
+
+char *lib_gets(LIBRARY *lib, char *line, int len)
+{
+  if (lib->mode==LIB_READ)
+    return fgets(line,len,lib->f);
+  return NULL;
+}
+
+int lib_printf(LIBRARY *lib, char *format, ...)
+{
+  va_list args;
+  int s;
+
+  if (lib->mode==LIB_READ)
+    return 0;
+  va_start(args,format);
+  s=vfprintf(lib->f,format,args);
+  va_end(args);
+  return s;
+}
diff --git a/library.h b/library.h
new file mode 100644
index 0000000..e1aaf29
--- /dev/null
+++ b/library.h
@@ -0,0 +1,33 @@
+/*
+ * $Id: library.h,v 1.1.1.1 2001/02/12 22:25:47 xtifr Exp $
+ *
+ * part of wmrack
+ *
+ * handles the library path searchs
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+#ifndef _LIBRARY_H
+#define _LIBRARY_H
+
+#define LIB_CLOSED 0
+#define LIB_READ   1
+#define LIB_WRITE  2
+#define LIB_APPEND 3
+
+typedef struct
+{
+  FILE *f;
+  char *name;
+  int mode;
+} LIBRARY;
+
+char *lib_findfile(char *name, int here);
+LIBRARY *lib_open(char *name, int mode);
+int lib_close(LIBRARY *lib);
+int lib_free(LIBRARY *lib);
+int lib_reopen(LIBRARY *lib, int mode);
+char *lib_gets(LIBRARY *lib, char *line, int len);
+int lib_printf(LIBRARY *lib, char *format, ...);
+
+#endif
diff --git a/mixctrl.c b/mixctrl.c
new file mode 100644
index 0000000..2386945
--- /dev/null
+++ b/mixctrl.c
@@ -0,0 +1,141 @@
+/*
+ * $Id: mixctrl.c,v 1.1.1.1 2001/02/12 22:25:47 xtifr Exp $
+ *
+ * Part of WMRack
+ *
+ * command line tool to control the mixer
+ * created to test the mixer control stuff
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mixer.h"
+
+void usage()
+{
+  fprintf(stderr,"Usage: mixctrl [-d DEVICE] [CHANNELNAME|CHANNELNUM] [0-100|0-100:0-100|src|nosrc|exsrc]\n");
+}
+
+int main(int argc, char **argv)
+{
+  MIXER *mix;
+  int fa=1, i, volid, left=0, right=0, command=0;
+  char *device="/dev/mixer", *d1;
+
+  if (argc<1)
+    {
+      usage();
+      exit(EXIT_FAILURE);
+    }
+
+  if (argc>2 && strcmp(argv[1],"-d")==0)
+    {
+      device=argv[2];
+      argc-=2;
+      fa=3;
+    }
+
+  if (argc>2)
+    {
+      volid=strtol(argv[fa],&d1,10);
+      if (*d1!=0)
+	{
+	  for (volid=0; volid<mixer_devices; volid++)
+	    if (strcmp(argv[fa],mixer_names[volid])==0)
+	      break;
+	}
+      d1=strchr(argv[fa+1],':');
+      if (d1)
+	{
+	  *d1++=0;
+	  left=atoi(argv[fa+1]);
+	  right=atoi(d1);
+	  command=1;
+	}
+      else
+	{
+	  if (strcmp(argv[fa+1],"src")==0)
+	    command=2;
+	  else if (strcmp(argv[fa+1],"nosrc")==0)
+	    command=3;
+	  else if (strcmp(argv[fa+1],"exsrc")==0)
+	    command=4;
+	  else
+	    {
+	      left=atoi(argv[fa+1]);
+	      command=0;
+	    }
+	}
+    }
+
+  mix=mixer_open(device);
+  if (mix==NULL)
+    printf("Can't open mixer\n");
+  else
+    {
+      printf("Mixer initialized\n");
+      printf("Mixer id %s, Mixer name %s\n",mix->id,mix->name);
+      printf("Supported devices:\n");
+      for (i=0; i<mixer_devices; i++)
+	if (mixer_isdevice(mix,i))
+	  {
+	    if (mixer_isstereo(mix,i))
+	      printf("  %2d - %-8s (%3d:%3d) %s%s\n",i,mixer_names[i],
+		     mixer_volleft(mix,i),mixer_volright(mix,i),
+		     (mixer_isrecdev(mix,i)?"REC":""),
+		     (mixer_isrecsrc(mix,i)?"SRC":""));
+	    else
+	      printf("  %2d - %-8s (  %3d  ) %s%s\n",i,mixer_names[i],
+		     mixer_volmono(mix,i),
+		     (mixer_isrecdev(mix,i)?"REC":""),
+		     (mixer_isrecsrc(mix,i)?"SRC":""));
+	  }
+    }
+
+  if (volid<mixer_devices)
+    {
+      switch (command)
+	{
+	case 0:
+	  printf("Setting %s to volume %d\n",mixer_names[volid],left);
+	  mixer_setvol(mix,volid,left);
+	  break;
+	case 1:
+	  printf("Setting %s to volume %d:%d\n",mixer_names[volid],left,right);
+	  mixer_setvols(mix,volid,left,right);
+	  break;
+	case 2:
+	  printf("Setting %s as recsrc\n",mixer_names[volid]);
+	  mixer_setrecsrc(mix,volid,1,0);
+	  break;
+	case 3:
+	  printf("Clearing recsrc of %s\n",mixer_names[volid]);
+	  mixer_setrecsrc(mix,volid,0,0);
+	  break;
+	case 4:
+	  printf("Setting %s as exclusive recsrc\n",mixer_names[volid]);
+	  mixer_setrecsrc(mix,volid,1,1);
+	  break;
+	}
+	if (mixer_isdevice(mix,volid))
+	  {
+	    if (mixer_isstereo(mix,volid))
+	      printf("  %2d - %-8s (%3d:%3d) %s%s\n",volid,mixer_names[volid],
+		     mixer_volleft(mix,volid),mixer_volright(mix,volid),
+		     (mixer_isrecdev(mix,volid)?"REC":""),
+		     (mixer_isrecsrc(mix,volid)?"SRC":""));
+	    else
+	      printf("  %2d - %-8s (  %3d  ) %s%s\n",volid,mixer_names[volid],
+		     mixer_volmono(mix,volid),
+		     (mixer_isrecdev(mix,volid)?"REC":""),
+		     (mixer_isrecsrc(mix,volid)?"SRC":""));
+	  }
+    }
+
+  mixer_close(mix);
+  printf("Mixer closed\n");
+  return EXIT_SUCCESS;
+}
diff --git a/mixer.c b/mixer.c
new file mode 100644
index 0000000..f5889ef
--- /dev/null
+++ b/mixer.c
@@ -0,0 +1,511 @@
+/*
+ * $Id: mixer.c,v 1.1.1.1 2001/02/12 22:25:53 xtifr Exp $
+ *
+ * mixer utility functions for WMRack
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ *
+ * this is very linux specific !!!
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <linux/soundcard.h>
+
+#include "mixer.h"
+
+char *mixer_labels[]=SOUND_DEVICE_LABELS;
+char *mixer_names[]=SOUND_DEVICE_NAMES;
+char *mixer_shortnames[]={"VO", "BA", "TR", "SY", "PC", "SP", "LI", "MI",
+			  "CD", "MX", "P2", "RE", "IG", "OG", "L1", "L2", "L3"};
+int mixer_devices=SOUND_MIXER_NRDEVICES;
+
+/*
+ * mixer_getinfo(MIXER)
+ *
+ * reads the supported devices and their capabilities
+ *
+ * returns 0 on success
+ */
+int mixer_getinfo(MIXER *mix)
+{
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (ioctl(mix->fd,SOUND_MIXER_INFO,&mix->id)) {
+    fprintf(stderr,"mixer_getinfo[info]: %s\n",strerror(errno));
+    memset(&mix->id,0,48);
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[info] - successful\n");
+#endif
+  if (ioctl(mix->fd,SOUND_MIXER_READ_DEVMASK,&mix->mask)) {
+    fprintf(stderr,"mixer_getinfo[devmask]: %s\n",strerror(errno));
+    mix->mask=0;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[devmask] - successful\n");
+#endif
+  if (ioctl(mix->fd,SOUND_MIXER_READ_STEREODEVS,&mix->stereo)) {
+    fprintf(stderr,"mixer_getinfo[stereodevs]: %s\n",strerror(errno));
+    mix->stereo=0;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[stereodevs] - successful\n");
+#endif
+  if (ioctl(mix->fd,SOUND_MIXER_READ_CAPS,&mix->caps)) {
+    fprintf(stderr,"mixer_getinfo[caps]: %s\n",strerror(errno));
+    mix->caps=0;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[caps] - successful\n");
+#endif
+  if (ioctl(mix->fd,SOUND_MIXER_READ_RECSRC,&mix->recsrc)) {
+    fprintf(stderr,"mixer_getinfo[recsrc]: %s\n",strerror(errno));
+    mix->recsrc=0;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[recsrc] - successful\n");
+#endif
+  if (ioctl(mix->fd,SOUND_MIXER_READ_RECMASK,&mix->recmask)) {
+    fprintf(stderr,"mixer_getinfo[recmask]: %s\n",strerror(errno));
+    mix->recmask=0;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_getinfo[recmask] - successful\n");
+#endif
+  return 0;
+}
+
+/*
+ * mixer_readvol(mixer,dev)
+ *
+ * reads the current volume setting of the specified device
+ *
+ * returns 0 if volume is equal to last read, 1 if volume has changed
+ * and a negative value on failure
+ */
+int mixer_readvol(MIXER *mix, int dev)
+{
+  int i;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  mix->old_vol[dev]=mix->cur_vol[dev];
+
+  if (mixer_isdevice(mix,dev))
+    {
+      if (ioctl(mix->fd,MIXER_READ(dev),&mix->cur_vol[dev]))
+	{
+	  fprintf(stderr,"mixer_readvol[%s]: %s\n",mixer_names[dev],strerror(errno));
+	  mix->cur_vol[dev]=-1;
+	}
+      else
+	if (mix->old_vol[dev]!=mix->cur_vol[dev])
+	  return 1;
+    }
+  else
+    mix->cur_vol[i]=-1;
+
+  return 0;
+}
+
+/*
+ * mixer_readvols(MIXER)
+ *
+ * reads the current volume settings of all supported devices
+ *
+ * returns 0 if volume is equal to last read, 1 if volume has changed
+ * and a negative value on failure
+ */
+int mixer_readvols(MIXER *mix)
+{
+  int i, change=0;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  memcpy(mix->old_vol,mix->cur_vol,sizeof(int)*32);
+
+  for (i=0; i<mixer_devices; i++)
+    {
+      if (mixer_isdevice(mix,i))
+	{
+	  if (ioctl(mix->fd,MIXER_READ(i),&mix->cur_vol[i]))
+	    {
+	      fprintf(stderr,"mixer_readvol[%s]: %s\n",mixer_names[i],strerror(errno));
+	      mix->cur_vol[i]=-1;
+	      /* mix->mask&=~(1<<i); */
+	    }
+	  else
+	    change|=mix->old_vol[i]!=mix->cur_vol[i];
+	}
+      else
+	mix->cur_vol[i]=-1;
+    }
+
+  return change;
+}
+
+/*
+ * mixer_open(char)
+ *
+ * opens the specified device as mixer and call getinfo and readvols
+ *
+ * returns a pointer to a MIXER struct on success or NULL on failure
+ */
+MIXER *mixer_open(char *device)
+{
+  MIXER *mix=NULL;
+  mix=malloc(sizeof(MIXER));
+  if (mix==NULL)
+    {
+      perror("mixer_open[malloc]");
+      return NULL;
+    }
+  mix->fd=open(device,0);
+  if (mix->fd<0) {
+    fprintf(stderr,"mixer_open: %s\n",strerror(errno));
+    free(mix);
+    return NULL;
+  }
+  mix->device=strdup(device);
+  mixer_getinfo(mix);
+  mixer_readvols(mix);
+  return mix;
+}
+
+/*
+ * mixer_close(MIXER)
+ *
+ * closes the mixer and frees all data
+ */
+void mixer_close(MIXER *mix)
+{
+  if (mix) {
+    close(mix->fd);
+    if (mix->device)
+      free(mix->device);
+    free(mix);
+  }
+}
+
+/*
+ * mixer_setvol(mix,dev,vol)
+ *
+ * sets the specified device to a mono volume
+ *
+ * returns 0 on success
+ */
+int mixer_setvol(MIXER *mix, int dev, int vol)
+{
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_setvol: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (vol<0) vol=0;
+  if (vol>100) vol=100;
+  
+  if (mixer_isstereo(mix,dev))
+    mixer_setvols(mix,dev,vol,vol);
+  else
+    {
+      vol=mixer_makevol(vol,vol);
+      if (ioctl(mix->fd,MIXER_WRITE(dev),&vol))
+	perror("mixer_setvol[write]");
+#ifdef DEBUG
+      else
+	fprintf(stderr,"mixer_setvol[set]: vol set to %02d\n",vol>>8);
+#endif
+    }
+
+  return 0;
+}
+
+/*
+ * mixer_setvols(mix,dev,left,right)
+ *
+ * sets the specified device to a stereo volume
+ *
+ * returns 0 on success
+ */
+int mixer_setvols(MIXER *mix, int dev, int left, int right)
+{
+  int vol;
+  
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_setvols: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (left<0) left=0;
+  if (left>100) left=100;
+  if (right<0) right=0;
+  if (right>100) right=100;
+  vol=mixer_makevol(left,right);
+
+  if (mixer_ismono(mix,dev))
+    mixer_setvol(mix,dev,(left+right)/2);
+  else
+    {
+      if (ioctl(mix->fd,MIXER_WRITE(dev),&vol))
+	perror("mixer_setvols[write]");
+#ifdef DEBUG
+      else
+	fprintf(stderr,"mixer_setvols[set]: vol set to %02d:%02d\n",
+		vol&0xff,(vol>>8)&0xff);
+#endif
+    }
+
+  return 0;
+}
+
+/*
+ * mixer_setrecsrc(mix,dev,state)
+ *
+ * sets or clears the RECSRC state of the specified device
+ *
+ * returns 0 on success
+ */
+int mixer_setrecsrc(MIXER *mix, int dev, int state, int exclusive)
+{
+  int new;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (mixer_isdevice(mix,dev) && mixer_isrecdev(mix,dev))
+    {
+      mix->old_recsrc=mix->recsrc;
+      if (state)
+	{
+	  if (mix->caps&SOUND_CAP_EXCL_INPUT || exclusive)
+	    new=(1<<dev);
+	  else
+	    new=mix->recsrc|(1<<dev);
+	}
+      else
+	new=mix->recsrc&(~(1<<dev));
+#ifdef DEBUG
+      if (new==0)
+	fprintf(stderr,"mixer_setrecsrc[write]: warning, no recsrc may not be possible");
+#endif
+      if (ioctl(mix->fd,SOUND_MIXER_WRITE_RECSRC,&new))
+	perror("mixer_serrecsrc[write]");
+      else
+	{
+	  if (ioctl(mix->fd,SOUND_MIXER_READ_RECSRC,&mix->recsrc))
+	    {
+	      perror("mixer_setrecsrc[read]");
+	      mix->recsrc=0;
+	    }
+#ifdef DEBUG
+	  else
+	    fprintf(stderr,"mixer_setrecsrc[read]: %s is %s\n",
+		    mixer_names[dev],
+		    mixer_isrecsrc(mix,dev)?"RECSRC":"not RECSRC");
+#endif
+	}
+    }
+  else
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_setrecsrc: unsupported device\n");
+#endif
+      return 1;
+    }
+  return 0;  
+}
+
+int mixer_changevol(MIXER *mix, int dev, int delta)
+{
+  int left, right;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_changevol: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (mixer_isstereo(mix,dev))
+    {
+      left=mixer_volleft(mix,dev)+delta;
+      if (left<0) left=0;
+      if (left>100) left=100;
+      right=mixer_volright(mix,dev)+delta;
+      if (right<0) right=0;
+      if (right>100) right=100;
+      left=mixer_makevol(left,right);
+    }
+  else
+    {
+      left=mixer_volmono(mix,dev)+delta;
+      if (left<0) left=0;
+      if (left>100) left=100;
+      left=mixer_makevol(left,left);
+    }
+  if (ioctl(mix->fd,MIXER_WRITE(dev),&left))
+    perror("mixer_changevol[write]");
+#ifdef DEBUG
+  else
+    fprintf(stderr,"mixer_changevol[set]: vol set to %02d:%02d\n",left&0xff,left>>8);
+#endif
+
+  return 0;
+}
+
+int mixer_changeleft(MIXER *mix, int dev, int delta)
+{
+  int vol;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_changeleft: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (mixer_ismono(mix,dev))
+    mixer_changevol(mix,dev,delta);
+  else
+    {
+      vol=mixer_volleft(mix,dev)+delta;
+      if (vol<0) vol=0;
+      if (vol>100) vol=100;
+      vol=mixer_makevol(vol,mixer_volright(mix,dev));
+      if (ioctl(mix->fd,MIXER_WRITE(dev),&vol))
+	perror("mixer_changeleft[write]");
+#ifdef DEBUG
+      else
+	fprintf(stderr,"mixer_changeleft[set]: vol set to %02d:%02d\n",
+		vol&0xff,(vol>>8)&0xff);
+#endif
+    }
+
+  return 0;
+}
+
+int mixer_changeright(MIXER *mix, int dev, int delta)
+{
+  int vol;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_changeright: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (mixer_ismono(mix,dev))
+    mixer_changevol(mix,dev,delta);
+  else
+    {
+      vol=mixer_volright(mix,dev)+delta;
+      if (vol<0) vol=0;
+      if (vol>100) vol=100;
+      vol=mixer_makevol(mixer_volleft(mix,dev),vol);
+      if (ioctl(mix->fd,MIXER_WRITE(dev),&vol))
+	perror("mixer_changeright[write]");
+#ifdef DEBUG
+      else
+	fprintf(stderr,"mixer_changeright[set]: vol set to %02d:%02d\n",
+		vol&0xff,(vol>>8)&0xff);
+#endif
+    }
+
+  return 0;
+}
+
+int mixer_changebal(MIXER *mix, int dev, int delta)
+{
+  int left, right;
+
+  if (!mix || mix->fd==0)
+    return -1;
+
+  if (!mixer_isdevice(mix,dev))
+    {
+#ifdef DEBUG
+      fprintf(stderr,"mixer_changebal: unsupported device\n");
+#endif
+      return 1;
+    }
+
+  if (mixer_ismono(mix,dev))
+    mixer_changevol(mix,dev,delta);
+  else
+    {
+      left=mixer_volleft(mix,dev)-delta;
+      right=mixer_volright(mix,dev)+delta;
+      if (left<0)
+	{
+	  right+=left;
+	  left=0;
+	}
+      if (right<0)
+	{
+	  left+=right;
+	  right=0;
+	}
+      if (left>100)
+	{
+	  right+=(left-100);
+	  left=100;
+	}
+      if (right>100)
+	{
+	  left+=(right-100);
+	  right=100;
+	}
+      left=mixer_makevol(left,right);
+      if (ioctl(mix->fd,MIXER_WRITE(dev),&left))
+	perror("mixer_changebal[write]");
+#ifdef DEBUG
+      else
+	fprintf(stderr,"mixer_changebal[set]: vol set to %02d:%02d\n",
+		left&0xff,(left>>8)&0xff);
+#endif
+    }
+
+  return 0;
+}
diff --git a/mixer.h b/mixer.h
new file mode 100644
index 0000000..9ce73f3
--- /dev/null
+++ b/mixer.h
@@ -0,0 +1,59 @@
+/*
+ * $Id: mixer.h,v 1.1.1.1 2001/02/12 22:25:53 xtifr Exp $
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+
+#ifndef _MYMIXER_H
+#define _MYMIXER_H
+
+extern char *mixer_labels[];
+extern char *mixer_names[];
+extern char *mixer_shortnames[];
+extern int mixer_devices;
+
+typedef struct {
+  char *device;
+  int fd;
+  char id[16];
+  char name[32];
+  int mask;
+  int recmask;
+  int recsrc;
+  int old_recsrc;
+  int stereo;
+  int caps;
+  int cur_vol[32];
+  int old_vol[32];
+} MIXER;
+
+#define mixer_isdevice(m,d) ((d<mixer_devices)?(m->mask&(1<<d)):0)
+#define mixer_isstereo(m,d) ((d<mixer_devices)?(m->stereo&(1<<d)):0)
+#define mixer_ismono(m,d)   (!mixer_isstereo(m,d))
+#define mixer_isrecsrc(m,d) ((d<mixer_devices)?(m->recsrc&(1<<d)):0)
+#define mixer_isrecdev(m,d) ((d<mixer_devices)?(m->recmask&(1<<d)):0)
+
+#define mixer_makevol(l,r) ((r<<8)+l)
+#define mixer_volmono(m,d) ((d<mixer_devices)?((m->cur_vol[d]>>8)&0xff):-1)
+#define mixer_volleft(m,d) (mixer_isstereo(m,d)?((d<mixer_devices)?(m->cur_vol[d]&0xff):-1):mixer_volmono(m,d))
+#define mixer_volright(m,d) mixer_volmono(m,d)
+
+#define mixer_volchanged(m,d) (mixer_isdevice(m,d)?(m->old_vol[d]!=m->cur_vol[d]):0)
+#define mixer_srcchanged(m,d) (mixer_isrecdev(m,d) \
+			       ? ((m->old_recsrc&(1<<d))!=(m->recsrc&(1<<d))) \
+			       : 0)
+
+MIXER *mixer_open(char *device);
+void mixer_close(MIXER *mix);
+int mixer_readvol(MIXER *mix, int dev);
+int mixer_readvols(MIXER *mix);
+int mixer_setvol(MIXER *mix, int dev, int vol);
+int mixer_setvols(MIXER *mix, int dev, int left, int right);
+int mixer_setrecsrc(MIXER *mix, int dev, int state, int exclusive);
+
+int mixer_changevol(MIXER *mix, int dev, int delta);
+int mixer_changeleft(MIXER *mix, int dev, int delta);
+int mixer_changeright(MIXER *mix, int dev, int delta);
+int mixer_changebal(MIXER *mix, int dev, int delta);
+
+#endif /* _MYMIXER_H */
diff --git a/wmrack.c b/wmrack.c
new file mode 100644
index 0000000..b4e79b6
--- /dev/null
+++ b/wmrack.c
@@ -0,0 +1,1503 @@
+/*
+ * $Id: wmrack.c,v 1.1.1.1 2001/02/12 22:26:04 xtifr Exp $
+ *
+ * WMRack - WindowMaker Sound Control Panel
+ *
+ * Copyright (c) 1997 by Oliver Graf  <ograf at fga.de>   http://www.fga.de/~ograf/
+ *
+ * ascd originally by Rob Malda <malda at cs.hope.edu>   http://www.cs.hope.edu/~malda/
+ *
+ * This is an 'WindowMaker Look & Feel' Dock applet that can be
+ * used to control the cdrom and the mixer.
+ *
+ * Should also work swallowed in any fvwm compatible button bar.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/xpm.h>
+#include <X11/extensions/shape.h>
+
+#include "xpmicon.h"
+#include "cdrom.h"
+#include "mixer.h"
+#include "library.h"
+
+/* Functions *****************************************************************/
+void  usage();
+void  parseCmdLine(int argc, char *argv[]);
+void  initHandler();
+void  createWindow(int, char **);
+void  shutDown(int);
+void  mainLoop();
+int   flushExpose(Window w);
+void  redrawWindow();
+void  redrawDisplay(int force_win, int force_disp);
+Pixel getColor(char *name);
+Time  getTime();
+int   loadMixerRC();
+int   saveMixerRC();
+void  rack_popup(char *msg);
+
+/* Global stuff **************************************************************/
+Display *Disp;
+Window Root;
+Window Iconwin;
+Window Win;
+char *Geometry=0;
+GC WinGC;
+
+/* varibles for the options */
+char *StyleXpmFile=NULL;
+char *LedColor=NULL;
+char *BackColor=NULL;
+char CdDevice[1024]="/dev/cdrom";
+char MixerDevice[1024]="/dev/mixer";
+int  withdraw=0;
+int noprobe=0;
+
+MSF last_time={-1,-1,-1};
+int last_track=-1;
+int last_cdmode=-1; /* to sense a change */
+int displaymode=0;  /* bit 1 is run/remain, bit 2 is track/total */
+int newdisc=0;
+int curMixer=0;     /* this is the device number of the currently shown mixer scale */
+int lastMixer=0;
+char *popup_display=NULL;
+time_t popup_time=0;
+int popup_done=0;
+
+/* Mode of WMRack */
+#define MODE_CDPLAYER 0
+#define MODE_MIXER    1
+int WMRack_Mode=MODE_CDPLAYER;
+
+/* our cd device */
+CD *cd=NULL;
+CDPlayList *playlist=NULL;
+int start_track=0;
+
+/* and the mixer */
+MIXER *mixer=NULL;
+int mixer_order[32], mixer_max=0;
+LIBRARY *mixer_lib=NULL;
+
+/*
+ * start the whole stuff and enter the MainLoop
+ */
+int main(int argc,char *argv[])
+{
+  struct timeval tm;
+  parseCmdLine(argc, argv);
+  cd=cd_open(CdDevice,noprobe);
+  if (cd_getStatus(cd,0,1)>0)
+    {
+      if (cd_list(cd,tracks)==0)
+	{
+	  rack_popup("DATA");
+	  cd_suspend(cd);
+	}
+      else
+	newdisc=1;
+    }
+  mixer=mixer_open(MixerDevice);
+  loadMixerRC();
+#ifdef DEBUG
+  fprintf(stderr,"wmrack: Mixer RC loaded\n");
+#endif
+  initHandler();
+  gettimeofday(&tm,NULL);
+  srandom(tm.tv_usec^tm.tv_sec);
+  createWindow(argc, argv);
+  mainLoop();
+  return 0;
+}
+
+/*
+ * usage()
+ *
+ * print out usage text and exit
+ */
+void usage()
+{
+  fprintf(stderr,"wmrack - Version 1.0b5\n");
+  fprintf(stderr,"usage: wmrack [OPTIONS] \n");
+  fprintf(stderr,"\n");
+  fprintf(stderr,"OPTION                  DEFAULT        DESCRIPTION\n");
+  fprintf(stderr,"-b|--background COLSPEC black          color of the led background\n");
+  fprintf(stderr,"-d|--device DEV         /dev/cdrom     device of the Drive\n");
+  fprintf(stderr,"-h|--help               none           display help\n");
+  fprintf(stderr,"-l|--ledcolor COLSPEC   green          set the color of the led\n");
+  fprintf(stderr,"-m|--mixer DEV          /dev/mixer     device of the Mixer\n");
+  fprintf(stderr,"-p|--noprobe            off            disable the startup probe\n");
+  fprintf(stderr,"-s|--style STYLEFILE    compile-time   load an alternate set of xpm\n");
+  fprintf(stderr,"-w|--withdrawn          off            start withdrawn or not\n");
+  fprintf(stderr,"-M|--mode [cd|mixer]    cd             start in which mode\n");
+  fprintf(stderr,"\n");
+  exit(1);
+}
+
+/*
+ * parseCmdLine(argc,argv)
+ *
+ * parse the command line args
+ */
+void parseCmdLine(int argc, char *argv[])
+{
+  int i, j;
+  char opt;
+  struct {char *name, option;} Options[]={{"background",'b'},
+					  {"device",'d'},
+					  {"withdrawn",'w'},
+					  {"help",'h'},
+					  {"ledcolor",'l'},
+					  {"mixer",'m'},
+					  {"style",'s'},
+					  {"noprobe",'p'},
+					  {"mode",'M'},
+					  {NULL,0}};
+
+  for(i=1; i<argc; i++)
+    {
+      if (argv[i][0]=='-')
+	{
+	  if (argv[i][1]=='-')
+	    {
+	      for (j=0; Options[j].name!=NULL; j++)
+		if (strcmp(Options[j].name,argv[i]+2)==0)
+		  {
+		    opt=Options[j].option;
+		    break;
+		  }
+	      if (Options[j].name==NULL)
+		usage();
+	    }
+	  else
+	    {
+	      if (argv[i][2]!=0)
+		usage();
+	      opt=argv[i][1];
+	    }
+	  switch (opt)
+	    {
+	    case 'b':  /* Led Color */
+	      if (++i>=argc)
+		usage();
+	      BackColor=strdup(argv[i]);
+	      continue;
+	    case 'd':  /* Device */
+	      if (++i>=argc)
+		usage();
+	      strcpy(CdDevice,argv[i]);
+	      continue;
+	    case 'w':  /* start Withdrawn */
+	      withdraw=1;
+	      continue;
+	    case 'h':  /* usage */
+	      usage();
+	      break;
+	    case 'l':  /* Led Color */
+	      if (++i>=argc)
+		usage();
+	      LedColor=strdup(argv[i]);
+	      continue;
+	    case 'm':  /* Device */
+	      if (++i>=argc)
+		usage();
+	      strcpy(MixerDevice,argv[i]);
+	      continue;
+	    case 's':
+	      if (++i>=argc)
+		usage();
+	      StyleXpmFile=strdup(argv[i]);
+	      continue;
+	    case 'p':
+	      noprobe=1;
+	      continue;
+	    case 'M':
+	      if (++i>=argc)
+		usage();
+	      if (strcmp(argv[i],"cd")==0)
+		{
+		  WMRack_Mode=MODE_CDPLAYER;
+		  curRack=RACK_NODISC;
+		}
+	      else if (strcmp(argv[i],"mixer")==0)
+		{
+		  WMRack_Mode=MODE_MIXER;
+		  curRack=RACK_MIXER;
+		}
+	      continue;
+	    default:
+	      usage();
+	    }
+	}
+      else
+	usage();
+    }
+
+}
+
+/*
+ * initHandler()
+ *
+ * inits the signal handlers
+ */
+void initHandler()
+{
+  struct sigaction sa;
+  sa.sa_handler=shutDown;
+  sigfillset(&sa.sa_mask);
+  sa.sa_flags=0;
+  sa.sa_restorer=NULL;
+  sigaction(SIGTERM,&sa,NULL);
+  sigaction(SIGINT,&sa,NULL);
+  sigaction(SIGHUP,&sa,NULL);
+  sigaction(SIGQUIT,&sa,NULL);
+  sigaction(SIGPIPE,&sa,NULL);
+  sa.sa_handler=SIG_IGN;
+  sigaction(SIGUSR1,&sa,NULL);
+  sigaction(SIGUSR2,&sa,NULL);
+}
+
+/*
+ * createWindow(argc,argv)
+ *
+ * create the basic shaped window and set all the required stuff
+ */
+void createWindow(int argc, char **argv)
+{
+  int i;
+  unsigned int borderwidth ;
+  char *display_name=NULL;
+  char *wname="wmrack";
+  XGCValues gcv;
+  unsigned long gcm;
+  XTextProperty name;
+  Pixel back_pix, fore_pix;
+  int screen;
+  int x_fd;
+  int d_depth;
+  int ScreenWidth, ScreenHeight;
+  XSizeHints SizeHints;
+  XWMHints WmHints;
+  XClassHint classHint;
+
+  /* Open display */
+  if (!(Disp = XOpenDisplay(display_name)))
+    {
+      fprintf(stderr,"wmrack: can't open display %s\n", XDisplayName(display_name));
+      exit (1);
+    }
+
+  screen=DefaultScreen(Disp);
+  Root=RootWindow(Disp, screen);
+  d_depth=DefaultDepth(Disp, screen);
+  x_fd=XConnectionNumber(Disp);
+  ScreenHeight=DisplayHeight(Disp,screen);
+  ScreenWidth=DisplayWidth(Disp,screen);
+
+  xpm_setDefaultAttr(Disp,Root,LedColor,BackColor);
+  if (StyleXpmFile)
+    {
+      if (xpm_loadSet(Disp,Root,StyleXpmFile))
+	{
+	  fprintf(stderr,"wmrack: can't load and create pixmaps\n");
+	  XCloseDisplay(Disp);
+	  exit(1);
+	}
+    }
+  else if (xpm_setDefaultSet(Disp,Root,RACK_MAX))
+    {
+      fprintf(stderr,"wmrack: can't create pixmaps\n");
+      XCloseDisplay(Disp);
+      exit(1);
+    }
+
+  SizeHints.flags=USSize|USPosition;
+  SizeHints.x=0;
+  SizeHints.y=0;
+  back_pix=getColor("white");
+  fore_pix=getColor("black");
+
+  XWMGeometry(Disp, screen, Geometry, NULL, (borderwidth=1), &SizeHints,
+	      &SizeHints.x,&SizeHints.y,&SizeHints.width,
+	      &SizeHints.height, &i);
+
+  SizeHints.width=currentXpm(attributes).width;
+  SizeHints.height=currentXpm(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="wmrack";
+  classHint.res_class="WMRack";
+  XSetClassHint(Disp, Win, &classHint);
+
+  XSelectInput(Disp, Win, (ExposureMask|ButtonPressMask|ButtonReleaseMask
+			   |StructureNotifyMask|ButtonMotionMask));
+  XSelectInput(Disp, Iconwin, (ExposureMask|ButtonPressMask|ButtonReleaseMask
+			       |StructureNotifyMask|ButtonMotionMask));
+
+  if (XStringListToTextProperty(&wname, 1, &name) ==0)
+    {
+      fprintf(stderr, "wmrack: 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);
+
+  XShapeCombineMask(Disp, Win, ShapeBounding, 0, 0,
+		    currentXpm(mask), ShapeSet);
+  XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0,
+		    currentXpm(mask), ShapeSet);
+
+  WmHints.initial_state=withdraw?WithdrawnState:NormalState;
+  WmHints.icon_window=Iconwin;
+  WmHints.window_group=Win;
+  WmHints.icon_x=SizeHints.x;
+  WmHints.icon_y=SizeHints.y;
+  WmHints.flags=StateHint|IconWindowHint|IconPositionHint|WindowGroupHint;
+  XSetCommand(Disp, Win, argv, argc);
+  XSetWMHints(Disp, Win, &WmHints);
+  XMapWindow(Disp,Win);
+  redrawDisplay(1,1);
+}
+
+/*
+ * shutDown(int sig)
+ *
+ * handler for signal and close-down function
+ */
+void shutDown(int sig)
+{
+#ifdef DEBUG
+  if (sig)
+    fprintf(stderr,"wmrack: got signal %s\n",strsignal(sig));
+  else
+    fprintf(stderr,"wmrack: manual shutdown\n");
+  fprintf(stderr,"wmrack: Shutting down\n");
+#endif
+  saveMixerRC();
+#ifdef DEBUG
+  fprintf(stderr,"wmrack: mixer RC written\n");
+#endif
+  cd_close(cd);
+#ifdef DEBUG
+  fprintf(stderr,"wmrack: cd closed\n");
+#endif
+  mixer_close(mixer);
+#ifdef DEBUG
+  fprintf(stderr,"wmrack: mixer closed\n");
+#endif
+/* cause it's no good, this is commented out (CloseDisplay woes)
+  xpm_freeSet(Disp);
+#  ifdef DEBUG
+  fprintf(stderr,"wmrack: XPMs freed\n");
+#  endif
+  XFreeGC(Disp, WinGC);
+#  ifdef DEBUG
+  fprintf(stderr,"wmrack: GC freed\n");
+#  endif
+  XDestroyWindow(Disp, Win);
+#  ifdef DEBUG
+  fprintf(stderr,"wmrack: Win destroyed\n");
+#  endif
+  XDestroyWindow(Disp, Iconwin);
+#  ifdef DEBUG
+  fprintf(stderr,"wmrack: Iconwin destroyed\n");
+#  endif
+*/
+  XCloseDisplay(Disp);
+#ifdef DEBUG
+  fprintf(stderr,"wmrack: Display closed\n");
+#endif
+  exit(0);
+}
+
+/*
+ * mainLoop()
+ *
+ * the main event loop
+ */
+void mainLoop()
+{
+  XEvent Event;
+  Time when;
+  Time press_time=-1;
+  int skip_count, skip_amount, skip_delay;
+  int force_win=0, force_disp=0;
+  int change_volume=0, vol_y, vol_side;
+
+  while(1)
+    {
+      /* Check events */
+      while (XPending(Disp))
+	{
+	  XNextEvent(Disp,&Event);
+	  switch (Event.type)
+	    {
+	    case Expose:
+	      if (Event.xexpose.count==0)
+		last_time.minute=last_time.second=last_time.frame=-1;
+	      force_win=1;
+	      break;
+	    case ButtonPress:
+	      switch (WMRack_Mode)
+		{
+		case MODE_CDPLAYER:
+		  newdisc=0;
+		  cd_getStatus(cd,0,0);
+		  if (Event.xbutton.y<15)
+		    {
+		      switch (Event.xbutton.button)
+			{
+			case 1:
+			  if (cd_cur(cd,mode)==CDM_PLAY)
+			    displaymode^=1;
+			  break;
+			case 2:
+			  if (cd_cur(cd,mode)==CDM_PLAY)
+			    displaymode^=2;
+			  break;
+			case 3:
+			  switch (cd_play(cd,repeat_mode))
+			    {
+			    case CDR_NONE:
+			      cd_play(cd,repeat_mode)=CDR_ALL;
+			      break;
+			    case CDR_ALL:
+			      cd_play(cd,repeat_mode)=CDR_ONE;
+			      break;
+			    default:
+			      cd_play(cd,repeat_mode)=CDR_NONE;
+			      break;
+			    }
+			  if (cd_play(cd,repeat_mode)==2 && cd_cur(cd,mode)==CDM_PLAY)
+			    start_track=cd_cur(cd,track);
+			  break;
+			}
+		      force_disp=1;
+		    }
+		  else if (Event.xbutton.y>15 && Event.xbutton.y<32)
+		    {
+		      if (Event.xbutton.x<13)
+			{
+			  if (cd_cur(cd,mode)==CDM_PLAY || cd_cur(cd,mode)==CDM_PAUSE)
+			    cd_doPause(cd);
+			  else if (cd_cur(cd,mode)==CDM_EJECT)
+			    {
+			      if (cd_getStatus(cd,1,0))
+				{
+				  start_track=0;
+				  if (cd_list(cd,tracks)==0)
+				    {
+				      rack_popup("DATA");
+				      cd_suspend(cd);
+				    }
+				  else
+				    {
+				      newdisc=1;
+				      cd_doPlay(cd,start_track);
+				    }
+				}
+			    }
+			  else
+			    {
+			      if (playlist!=NULL)
+				{
+				  cd_setpl(cd,playlist);
+				  cdpl_free(playlist);
+				  playlist=NULL;
+				  cd_doPlay(cd,0);
+				}
+			      else
+				cd_doPlay(cd,start_track);
+			    }
+			}
+		      else if (Event.xbutton.x>34)
+			{
+			  if (cd_cur(cd,mode)==CDM_PLAY || cd_cur(cd,mode)==CDM_PAUSE)
+			    {
+			      cd_doStop(cd);
+			      start_track=cd_play(cd,cur_track);
+			    }
+			  else if (cd_cur(cd,mode)==CDM_EJECT)
+			    {
+			      if (Event.xbutton.button==3)
+				cd_doEject(cd);
+			      else
+				{
+				  if (cd_getStatus(cd,1,1))
+				    {
+				      start_track=0;
+				      if (cd_list(cd,tracks)==0)
+					{
+					  rack_popup("DATA");
+					  cd_suspend(cd);
+					}
+				      else
+					newdisc=1;
+				    }
+				}
+			    }
+			  else
+			    cd_doEject(cd);
+			}
+		      else
+			{
+			  if (Event.xbutton.button==3
+			      && (Event.xbutton.state&ControlMask))
+			    shutDown(0);
+			  WMRack_Mode=MODE_MIXER;
+			  force_win=1;
+			}
+		    }
+		  else if (Event.xbutton.y>32)
+		    {
+		      if (Event.xbutton.x<13 || Event.xbutton.x>34)
+			{
+			  press_time=Event.xbutton.time;
+			  skip_count=0;
+			  skip_delay=8;
+			  if (Event.xbutton.x<13)
+			    skip_amount=-1;
+			  else
+			    skip_amount=1;
+			}
+		      else /* track display clicked */
+			{
+			  if (cd_cur(cd,mode)!=CDM_STOP) break;
+			  if (Event.xbutton.state&ControlMask)
+			    {
+			      switch (Event.xbutton.button)
+				{
+				case 1:
+				  if (playlist!=NULL)
+				    {
+				      cdpl_free(playlist);
+				      playlist=NULL;
+				      force_disp=1;
+				    }
+				  else
+				    {
+				      playlist=cdpl_new();
+				      cd_resetpl(cd);
+				      rack_popup("PROG");
+				    }
+				  break;
+				case 3:
+				  if (playlist!=NULL)
+				    cdpl_free(playlist);
+				  playlist=NULL;
+				  cd_randomize(cd);
+				  rack_popup("RAND");
+				  break;
+				}
+			    }
+			  else if (Event.xbutton.state&Mod1Mask
+				   && playlist!=NULL)
+			    {
+			      char num[20];
+			      /* add current track to playlist */
+			      cdpl_add(playlist,cd,start_track);
+			      sprintf(num,"%02d%02d",
+				      playlist->tracks,
+				      playlist->track[playlist->tracks-1]);
+			      rack_popup(num);
+			    }
+			}
+		    }
+		  break;
+		case MODE_MIXER:
+		  if (Event.xbutton.y<15
+		      && Event.xbutton.x>13 && Event.xbutton.x<34)
+		    {
+		      if (Event.xbutton.state&ControlMask)
+			{
+			  int i, j, c;
+			  switch (Event.xbutton.button)
+			    {
+			    case 1: /* show all mixer devices */
+			      c=mixer_order[curMixer];
+			      for (j=i=0; i<mixer_devices; i++)
+				if (mixer_isdevice(mixer,i))
+				  {
+				    if (i==c)
+				      curMixer=j;
+				    mixer_order[j++]=i;
+				  }
+			      mixer_max=j;
+			      force_disp=1;
+			      break;
+			    case 3: /* delete this device */
+			      if (mixer_max>1)
+				{
+				  if (curMixer==mixer_max-1)
+				    curMixer--;
+				  else
+				    memmove(&mixer_order[curMixer],
+					    &mixer_order[curMixer+1],
+					    sizeof(int)*(mixer_max-curMixer));
+				  mixer_max--;
+				  force_disp=1;
+				}
+			      break;
+			    }
+			}
+		      else
+			{
+			  switch (Event.xbutton.button)
+			    {
+			    case 1:
+			      curMixer++;
+			    mixup:
+			      while (!mixer_isdevice(mixer,mixer_order[curMixer])
+				     && curMixer<mixer_max)
+				curMixer++;
+			      if (curMixer==mixer_max)
+				{
+				  curMixer=0;
+				  goto mixup;
+				}
+			      break;
+			    case 2:
+			      curMixer=0;
+			      break;
+			    case 3:
+			      curMixer--;
+			    mixdown:
+			      while (!mixer_isdevice(mixer,mixer_order[curMixer])
+				     && curMixer>=0)
+				curMixer--;
+			      if (curMixer<0)
+				{
+				  curMixer=mixer_max-1;
+				  goto mixdown;
+				}
+			      break;
+			    }
+			}
+		    }
+		  else if (Event.xbutton.y>15 && Event.xbutton.y<32
+			   && Event.xbutton.x>13 && Event.xbutton.x<34)
+		    {
+		      if (Event.xbutton.button==3
+			  && (Event.xbutton.state&ControlMask))
+			shutDown(0);
+		      WMRack_Mode=MODE_CDPLAYER;
+		      force_win=1;
+		    }
+		  else if (mixer_isrecdev(mixer,mixer_order[curMixer])
+			   && Event.xbutton.y>32
+			   && Event.xbutton.x>13 && Event.xbutton.x<34)
+		    {
+		      switch (Event.xbutton.button)
+			{
+			case 1:
+			  mixer_setrecsrc(mixer,mixer_order[curMixer],
+					  mixer_isrecsrc(mixer,mixer_order[curMixer])
+					  ? 0
+					  : 1,0);
+			  break;
+			case 2:
+			  mixer_setrecsrc(mixer,mixer_order[curMixer],1,1);
+			  break;
+			}
+		    }
+		  else if (Event.xbutton.x<11 || Event.xbutton.x>36)
+		    {
+		      int change;
+		      /* change volume */
+		      change_volume=Event.xbutton.button;
+		      vol_y=Event.xbutton.y_root;
+		      vol_side=Event.xbutton.x<24;
+		      switch (change_volume)
+			{
+			case 1:
+			  if (vol_side)
+			    mixer_setvols(mixer,mixer_order[curMixer],
+					  ((47-Event.xbutton.y)/4)*10,
+					  mixer_volright(mixer,mixer_order[curMixer]));
+			  else
+			    mixer_setvols(mixer,mixer_order[curMixer],
+					  mixer_volleft(mixer,mixer_order[curMixer]),
+					  ((47-Event.xbutton.y)/4)*10);
+			  break;
+			case 2:
+			  mixer_setvol(mixer,mixer_order[curMixer],
+				       ((47-Event.xbutton.y)/4)*10);
+			  break;
+			case 3:
+			  change=(((47-Event.xbutton.y)/4)*10-
+				  (vol_side
+				   ? mixer_volleft(mixer,mixer_order[curMixer])
+				   : mixer_volright(mixer,mixer_order[curMixer])));
+			  if (vol_side)
+			    mixer_changebal(mixer,mixer_order[curMixer],-change);
+			  else
+			    mixer_changebal(mixer,mixer_order[curMixer],change);
+			  break;
+			}
+		    }
+		  break;
+		}
+	      break;
+	    case MotionNotify:
+	      switch (WMRack_Mode)
+		{
+		case MODE_MIXER:
+		  if (change_volume)
+		    {
+		      if ((Event.xmotion.y_root-vol_y)/8)
+			{
+			  int change=((vol_y-Event.xmotion.y_root)/8)*10;
+			  switch (change_volume)
+			    {
+			    case 1:
+			      if (vol_side)
+				mixer_changeleft(mixer,mixer_order[curMixer],change);
+			      else
+				mixer_changeright(mixer,mixer_order[curMixer],change);
+			      break;
+			    case 2:
+			      mixer_changevol(mixer,mixer_order[curMixer],change);
+			      break;
+			    case 3:
+			      if (vol_side)
+				mixer_changebal(mixer,mixer_order[curMixer],-change);
+			      else
+				mixer_changebal(mixer,mixer_order[curMixer],change);
+			    }
+			  vol_y=Event.xmotion.y_root;
+			}
+		    }
+		}
+	      break;
+	    case ButtonRelease:
+	      switch (WMRack_Mode)
+		{
+		case MODE_CDPLAYER:
+		  if (press_time==-1) break;
+		  if (Event.xbutton.time-press_time<200 && Event.xbutton.y>32)
+		    {
+		      if (cd_cur(cd,mode)==CDM_PLAY || cd_cur(cd,mode)==CDM_PAUSE)
+			{
+			  if (Event.xbutton.x<13)
+			    {
+			      if (cd_cur(cd,relmsf.minute) ||
+				  cd_cur(cd,relmsf.second>2))
+				cd_doPlay(cd,cd_cur(cd,track));
+			      else
+				cd_doPlay(cd,cd_cur(cd,track)-1);
+			    }
+			  else if (Event.xbutton.x>34
+				   && cd_cur(cd,track)<cd_list(cd,tracks)-1)
+			    cd_doPlay(cd,cd_cur(cd,track)+1);
+			}
+		      else if (cd_cur(cd,mode)==CDM_STOP)
+			{
+			  if (Event.xbutton.x<13)
+			    {
+			      if (start_track>0)
+				start_track--;
+			      else
+				start_track=cd_list(cd,tracks)-1;
+			    }
+			  else if (Event.xbutton.x>34)
+			    {
+			      if (start_track<cd_list(cd,tracks)-1)
+				start_track++;
+			      else
+				start_track=0;
+			    }
+			}
+		      else
+			;
+		    }
+		  break;
+		case MODE_MIXER:
+		  if (change_volume)
+		    {
+		      change_volume=0;
+		    }
+		  break;
+		}
+	      press_time=-1;
+	      change_volume=0;
+	      break;
+	    case DestroyNotify:
+	      shutDown(SIGTERM);
+	      break;
+	    }
+	  XFlush(Disp);
+	}
+      /* now check for a pressed button */
+      if (press_time!=-1)
+	{
+	  if (cd_cur(cd,mode)==CDM_PLAY)
+	    {
+	      when=getTime();
+	      if (when-press_time>500)
+		{
+		  /* this is needed because of the faster pace */
+		  cd_getStatus(cd,0,1);
+		  skip_count++;
+		  if (skip_count%skip_delay==0)
+		    {
+		      if (Event.xbutton.x<17)
+			cd_doSkip(cd,skip_amount);
+		      else if (Event.xbutton.x>34)
+			cd_doSkip(cd,skip_amount);
+		    }
+		  switch (skip_count)
+		    {
+		    case 5:
+		    case 10:
+		    case 20:
+		      skip_delay>>=1;
+		      break;
+		    }
+		}
+	    }
+	}
+      /* do a redraw of the LED display */
+      redrawDisplay(force_win,force_disp);
+      usleep(5000L);
+      force_win=force_disp=0;
+    }
+}
+
+/*
+ * flushExpose(window)
+ *
+ * remove any Expose events from the current EventQueue
+ */
+int flushExpose(Window w)
+{
+  XEvent dummy;
+  int i=0;
+
+  while (XCheckTypedWindowEvent (Disp, w, Expose, &dummy)) i++;
+  return i;
+}
+
+/*
+ * redrawWindow()
+ *
+ * combine mask and draw pixmap
+ */
+void redrawWindow()
+{
+  flushExpose(Win);
+  flushExpose(Iconwin);
+  
+  XShapeCombineMask(Disp, Win, ShapeBounding, 0, 0,
+		    currentXpm(mask), ShapeSet);
+  XShapeCombineMask(Disp, Iconwin, ShapeBounding, 0, 0,
+		    currentXpm(mask), ShapeSet);
+  
+  XCopyArea(Disp,currentXpm(pixmap),Win,WinGC,
+	    0,0,currentXpm(attributes).width, currentXpm(attributes).height,0,0);
+  XCopyArea(Disp,currentXpm(pixmap),Iconwin,WinGC,
+	    0,0,currentXpm(attributes).width, currentXpm(attributes).height,0,0);
+}
+
+/*
+ * paint_cd_led(flash,track,cdtime)
+ *
+ * draws the digital numbers to the pixmaps
+ */
+void paint_cd_led(int flash, int track[], int cdtime[])
+{
+  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+	    (track[0]?8*track[0]:80),0, 8,11, 16,35);
+  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+	    (track[0]?8*track[0]:80),0, 8,11, 16,35);
+  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+	    8*track[1],0, 8,11, 24,35);
+  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+	    8*track[1],0, 8,11, 24,35);
+
+  if (flash || cd_cur(cd,mode)!=CDM_PAUSE)
+    {
+      if (cd_cur(cd,mode)==CDM_PLAY || cd_cur(cd,mode)==CDM_PAUSE)
+	{
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    ((displaymode&2)?94:98),0, 4,5, 3,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    ((displaymode&2)?94:98),0, 4,5, 3,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    ((displaymode&1)?94:98),5, 4,1, 3,7);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    ((displaymode&1)?94:98),5, 4,1, 3,7);
+	}
+      else
+	{
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    98,0, 4,6, 3,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    98,0, 4,6, 3,2);
+	}
+	  
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		((playlist!=NULL)?94:98),6, 4,5, 3,8);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		((playlist!=NULL)?94:98),6, 4,5, 3,8);
+
+      if (popup_display==NULL)
+	{
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    (cdtime[0]?8*cdtime[0]:80),0, 8,11, 7,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    (cdtime[0]?8*cdtime[0]:80),0, 8,11, 7,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    8*cdtime[1],0, 8,11, 15,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    8*cdtime[1],0, 8,11, 15,2);
+
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    88,0, 3,11, 23,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    88,0, 3,11, 23,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    8*cdtime[2],0, 8,11, 26,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    8*cdtime[2],0, 8,11, 26,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    8*cdtime[3],0, 8,11, 34,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    8*cdtime[3],0, 8,11, 34,2);
+
+	}
+
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		(cd_play(cd,repeat_mode)!=CDR_NONE?102:106),0, 4,5, 42,2);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		(cd_play(cd,repeat_mode)!=CDR_NONE?102:106),0, 4,5, 42,2);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		(cd_play(cd,repeat_mode)==CDR_ONE?102:106),6, 4,5, 42,8);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		(cd_play(cd,repeat_mode)==CDR_ONE?102:106),6, 4,5, 42,8);
+    }
+  else
+    {
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		98,0, 4,11, 3,2);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		98,0, 4,11, 3,2);
+
+      if (popup_display==NULL)
+	{
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    80,0, 8,11, 7,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    80,0, 8,11, 7,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    80,0, 8,11, 15,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    80,0, 8,11, 15,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    91,0, 3,11, 23,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    91,0, 3,11, 23,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    80,0, 8,11, 26,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    80,0, 8,11, 26,2);
+	  
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		    80,0, 8,11, 34,2);
+	  XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		    80,0, 8,11, 34,2);
+	}
+
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Win, WinGC,
+		106,0, 4,11, 42,2);
+      XCopyArea(Disp, ledXpm(RACK_LED_PLAYER,pixmap), Iconwin, WinGC,
+		106,0, 4,11, 42,2);
+    }
+
+  if (popup_display!=NULL)
+    {
+      int disp_pos[4]={7,15,26,34};
+      char *d;
+      int i, j;
+
+      /*      
+      if (!popup_done)
+	{
+	  XFillRectangle(Disp, Win, WinGC, 7, 2, 35, 11);
+	  XFillRectangle(Disp, Iconwin, WinGC, 7, 2, 35, 11);
+	  popup_done=1;
+	}
+      */
+
+      for (j=0, d=popup_display; *d; d++, j++)
+	{
+	  for (i=0; ledAlphabet[i]; i++)
+	    if (toupper(*d)==ledAlphabet[i])
+	      {
+		XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Win, WinGC,
+			  i*8,0, 8,11, disp_pos[j],2);
+		XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Iconwin, WinGC,
+			  i*8,0, 8,11, disp_pos[j],2);
+		break;
+	      }
+	}
+    }
+
+}
+
+/*
+ * paint_mixer_led()
+ *
+ * draws the digital scales and signs to the pixmaps
+ */
+void paint_mixer_led()
+{
+  int i;
+
+  /* the device name */
+  for (i=0; ledAlphabet[i]; i++)
+    if (toupper(mixer_shortnames[mixer_order[curMixer]][0])==ledAlphabet[i])
+      {
+	XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Win, WinGC,
+		  i*8,0, 8,11, 16,2);
+	XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Iconwin, WinGC,
+		  i*8,0, 8,11, 16,2);
+	break;
+      }
+  for (i=0; ledAlphabet[i]; i++)
+    if (toupper(mixer_shortnames[mixer_order[curMixer]][1])==ledAlphabet[i])
+      {
+	XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Win, WinGC,
+		  i*8,0, 8,11, 24,2);
+	XCopyArea(Disp, ledXpm(RACK_LED_ALPHA,pixmap), Iconwin, WinGC,
+		  i*8,0, 8,11, 24,2);
+	break;
+      }
+
+  /* the recsrc button */
+  if (mixer_isrecdev(mixer,mixer_order[curMixer]))
+    {
+      if (mixer_isrecsrc(mixer,mixer_order[curMixer]))
+	i=13;
+      else
+	i=0;
+    }
+  else
+    i=26;
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Win, WinGC,
+	    44,i, 14,13, 17,34);
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Iconwin, WinGC,
+	    44,i, 14,13, 17,34);
+  
+  /* the volume displays */
+  /* left */
+  i=(mixer_volleft(mixer,mixer_order[curMixer])/10);
+  if (i<0) i=0;
+  if (i>10) i=10;
+  i*=4;
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Win, WinGC,
+	    i,0, 3,39, 4,4);
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Iconwin, WinGC,
+	    i,0, 3,39, 4,4);
+  /* right */
+  i=(mixer_volright(mixer,mixer_order[curMixer])/10);
+  if (i<0) i=0;
+  if (i>10) i=10;
+  i*=4;
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Win, WinGC,
+	    i,0, 3,39, 41,4);
+  XCopyArea(Disp, ledXpm(RACK_LED_MIXER,pixmap), Iconwin, WinGC,
+	    i,0, 3,39, 41,4);
+  
+}
+
+/*
+ * split this function into the real redraw and a pure 
+ * display time/track function.
+ * redraw wants a complete redraw (covering, movement, etc.)
+ * but the display of the time/track does not need this overhead (SHAPE)
+ */
+void redrawDisplay(int force_win, int force_disp)
+{
+  int track[2]={0,0};
+  int cdtime[4]={0,0,0,0};
+  static time_t last_flash_time;
+  static flash=0;
+  int st=0, newRack=RACK_NODISC, im_stop=0;
+  MSF pos;
+
+  st=cd_getStatus(cd,0,0);
+
+  if (!force_win && !force_disp && popup_display==NULL)
+    {
+      /* test if something has changed */
+      switch (WMRack_Mode)
+	{
+	case MODE_CDPLAYER:
+	  if (cd_cur(cd,mode)!=CDM_PAUSE
+	      && last_cdmode==cd_cur(cd,mode)
+	      && (st<1 ||
+		  (last_time.minute==cd_cur(cd,relmsf.minute)
+		   && last_time.second==cd_cur(cd,relmsf.second)
+		   && last_track==start_track)))
+	    return;
+	  break;
+	case MODE_MIXER:
+	  mixer_readvol(mixer,mixer_order[curMixer]);
+	  if (curMixer==lastMixer
+	      && !mixer_volchanged(mixer,mixer_order[curMixer])
+	      && !mixer_srcchanged(mixer,mixer_order[curMixer]))
+	    return;
+	  break;
+	}
+    }
+  
+#ifdef DEBUG
+  if (last_cdmode!=cd_cur(cd,mode)) {
+    fprintf(stderr,"wmrack: cur_cdmode %d\n",cd_cur(cd,mode));
+  }
+#endif
+
+  if (cd_cur(cd,mode)==CDM_STOP && cd_play(cd,last_action)==CDA_PLAY)
+    start_track=0;
+
+  lastMixer=curMixer;
+
+  last_cdmode=cd_cur(cd,mode);
+  if (st>0)
+    {
+      last_time=cd_cur(cd,relmsf);
+      last_track=start_track;
+    }
+  else
+    {
+      MSFnone(last_time);
+      last_track=-1;
+    }
+  
+  if (cd_cur(cd,mode)==CDM_PAUSE)
+    {
+      time_t flash_time=time(NULL);
+      if (flash_time==last_flash_time && !force_win)
+	return;
+      last_flash_time=flash_time;
+      flash=!flash;
+    }
+  else
+    {
+      last_flash_time=0;
+      flash=1;
+    }
+
+  if (popup_display!=NULL)
+    {
+      if (popup_time==0)
+	popup_time=time(NULL);
+      else
+	{
+	  time_t now=time(NULL);
+	  if (now>popup_time+1)
+	    {
+	      free(popup_display);
+	      popup_display=NULL;
+	      popup_time=0;
+	      popup_done=0;
+	    }
+	}
+    }
+  
+  newRack=RACK_PLAY;
+
+  if (WMRack_Mode==MODE_MIXER)
+    newRack=RACK_MIXER;
+  else
+    {
+      switch (cd_cur(cd,mode))
+	{
+	case CDM_PAUSE:
+	  newRack=RACK_PAUSE;
+	case CDM_PLAY:
+	  track[0]=cd_list(cd,track)[cd_cur(cd,track)].num/10;
+	  track[1]=cd_list(cd,track)[cd_cur(cd,track)].num%10;
+	  switch (displaymode)
+	    {
+	    case 0:
+	      pos=cd_cur(cd,relmsf);
+	      break;
+	    case 1:
+	      pos=subMSF(cd_list(cd,track)[cd_cur(cd,track)].length,
+			 cd_cur(cd,relmsf));
+	      break;
+	    case 2:
+	      pos=subMSF(cd_cur(cd,absmsf),
+			 cd_info(cd,track)[0].start);
+	      break;
+	    case 3:
+	      pos=subMSF(cd_info(cd,track)[cd_info(cd,tracks)-1].end,
+			 cd_cur(cd,absmsf));
+	      break;
+	    }
+	  cdtime[0]=pos.minute/10;
+	  cdtime[1]=pos.minute%10;
+	  cdtime[2]=pos.second/10;
+	  cdtime[3]=pos.second%10;
+	  break;
+	case CDM_STOP:
+	  newRack=RACK_STOP;
+	  if (newdisc)
+	    {
+	      track[0]=cd_list(cd,tracks)/10;
+	      track[1]=cd_list(cd,tracks)%10;
+	    }
+	  else
+	    {
+	      track[0]=cd_list(cd,track)[start_track].num/10;
+	      track[1]=cd_list(cd,track)[start_track].num%10;
+	    }
+	  if (playlist==NULL)
+	    {
+	      cdtime[0]=cd_list(cd,length).minute/10;
+	      cdtime[1]=cd_list(cd,length).minute%10;
+	      cdtime[2]=cd_list(cd,length).second/10;
+	      cdtime[3]=cd_list(cd,length).second%10;
+	    }
+	  else
+	    {
+	      cdtime[0]=playlist->length.minute/10;
+	      cdtime[1]=playlist->length.minute%10;
+	      cdtime[2]=playlist->length.second/10;
+	      cdtime[3]=playlist->length.second%10;
+	    }
+	  break;
+	case CDM_COMP:
+	  newRack=RACK_STOP;
+	  goto set_null;
+	case CDM_EJECT:
+	  newRack=RACK_NODISC;
+	default:
+	set_null:
+	  track[0]= 0;
+	  track[1]= 0;
+	  cdtime[0]=0;
+	  cdtime[1]=0;
+	  cdtime[2]=0;
+	  cdtime[3]=0;
+	  break;
+	}
+    }
+
+  if (newRack!=curRack || force_win)
+    {
+      /* Mode has changed, paint new mask and pixmap */
+      curRack=newRack;
+      redrawWindow();
+    }
+
+  switch (curRack)
+    {
+    case RACK_MIXER:
+      paint_mixer_led();
+      break;
+    default:
+      paint_cd_led(flash,track,cdtime);
+      break;
+    }
+
+}
+
+/*
+ * getColor(colorname)
+ *
+ * save way to get a color from X
+ */
+Pixel getColor(char *ColorName)
+{
+  XColor Color;
+  XWindowAttributes Attributes;
+
+  XGetWindowAttributes(Disp,Root,&Attributes);
+  Color.pixel = 0;
+
+  if (!XParseColor (Disp, Attributes.colormap, ColorName, &Color))
+    fprintf(stderr,"wmrack: can't parse %s\n", ColorName);
+  else if(!XAllocColor (Disp, Attributes.colormap, &Color))
+    fprintf(stderr,"wmrack: can't allocate %s\n", ColorName);
+
+  return Color.pixel;
+}
+
+/*
+ * getTime()
+ *
+ * returns the time in milliseconds
+ */
+Time getTime()
+{
+  struct timeval tv;
+  gettimeofday(&tv,NULL);
+  return (tv.tv_sec*1000)+(tv.tv_usec/1000);
+}
+
+/*
+ * loadMixerRC()
+ *
+ * loads the mixer defaults
+ */
+int loadMixerRC()
+{
+  char line[1024], dev[50], src[10], *d;
+  int i, l, r, n, j, err=0;
+
+  mixer_max=0;
+  mixer_lib=lib_open("mixer",LIB_READ);
+  if (mixer_lib==NULL)
+    {
+      fprintf(stderr,"wmrack: can't read mixer file\n");
+      err=-1;
+      goto endload;
+    }
+
+  while ((lib_gets(mixer_lib,line,1024))!=NULL)
+    {
+      for (i=0; i<mixer_devices; i++)
+	if (strncmp(line,mixer_names[i],strlen(mixer_names[i]))==0)
+	  break;
+      if (i<mixer_devices)
+	{
+	  n=sscanf(line,"%s %d:%d %s",&dev,&l,&r,&src);
+	  if (n>1)
+	    {
+	      mixer_setvols(mixer,i,l,r);
+	      if (strcmp(src,"src")==0)
+		mixer_setrecsrc(mixer,i,1,0);
+	    }
+	  *dev=*src=0;
+	}
+      else if (strncmp(line,"ORDER ",6)==0)
+	{
+	  for (d=strchr(line,32); d!=NULL; d=strchr(d,32))
+	    {
+	      while (*d==32) *d++;
+	      if (*d==0 || *d=='\n' || *d=='\r') break;
+	      for (i=0; i<mixer_devices; i++)
+		if (strncmp(d,mixer_names[i],strlen(mixer_names[i]))==0)
+		  break;
+	      if (i<mixer_devices && mixer_isdevice(mixer,i))
+		{
+		  mixer_order[mixer_max++]=i;
+#ifdef DEBUG
+		  fprintf(stderr,"wmrack: mixer_order %d=%s\n",mixer_max,mixer_names[i]);
+#endif
+		}
+#ifdef DEBUG
+	      else
+		fprintf(stderr,"wmrack: unsupported device '%s'\n",d);
+#endif
+	    }
+	}
+    }
+
+  lib_free(mixer_lib);
+
+ endload:
+  if (mixer_max==0)
+    {
+#ifdef DEBUG
+      fprintf(stderr,"wmrack: setting default mixer_order\n");
+#endif
+      for (j=i=0; i<mixer_devices; i++)
+	if (mixer_isdevice(mixer,i))
+	  mixer_order[j++]=i;
+      mixer_max=j;
+    }
+  
+  mixer_readvols(mixer);
+
+  return err;
+}
+
+/*
+ * saveMixerRC()
+ *
+ * writes the mixer defaults
+ */
+int saveMixerRC()
+{
+  int i;
+
+  mixer_lib=lib_open("mixer",LIB_WRITE);
+  if (mixer_lib==NULL)
+    {
+      fprintf(stderr,"wmrack: can't write mixer file\n");
+      return -1;
+    }
+
+  for (i=0; i<mixer_devices; i++)
+    {
+      if (mixer_isdevice(mixer,i))
+	{
+	  if (mixer_isstereo(mixer,i))
+	    lib_printf(mixer_lib,"%s %d:%d%s\n",
+		       mixer_names[i],
+		       mixer_volleft(mixer,i),
+		       mixer_volright(mixer,i),
+		       mixer_isrecsrc(mixer,i)?" src":"");
+	  else
+	    lib_printf(mixer_lib,"%s %d:%d%s\n",
+		       mixer_names[i],
+		       mixer_volmono(mixer,i),
+		       mixer_volmono(mixer,i),
+		       mixer_isrecsrc(mixer,i)?" src":"");
+	}
+    }
+  if (mixer_max>0)
+    {
+      lib_printf(mixer_lib,"ORDER ");
+      for (i=0; i<mixer_max; i++)
+	{
+	  lib_printf(mixer_lib,"%s ",mixer_names[mixer_order[i]]);
+	}
+      lib_printf(mixer_lib,"\n");
+    }
+  lib_close(mixer_lib);
+
+  return 0;
+}
+
+void rack_popup(char *msg)
+{
+  if (popup_display!=NULL)
+    free(popup_display);
+  popup_display=strdup(msg);
+  popup_done=0;
+}
diff --git a/wmrack.man b/wmrack.man
new file mode 100644
index 0000000..165affe
--- /dev/null
+++ b/wmrack.man
@@ -0,0 +1,235 @@
+.ds = \-\^\-
+.de Sp
+.if t .sp .3
+.if n .sp
+..
+.TH wmrack 1.0 "1 June 1997" wmrack
+.UC
+.SH NAME
+\fBwmrack\fP \- the WindowMaker Sound Control
+.SH SYNOPSIS
+.B wmrack
+[options]
+.SH DESCRIPTION
+The \fBwmrack\fP is CD player and Audio Mixer written to be
+docked to WindowMaker's dock. It can also be used swallowed into
+the button bars of most fvwm compatible window managers.
+\fBwmrack\fP handles mounted volumes, opens and closes the tray, can
+display the current position in various ways and skips also data tracks.
+It gives you access to all your mixer devices, so that you may change
+volume or balance and set the record source.
+.SH OPTIONS
+.TP
+\fB\-b\fP \fBCOLSPEC\fP or \fB\*=background\fP \fBCOLSPEC\fP
+Specifies the background color of the LED. It is avaiable through the symbolic 
+XPM colorname
+.I led_color_black.
+.SP
+The other colors of the LED can be changed using the \fB-l\fP option.
+.Sp
+To find out what colors are available, try
+.I showrgb
+(part of X11).
+.TP
+\fB\-d\fP \fBDEVICE\fP or \fB\*=device\fP \fBDEVICE\fP
+Sets the CD-ROM device. This defaults to /dev/cdrom.
+.TP
+\fB\-h\fP or  \fB\*=help\fP
+Prints a summary of supported options and their default values.
+.TP
+\fB\-l\fP \fBCOLSPEC\fP or \fB\*=ledcolor\fP \fBCOLSPEC\fP
+Specifies the color of the led. It is darkened two times (for a total of
+three colors) to get all needed colors. So better use a bright color.
+.Sp
+For the design of own XPM, the ledcolor is made avaiable through the use
+of the symbolic xpm color names
+.I led_color_high,
+.I led_color_low,
+and
+.I led_color_med.
+There is also a symbol named
+.I led_color_back
+to get the default background color of the led\-display. It can be changed
+using the \fB-l\fP option.
+.Sp
+To find out what colors are available, try
+.I showrgb
+(part of X11).
+.TP
+\fB\-m\fP \fBDEVICE\fP or \fB\*=mixer\fP \fBDEVICE\fP
+Sets the MIXER device. This defaults to /dev/mixer.
+.TP
+\fB\-p\fP or \fB\*=noprobe\fP
+This option disables the startup probing for a cd. Default is to probe the
+cdrom. This will close the tray and read the TOC of the cd (if there is one).
+.TP
+\fB\-s\fP \fBSTYLEFILE\fP or \fB\*=style\fP \fBSTYLEFILE\fP
+.B wmrack
+will try to load its window\-pixmaps from the specified
+.B STYLEFILE.
+It will search this file for XPM pixmaps named
+.I cdnodisc,
+.I cdplaying,
+.I cdpaused,
+.I cdstopped,
+.I cdled,
+.I mixer,
+and
+.I mixled.
+If some of those are not defined, the compile\-time defaults will be used.
+.TP
+\fB\-w\fP or \fB\*=withdrawn\fP
+Starts the
+.B wmrack
+in withdrawn window state. This is useful to dock the window to
+.B WindowMaker.
+.TP
+\fB\-M\fP \fBMODESTRING\fP or \fB\*=mode\fP \fBMODESTRING\fP
+By default
+.B wmrack
+will startup showing the CDROM controls. With this option you can specify what 
+controls should be shown. Valid \fBMODESTRINGS\FP are
+.I cdrom,
+and
+.I mixer.
+.SH INVOCATION
+\fBwmrack\fP can be called using different ways. The most common invocation
+is from your dock file:
+.Sp
+        wmrack
+        WMRack
+        \fIPOSITION\fP 2 -1 0
+        wmrack
+        --withdrawn
+.Sp
+Another way to call \fBwmrack\fP is to swallow it into the \fBafterstep (1)\fP
+\fBWharf (1)\fP. This is best done playcing the following line into your
+\fI.steprc\fP:
+.Sp
+	*Wharf WMRack nil Swallow "wmrack" wmrack &
+.Sp
+This method will also work for other button\-bars, such as the \fBFvwmButtons (1)\fP
+of the \fBfvwm (1)\fP window manager.
+.SH GENERAL USAGE
+The \fBwmrack\fP features a simple click interface. All times the buttons will
+show a standart sign which specifies the action it will do. But there are some 
+noteable extensions to that explained below.
+.Sp
+You can always change the controls shown by clicking the middle button (this
+is the one which shows a disc or a speaker) of the controls. This button will
+show a symbol of the controls you can change to by pressing it (the disc and
+the speaker).
+.Sp
+If you click this button with Control-Button-3, \fBWMrack\fP will exit.
+.SH CDROM USAGE
+The default behavior of \fBwmrack\fP is to try to read the cdrom at
+startup. If there was no cd, it will not try again unless you press the close
+or play button. This will close the cdrom and again try to read it. Unless
+there is a cd, \fBwmrack\fP will again suspend until your next action.
+.TP
+.B open tray
+Clicking an open/eject button with button-3 will always open the tray.
+.TP
+.B skip
+By pressing the button down and holding it on one of the prev/next track
+buttons the cdrom goes fast forward or backward.
+.TP
+.B time left
+A button-1 click into the time display switches between time running and time
+left display.
+.TP
+.B total time
+A button-2 click into the time display switches between track and total time.
+.TP
+.B repeat
+A button-3 click into the time display cycles through normal mode, repeat all, 
+and repeat one play mode.
+.PP
+The cd player also offers a play list functionality. By default it will map
+out all data tracks of the current cdrom, but you can also randomize the list
+or program it to the tracks you want to hear. These functions are only
+avaiable while a cdrom is in the drive and the drive is \fIstopped\fP.
+.TP
+.B randomize
+Clicking Control-Button-3 to the track display causes the playlist to be
+randomized. No track will repeat, the tracks are just mixed up.
+.Sp
+You will see the short message \fIRA:ND\fP in the time display.
+.TP
+.B start programming
+Click Control-Button-1 into the track display to start programing a new
+playlist. You will see a short \fIPR:OG\fP message in the time display and a
+\fIM\fP will show up in the lower left corner of the display.
+.TP
+.B add track to list
+Use the prev-/next-track buttons to select a track and click Mod1-Button-1
+into the track display to add it to the playlist. The time display will show
+the number of the tracks in the list and the number of the selected track for
+a short time and will than switch back and display the total ength of the
+playlist.
+.TP
+.B clear list
+To abort the programing of a playlist click Control-Button-1 into the
+track-display.
+.TP
+.B start playing the list
+Simply press the PLAY button to play the list.
+.SH MIXER USAGE
+Main controls of the mixer are the two volume scales at the left and the right 
+side of the display. Using the mouse the scales can be modified.
+.TP
+.B button-1
+change volume of clicked scale
+.TP
+.B button-2
+change volume of both scales
+.TP
+.B button-3
+change the balance of the volume
+.PP
+Clicking into the alphanumeric display changes the currently shown mixer
+device. Valid devices are VOlume, BAss, TReble, SYnth, PCm, SPeaker, LIne,
+MIc, CD, MiXer, Pcm2, REcord, IGain, OGain, Line1, Line2, and Line3.
+You can also remove devices from this list.
+.TP
+.B button-1
+go to the next device
+.TP
+.B button-2
+go to the main volume (first device)
+.TP
+.B button-3
+go to the previous device
+.TP
+.B control-button-1
+show all devices
+.TP
+.B control-button-3
+remove current device
+.PP
+Below the change-controls button is the record source button. It show either
+a 'X' and is inactive, or it show a speaker or a recording sign and is active.
+By pressing this button you can change the source of your recordings.
+.TP
+.B button-1
+toggle record source button
+.TP
+.B button-2
+set as record source and clear all other
+.SH COPYRIGHTS
+Copyright 1997, Oliver Graf <ograf at fga.de>.
+Most styles copyright 1997, Heiko Wagner <hwagner at fga.de>.
+.Sp
+No guarantees or warranties or anything are provided or implied in any way
+whatsoever. Use this program at your own risk. Permission to use this program
+for any purpose is given, as long as the copyright is kept intact.
+.SH AUTHORS
+Oliver Graf <ograf at fga.de> -- the coding
+.Sp
+Heiko Wagner <hwagner at fga.de> -- the hyped window shapes
+.SH CREDITS
+Rob Malda <malda at cs.hope.edu> -- who had written ascd and asmixer
+.Sp
+Michael Kurz <mkurz at rzws.fh-aalen.de> -- also for ascd and asmixer
+.Sp
+Thomas McWilliams <tgm at netcom.com> -- who has done Workbone
diff --git a/xpmicon.c b/xpmicon.c
new file mode 100644
index 0000000..58b232b
--- /dev/null
+++ b/xpmicon.c
@@ -0,0 +1,338 @@
+/*
+ * $Id: xpmicon.c,v 1.1.1.1 2001/02/12 22:26:11 xtifr Exp $
+ *
+ * part of WMRack
+ *
+ * handles the whole pixmap stuff (styles)
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+#include <X11/xpm.h>
+#include <X11/extensions/shape.h>
+
+#include "library.h"
+#include "xpmicon.h"
+
+/* include the default xpms */
+#include "XPM/standart.style"
+
+/*
+ * first some requires variables
+ */
+XpmAttributes rackDefaultAttr;
+XpmIcon rackXpm[]={{"cdnodisc",cdnodisc},
+		   {"cdstopped",cdstopped},
+		   {"cdplaying",cdplaying},
+		   {"cdpaused",cdpaused},
+		   {"mixer",mixer},
+		   {"cdled",cdled},
+		   {"mixled",mixled},
+		   {"alphaled",alphaled}};
+
+int curRack=RACK_NODISC;
+
+XpmColorSymbol LedColorSymbols[4]={{"led_color_back", "#000000000000", 0},
+				   {"led_color_high", "#0000FFFF0000", 0},
+				   {"led_color_med",  "#00009CE60000", 0},
+				   {"led_color_low",  "#000063180000", 0}};
+
+char *ledAlphabet="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ";
+
+/*
+ * some internal functions
+ */
+/****************************************************************************/
+Pixel xpm_getDimColor(Display *disp, Drawable draw, char *ColorName, float dim)
+{
+  XColor Color;
+  XWindowAttributes Attributes;
+
+  XGetWindowAttributes(disp,draw,&Attributes);
+  Color.pixel = 0;
+
+  if (!XParseColor (disp, Attributes.colormap, ColorName, &Color))
+    fprintf(stderr,"xpm_getDimColor: can't parse %s\n", ColorName);
+  else
+    {
+      Color.red/=dim;
+      Color.green/=dim;
+      Color.blue/=dim;
+      Color.flags=DoRed|DoGreen|DoBlue;
+      if (!XAllocColor (disp, Attributes.colormap, &Color))
+	fprintf(stderr,"xpm_getDimColor: can't allocate %s\n", ColorName);
+    }
+
+  return Color.pixel;
+}
+
+int parseXpm(Display *disp, Drawable draw, char *buffer)
+{
+  int i, len;
+  char *d1, *d2;
+
+  /* check header */
+  if (strncmp(buffer,"/* XPM */\nstatic char *",23)!=0)
+    {
+      fprintf(stderr,"parseXpm: invalid start of xpm\n");
+      fprintf(stderr,buffer);
+      return 1;
+    }
+  /* skip spaces */
+  for (d1=buffer+23; *d1==32; d1++);
+  /* find end */
+  d2=strchr(d1,'[');
+  if (d2==NULL)
+    {
+      fprintf(stderr,"parseXpm: can't parse xpm-name\n");
+      return 1;
+    }
+  for (; *(d2-1)==32; d2--);
+  len=d2-d1;
+#ifdef DEBUG
+  {
+    char name[200];
+    strncpy(name,d1,len);
+    name[len]=0;
+    fprintf(stderr,"parseXpm: found XPM %s\n",name);
+  }
+#endif
+  /* find the right place */
+  for (i=0; i<RACK_MAX; i++)
+    {
+      if (strncmp(rackXpm[i].name,d1,len)==0)
+	{
+	  if (rackXpm[i].loaded)
+	    {
+	      fprintf(stderr,"parseXpm: skipping double XPM for %s\n",d1);
+	      break;
+	    }
+	  else
+	    {
+	      rackXpm[i].attributes=rackDefaultAttr;
+	      if (XpmCreatePixmapFromBuffer(disp, draw, buffer,
+					    &rackXpm[i].pixmap,
+					    &rackXpm[i].mask,
+					    &rackXpm[i].attributes)!=XpmSuccess)
+		{
+		  fprintf(stderr,"parseXpm: can't create pixmap from buffer\n");
+		  return 1;
+		}
+	      rackXpm[i].loaded=1;
+	      break;
+	    }
+	}
+    }
+  return 0;
+}
+
+/*
+ * now the interface functions
+ */
+
+/*
+ * xpm_setDefaultAttr(color)
+ *
+ * creates the attributes for xpm pixmap creation and sets
+ * the led symbol colors to the specified color and 2 shades of it.
+ */
+int xpm_setDefaultAttr(Display *disp, Drawable draw, char *color, char *back)
+{
+  rackDefaultAttr.valuemask=XpmReturnPixels | XpmReturnExtensions | XpmColorSymbols;
+  rackDefaultAttr.numsymbols=4;
+  if (color!=NULL)
+    {
+      LedColorSymbols[1].value=NULL;
+      LedColorSymbols[1].pixel=xpm_getDimColor(disp,draw,color,1);
+      LedColorSymbols[2].value=NULL;
+      LedColorSymbols[2].pixel=xpm_getDimColor(disp,draw,color,1.65);
+      LedColorSymbols[3].value=NULL;
+      LedColorSymbols[3].pixel=xpm_getDimColor(disp,draw,color,2.6);
+    }
+  if (back!=NULL)
+    {
+      LedColorSymbols[0].value=NULL;
+      LedColorSymbols[0].pixel=xpm_getDimColor(disp,draw,back,1);
+    }
+  rackDefaultAttr.colorsymbols=LedColorSymbols;
+  return 0;
+}
+
+/*
+ * xpm_loadSet(display, drawable, filename)
+ *
+ * loads a style file
+ */
+int xpm_loadSet(Display *disp, Drawable draw, char *filename)
+{
+  FILE *f;
+  char *buffer=NULL, line[4096], path[4096];
+  int bufpos=0, bufalloc=0, i;
+
+  buffer=lib_findfile(filename,1);
+  if (buffer==NULL)
+    {
+      fprintf(stderr,"xpm_loadSet: can't find file\n");
+      return 1;
+    }
+  strcpy(path,buffer);
+  buffer=NULL;
+#ifdef DEBUG
+  fprintf(stderr,"xpm_loadSet: loading %s\n",path);
+#endif
+
+  f=fopen(path,"r");
+  if (f==NULL)
+    {
+      perror("xpm_loadSet");
+      return 1;
+    }
+
+  for (i=0; i<RACK_MAX; i++)
+    rackXpm[i].loaded=0;
+
+  while (fgets(line,4095,f)!=NULL)
+    {
+      if (strcmp(line,"/* XPM */\n")==0)
+	{
+	  if (buffer!=NULL)
+	    {
+	      if (parseXpm(disp,draw,buffer))
+		{
+		  free(buffer);
+		  fclose(f);
+		  return 1;
+		}
+	      free(buffer);
+	      bufpos=bufalloc=0;
+	    }
+	  buffer=(char *)malloc(4096);
+	  if (buffer==NULL)
+	    {
+	      fprintf(stderr,"xpm_loadSet: can' alloc enough mem\n");
+	      fclose(f);
+	      return 1;
+	    }
+	  bufalloc=4096;
+	  strcpy(buffer+bufpos,line);
+	  bufpos=strlen(buffer);
+	  continue;
+	}
+      if (buffer!=NULL)
+	{
+	  if (bufpos+strlen(line)>=bufalloc)
+	    {
+	      char *newbuf;
+	      newbuf=(char *)realloc(buffer,bufalloc+4096);
+	      if (newbuf==NULL)
+		{
+		  fprintf(stderr,"xpm_loadSet: can' alloc enough mem\n");
+		  fclose(f);
+		  return 1;
+		}
+	      buffer=newbuf;
+	      bufalloc+=4096;
+	    }
+	  strcpy(buffer+bufpos,line);
+	  bufpos+=strlen(line);
+	}
+    }
+  fclose(f);
+
+  if (buffer!=NULL)
+    {
+      if (parseXpm(disp,draw,buffer))
+	{
+	  free(buffer);
+	  return 1;
+	}
+      free(buffer);
+    }
+
+  /* check if all xpms are loaded */
+  for (i=0; i<RACK_MAX; i++)
+    if (!rackXpm[i].loaded)
+      {
+	fprintf(stderr,"xpm_loadSet: xpm for %s is missing, using default\n",
+		rackXpm[i].name);
+	if (xpm_setDefaultSet(disp,draw,i))
+	  {
+	    fprintf(stderr,"xpm_loadSet: can't set default pixmap\n");
+	    return 1;
+	  }
+      }
+
+  return 0;
+}
+
+/*
+ * int xpm_getDefaultsSet(display, drawable, num)
+ *
+ * sets the specified pixmap buffer to the compiletime default
+ * sets all pixmap buffers, if num is RACK_MAX
+ *
+ * returns 0 on success
+ */
+int xpm_setDefaultSet(Display *disp, Drawable draw, int num)
+{
+  int i, ret=0, x;
+
+  if (num==RACK_MAX)
+    for (i=0; i<RACK_MAX; i++)
+      {
+	if (rackXpm[i].standart==NULL)
+	  continue;
+	rackXpm[i].attributes=rackDefaultAttr;
+	x=XpmCreatePixmapFromData(disp, draw, rackXpm[i].standart,
+				  &rackXpm[i].pixmap,
+				  &rackXpm[i].mask,
+				  &rackXpm[i].attributes)!=XpmSuccess;
+	ret|=x;
+#ifdef DEBUG
+	if (x)
+	  fprintf(stderr,"xpm_setDefaultSet: failure to load %d (XpmErrNo %d)\n",i,x);
+#endif
+      }
+  else
+    {
+      if (rackXpm[num].standart==NULL)
+	return 0;
+      rackXpm[num].attributes=rackDefaultAttr;
+      ret|=XpmCreatePixmapFromData(disp, draw, rackXpm[num].standart,
+				   &rackXpm[num].pixmap,
+				   &rackXpm[num].mask,
+				   &rackXpm[num].attributes)!=XpmSuccess;
+#ifdef DEBUG
+      if (ret)
+	fprintf(stderr,"xpm_setDefaultSet: failure to load %d (XpmErrNo %d)\n",i,x);
+#endif
+    }
+  return ret;
+}
+
+/*
+ * xpm_freeSet(display)
+ *
+ * frees all pixmap data
+ */
+void xpm_freeSet(Display *disp)
+{
+  int i;
+
+#ifdef DEBUG
+  fprintf(stderr,"xpm_freeSet: freeing pixmaps\n");
+#endif
+  for (i=0; i<RACK_MAX; i++)
+    {
+      XFreePixmap(disp,rackXpm[i].pixmap);
+      XFreePixmap(disp,rackXpm[i].mask);
+    }
+#ifdef DEBUG
+  fprintf(stderr,"xpm_freeSet: done.\n");
+#endif
+}
+
diff --git a/xpmicon.h b/xpmicon.h
new file mode 100644
index 0000000..3921723
--- /dev/null
+++ b/xpmicon.h
@@ -0,0 +1,46 @@
+/*
+ * $Id: xpmicon.h,v 1.1.1.1 2001/02/12 22:26:11 xtifr Exp $
+ *
+ * part of wmrack
+ *
+ * handles the whole pixmap stuff
+ *
+ * Copyright (c) 1997 by Oliver Graf <ograf at fga.de>
+ */
+#ifndef _XPMICON_H
+#define _XPMICON_H
+
+/* Xpm struct */
+typedef struct {
+  char *name;
+  char **standart;
+  int loaded;
+  XpmAttributes attributes;
+  Pixmap pixmap;
+  Pixmap mask;
+} XpmIcon;
+
+/* the XpmIcon definitions and variables */
+#define RACK_NODISC     0
+#define RACK_STOP       1
+#define RACK_PLAY       2
+#define RACK_PAUSE      3
+#define RACK_MIXER      4
+#define RACK_LED_PLAYER 5
+#define RACK_LED_MIXER  6
+#define RACK_LED_ALPHA  7
+#define RACK_MAX        8
+
+extern XpmIcon rackXpm[];
+extern int curRack;
+extern char *ledAlphabet;
+
+#define currentXpm(w) rackXpm[curRack].##w
+#define ledXpm(x,w) rackXpm[x].##w
+
+int xpm_setDefaultAttr(Display *disp, Drawable draw, char *color, char *back);
+int xpm_loadSet(Display *disp, Drawable draw, char *filename);
+int xpm_setDefaultSet(Display *disp, Drawable draw, int num);
+void xpm_freeSet(Display *disp);
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-wmaker/wmrack.git



More information about the Pkg-wmaker-commits mailing list