[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