Add AlsaMixer.app to repositoryAlsaMixer.app-0.1
authorWade Berrier <wberrier@gmail.com>
Wed, 13 Jun 2012 04:21:21 +0000 (12 22:21 -0600)
committerCarlos R. Mafra <crmafra@gmail.com>
Tue, 2 Oct 2012 22:26:31 +0000 (2 23:26 +0100)
http://dockapps.windowmaker.org/file.php/id/253 shows a version available from

http://www.stud.fit.vutbr.cz/~xhlavk00/AlsaMixer.app/

but it's a dead link.

Check in the version from

http://dockapps.windowmaker.org/download.php/id/517/AlsaMixer.app-0.1.tar.gz

Untarred and removed version from directory.  No other changes.

Signed-off-by: Wade Berrier <wberrier@gmail.com>
28 files changed:
AlsaMixer.app/AMixer/AChannel.cc [new file with mode: 0644]
AlsaMixer.app/AMixer/AChannel.h [new file with mode: 0644]
AlsaMixer.app/AMixer/AItem.cc [new file with mode: 0644]
AlsaMixer.app/AMixer/AItem.h [new file with mode: 0644]
AlsaMixer.app/AMixer/AMixer.cc [new file with mode: 0644]
AlsaMixer.app/AMixer/AMixer.h [new file with mode: 0644]
AlsaMixer.app/AlsaMixer.app.spec [new file with mode: 0644]
AlsaMixer.app/COPYING [new file with mode: 0644]
AlsaMixer.app/INSTALL [new file with mode: 0644]
AlsaMixer.app/Main.cc [new file with mode: 0644]
AlsaMixer.app/Makefile [new file with mode: 0644]
AlsaMixer.app/Mixer.cc [new file with mode: 0644]
AlsaMixer.app/Mixer.h [new file with mode: 0644]
AlsaMixer.app/README [new file with mode: 0644]
AlsaMixer.app/Xpm.cc [new file with mode: 0644]
AlsaMixer.app/Xpm.h [new file with mode: 0644]
AlsaMixer.app/olddoc/ChangeLog.Mixer.app [new file with mode: 0644]
AlsaMixer.app/olddoc/INSTALL.Mixer.app [new file with mode: 0644]
AlsaMixer.app/olddoc/README.Mixer.app [new file with mode: 0644]
AlsaMixer.app/pixmaps [new symlink]
AlsaMixer.app/skins/barross@web.de/button.xpm [new file with mode: 0644]
AlsaMixer.app/skins/barross@web.de/main.xpm [new file with mode: 0644]
AlsaMixer.app/skins/barross@web.de/mutebutton.xpm [new file with mode: 0644]
AlsaMixer.app/skins/barross@web.de/redlight.xpm [new file with mode: 0644]
AlsaMixer.app/skins/default/button.xpm [new file with mode: 0644]
AlsaMixer.app/skins/default/main.xpm [new file with mode: 0644]
AlsaMixer.app/skins/default/mutebutton.xpm [new file with mode: 0644]
AlsaMixer.app/skins/default/redlight.xpm [new file with mode: 0644]

diff --git a/AlsaMixer.app/AMixer/AChannel.cc b/AlsaMixer.app/AMixer/AChannel.cc
new file mode 100644 (file)
index 0000000..b0e55bb
--- /dev/null
@@ -0,0 +1,41 @@
+// AChannel.cc, Petr Hlavka, 2004
+
+#include "AMixer.h"
+#include "AItem.h"
+#include "AChannel.h"
+
+#include <iostream>
+
+
+AChannel::AChannel(AItem *item, SNDCHID_T cID) {
+  aItem = item;
+  id = cID;
+}
+
+
+AChannel::~AChannel() {
+}
+
+
+long AChannel::getVolume() {
+  long vol = 0;
+
+  snd_mixer_selem_get_playback_volume(aItem->aElem, (SNDCHID_T) id, &vol);
+
+  return (vol);
+}
+
+
+// it isn't necessery when using snd_mixer_selem_set_x_volume_all
+void AChannel::setVolume(long value) {
+  std::cerr << "AChannel::setVolume not implemented!" << std::endl;
+}
+
+
+bool AChannel::isMuted() {
+  int val;
+  
+  snd_mixer_selem_get_playback_switch(aItem->aElem, (SNDCHID_T) id, &val);
+
+  return (! (bool) val);
+}
diff --git a/AlsaMixer.app/AMixer/AChannel.h b/AlsaMixer.app/AMixer/AChannel.h
new file mode 100644 (file)
index 0000000..57ad075
--- /dev/null
@@ -0,0 +1,28 @@
+// AChannel.h, Petr Hlavka, 2004
+
+#ifndef ACHANNEL_H
+#define ACHANNEL_H
+
+#include "AMixer.h"
+#include "AItem.h"
+
+#include <alsa/asoundlib.h>
+
+#define SNDCHID_T      snd_mixer_selem_channel_id_t
+
+class AItem;
+
+class AChannel {
+  private:
+    SNDCHID_T id;              // channel id (front left, f. right, ...)
+    AItem *aItem;              // parent mixer item
+  public:
+    AChannel(AItem *item, SNDCHID_T cID);      // ctor
+    ~AChannel();                               // dtor
+
+    long getVolume();          // get channel volume
+    void setVolume(long value);        // set channel volume
+    bool isMuted();            // return true, if channel is muted
+};
+
+#endif
diff --git a/AlsaMixer.app/AMixer/AItem.cc b/AlsaMixer.app/AMixer/AItem.cc
new file mode 100644 (file)
index 0000000..7272268
--- /dev/null
@@ -0,0 +1,87 @@
+// AItem.cc, Petr Hlavka, 2004
+
+#include "AItem.h"
+#include "AMixer.h"
+
+#include <alsa/asoundlib.h>
+#include <vector>
+
+#define ROUND_POS(x)   (long ((long (x) + 0.5 > (x)) ? (x) : (x) + 1))
+
+
+// load only playback channels, don't care about common items
+AItem::AItem(AMixer *m, snd_mixer_elem_t *e) {
+  mixer = m;
+  aElem = e;
+
+  name = snd_mixer_selem_get_name(aElem);
+
+  hPVolume = snd_mixer_selem_has_playback_volume(aElem);
+  hPSwitch = snd_mixer_selem_has_playback_switch(aElem);
+
+  if (hPVolume)
+    snd_mixer_selem_get_playback_volume_range(aElem, &minPVolume, &maxPVolume);
+  else
+    minPVolume = maxPVolume = 0;
+
+  for (int channel = 0; channel <= (int) SND_MIXER_SCHN_LAST; channel++) {
+    if (snd_mixer_selem_has_playback_channel(aElem, (SNDCHID_T) channel)) {
+      AChannel *ch = new AChannel(this, (SNDCHID_T) channel);
+      pbChannels.push_back(ch);
+    }
+  }
+}
+
+
+AItem::~AItem() {
+  for (unsigned int i = 0; i < pbChannels.size(); i++)
+    delete pbChannels[i];
+}
+
+
+// set same volume for all channels in this item in percent
+void AItem::setVolumePerc(unsigned int percent) {
+  if (percent > 100)
+    percent = 100;
+
+  snd_mixer_selem_set_playback_volume_all(aElem, (long) ROUND_POS((minPVolume + (maxPVolume - minPVolume) * percent / 100.0)));
+}
+
+
+// get max channel volume of all channels in this item in percent
+unsigned int AItem::getVolumePerc() {
+  long max_vol = 0, act_vol;
+
+  // find the max volume
+  for (unsigned int i = 0; i < pbChannels.size(); i++)
+    if ((act_vol = pbChannels[i]->getVolume()) > max_vol)
+      max_vol = act_vol;
+
+  // convert it into percent
+  if (minPVolume != maxPVolume)
+    return ((unsigned int) ROUND_POS((max_vol - minPVolume) * 100.0 / (maxPVolume - minPVolume)));
+  else
+    return (0);
+}
+
+
+// in this app side of view, item is muted if all channels is muted
+bool AItem::isMuted() {
+  for (unsigned int i = 0; i < pbChannels.size(); i++)
+    if (!pbChannels[i]->isMuted())
+      return (false);
+
+  return (true);
+}
+
+
+// mute all channels
+void AItem::mute() {
+  snd_mixer_selem_set_playback_switch_all(aElem, false);
+}
+
+
+// unmute all channels
+void AItem::unmute() {
+  snd_mixer_selem_set_playback_switch_all(aElem, true);
+}
diff --git a/AlsaMixer.app/AMixer/AItem.h b/AlsaMixer.app/AMixer/AItem.h
new file mode 100644 (file)
index 0000000..0f4f71a
--- /dev/null
@@ -0,0 +1,39 @@
+// AItem.h, Petr Hlavka, 2004
+
+#ifndef AITEM_H
+#define AITEM_H
+
+#include "AMixer.h"
+#include "AChannel.h"
+
+#include <alsa/asoundlib.h>
+#include <vector>
+
+
+class AChannel;
+class AMixer;
+
+class AItem {
+  private:
+    AMixer *mixer;                     // parent mixer
+    std::vector<AChannel *> pbChannels;        // item channels 
+
+    long minPVolume, maxPVolume;       // min/max playback volume
+    bool hPVolume;                     // has Playback volume
+    bool hPSwitch;                     // has Playback switch
+
+  public:
+    snd_mixer_elem_t *aElem;           // mixer item element
+    const char *name;                  // item name
+
+    AItem(AMixer *m, snd_mixer_elem_t *e);     // ctor
+    ~AItem();                                  // dtor
+
+    void setVolumePerc(unsigned int percent);
+    unsigned int getVolumePerc();
+    bool isMuted();
+    void mute();
+    void unmute();
+};
+
+#endif
diff --git a/AlsaMixer.app/AMixer/AMixer.cc b/AlsaMixer.app/AMixer/AMixer.cc
new file mode 100644 (file)
index 0000000..dbf9002
--- /dev/null
@@ -0,0 +1,203 @@
+// AMixer.cc, Petr Hlavka, 2004
+
+#include "AMixer.h"
+#include "AItem.h"
+
+#include <alsa/asoundlib.h>
+#include <iostream>
+#include <cstdio>
+#include <cstring>
+
+static bool mixerChangeIndicator = false;
+static bool mixerReinitIndicator = false;
+static int mixerCallback(snd_mixer_t *ctl, unsigned int mask,
+                        snd_mixer_elem_t *elem);
+static int itemCallback(snd_mixer_elem_t *elem, unsigned int mask);
+
+
+AMixer::AMixer(const char *card) {
+  int err;
+
+  if (card) {
+    cardName = new char[std::strlen(card)];
+    std::strcpy(cardName, card);
+    for (int i = 0; i < MIXER_ITEMS; i++)
+      mixerItems[i] = NULL;
+
+    if ((err = snd_mixer_open(&mixerHandle, 0)) < 0) {
+      error("snd_mixer_open error", err);
+      mixerHandle = NULL;
+
+      return;
+    }
+    if ((err = snd_mixer_attach(mixerHandle, card)) < 0) {
+      error("snd_mixer_attach error", err);
+      snd_mixer_close(mixerHandle);
+      mixerHandle = NULL;
+
+      return;
+    }
+    if ((err = snd_mixer_selem_register(mixerHandle, NULL, NULL)) < 0) {
+      error("snd_mixer_selem_register error", err);
+      snd_mixer_close(mixerHandle);
+      mixerHandle = NULL;
+
+      return;
+    }
+    if ((err = snd_mixer_load(mixerHandle)) < 0) {
+      error("snd_mixer_load error", err);
+      snd_mixer_close(mixerHandle);
+      mixerHandle = NULL;
+
+      return;
+    }
+
+    snd_mixer_set_callback(mixerHandle, (snd_mixer_callback_t) &mixerCallback);
+  }
+}
+
+
+AMixer::~AMixer() {
+  if (mixerHandle) {
+    snd_mixer_free(mixerHandle);
+    snd_mixer_detach(mixerHandle, cardName);
+    delete[] cardName;
+    snd_mixer_close(mixerHandle);
+  }
+}
+
+
+bool AMixer::opened() {
+  return (mixerHandle != NULL);
+}
+
+
+void AMixer::error(const char *errorString, int errorCode) {
+  std::cerr << cardName << ": " << errorString << ": " << snd_strerror(errorCode) << std::endl;
+}
+
+
+void AMixer::handleEvents() {
+  snd_mixer_handle_events(mixerHandle);
+}
+
+
+AItem *AMixer::attachItem(unsigned int itemNumber, const char *itemName) {
+  if (itemNumber >= MIXER_ITEMS || !itemName)
+    return (NULL);
+
+  // item was already created, so deregister callback and free it first
+  if (mixerItems[itemNumber]) {
+    snd_mixer_elem_set_callback(mixerItems[itemNumber]->aElem, NULL);
+    delete mixerItems[itemNumber];
+  }
+
+  // try to find item by name, register callback, return success
+  snd_mixer_elem_t *elem;
+  for (elem = snd_mixer_first_elem(mixerHandle); elem; elem = snd_mixer_elem_next(elem)) {
+    if (snd_mixer_selem_is_active(elem) &&
+       snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE &&
+       std::strcmp(snd_mixer_selem_get_name(elem), itemName) == 0) {
+      snd_mixer_elem_set_callback(elem, (snd_mixer_elem_callback_t) &itemCallback);
+      return (mixerItems[itemNumber] = new AItem(this, elem));
+    }
+  }
+
+  return (NULL);
+}
+
+
+bool AMixer::itemOK(unsigned int itemNumber) {
+  return (itemNumber < MIXER_ITEMS && mixerItems[itemNumber]);
+}
+
+
+int AMixer::itemGetVolume(unsigned int itemNumber) {
+  if (itemNumber >= MIXER_ITEMS || !mixerItems[itemNumber])
+    return (-1);
+  
+  return ((int) mixerItems[itemNumber]->getVolumePerc());
+}
+
+
+void AMixer::itemSetVolume(unsigned int itemNumber, unsigned int volume) {
+  if (itemNumber < MIXER_ITEMS && mixerItems[itemNumber])
+    mixerItems[itemNumber]->setVolumePerc(volume);
+}
+
+
+int AMixer::itemIsMuted(unsigned int itemNumber) {
+  if (itemNumber >= MIXER_ITEMS || !mixerItems[itemNumber])
+    return (-1);
+  
+  return ((bool) mixerItems[itemNumber]->isMuted());
+}
+
+
+void AMixer::itemToggleMute(unsigned int itemNumber) {
+  if (itemNumber < MIXER_ITEMS && mixerItems[itemNumber]) {
+    if (itemIsMuted(itemNumber))
+      mixerItems[itemNumber]->unmute();
+    else
+      mixerItems[itemNumber]->mute();
+  }
+}
+
+
+// return true if mixer elm sent callback and this callback wasn't picked up yet
+bool AMixer::mixerElemsChanged() {
+  if (mixerChangeIndicator) {
+    mixerChangeIndicator = false;
+
+    return (true);
+  }
+  else
+    return (false);
+}
+
+
+// return true if mixer sent callback and this callback wasn't picked up yet
+bool AMixer::mixerChanged() {
+  if (mixerReinitIndicator) {
+    mixerReinitIndicator = false;
+
+    return (true);
+  }
+  else
+    return (false);
+}
+
+
+// this function should be called after mixer callback, reInit all items
+void AMixer::reInit() {
+  for (int i = 0; i < MIXER_ITEMS; i++)
+    this->attachItem(i, mixerItems[i]->name);
+}
+
+
+int mixerCallback(snd_mixer_t *ctl, unsigned int mask,
+                         snd_mixer_elem_t *elem) {
+  mixerReinitIndicator = true;
+
+  return (0);
+}
+
+
+int itemCallback(snd_mixer_elem_t *elem, unsigned int mask) {
+  mixerChangeIndicator = true;
+
+  return (0);
+}
+
+
+char* AMixer::convertIDToCard(const char* cardId) {
+  static char card[32] = "";
+  int i = snd_card_get_index(cardId);
+  
+  if (i >= 0 && i < 32)
+    std::snprintf(card, 32, "hw:%i", i);
+  else
+    return (NULL);
+
+  return (card);
+}
diff --git a/AlsaMixer.app/AMixer/AMixer.h b/AlsaMixer.app/AMixer/AMixer.h
new file mode 100644 (file)
index 0000000..16c2960
--- /dev/null
@@ -0,0 +1,42 @@
+// AMixer.h, Petr Hlavka, 2004
+
+#ifndef AMIXER_H
+#define AMIXER_H
+
+#include "AItem.h"
+
+#include <alsa/asoundlib.h>
+
+#define MIXER_ITEMS    3
+
+
+class AItem;
+
+class AMixer {
+  private:
+    snd_mixer_t *mixerHandle;
+    AItem *mixerItems[MIXER_ITEMS];
+    char *cardName;
+
+    void error(const char *errorString, int errorCode);
+
+  public:
+    AMixer(const char *card);          // ctor
+    ~AMixer();                         // dtor
+
+    bool opened();
+    void handleEvents();
+    AItem *attachItem(unsigned int itemNumber, const char *itemName);
+    bool itemOK(unsigned int itemNumber);
+    int itemGetVolume(unsigned int itemNumber);
+    void itemSetVolume(unsigned int itemNumber, unsigned int volume);
+    int itemIsMuted(unsigned int itemNumber);
+    void itemToggleMute(unsigned int itemNumber);
+    void reInit();
+
+    static bool mixerElemsChanged();
+    static bool mixerChanged();
+    static char* convertIDToCard(const char* cardId);
+};
+
+#endif
diff --git a/AlsaMixer.app/AlsaMixer.app.spec b/AlsaMixer.app/AlsaMixer.app.spec
new file mode 100644 (file)
index 0000000..41b0aa0
--- /dev/null
@@ -0,0 +1,42 @@
+%define prefix /usr/local
+
+Summary: dockable mixer for ALSA driver and Window Maker
+Name: AlsaMixer.app
+Version: 0.1
+Release: 1
+Source0: %{name}-%{version}.tar.gz
+License: GPL
+Group: X11/Utilities
+BuildRoot: %{_tmppath}/%{name}-root
+Packager: Petr Hlavka <xhlavk00@stud.fit.vutbr.cz>
+Requires: XFree86-devel, libXpm-devel
+URL: http://www.stud.fit.vutbr.cz/~xhlavk00/AlsaMixer.app/
+
+%description
+AlsaMixer.app is simple dockable mixer application for WindowMaker. It can
+control up to three volume sources, load/store mixer settings, run external
+application on middle click (i.e. more sophisticated mixer)
+
+%prep
+%setup -q
+
+%build
+make
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p -m 0755 $RPM_BUILD_ROOT%{prefix}/bin
+cp -f AlsaMixer.app $RPM_BUILD_ROOT%{prefix}/bin
+
+
+%clean
+if [ -d $RPM_BUILD_ROOT ]; then rm -rf $RPM_BUILD_ROOT; fi
+if [ -d $RPM_BUILD_DIR/%{name}-%{version} ]; then rm -rf $RPM_BUILD_DIR/%{name}-%{version}; fi
+
+%files
+%defattr(-,root,root)
+%attr(0755,root,root) %{prefix}/bin/AlsaMixer.app
+
+%changelog
+* Tue Sep 30 2004 Petr Hlavka
+- initial release
diff --git a/AlsaMixer.app/COPYING b/AlsaMixer.app/COPYING
new file mode 100644 (file)
index 0000000..96e4591
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+               59 Temple Place, Suite 330, Boston, MA 02111-1307, 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.
+\f
+                   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.)
+\f
+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.
+\f
+  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.
+\f
+  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
+\f
+       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/AlsaMixer.app/INSTALL b/AlsaMixer.app/INSTALL
new file mode 100644 (file)
index 0000000..e9e04ca
--- /dev/null
@@ -0,0 +1,33 @@
+Installation instructions for AlsaMixer.app
+
+
+Requirements
+-------------------------------------------------------------------
+- X11, libxpm (devel version of both), C++ development environment
+        Most (Linux) systems have these things installed by default.
+        If you don't have it look for packages that fit your
+        distribution (especially somelib-devel packages).
+
+
+Installation
+-------------------------------------------------------------------
+1) make
+2) su
+3) make install       (to put it in /usr/local/GNUstep/Apps/AlsaMixer.app)
+   or
+   make install-x11   (to put it in /usr/X11R6/bin)
+5) exit
+
+
+Running
+-------------------------------------------------------------------
+To run this program:
+/usr/local/GNUstep/Apps/AlsaMixer.app/AlsaMixer &
+or
+/usr/X11R6/bin/AlsaMixer.app &
+
+
+For more information about available command line arguments:
+/usr/local/GNUstep/Apps/Mixer.app/AlsaMixer --help
+or
+/usr/X11R6/bin/AlsaMixer.app --help
diff --git a/AlsaMixer.app/Main.cc b/AlsaMixer.app/Main.cc
new file mode 100644 (file)
index 0000000..e3b5fd7
--- /dev/null
@@ -0,0 +1,31 @@
+//
+//  Mixer.app
+// 
+//  Copyright (c) 1998-2002 Per Liden
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
+//  USA.
+//
+
+#include "Mixer.h"
+
+Mixer* app;
+
+int main(int argc, char** argv) 
+{
+   app = new Mixer(argc, argv);
+   app->run();
+   return 0;
+}
diff --git a/AlsaMixer.app/Makefile b/AlsaMixer.app/Makefile
new file mode 100644 (file)
index 0000000..14f510c
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Mixer.app Makefile
+#
+
+DESTDIR =
+GNUSTEP_BINDIR = /usr/local/GNUstep/Apps/AlsaMixer.app
+X11_BINDIR = /usr/X11R6/bin
+
+CXX=c++
+CXXFLAGS += -Wall -pedantic -fno-rtti -fno-exceptions -O2 -I/usr/X11R6/include
+LDFLAGS += -L/usr/X11R6/lib -lXpm -lXext -lX11 -lasound
+
+OBJECTS = Main.o Mixer.o Xpm.o AMixer/AMixer.o AMixer/AItem.o AMixer/AChannel.o
+
+all: AlsaMixer.app
+
+AlsaMixer.app: $(OBJECTS)
+       $(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
+
+.PHONY:        install clean distclean
+
+install: install-gnustep
+
+install-gnustep: all
+       install -d  $(DESTDIR)$(GNUSTEP_BINDIR)
+       install -m 0755 AlsaMixer.app $(DESTDIR)$(GNUSTEP_BINDIR)/AlsaMixer
+
+install-x11: all
+       install -d  $(DESTDIR)$(X11_BINDIR)
+       install -m 0755 AlsaMixer.app $(DESTDIR)$(X11_BINDIR)/AlsaMixer.app
+
+clean:
+       rm -f *~ $(OBJECTS) AlsaMixer.app
+
+# End of file
diff --git a/AlsaMixer.app/Mixer.cc b/AlsaMixer.app/Mixer.cc
new file mode 100644 (file)
index 0000000..11bec7c
--- /dev/null
@@ -0,0 +1,598 @@
+//
+//  Mixer.app
+// 
+//  Copyright (c) 1998-2002 Per Liden
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
+//  USA.
+//
+
+#include <X11/Xlib.h>
+#include <iostream>
+#include <fstream>
+#include <cstdlib>
+#include <cstring>
+#include <csignal>
+#include "Xpm.h"
+#include "Mixer.h"
+
+#include "AMixer/AMixer.h"
+
+#include "pixmaps/main.xpm"
+#include "pixmaps/button.xpm"
+#include "pixmaps/mutebutton.xpm"
+#include "pixmaps/redlight.xpm"
+
+#define ROUND_POS(x)   (int ((x) + 0.5) > int (x)) ? (int) ((x) + 1) : (int) (x)
+
+using namespace std;
+
+static const int ButtonX[] = {6, 24, 42};
+static const char* MixerSources[] = { "Master", "PCM", "CD" };
+
+extern Mixer* app;
+
+void catchBrokenPipe(int sig) 
+{
+   app->saveVolumeSettings();
+   exit(0);
+}
+
+int positionToPercent(int position) {
+  return ROUND_POS(100 - (((position - BUTTON_MAX) * 100.0) / (BUTTON_MIN - BUTTON_MAX)));
+}
+
+int percentToPosition(int percent) {
+  return ROUND_POS(BUTTON_MIN - (percent * (BUTTON_MIN - BUTTON_MAX)) / 100.0);
+}
+
+Mixer::Mixer(int argc, char** argv) 
+{
+   XClassHint classHint;
+   XSizeHints sizeHints;
+   XWMHints   wmHints;
+   Atom       deleteWindow;
+   Xpm*       image;
+   char*      displayName = NULL;
+   char*      card = "default";
+
+   mError = 0;
+   mInstanceName = INSTANCENAME;
+   mVolumeSource[0] = -1;
+   mVolumeSource[1] = -1;
+   mVolumeSource[2] = -1;
+   mVolumeMute[0] = 0;
+   mVolumeMute[1] = 0;
+   mVolumeMute[2] = 0;
+   mWheelButton = 1;
+   mLabelText = 0;
+   mSettingsFile = 0;
+   mSaveSettings = false;
+   mLoadSettings = false;
+   mCommand = NULL;
+
+   // Parse command line
+   if (argc>1) {
+      for (int i=1; i<argc; i++) {
+         // Display
+         if (!strcmp(argv[i], "-d")) {
+            checkArgument(argv, argc, i);
+            displayName = argv[i+1];
+            i++;
+         }
+
+         // Sound source
+         else if (!strcmp(argv[i], "-1") || !strcmp(argv[i], "-2") || !strcmp(argv[i], "-3")) {
+            checkArgument(argv, argc, i);
+           MixerSources[argv[i][1] - '1'] = argv[i + 1];
+           i++;
+         }
+
+         // Wheel binding
+         else if (!strcmp(argv[i], "-w")) {
+            checkArgument(argv, argc, i);
+            mWheelButton = atoi(argv[i+1]);
+
+            if (mWheelButton < 1 || mWheelButton > 3) {
+               cerr << APPNAME << ": invalid wheel binding, must be 1, 2 or 3, not " << argv[i+1] << endl;
+               tryHelp(argv[0]);
+               exit(0);
+            }
+
+            i++;
+         }
+
+         // Label text
+         else if (!strcmp(argv[i], "-l")) {
+            checkArgument(argv, argc, i);
+            mLabelText = argv[i+1];
+            i++;
+         }
+
+         // Save settings on exit
+         else if (!strcmp(argv[i], "-S")) {
+           mSaveSettings = true;
+         }
+
+        // Load settings on startup
+        else if (!strcmp(argv[i], "-L")) {
+           mLoadSettings = true;
+        }
+
+         // Load/Save settings file
+         else if (!strcmp(argv[i], "-f")) {
+            checkArgument(argv, argc, i);
+            mSettingsFile = argv[i+1];
+            i++;
+         }
+
+        // Execute command on middle click
+         else if (!strcmp(argv[i], "-e")) {
+           checkArgument(argv, argc, i);
+          mCommand = argv[i + 1];
+          i++;
+        }
+
+         // Instance name
+         else if (!strcmp(argv[i], "-n")) {
+            checkArgument(argv, argc, i);
+            mInstanceName = argv[i+1];
+            i++;
+         }
+
+         // Version
+         else if (!strcmp(argv[i], "-v")) {
+            cerr << APPNAME << " version " << VERSION << endl;
+            exit(0);
+         }
+
+         // Help
+         else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
+            showHelp();
+            exit(0);
+         }
+
+        // card
+        else if (!strcmp(argv[i], "--card")) {
+          card = AMixer::convertIDToCard(argv[i + 1]);
+          if (!card) {
+            cerr << APPNAME << ": invalid card number '" << argv[i + 1] << "'" << endl;
+            tryHelp(argv[0]);
+            exit(0);
+          }
+          i++;
+        }
+
+        // device
+        else if (!strcmp(argv[i], "--device")) {
+          card = argv[i + 1];
+          i++;
+        }
+
+         // Unknown option
+         else {
+            cerr << APPNAME << ": invalid option '" << argv[i] << "'" << endl;
+            tryHelp(argv[0]);
+            exit(0);
+         }
+      }
+   }
+
+   // default settings file
+   if (!mSettingsFile) {
+     char* home = getenv("HOME");
+     if (home) {
+       mSettingsFile = new char[strlen(home) + strlen(SETTINGS) + 1];
+       strcpy(mSettingsFile, home);
+       strcat(mSettingsFile, SETTINGS);
+     } else {
+       cerr << APPNAME << ": $HOME not set, could not find saved settings" << endl;
+     }
+   }
+
+   // init mixer
+   aMixer = new AMixer(card);
+   if (!aMixer->opened()) {
+     cerr << APPNAME << ": could not open mixer device for card '" << card << "'" << endl;
+     exit(0);
+   }
+
+   // open mixer sources
+   for (int i = 0; i < 3; i++) {
+     aMixer->attachItem(i, MixerSources[i]);
+     if (!aMixer->itemOK(i))
+       cerr << APPNAME << ": could not select mixer source '" << MixerSources[i] << "'" << endl;
+   }
+
+   // Open display
+   if ((mDisplay = XOpenDisplay(displayName)) == NULL) {
+      cerr << APPNAME << ": could not open display " << displayName << endl;
+      exit(0);
+   }
+   // Get root window
+   mRoot = RootWindow(mDisplay, DefaultScreen(mDisplay));
+
+   // Create windows
+   mAppWin = XCreateSimpleWindow(mDisplay, mRoot, 1, 1, 64, 64, 0, 0, 0);
+   mIconWin = XCreateSimpleWindow(mDisplay, mAppWin, 0, 0, 64, 64, 0, 0, 0);
+
+   // Set classhint
+   classHint.res_name =  mInstanceName;
+   classHint.res_class = CLASSNAME;
+   XSetClassHint(mDisplay, mAppWin, &classHint);
+
+   // Create delete atom
+   deleteWindow = XInternAtom(mDisplay, "WM_DELETE_WINDOW", False);
+   XSetWMProtocols(mDisplay, mAppWin, &deleteWindow, 1);
+   XSetWMProtocols(mDisplay, mIconWin, &deleteWindow, 1);
+
+   // Set windowname
+   XStoreName(mDisplay, mAppWin, APPNAME);
+   XSetIconName(mDisplay, mAppWin, APPNAME);
+
+   // Set sizehints
+   sizeHints.flags= USPosition;
+   sizeHints.x = 0;
+   sizeHints.y = 0;
+   XSetWMNormalHints(mDisplay, mAppWin, &sizeHints);
+
+   // Set wmhints
+   wmHints.initial_state = WithdrawnState;
+   wmHints.icon_window = mIconWin;
+   wmHints.icon_x = 0;
+   wmHints.icon_y = 0;
+   wmHints.window_group = mAppWin;
+   wmHints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint;
+   XSetWMHints(mDisplay, mAppWin, &wmHints);
+
+   // Set command
+   XSetCommand(mDisplay, mAppWin, argv, argc);
+
+   // Set background image
+   image = new Xpm(mDisplay, mRoot, main_xpm);
+   if (mLabelText) {
+      image->drawString(LABEL_X, LABEL_Y, mLabelText);
+   }
+   image->setWindowPixmapShaped(mIconWin);
+   delete image;
+
+   // Create buttons
+   mButton[0] = XCreateSimpleWindow(mDisplay, mIconWin, ButtonX[0], BUTTON_MIN, 5, 5, 0, 0, 0);
+   mButton[1] = XCreateSimpleWindow(mDisplay, mIconWin, ButtonX[1], BUTTON_MIN, 5, 5, 0, 0, 0);
+   mButton[2] = XCreateSimpleWindow(mDisplay, mIconWin, ButtonX[2], BUTTON_MIN, 5, 5, 0, 0, 0);
+
+   image = new Xpm(mDisplay, mRoot, button_xpm);
+   image->setWindowPixmap(mButton[0]);
+   image->setWindowPixmap(mButton[1]);
+   image->setWindowPixmap(mButton[2]);
+   delete image;
+
+   XSelectInput(mDisplay, mButton[0], ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+   XSelectInput(mDisplay, mButton[1], ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+   XSelectInput(mDisplay, mButton[2], ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+   XSelectInput(mDisplay, mIconWin, ButtonPressMask);
+
+   XMapWindow(mDisplay, mButton[0]);
+   XMapWindow(mDisplay, mButton[1]);
+   XMapWindow(mDisplay, mButton[2]);
+
+   XMapWindow(mDisplay, mIconWin);
+   XMapWindow(mDisplay, mAppWin);
+   XSync(mDisplay, False);
+
+   // Catch broker pipe signal
+   signal(SIGPIPE, catchBrokenPipe);
+
+   // Check if error
+   if (mError) {
+      showErrorLed();
+   } else {
+      getVolume();
+      if (mLoadSettings)
+       loadVolumeSettings();
+   }
+}
+
+void Mixer::tryHelp(char* appname)
+{
+   cerr << "Try `" << appname << " --help' for more information" << endl;
+}
+
+void Mixer::showHelp() 
+{
+   cerr << APPNAME << " Copyright (c) 1998-2002 by Per Liden (per@fukt.bth.se), Petr Hlavka (xhlavk00@stud.fit.vutbr.cz)" << endl << endl
+        << "options:" << endl
+        << " -1 <source>     set sound source for control 1 (default is Master)" << endl
+        << " -2 <source>     set sound source for control 2 (default is PCM)" << endl
+        << " -3 <source>     set sound source for control 3 (default is CD)" << endl
+        << " -w 1|2|3        bind a control button to the mouse wheel (default is 1)" << endl
+        << " -l <text>       set label text" << endl
+        << " -S              save volume settings on exit" << endl
+       << " -L              load volume settings on start up" << endl
+       << " -f <file>       use setting <file> instead of ~/GNUstep/Defaults/AlsaMixer" << endl
+       << " --card <id>     select card" << endl
+       << " --device <dev>  select device, default 'default'" << endl
+       << " -e <command>    execute <command> on middle click" << endl
+        << " -n <name>       set client instance name" << endl
+        << " -d <disp>       set display" << endl
+        << " -v              print version and exit" << endl
+        << " -h, --help      display this help and exit" << endl << endl;
+}
+
+void Mixer::checkArgument(char** argv, int argc, int index)
+{
+   if (argc-1 < index+1) {
+      cerr << APPNAME << ": option '" << argv[index] << "' requires an argument" << endl;
+      tryHelp(argv[0]);
+      exit(0);
+   }
+}
+
+void Mixer::showErrorLed() 
+{
+   Window led;
+   Xpm*   image;
+
+   led = XCreateSimpleWindow(mDisplay, mIconWin, LED_X, LED_Y, 3, 2, 0, 0, 0);
+
+   // Set background image
+   image = new Xpm(mDisplay, mRoot, redlight_xpm);
+   image->setWindowPixmap(led);
+   delete image;
+
+   // Show window
+   XMapWindow(mDisplay, led);
+   mError = 1;
+}
+
+void Mixer::loadVolumeSettings()
+{
+   if (mSettingsFile) {
+      ifstream file(mSettingsFile);
+      if (file) {
+         // This could fail if the user has edited the file by hand and destroyed the structure
+         char dummy[1024];
+         file >> dummy; // {
+         file >> dummy; // Volume1
+         file >> dummy; // =
+         file >> mVolume[0];
+         file >> dummy; // ;
+
+         file >> dummy; // Volume2
+         file >> dummy; // =
+         file >> mVolume[1];
+         file >> dummy; // ;
+
+         file >> dummy; // Volume3
+         file >> dummy; // =
+         file >> mVolume[2];
+
+         file.close();
+        for (int i = 0; i < 3; i++) {
+          setVolume(i, mVolume[i]);
+          setButtonPosition(i, percentToPosition(mVolume[i]));
+        }
+      }
+   }
+}
+
+void Mixer::saveVolumeSettings()
+{
+   if (mSaveSettings) {
+      ofstream file(mSettingsFile);
+      if (file) {
+         // Files in ~/GNUstep/Defaults/ should follow the property list format
+         file << "{" << endl 
+              << "  Volume1 = " << mVolumePos[0] << ";" << endl
+              << "  Volume2 = " << mVolumePos[1] << ";" << endl
+              << "  Volume3 = " << mVolumePos[2] << ";" << endl
+              << "}" << endl;
+         file.close();
+      } else {
+         cerr << APPNAME << ": failed to save volume settings in " << mSettingsFile << endl;
+      }
+   }
+}
+
+void Mixer::getVolume() 
+{
+   static int lastVolume[3] = {-1, -1, -1};
+   static int lastVolumeMute[3] = {-1, -1, -1};
+
+   if (mError) {
+      return;
+   }
+
+   // Read from device
+   for (int i=0; i<3; i++) {
+      mVolume[i] = aMixer->itemGetVolume(i);
+      mVolumeMute[i] = aMixer->itemIsMuted(i);
+
+      if (lastVolume[i] != mVolume[i]) {
+         int y;
+
+         // Set button position
+         if (mError) {
+            y = BUTTON_MIN;
+         } else {
+           y = percentToPosition(mVolume[i]);
+         }
+
+        setButtonPosition(i, y);
+         lastVolume[i] = mVolume[i];
+      }
+
+      // set buttom type muted/unmuted
+      if (lastVolumeMute[i] != mVolumeMute[i]) {
+       setButtonType(i);
+       lastVolumeMute[i] = mVolumeMute[i];
+      }
+   }
+
+   if (mError) {
+      cerr << APPNAME << ": unable to read from " << mMixerDevice << endl;
+      showErrorLed();
+      return;
+   }
+}
+
+void Mixer::setVolume(int button, int volume) 
+{
+   if (mError) {
+      return;
+   }
+
+   // Store volume
+   mVolume[button] = volume;
+
+   // Write to device
+   aMixer->itemSetVolume(button, mVolume[button]);
+}
+
+void Mixer::toggleMute(int button)
+{
+  mVolumeMute[button] = !mVolumeMute[button];
+  aMixer->itemToggleMute(button);
+  setButtonType(button);
+}
+
+void Mixer::setButtonType(int button) 
+{
+   Xpm* image;
+
+   if (mVolumeMute[button] == 1) {             // muted
+      image = new Xpm(mDisplay, mRoot, mutebutton_xpm);
+      image->setWindowPixmap(mButton[button]);
+      delete image;
+
+      XClearWindow(mDisplay, mButton[button]);
+   } else {
+      image = new Xpm(mDisplay, mRoot, button_xpm);
+      image->setWindowPixmap(mButton[button]);
+      delete image;
+
+      XClearWindow(mDisplay, mButton[button]);
+   }
+}
+
+void Mixer::setButtonPosition(int button, int position) {
+   if (position > BUTTON_MIN) {
+      position = BUTTON_MIN;
+   } else if (position < BUTTON_MAX) {
+      position = BUTTON_MAX;
+   }
+
+   XMoveWindow(mDisplay, mButton[button], ButtonX[button], position);
+
+   mVolumePos[button] = position;
+}
+
+void Mixer::setButtonPositionRelative(int button, int relativePosition) 
+{
+   int y;
+    
+   // Calc new button position
+   y = mVolumePos[button] + relativePosition;
+
+   if (y > BUTTON_MIN) {
+      y = BUTTON_MIN;
+   } else if (y < BUTTON_MAX) {
+      y = BUTTON_MAX;
+   }
+    
+   // Set button position and volume
+   XMoveWindow(mDisplay, mButton[button], ButtonX[button], y);
+
+   mVolumePos[button] = y;
+    
+   // set volume
+   setVolume(button, positionToPercent(y));
+}
+
+void Mixer::run() 
+{
+   XEvent event;
+   int    buttonDown = 0;
+   int    buttonDownPosition = 0;
+
+   // Start handling events
+   while(1) {
+      while(XPending(mDisplay) || buttonDown) {
+         XNextEvent(mDisplay, &event);
+           
+         switch(event.type) {
+         case ButtonPress:
+            if (event.xbutton.button == Button4 || event.xbutton.button == Button5) {
+               // Wheel scroll
+               setButtonPositionRelative(mWheelButton - 1, event.xbutton.button == Button5? 3: -3);
+            } else if (event.xbutton.button == Button1 && event.xbutton.window != mIconWin) {
+               // Volume change
+               buttonDown = 1;
+               buttonDownPosition = event.xbutton.y;
+            } else if (event.xbutton.button == Button3 && buttonDown == 0 && event.xbutton.window != mIconWin) {
+               // Mute
+               for (int i=0; i<3; i++) {
+                  if (mButton[i] == event.xbutton.window) {
+                    toggleMute(i);
+                     break;
+                  }
+               }
+            } else if (event.xbutton.button == Button2) {
+              // Load defaults or execute command
+              if (mCommand) {
+                char command[512];
+
+                snprintf(command, 512, "%s &", mCommand);
+                system(command);
+              }
+              else
+                loadVolumeSettings();
+           }
+            break;
+               
+         case ButtonRelease:
+            if (event.xbutton.button == Button1) {
+               buttonDown = 0;
+            }
+            break;
+               
+         case MotionNotify:
+            if (buttonDown) {
+               // Find button
+               for (int i=0; i<3; i++) {
+                  if (mButton[i] == event.xmotion.window) {
+                     setButtonPositionRelative(i, event.xmotion.y - buttonDownPosition);
+                     break;
+                  }
+               }
+            }
+            break;
+         }
+      }
+
+      // Idle for a moment
+      usleep(100000);
+
+      // Update volume status
+      aMixer->handleEvents();
+      if (AMixer::mixerChanged())
+       aMixer->reInit();
+      else if (AMixer::mixerElemsChanged())
+       getVolume();
+      XSync(mDisplay, False);
+   }
+}
+
diff --git a/AlsaMixer.app/Mixer.h b/AlsaMixer.app/Mixer.h
new file mode 100644 (file)
index 0000000..98c0d66
--- /dev/null
@@ -0,0 +1,88 @@
+//
+//  Mixer.app
+// 
+//  Copyright (c) 1998-2002 Per Liden
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
+//  USA.
+//
+
+#ifndef _MIXER_H_
+#define _MIXER_H_
+
+#include "AMixer/AMixer.h"
+
+#include <X11/Xlib.h>
+
+#define APPNAME                "AlsaMixer.app"
+#define VERSION                "1.8.0"
+#define INSTANCENAME   "alsamixer_app"
+#define CLASSNAME      "AlsaMixer_app"
+#define SETTINGS        "/GNUstep/Defaults/AlsaMixer"
+#define MAX_COMMAND_LENGTH     512
+
+#define LABEL_X                4
+#define LABEL_Y                54
+#define LABEL_FONT     "-*-helvetica-medium-r-*-*-8-*-*-*-*-*-*-*"
+
+#define LED_X          57
+#define LED_Y          59
+#define BUTTON_MIN     45
+#define BUTTON_MAX     6
+
+class Mixer 
+{
+public:
+   Mixer(int argc, char** argv);
+   ~Mixer() {};
+   void run();
+   void saveVolumeSettings();
+
+private:
+   void tryHelp(char* appname);
+   void showHelp();
+   void checkArgument(char** argv, int argc, int index);
+   void showErrorLed();
+   void findMixerDevice();
+   void getVolume();
+   void setVolume(int button, int volume);
+   void toggleMute(int button);
+   void setButtonType(int button);
+   void setButtonPosition(int button, int position);
+   void setButtonPositionRelative(int button, int relativePosition);
+   void loadVolumeSettings();
+
+   Display* mDisplay;
+   Window   mRoot;
+   Window   mAppWin;
+   Window   mIconWin;
+   Window   mButton[3];
+   char*    mMixerDevice;
+   char*    mInstanceName;
+   char*    mLabelText;
+   char*    mSettingsFile;
+   char*    mCommand;
+   int      mError;
+   int      mVolumeSource[3];
+   int      mVolume[3];
+   int      mVolumePos[3];
+   int      mVolumeMute[3];
+   int      mWheelButton;
+   bool            mSaveSettings;
+   bool            mLoadSettings;
+   AMixer*  aMixer;
+};
+
+#endif
diff --git a/AlsaMixer.app/README b/AlsaMixer.app/README
new file mode 100644 (file)
index 0000000..477649e
--- /dev/null
@@ -0,0 +1,80 @@
+Description
+--------------------------------------------------------------
+AlsaMixer.app is a mixer utility for Linux systems with ALSA sound driver.
+It is designed to be docked in Window Maker (and other wms). This utility has
+three volume controllers that can be configured to handle any sound source,
+he default sources are 'Master', 'PCM' and 'CD' volume. Sound sources can be
+easily muted and there is also wheel mouse support.
+The whole GUI and command parsing was taken from Mixer.app (see old doc
+for URL's), only connection to ALSA driver was added.
+
+
+Hints
+--------------------------------------------------------------
+Error led:
+       If the led on Mixer.app is red an error message has 
+       been printed to stderr and something is not working 
+       correctly. If the led is green everything is working ok.
+       (Error led doesn't work in AlsaMixer.app, TODO)
+
+Mute:
+       Right click on a volume controller to mute the sound
+       source. The button will then have a red led in one corner.
+       Right click again to restore the volume. If a muted sound
+       source is modified by another application Mixer.app will 
+       automaticaly release its muted state.
+
+Wheel mouse:
+       If you have a wheel mouse (where the wheel is configured as 
+       Button4 and Button5) you can control the volume by just moving
+       the mouse over Mixer.app and roll the wheel up and down. Use 
+       the command line option -w to specify which slider that should 
+       react to the wheel movement.
+
+Label:
+       If you run multiple instances of AlsaMixer.app you might want
+       to be able to tell them apart. This can easily be done
+       by setting a label to each one of them. By using the -l
+       option you can add a little text label at the bottom of
+       the mixer.
+
+Save volume settings:
+       Use the option -S (and -f <file>) if you want the volume 
+       settings to be saved when AlsaMixer.app exits, and then 
+       -L to be loaded again when AlsaMixer.app is started the next time.
+       When not using -f the settings are saved in/loaded from
+       ~/GNUstep/Defaults/AlsaMixer. Use the -f <file> option
+       if you want to use a different file.
+       (TODO: mute states aren't saved/loaded)
+
+Configurable middle click:
+       By default, when you middle click anywhere inside application
+       window, app tries to load default mixer setting from default
+       or explicitly configured (-f) file. If file doesn't exist,
+       nothing happens.
+       You can also configure AlsaMixer.app to run command (i.e.
+       better mixer) on middle click by using -e <command> option.
+
+Bugs
+--------------------------------------------------------------
+If you discover any bugs in this software, please send a 
+bugreport to xhlavk00@stud.fit.vutbr.cz and describe the problem.
+
+
+Special thanks to
+--------------------------------------------------------------
+Per Liden <per@fukt.bth.se> - original author of Mixer.app
+David Sauer <davids@iol.cz>
+Theo Schlossnagle <theo@omniti.com>
+Alban Hertroys <dalroi@wit401310.student.utwente.nl>
+
+
+Copyright
+--------------------------------------------------------------
+AlsaMixer.app, 2004, Petr Hlavka
+Mixer.app is copyright (c) 1998-2002 by Per Liden and is 
+licensed through the GNU General Public License. Read the 
+COPYING file for the complete license.
+
+Minor parts of this code were taken from asmixer by Rob Malda
+(malda@slashdot.org)
diff --git a/AlsaMixer.app/Xpm.cc b/AlsaMixer.app/Xpm.cc
new file mode 100644 (file)
index 0000000..a814ede
--- /dev/null
@@ -0,0 +1,107 @@
+//
+//  Mixer.app
+// 
+//  Copyright (c) 1998-2002 Per Liden
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
+//  USA.
+//
+
+#include <X11/Xlib.h>
+#include <X11/xpm.h>
+#include <X11/extensions/shape.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include "Mixer.h"
+#include "Xpm.h"
+
+using namespace std;
+
+Xpm::Xpm(Display* display, Window root, char** data) 
+{
+   int error;
+
+   mDisplay = display;
+
+   mAttributes.valuemask = 0;
+   error = XpmCreatePixmapFromData(mDisplay, root, data, &mImage, &mMask, &mAttributes);
+
+   switch (error) {
+   case XpmColorError:
+      cerr << APPNAME << ": xpm image loaded but did not get all colors needed" << endl;
+      break;
+
+   case XpmColorFailed:
+      cerr << APPNAME << ": could not load xpm image (not enough colors available)" << endl;
+      exit(0);
+      break;
+
+   case XpmNoMemory:
+      cerr << APPNAME << ": could not load xpm image (not enough memory available)" << endl;
+      exit(0);
+      break;
+
+   case XpmOpenFailed:
+   case XpmFileInvalid:
+      cerr << APPNAME << ": could not load xpm image (image broken or corrupt)" << endl;
+      exit(0);
+      break;
+
+   case XpmSuccess:
+   default:
+      // Image loaded ok
+      break;
+   }
+}
+
+Xpm::~Xpm() 
+{
+   if (mImage) {
+      XFreePixmap(mDisplay, mImage);
+   }
+
+   if (mMask) {
+      XFreePixmap(mDisplay, mMask);
+   }
+}
+
+void Xpm::setWindowPixmap(Window win) 
+{
+   XResizeWindow(mDisplay, win, mAttributes.width, mAttributes.height);
+   XSetWindowBackgroundPixmap(mDisplay, win, mImage);
+}
+
+void Xpm::setWindowPixmapShaped(Window win) 
+{
+   XResizeWindow(mDisplay, win, mAttributes.width, mAttributes.height);
+   XSetWindowBackgroundPixmap(mDisplay, win, mImage);
+   XShapeCombineMask(mDisplay, win, ShapeBounding, 0, 0, mMask, ShapeSet);
+}
+
+void Xpm::drawString(int x, int y, char* text) 
+{
+   Font      font;
+   GC        gc;
+   XGCValues gcv;
+
+   font = XLoadFont(mDisplay, LABEL_FONT);
+   gcv.font = font;
+   gcv.foreground = WhitePixel(mDisplay, DefaultScreen(mDisplay));
+   gc = XCreateGC(mDisplay, mImage, GCFont | GCForeground, &gcv);
+   XDrawString(mDisplay, mImage, gc, x, y, text, strlen(text));
+   XFreeGC(mDisplay, gc);
+   XUnloadFont(mDisplay, font);
+}
diff --git a/AlsaMixer.app/Xpm.h b/AlsaMixer.app/Xpm.h
new file mode 100644 (file)
index 0000000..9405372
--- /dev/null
@@ -0,0 +1,44 @@
+//
+//  Mixer.app
+// 
+//  Copyright (c) 1998-2002 Per Liden
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
+//  USA.
+//
+
+#ifndef _XPM_H_
+#define _XPM_H_
+
+#include <X11/Xlib.h>
+#include <X11/xpm.h>
+
+class Xpm 
+{
+public:
+   Xpm(Display* display, Window root, char** data);
+   virtual ~Xpm();
+   void setWindowPixmap(Window win);
+   void setWindowPixmapShaped(Window win);
+   void drawString(int x, int y, char* text);
+
+private:
+   Display*      mDisplay;
+   XpmAttributes mAttributes;
+   Pixmap        mImage;
+   Pixmap        mMask;
+};
+
+#endif
diff --git a/AlsaMixer.app/olddoc/ChangeLog.Mixer.app b/AlsaMixer.app/olddoc/ChangeLog.Mixer.app
new file mode 100644 (file)
index 0000000..b2ae9f1
--- /dev/null
@@ -0,0 +1,95 @@
+Version                Description
+--------------------------------------------------------------------------------
+1.8.0          - Released 2002-09-15
+               - Now supports all mixer sources. NOTE! The source names have
+                 been changed. See "Mixer.app -h".
+               - Added alternative skin submitted by Hans D. <barross@web.de>.
+               - Fixed warnings when compiling with GCC 3.2.
+               - Added OpenBSD support (thanks to ptiJo <ptiJo@noos.fr>).
+
+1.7.0          - Released 2001-06-25
+               - Fixed compilation problems.
+
+1.6.0          - Released 2001-03-17
+               - Mixer.app is now devfs friendly, which means it will try to
+                 use /dev/sound/mixer or /dev/sound/mixer1 first and fall back
+                 to /dev/mixer if that didn't work.
+               - New Makefile.
+
+1.5.0          - Released 2000-02-21.
+               - Added command line options -s and -S <file>, which cause 
+                 Mixer.app to load/save volume settings when starting/exiting.
+                 When the option -s is used, settings are loaded from/saved in
+                 ~/GNUstep/Defaults/Mixer. Use -S <file> if you want Mixer.app
+                 to use a different file.
+               - Fixed potential bug in command line parsing.
+
+1.4.1          - Released 1999-05-28.
+               - Added command line option -l <text> that can be used to 
+                 add a text label in the corner of the mixer.
+
+1.4.0          - Released 1999-05-09.
+               - Added support for wheel mice. One of the sliders (use -w to 
+                 specify which one) will react on wheel movement. 
+               - Misc. code clean up.
+
+1.3.3          - Released 1999-05-02.
+               - Fixed problem that caused Mixer.app to die.
+
+1.3.2          - Released 1999-04-18.
+               - Fixed exit bug. Mixer.app will now exit properly when 
+                 the windowmanager terminates.
+
+1.3.1          - Released 1999-02-09.
+               - Added new mute function (right click).
+               - Rewrote command-line parsing, not using getopt anymore.
+               - Minor code clean up.
+
+1.3.0          - Released 1999-02-04.
+               - New design.
+               - I didn't find the mute function very usefull so I removed it.
+               - Doing 'make install' will now install it in 
+                  /usr/local/GNUstep/Apps/Mixer.app/.
+
+1.2.0          - Released 1998-12-01.
+               - Moved back to old design. The design of version 1.1.1 made 
+                 Mixer.app (and Window Maker) unstable due to some strange 
+                  race condition at startup. It worked on some machines and 
+                 some not, so I desided to go back to the old design.
+               - Increased idle interval to reduce CPU usage.
+
+1.1.1          - Released 1998-11-14.
+               - Fixed XGetImage errors, (slow machines may still have this 
+                 problem, please report any errors).
+               - Added command line option -m <dev> to set mixer device.
+               - Added command line option -n <name> to set instance name.
+               - Compiling under FreeBSD now works fine.
+       
+1.1.0          - Released 1998-11-14.
+               - Alarm singals are no longer used so now the "Alarm Clock" 
+                 problem is solved for sure!
+               - Mute function.
+               - New design.
+
+1.0.5          - Released 1998-09-05.
+               - Fixed the "Alarm Clock" problem.
+               - Fixed problem when using WindowPlacement = manual
+                 in WindowMaker.
+
+1.0.4          - Released 1998-03-19.
+               - Just some minor internal changes.
+
+1.0.3          - Released 1998-02-24.
+               - Changed default timerinterval.
+               - Minor changes to eventhandling code.
+
+1.0.2          - Released 1998-02-23.
+               - If the red led goes on (an error has occured) the control 
+                 buttons are set to volume 0.
+
+1.0.1          - Released 1998-02-23.
+               - Changed classname to "mixer_app.Mixer_app".
+
+1.0.0          - Released 1998-02-22.
+               - First official version.
+
diff --git a/AlsaMixer.app/olddoc/INSTALL.Mixer.app b/AlsaMixer.app/olddoc/INSTALL.Mixer.app
new file mode 100644 (file)
index 0000000..a3766b5
--- /dev/null
@@ -0,0 +1,33 @@
+Installation instructions for Mixer.app
+
+
+Requirements
+-------------------------------------------------------------------
+- X11, libxpm, C++ development environment
+        Most (Linux) systems have these things installed by default.
+        If you don't have it look for packages that fit your
+        distribution.
+
+
+Installation
+-------------------------------------------------------------------
+1) make
+2) su
+3) make install       (to put it in /usr/local/GNUstep/Apps/Mixer.app)
+   or
+   make install-x11   (to put it in /usr/X11R6/bin)
+5) exit
+
+
+Running
+-------------------------------------------------------------------
+To run this program:
+/usr/local/GNUstep/Apps/Mixer.app/Mixer &
+or
+/usr/X11R6/bin/Mixer.app &
+
+
+For more information about available command line arguments:
+/usr/local/GNUstep/Apps/Mixer.app/Mixer --help
+or
+/usr/X11R6/bin/Mixer.app --help
diff --git a/AlsaMixer.app/olddoc/README.Mixer.app b/AlsaMixer.app/olddoc/README.Mixer.app
new file mode 100644 (file)
index 0000000..2fa41db
--- /dev/null
@@ -0,0 +1,75 @@
+
+                       Mixer.app
+            <http://www.fukt.bth.se/~per/mixer/>
+
+                      by Per Liden
+                    <per@fukt.bth.se>
+
+
+Description
+--------------------------------------------------------------
+Mixer.app is a mixer utility for Linux/FreeBSD/OpenBSD systems.
+It is designed to be docked in Window Maker. This utility has
+three volume controllers that can be configured to handle any
+sound source, the default sources are master-, cd- and pcm-volume.
+Sound sources can easily be muted and there is also wheel mouse
+support.
+
+
+Hints
+--------------------------------------------------------------
+Error led:
+       If the led on Mixer.app is red an error message has 
+       been printed to stderr and something is not working 
+       correctly. If the led is green everything is working ok.
+
+Mute:
+       Right click on a volume controller to mute the sound
+       source. The button will then have a red led in one corner.
+       Right click again to restore the volume. If a muted sound
+       source is modified by another application Mixer.app will 
+       automaticaly release its muted state.
+
+Wheel mouse:
+       If you have a wheel mouse (where the wheel is configured as 
+       Button4 and Button5) you can control the volume by just moving
+       the mouse over Mixer.app and roll the wheel up and down. Use 
+       the command line option -w to specify which slider that should 
+       react to the wheel movement.
+
+Label:
+       If you run multiple instances of Mixer.app you might want
+       to be able to tell them apart. This can easily be done
+       by setting a label to each one of them. By using the -l
+       option you can add a little text label at the bottom of
+       the mixer.
+
+Save volume settings:
+       Use the option -s or -S <file> if you want the volume 
+       settings to be saved when Mixer.app exits, and then 
+       loaded again when Mixer.app is started the next time.
+       When using -s the settings are saved in/loaded from
+       ~/GNUstep/Defaults/Mixer. Use the -S <file> option
+       if you want to use a different file. 
+
+Bugs
+--------------------------------------------------------------
+If you discover any bugs in this software, please send a 
+bugreport to per@fukt.bth.se and describe the problem.
+
+
+Special thanks to
+--------------------------------------------------------------
+David Sauer <davids@iol.cz>
+Theo Schlossnagle <theo@omniti.com>
+Alban Hertroys <dalroi@wit401310.student.utwente.nl>
+
+
+Copyright
+--------------------------------------------------------------
+Mixer.app is copyright (c) 1998-2002 by Per Liden and is 
+licensed through the GNU General Public License. Read the 
+COPYING file for the complete license.
+
+Minor parts of this code were taken from asmixer by Rob Malda
+(malda@slashdot.org)
diff --git a/AlsaMixer.app/pixmaps b/AlsaMixer.app/pixmaps
new file mode 120000 (symlink)
index 0000000..9191efc
--- /dev/null
@@ -0,0 +1 @@
+skins/default
\ No newline at end of file
diff --git a/AlsaMixer.app/skins/barross@web.de/button.xpm b/AlsaMixer.app/skins/barross@web.de/button.xpm
new file mode 100644 (file)
index 0000000..26f15c6
--- /dev/null
@@ -0,0 +1,47 @@
+/* XPM */
+static char * button_xpm[] = {
+"15 9 35 1",
+"      c None",
+".     c #DEDEE6",
+"+     c #D5DAE6",
+"@     c #D5D6E6",
+"#     c #CDD2DE",
+"$     c #CDCEDE",
+"%     c #C5CAD5",
+"&     c #C5C6D5",
+"*     c #BDC2CD",
+"=     c #B4BECD",
+"-     c #BDBEC5",
+";     c #C5CADE",
+">     c #BDC6D5",
+",     c #BDBECD",
+"'     c #B4B6C5",
+")     c #ACB6C5",
+"!     c #ACB2C5",
+"~     c #ACB2BD",
+"{     c #ACAEBD",
+"]     c #8B8D9C",
+"^     c #A4A5B4",
+"/     c #9C9DAC",
+"(     c #94959C",
+"_     c #8B919C",
+":     c #CDD2E6",
+"<     c #B4BAC5",
+"[     c #BDC2D5",
+"}     c #B4BACD",
+"|     c #8B8D94",
+"1     c #ACAAB4",
+"2     c #9CA1AC",
+"3     c #9C99A4",
+"4     c #8B8994",
+"5     c #B4BEC5",
+"6     c #83858B",
+"....++@@#$%&*=-",
+".++@@#;>,')!~{]",
+",~^/(__]]]]]]]]",
+".+++@@:$%&*,,<]",
+"++@:$&[}'!~{{~|",
+"123(_]]]]]_]]]4",
+"++@@@#;%>*,-<56",
+"@@#;>*''!~~~~~6",
+"/(__]]]_]]|]466"};
diff --git a/AlsaMixer.app/skins/barross@web.de/main.xpm b/AlsaMixer.app/skins/barross@web.de/main.xpm
new file mode 100644 (file)
index 0000000..2dc3ab5
--- /dev/null
@@ -0,0 +1,167 @@
+/* XPM */
+static char * main_xpm[] = {
+"64 64 100 2",
+"      c None",
+".     c #212121",
+"+     c #222223",
+"@     c #E6EAEE",
+"#     c #DEE6EE",
+"$     c #DEE2EE",
+"%     c #DEE2E6",
+"&     c #D5E2E6",
+"*     c #D5DEE6",
+"=     c #D5DAE6",
+"-     c #D5DADE",
+";     c #CDDADE",
+">     c #CDD6DE",
+",     c #CDD2DE",
+"'     c #C5D2D5",
+")     c #C5CED5",
+"!     c #C5CAD5",
+"~     c #BDCAD5",
+"{     c #BDC6D5",
+"]     c #BDC6CD",
+"^     c #BDC2CD",
+"/     c #EEF2EE",
+"(     c #C5D2DE",
+"_     c #5A5D62",
+":     c #5A6162",
+"<     c #5A595A",
+"[     c #B4C2CD",
+"}     c #5A555A",
+"|     c #52555A",
+"1     c #4A4C5A",
+"2     c #B4BECD",
+"3     c #EBEEEB",
+"4     c #4A4C52",
+"5     c #D5D6DE",
+"6     c #4A505A",
+"7     c #B4BEC5",
+"8     c #E5E7E5",
+"9     c #4A484A",
+"0     c #E2E3E2",
+"a     c #4A444A",
+"b     c #E1E2E1",
+"c     c #41404A",
+"d     c #E1E1E1",
+"e     c #393C4A",
+"f     c #41444A",
+"g     c #393C41",
+"h     c #39404A",
+"i     c #C5CEDE",
+"j     c #393839",
+"k     c #B4BAC5",
+"l     c #393439",
+"m     c #313039",
+"n     c #293031",
+"o     c #B3B9C4",
+"p     c #ACBAC5",
+"q     c #D4DDE5",
+"r     c #292C31",
+"s     c #D4DAE1",
+"t     c #292829",
+"u     c #D5D6E6",
+"v     c #293039",
+"w     c #D2D8DE",
+"x     c #292429",
+"y     c #ACB6C5",
+"z     c #D1D6DC",
+"A     c #202429",
+"B     c #292C29",
+"C     c #ACB6BD",
+"D     c #D1D6D9",
+"E     c #182020",
+"F     c #C4CDD4",
+"G     c #D1D6D8",
+"H     c #181C20",
+"I     c #CFD4D8",
+"J     c #CED3D9",
+"K     c #ACB2BD",
+"L     c #CFD4DB",
+"M     c #D0D3DA",
+"N     c #313439",
+"O     c #CDD4DC",
+"P     c #CCD5DD",
+"Q     c #BCC5D4",
+"R     c #BCC5CC",
+"S     c #ACAEBD",
+"T     c #A4AEB4",
+"U     c #A4AEBD",
+"V     c #A4AAB4",
+"W     c #4A555A",
+"X     c #ACAEB4",
+"Y     c #5A5D5A",
+"Z     c #9CAAB4",
+"`     c #626162",
+" .    c #9CA5B4",
+"..    c #62656A",
+"+.    c #62696A",
+"@.    c #7B8183",
+"#.    c #6A6D73",
+"$.    c #9CA1AC",
+"%.    c #1F1E22",
+"&.    c #26D526",
+"                                                                                                                                ",
+"                                                                                                                                ",
+"                                                                                                                                ",
+"      . . . . . . . . . . . . . . . . . . + + + + + + + + + + + + + + + + + + + + + . . . . . . . . . . . . . . . . . . .       ",
+"      . @ @ @ @ @ # # # # # $ $ $ % % & & * * * * * * * = = = = - ; > > > > > , , , , ' ) ) ) ) ! ! ! ! ! ~ { ] ] ] ^ ^ /       ",
+"      . @ @ @ @ # # # # # $ $ $ % % % & * * * * * * * = = = = - - > > > > > > , , , ( ) ) ) ) ) ! ! ! ! ~ { ] ] ] ] ^ ^ /       ",
+"      . @ @ @ # # # # # $ $ $ % % % & & * * * * * * * = = = = = ; > > > > > > , , , , ' ) ) ) ! ! ! ! ~ { ] ] ] ] ] ^ ^ /       ",
+"      . @ @ # # # # # $ $ $ % % % & & * * * * * * * = = = = = - > > > > > > , , , , ' ) ) ) ) ! ! ! ~ { ] ] ] ] ] ^ ^ ^ /       ",
+"      . @ # # # # # $ $ $ _ / % % % * * * * * * * * = = = = = : / > > > > > , , , , ' ) ) ) ! ! ! _ / { ] ] ] ] ^ ^ ^ ^ /       ",
+"      . # # # # # $ $ $ $ < / % % * * * * * * * * = = = = = - _ / > > > > > , , , ( ) ) ) ) ) ! ! < / ] ] ] ] ^ ^ ^ ^ [ /       ",
+"      . # # # # $ $ $ $ $ } / % * * * * * * * * = * = = = = = < / > > > > , , , , ( ) ) ) ) ! ! ! } / ] ] ] ^ ^ ^ ^ ^ [ /       ",
+"      . # # # $ $ $ $ $ % | / & * * * * * * * * * = = = = = - < / > > > > > , , , ' ) ) ) ) ! ! ~ | / ] ] ^ ^ ^ ^ ^ [ [ /       ",
+"      . # # $ $ $ $ % % % 1 / & * * * * * * * * * = = = = = - | / > > > > , , , , ) ) ) ) ! ! ! ! 1 / ] ] ^ ^ ^ ^ [ [ 2 3       ",
+"      . # $ $ $ $ % % % % 4 / * * * * * * * * * = = = = = - 5 6 / > > > > , , , , ) ) ) ) ! ! ! ~ 4 / ] ^ ^ ^ ^ [ [ 2 7 8       ",
+"      . $ $ $ $ % % % % & 9 / * * * * * * * * = = = = = = = 5 4 / > > > , , , , ( ) ) ) ) ! ! ! ~ 9 / ] ] ^ ^ ^ [ 2 7 7 0       ",
+"      . $ $ $ % % % % & & a / * * * * * * * = = = = = = = - 5 9 / > > > , , , , ' ) ) ) ) ! ! ~ { a / ] ^ ^ ^ [ 2 7 7 7 b       ",
+"      . $ $ % % % & & & * c / * * * * * * = = = = = = = = - > 9 / > > > > , , ( ) ) ) ) ) ! ! ~ { c / ] ^ ^ ^ [ 2 7 7 7 d       ",
+"      . $ % % % & & * * * e / * * * * * = * = = = = = = - 5 > f / > > > , , , ( ) ) ) ) ! ! ! { { e / ^ ^ ^ [ [ 2 7 7 7 d       ",
+"      . % % % & & * * * * g / * * * * = * = = = = = = - = > > h / > > > , , , i ) ) ) ) ! ! ~ ~ ] g / ^ ^ ^ ^ 2 7 7 7 7 d       ",
+"      . % & & & * * * * * j / * * * = * = = = = = = = = 5 > > g / > > , , , , ' ) ) ) ! ! ! ! { ] j / ^ ^ ^ [ 2 7 7 7 k d       ",
+"      . & & * * * * * * * l / * * * * = = = = = = = = - 5 > > g / > > , , , ( ) ) ) ) ! ! ! ~ ] ] l / ^ ^ ^ 2 7 7 7 k k b       ",
+"      . * * * * * * * * * m / * * * = = = = = = = = = 5 5 > > j / > , , , , ' ) ) ) ) ! ! ~ { ] ] m / ^ ^ [ 7 7 7 7 k k 0       ",
+"      . * * * * * * * * * n / * = = = = = = = = = = 5 - > > > l / > > , , , i ) ) ) ! ! ! ~ { ] ] n / ^ [ 2 2 7 7 o k p 8       ",
+"      . q * * * * * * * * r / = = = = = = = = = = 5 - > > > > m / > , , , ( ) ) ) ) ! ! ~ { ] ] ] r / ^ [ 2 7 7 7 k k p 3       ",
+"      . s * * * * * * * * t / = = = = = = = = = u - > > > > > v / > , , , i ) ) ) ! ! ! ~ { ] ] ^ t / ^ [ 7 7 7 k k p p /       ",
+"      . w * * * * = * = = x / = = = = = = = - = - > > > > > > n / , , , , ' ) ) ) ! ! ~ ~ ] ] ] ^ x / ^ 2 7 7 k k k p y /       ",
+"      . z * * = = = = = = A / = = = = = = 5 - 5 > > > > > > > B / , , , , ) ) ) ! ! ! ~ ] ] ] ^ ^ A / [ 7 7 7 k k k y C /       ",
+"      . D = = = = = = = = E / = = = = 5 - - > > > > > > > > > t / , , , ( ) ) F ! ! ! { ] ] ] ^ ^ E / 2 7 7 7 k k p C C /       ",
+"      + G = = = = = = = = H / - = - 5 - > > > > > > > > > > > t / , , ( ) ) ) ) ! ! ~ { ] ] ] ^ ^ H / 2 7 7 k k p y C C /       ",
+"      + I = = = = = = = = E / 5 5 5 > > > > > > > > > > > > > B / , , i ) ) ) ! ! ! { ] ] ] ^ ^ ^ E / 7 7 7 k k p y C C /       ",
+"      + I = = = = - = - - A / 5 > > > > > > > > > > > > > > > r / , ( ) ) ) ) ! ! ~ ] ] ] ^ ^ ^ [ A / 7 7 k k p p C C C /       ",
+"      . J = = - = - ; > 5 x / > > > > > > > > > > > > , > , , n / ( ' ) ) ) ! ! ~ ~ ] ] ] ^ ^ ^ [ x / 7 k k p p C C C K /       ",
+"      . L - - - > > > > > t / > > > > > > > > > > , > , , , , m / ' ) ) ) ! ! ! ~ ] ] ] ^ ^ ^ [ 2 t / k k k p y C C K K /       ",
+"      . M - > > > > > > > r / > > > > > > > , , , , , , , , ( N / ) ) ) ! ! ! ~ { ] ] ^ ^ ^ [ [ 2 r / k k p p C C C K K /       ",
+"      . O > > P P > > > > n / > > > > > > , , , , , , , , ( ' j / ) ) ! ! ! ! Q ] ] ^ ^ ^ ^ [ 2 7 n / k p p y C C K K K /       ",
+"      . > > > > > > > > > m / > > > , , , , , , , , ( ( ) ) ) j / ) ! ! ! ! { R ] ] ^ ^ ^ ^ 2 7 7 m / k p y C C C K K S /       ",
+"      . > > > > > > > > > l / > , , , , , , , , ( ( ) ) ) ) ) g / ! ! ! ! { ] ] ] ^ ^ ^ ^ 2 7 7 7 l / p y C C C K K S S /       ",
+"      . > > > > > > > , , j / , , , , , , , ( ' ) ) ) ) ) ) ) h / ! ! ~ { ] ] ] ^ ^ ^ ^ [ 2 7 7 k j / y y C C K K K S S /       ",
+"      . > > > > > , , , , g / , , , , , ( ) ) ) ) ) ) ) ) ! ! f / ! ~ { ] ] ] ^ ^ ^ ^ [ 2 7 7 7 k g / y C C C K K S S S /       ",
+"      . > > , , , , , , , h / , , ' ' ) ) ) ) ) ) ) ) ) ! ! ! a / ~ { ] ] ] ^ ^ ^ ^ [ 2 7 7 7 k k h / C C C K K K S S T /       ",
+"      . , , , , , , , , , f / ' ' ) ) ) ) ) ) ) ) ) ! ! ! ! ! 9 / ] ] ] ] ^ ^ ^ ^ [ 2 2 7 7 k k p f / C C K K K S S T T /       ",
+"      . , , , , , , ( ' ( a / ) ) ) ) ) ) ) ) ) ! ! ! ! ! ! ~ 9 / ] ] ] ^ ^ ^ ^ [ 2 2 7 7 k k p p a / C K K K S S U T V /       ",
+"      . , , , , ( ' ) ) ) 9 / ) ) ) ) ) ) ) ! ! ! ! ! ! ~ { { 4 / ] ] ^ ^ ^ ^ [ 2 7 7 7 k k p p C 9 / K K K S S S T T V /       ",
+"      . , ( ( ' ) ) ) ) ) 4 / ) ) ) ) ! ! ! ! ! ~ ! ~ { { ] ] W / ^ ^ ^ ^ ^ [ 2 7 7 7 k k p p y C 4 / K K S S S T T V V /       ",
+"      . ( ' ) ) ) ) ) ) ) 6 / ) ) ! ! ! ! ! ! ! ~ { ] ] ] ] ] | / ^ ^ ^ [ [ 2 7 7 7 k k p p y C C 6 / K K S S X T V V V /       ",
+"      . ' ) ) ) ) ) ) ) ) | / ! ! ! ! ! ! ~ ~ { { ] ] ] ] ] ^ < / ^ ^ [ [ 2 7 7 7 k k p p y C C C | / K S S S T V V V V /       ",
+"      . ) ) ) ) ) ) ) ! ! < / ! ! ! ~ ~ ~ { { ] ] ] ] ] ] ^ ^ Y / [ [ 2 2 7 7 7 k k p p y C C C K < / S S S T T V V V Z /       ",
+"      . ) ) ) ) ) ! ! ! ! < / ! ~ ~ ~ ] { ] ] ] ] ] ] ^ ^ ^ ^ _ / [ 7 7 7 7 7 k k k p y C C C K K < / S S T T V V V Z Z /       ",
+"      . ) ) ) ! ! ! ! ! ! _ / ~ { ] { ] ] ] ] ] ] ^ ^ ^ ^ ^ [ ` / 7 7 7 7 7 k k p y y C C C K K K _ / S T T V V V Z Z  ./       ",
+"      . ) ) ! ! ! ! ! ~ ~ ` / { ] ] ] ] ] ] ] ^ ^ ^ ^ ^ ^ [ [ ../ 7 7 7 k k k p y y C C C K K K S ` / T T V V V Z Z  . ./       ",
+"      . ) ! ! ! ! ! ~ ~ { ../ ] ] ] ] ] ^ ^ ^ ^ ^ ^ ^ [ [ 2 7 +./ 7 7 k k k p y C C C C K K K S S ../ T V V V Z Z  . . ./       ",
+"      . ! ! ! ! ! ~ { { ] @./ ] ] ] ^ ^ ^ ^ ^ ^ ^ [ [ [ 2 7 7 #./ 7 k k k p y C C C C K K K S S S +./ V V V Z Z  . . . ./       ",
+"      . ! ! ! ! ~ { { ] ] ] ] ^ ^ ^ ^ ^ ^ ^ ^ ^ [ [ 2 7 7 7 7 7 k k k p p y C C C C K K K S S S T T V V V Z Z  . . . . ./       ",
+"      . ! ! ~ ~ { { ] ] ] ] ^ ^ ^ ^ ^ ^ ^ [ [ [ 2 7 7 7 7 k k k k k p y y C C C K K K K S S X T T V V V Z Z  . . . . .$./       ",
+"      . ! ~ ~ { { ] ] ] ] ^ ^ ^ ^ ^ ^ [ [ 2 7 2 7 7 7 7 7 k k k p p y C C C C K K K K S S U T V V V V Z Z  . . . . .$.$./       ",
+"      . ~ ~ { { ] ] ] ] ^ ^ ^ ^ ^ [ [ 2 2 2 7 7 7 7 k k k k k p y y C C C K K K K S S S S T T V V V Z Z  . . . . .$.$.$./       ",
+"      . / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /       ",
+"        %.      %.  %.  %.    %.  %.%.%.  %.%.%.                                                                                ",
+"        %.%.  %.%.  %.  %.    %.  %.      %.    %.                                                              %.%.%.%.        ",
+"        %.  %.  %.  %.    %.%.    %.%.%.  %.%.%.                                                                %.&.&.&.        ",
+"        %.      %.  %.  %.    %.  %.      %.    %.                                                              %.&.&.&.        ",
+"        %.      %.  %.  %.    %.  %.%.%.  %.    %.                                                                              ",
+"                                                                                                                                ",
+"                                                                                                                                "};
diff --git a/AlsaMixer.app/skins/barross@web.de/mutebutton.xpm b/AlsaMixer.app/skins/barross@web.de/mutebutton.xpm
new file mode 100644 (file)
index 0000000..1aaa726
--- /dev/null
@@ -0,0 +1,64 @@
+/* XPM */
+static char * mutebutton_xpm[] = {
+"16 9 52 1",
+"      c None",
+".     c #DEDEE6",
+"+     c #D5DAE6",
+"@     c #D5D6E6",
+"#     c #CDD2DE",
+"$     c #CDCEDE",
+"%     c #C5CAD5",
+"&     c #C5C6D5",
+"*     c #BDC2CD",
+"=     c #B4BECD",
+"-     c #BDBEC5",
+";     c #C5CADE",
+">     c #BDC6D5",
+",     c #BDBECD",
+"'     c #B4B6C5",
+")     c #ACB6C5",
+"!     c #ACB2C5",
+"~     c #ACB2BD",
+"{     c #ACAEBD",
+"]     c #8B8D9C",
+"^     c #A4A5B4",
+"/     c #9C9DAC",
+"(     c #94959C",
+"_     c #8B919C",
+":     c #CDD2E6",
+"<     c #B4BAC5",
+"[     c #BDC2D5",
+"}     c #B4BACD",
+"|     c #8B8D94",
+"1     c #ACAAB4",
+"2     c #9CA1AC",
+"3     c #9C99A4",
+"4     c #C07681",
+"5     c #DC5156",
+"6     c #ED3638",
+"7     c #D14648",
+"8     c #96555B",
+"9     c #DA585D",
+"0     c #F35F5E",
+"a     c #FB3A39",
+"b     c #FB2324",
+"c     c #B31818",
+"d     c #D4585C",
+"e     c #F71A1C",
+"f     c #FE1212",
+"g     c #FF1313",
+"h     c #D70E0E",
+"i     c #9E5C64",
+"j     c #C61A1D",
+"k     c #DB1010",
+"l     c #F80E0E",
+"m     c #CB0C0C",
+".....++@@#$%&*=-",
+"..++@@#;>,')!~{]",
+".,~^/(__]]]]]]]]",
+"..+++@@:$%&*,,<]",
+".++@:$&[}'!~{{~|",
+".123(_]]]]]45678",
+".++@@@#;%>*90abc",
+"+@@#;>*''!~defgh",
+"+/(__]]]_]]ijklm"};
diff --git a/AlsaMixer.app/skins/barross@web.de/redlight.xpm b/AlsaMixer.app/skins/barross@web.de/redlight.xpm
new file mode 100644 (file)
index 0000000..43d19e3
--- /dev/null
@@ -0,0 +1,7 @@
+/* XPM */
+static char * redlight_xpm[] = {
+"3 2 2 1",
+"      c None",
+".     c #FF0000",
+"...",
+"..."};
diff --git a/AlsaMixer.app/skins/default/button.xpm b/AlsaMixer.app/skins/default/button.xpm
new file mode 100644 (file)
index 0000000..acb9993
--- /dev/null
@@ -0,0 +1,29 @@
+/* XPM */
+static char * button_xpm[] = {
+"16 9 17 1",
+"      c None",
+".     c #B7BAC7",
+"+     c #848694",
+"@     c #838593",
+"#     c #828392",
+"$     c #808290",
+"%     c #7F818F",
+"&     c #7E808E",
+"*     c #7C7E8C",
+"=     c #7B7D8B",
+"-     c #7A7C8A",
+";     c #787A88",
+">     c #777987",
+",     c #767886",
+"'     c #747784",
+")     c #737583",
+"!     c #000000",
+"................",
+".+@#$%&*=-;>,')!",
+".!!!!!!!!!!!!!!!",
+"...............!",
+".+@#$%&*=-;>,')!",
+".!!!!!!!!!!!!!!!",
+"...............!",
+".+@#$%&*=-;>,')!",
+".!!!!!!!!!!!!!!!"};
diff --git a/AlsaMixer.app/skins/default/main.xpm b/AlsaMixer.app/skins/default/main.xpm
new file mode 100644 (file)
index 0000000..14c6901
--- /dev/null
@@ -0,0 +1,261 @@
+/* XPM */
+static char * main_xpm[] = {
+"64 64 194 2",
+"      c None",
+".     c #000000",
+"+     c #2F2542",
+"@     c #302643",
+"#     c #322745",
+"$     c #332846",
+"%     c #342948",
+"&     c #352A49",
+"*     c #362B4B",
+"=     c #372C4C",
+"-     c #382D4E",
+";     c #392E4F",
+">     c #3A2E50",
+",     c #3B2F52",
+"'     c #3C3053",
+")     c #3C3154",
+"!     c #3D3155",
+"~     c #3E3256",
+"{     c #3F3357",
+"]     c #3F3358",
+"^     c #403459",
+"/     c #41345A",
+"(     c #41355A",
+"_     c #41355B",
+":     c #42355B",
+"<     c #42365C",
+"[     c #43365D",
+"}     c #B7BAC7",
+"|     c #312745",
+"1     c #352A4A",
+"2     c #372C4D",
+"3     c #392F50",
+"4     c #3B3052",
+"5     c #43365C",
+"6     c #43375E",
+"7     c #44375E",
+"8     c #44375F",
+"9     c #44385F",
+"0     c #45385F",
+"a     c #3A2F51",
+"b     c #322846",
+"c     c #392E50",
+"d     c #3A2F52",
+"e     c #453860",
+"f     c #463961",
+"g     c #3C3054",
+"h     c #3B3053",
+"i     c #332948",
+"j     c #403358",
+"k     c #463962",
+"l     c #473A62",
+"m     c #473A63",
+"n     c #483A63",
+"o     c #473963",
+"p     c #483A64",
+"q     c #3D3154",
+"r     c #332947",
+"s     c #342A49",
+"t     c #2E2F40",
+"u     c #9F9FB1",
+"v     c #483B64",
+"w     c #493B65",
+"x     c #493C65",
+"y     c #493C66",
+"z     c #303143",
+"A     c #A1A1B3",
+"B     c #2F2F40",
+"C     c #352B4A",
+"D     c #483B65",
+"E     c #4A3C66",
+"F     c #4A3C67",
+"G     c #4A3D67",
+"H     c #4B3D67",
+"I     c #4B3D68",
+"J     c #313143",
+"K     c #A1A1B4",
+"L     c #2F3041",
+"M     c #362B4C",
+"N     c #382D4D",
+"O     c #43375D",
+"P     c #4B3E69",
+"Q     c #4C3E69",
+"R     c #4C3E6A",
+"S     c #313244",
+"T     c #A2A1B4",
+"U     c #4C3F6A",
+"V     c #392D4F",
+"W     c #A0A0B2",
+"X     c #453960",
+"Y     c #4D3F6A",
+"Z     c #4D3F6B",
+"`     c #4E406C",
+" .    c #A2A2B5",
+"..    c #4F406D",
+"+.    c #4F416D",
+"@.    c #4F416E",
+"#.    c #323245",
+"$.    c #50416E",
+"%.    c #303042",
+"&.    c #382C4D",
+"*.    c #4D3F6C",
+"=.    c #4E406D",
+"-.    c #50426F",
+";.    c #504270",
+">.    c #514270",
+",.    c #A3A2B6",
+"'.    c #514371",
+").    c #2F3042",
+"!.    c #524371",
+"~.    c #524372",
+"{.    c #524472",
+"].    c #534473",
+"^.    c #323345",
+"/.    c #303142",
+"(.    c #A0A0B3",
+"_.    c #534574",
+":.    c #544574",
+"<.    c #544575",
+"[.    c #333346",
+"}.    c #A3A3B6",
+"|.    c #A1A0B3",
+"1.    c #554676",
+"2.    c #564777",
+"3.    c #A3A3B7",
+"4.    c #50416F",
+"5.    c #554675",
+"6.    c #574778",
+"7.    c #574879",
+"8.    c #333347",
+"9.    c #A4A3B7",
+"0.    c #58497A",
+"a.    c #58497B",
+"b.    c #59497B",
+"c.    c #343447",
+"d.    c #A4A3B8",
+"e.    c #3E3257",
+"f.    c #564778",
+"g.    c #594A7C",
+"h.    c #5A4A7D",
+"i.    c #5A4B7D",
+"j.    c #343448",
+"k.    c #A4A4B8",
+"l.    c #5B4B7E",
+"m.    c #313144",
+"n.    c #5C4C7F",
+"o.    c #A5A4B9",
+"p.    c #5C4C80",
+"q.    c #5A4A7C",
+"r.    c #5D4D81",
+"s.    c #5D4D82",
+"t.    c #353448",
+"u.    c #5E4D82",
+"v.    c #5E4E83",
+"w.    c #5F4F84",
+"x.    c #353549",
+"y.    c #A5A5B9",
+"z.    c #5E4E82",
+"A.    c #604F85",
+"B.    c #615086",
+"C.    c #A6A5BA",
+"D.    c #605086",
+"E.    c #615187",
+"F.    c #625188",
+"G.    c #35354A",
+"H.    c #625288",
+"I.    c #323244",
+"J.    c #625187",
+"K.    c #635289",
+"L.    c #63528A",
+"M.    c #36364A",
+"N.    c #A6A5BB",
+"O.    c #64538B",
+"P.    c #64538A",
+"Q.    c #65548C",
+"R.    c #36364B",
+"S.    c #A7A6BB",
+"T.    c #66548D",
+"U.    c #66558D",
+"V.    c #A7A6BC",
+"W.    c #67558F",
+"X.    c #685790",
+"Y.    c #584879",
+"Z.    c #59497C",
+"`.    c #67568F",
+" +    c #37364B",
+".+    c #A8A6BD",
+"++    c #695791",
+"@+    c #2E2F3F",
+"#+    c #9F9FB0",
+"$+    c #382E4E",
+"%+    c #42355C",
+"&+    c #2E2440",
+"*+    c #292039",
+"=+    c #00FF29",
+"                                                                                                                                ",
+"                                                                                                                                ",
+"                                                                                                                                ",
+"      . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       ",
+"      . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < < [ [ [ [ [ [ [ < < : _ ( / ^ ] { ~ ! ) ' , > ; - = * & % $ # @ }       ",
+"      . @ | $ % 1 * 2 - ; 3 4 ' ! ~ { ] ^ / _ < 5 [ 6 7 7 8 9 7 0 0 9 8 7 7 6 [ 5 < _ / ^ ] { ~ ! , 4 a ; - 2 * 1 % $ | }       ",
+"      . | b % & * 2 - c a d ) ! ~ ] ^ / : < [ 6 7 0 e e f f f e f f f f f e e 0 7 6 [ < : / ^ ] ~ g ) h a c - 2 * & % b }       ",
+"      . b i & * 2 - c a ' ' ~ { j ^ _ < [ 7 9 e f f k l m m n o p p n m m l k f f e 9 7 [ < _ ^ j ~ ~ q ' a c - 2 * & i }       ",
+"      . r s * = - c a ' q t u ^ / : [ 6 8 e f k m n v v w x y z A y y x w v v n m k f e 8 6 [ : / B u ~ q ' a c - = * s }       ",
+"      . s C = - ; a ' q ~ t u ( < [ 7 e f k m v D x E F G H I J K I I H G F E x D v m k f e 7 [ < L u { ~ q ' a ; - = C }       ",
+"      . 1 M N ; a h q ~ { B u < O 8 e f m v w y F H I P Q R R S T U R R Q P I H F y w v m f e 8 O L u ^ { ~ q h a ; N M }       ",
+"      . * 2 V > 4 ) ~ { ^ L W 6 9 X k m v y F I P Q Y Z Z ` ` S  .` ` ` Z Z Y Q P I F y v m k X 9 L W ( ^ { ~ ) 4 > V 2 }       ",
+"      . = - c , ' ! { ^ ( L W 0 f l p w E H P R Z Z ` ..+.@.@.#. .$.@.@.+...` Z Z R P H E w p l f %.W < ( ^ { ! ' , c - }       ",
+"      . &.; a ' ! ~ j / < L W f l v w F I Q Y *.=.+.$.-.;.>.>.#.,.'.>.>.;.-.$.+.=.*.Y Q I F w v l %.W O < / j ~ ! ' a ; }       ",
+"      . - > 4 ) ~ ] ^ : [ ).W l v x G I R Z ` +.$.-.>.!.~.{.].^.,.].].{.~.!.>.-.$.+.` Z R I G x v /.W 8 [ : ^ ] ~ ) 4 > }       ",
+"      . ; a ' ! { ^ _ [ 7 %.(.p w G I R Z =.@.-.>.!.{.]._.:.<.[.}.<.<.:._.].{.!.>.-.@.=.Z R I G w z (.e 7 [ _ ^ { ! ' a }       ",
+"      . > 4 q ~ ] / < 6 e %.|.w F I R Z ..$.>.!.{.].:.<.1.1.2.[.3.2.2.1.1.<.:.].{.!.>.$...Z R I F z |.f e 6 < / ] ~ q 4 }       ",
+"      . a ' ! { ^ : [ 8 f /.A E I R Z ..4.>.!.].:.5.1.2.6.7.7.8.9.7.7.7.6.2.1.5.:.].!.>.4...Z R I J A m f 8 [ : ^ { ! ' }       ",
+"      . , ) ~ ] / < 7 e k z A H Q Z =.$.>.~.].<.1.2.6.7.0.a.b.c.d.b.b.a.0.7.6.2.1.<.].~.>.$.=.Z Q J A v k e 7 < / ] ~ ) }       ",
+"      . ' ! e.^ _ [ 9 f m z K P Y ` @.>.!.].<.1.f.7.0.b.g.h.i.j.k.l.i.h.g.b.0.7.f.1.<.].!.>.@.` Y m.K w m f 9 [ _ ^ e.! }       ",
+"      . ' ~ ] / < 6 e k v z K R *.+.-.!.].<.1.f.7.a.g.h.l.n.n.j.o.p.n.n.l.h.g.a.7.f.1.<.].!.-.+.*.m.K y v k e 6 < / ] ~ }       ",
+"      . ) ~ j ( 5 7 f m D J K Z =.$.>.{.:.1.f.7.b.q.l.n.p.r.s.t.o.u.s.r.p.n.l.q.b.7.f.1.:.{.>.$.=.S K F D m f 7 5 ( j ~ }       ",
+"      . ! e.^ _ [ 0 f n x J T Z +.-.!.].5.2.7.a.q.l.n.r.u.v.w.x.y.w.w.v.u.r.n.l.q.a.7.2.5.].!.-.+.S T H x n f 0 [ _ ^ e.}       ",
+"      . ! { ^ : 6 e k v E J T ` $.>.{.:.1.6.0.g.l.n.r.z.w.A.B.x.C.B.B.A.w.z.r.n.l.g.0.6.1.:.{.>.$.S T I E v k e 6 : ^ { }       ",
+"      . ~ ] / < 7 e l v F m.T ..-.!.].<.2.7.b.h.n.r.z.w.D.E.F.G.C.H.F.E.D.w.z.r.n.h.b.7.2.<.].!.-.I.T P F v l e 7 < / ] }       ",
+"      . ~ ] ( < 7 f m w G m.T +.;.~._.1.6.0.g.l.p.u.w.D.J.K.L.M.N.O.L.K.J.D.w.u.p.l.g.0.6.1._.~.;.I.T Q G w m f 7 < ( ] }       ",
+"      . ~ j ( [ 8 f m x H m. .@.>.{.:.1.7.a.h.n.r.v.A.E.K.P.Q.R.S.T.Q.P.K.E.A.v.r.n.h.a.7.1.:.{.>.#. .R H x m f 8 [ ( j }       ",
+"      . ~ ^ _ [ 9 f n y I m. .@.>.].<.2.7.b.i.n.s.w.B.F.L.Q.U.R.V.W.U.Q.L.F.B.w.s.n.i.b.7.2.<.].>.#. .R I y n f 9 [ _ ^ }       ",
+"      . ~ ^ _ [ 0 f p y I S  .$.'.].<.2.7.b.l.p.u.w.B.H.O.T.W.R.V.X.W.T.O.H.B.w.u.p.l.b.7.2.<.].'.#. .U I y p f 0 [ _ ^ }       ",
+"      . e.^ _ [ 0 f p y I S  .$.'.].<.2.Y.Z.l.p.z.w.B.K.O.T.`. +.+++`.T.O.K.B.w.z.p.l.Z.Y.2.<.].'.#. .U I y p f 0 [ _ ^ }       ",
+"      . ~ ^ _ [ 0 f p y I S  .$.'.].<.2.7.b.l.p.u.w.B.H.O.T.W.R.V.X.W.T.O.H.B.w.u.p.l.b.7.2.<.].'.#. .U I y p f 0 [ _ ^ }       ",
+"      . ~ ^ _ [ 9 f n y I m. .@.>.].<.2.7.b.i.n.s.w.B.F.L.Q.U.R.V.W.U.Q.L.F.B.w.s.n.i.b.7.2.<.].>.#. .R I y n f 9 [ _ ^ }       ",
+"      . ~ j ( [ 8 f m x H m. .@.>.{.:.1.7.a.h.n.r.v.A.E.K.P.Q.R.S.T.Q.P.K.E.A.v.r.n.h.a.7.1.:.{.>.#. .R H x m f 8 [ ( j }       ",
+"      . ~ ] ( < 7 f m w G m.T +.;.~._.1.6.0.g.l.p.u.w.D.J.K.L.M.N.O.L.K.J.D.w.u.p.l.g.0.6.1._.~.;.I.T Q G w m f 7 < ( ] }       ",
+"      . ~ ] / < 7 e l v F m.T ..-.!.].<.2.7.b.h.n.r.z.w.D.E.F.G.C.H.F.E.D.w.z.r.n.h.b.7.2.<.].!.-.I.T P F v l e 7 < / ] }       ",
+"      . ! { ^ : 6 e k v E J T ` $.>.{.:.1.6.0.g.l.n.r.z.w.A.B.x.C.B.B.A.w.z.r.n.l.g.0.6.1.:.{.>.$.S T I E v k e 6 : ^ { }       ",
+"      . ! e.^ _ [ 0 f n x J T Z +.-.!.].5.2.7.a.q.l.n.r.u.v.w.x.y.w.w.v.u.r.n.l.q.a.7.2.5.].!.-.+.S T H x n f 0 [ _ ^ e.}       ",
+"      . ) ~ j ( 5 7 f m D J K Z =.$.>.{.:.1.f.7.b.q.l.n.p.r.s.t.o.u.s.r.p.n.l.q.b.7.f.1.:.{.>.$.=.S K F D m f 7 5 ( j ~ }       ",
+"      . ' ~ ] / < 6 e k v z K R *.+.-.!.].<.1.f.7.a.g.h.l.n.n.j.o.p.n.n.l.h.g.a.7.f.1.<.].!.-.+.*.m.K y v k e 6 < / ] ~ }       ",
+"      . ' ! e.^ _ [ 9 f m z K P Y ` @.>.!.].<.1.f.7.0.b.g.h.i.j.k.l.i.h.g.b.0.7.f.1.<.].!.>.@.` Y m.K w m f 9 [ _ ^ e.! }       ",
+"      . , ) ~ ] / < 7 e k z A H Q Z =.$.>.~.].<.1.2.6.7.0.a.b.c.d.b.b.a.0.7.6.2.1.<.].~.>.$.=.Z Q J A v k e 7 < / ] ~ ) }       ",
+"      . a ' ! { ^ : [ 8 f /.A E I R Z ..4.>.!.].:.5.1.2.6.7.7.8.9.7.7.7.6.2.1.5.:.].!.>.4...Z R I J A m f 8 [ : ^ { ! ' }       ",
+"      . > 4 q ~ ] / < 6 e %.|.w F I R Z ..$.>.!.{.].:.<.1.1.2.[.3.2.2.1.1.<.:.].{.!.>.$...Z R I F z |.f e 6 < / ] ~ q 4 }       ",
+"      . ; a ' ! { ^ _ [ 7 %.(.p w G I R Z =.@.-.>.!.{.]._.:.<.[.}.<.<.:._.].{.!.>.-.@.=.Z R I G w z (.e 7 [ _ ^ { ! ' a }       ",
+"      . - > 4 ) ~ ] ^ : [ ).W l v x G I R Z ` +.$.-.>.!.~.{.].^.,.].].{.~.!.>.-.$.+.` Z R I G x v /.W 8 [ : ^ ] ~ ) 4 > }       ",
+"      . &.; a ' ! ~ j / < L W f l v w F I Q Y *.=.+.$.-.;.>.>.#.,.'.>.>.;.-.$.+.=.*.Y Q I F w v l %.W O < / j ~ ! ' a ; }       ",
+"      . = - c , ' ! { ^ ( L W 0 f l p w E H P R Z Z ` ..+.@.@.#. .$.@.@.+...` Z Z R P H E w p l f %.W < ( ^ { ! ' , c - }       ",
+"      . * 2 V > 4 ) ~ { ^ L W 6 9 X k m v y F I P Q Y Z Z ` ` S  .` ` ` Z Z Y Q P I F y v m k X 9 L W ( ^ { ~ ) 4 > V 2 }       ",
+"      . 1 M N ; a h q ~ { B u < O 8 e f m v w y F H I P Q R R S T U R R Q P I H F y w v m f e 8 O L u ^ { ~ q h a ; N M }       ",
+"      . s C = - ; a ' q ~ t u ( < [ 7 e f k m v D x E F G H I J K I I H G F E x D v m k f e 7 [ < L u { ~ q ' a ; - = C }       ",
+"      . r s * = - c a ' q t u ^ / : [ 6 8 e f k m n v v w x y z A y y x w v v n m k f e 8 6 [ : / B u ~ q ' a c - = * s }       ",
+"      . b i & * 2 - c a ' @+#+{ j ^ _ < [ 7 9 e f f k l m m n z |.p n m m l k f f e 9 7 [ < _ ^ j t #+q ' a c - 2 * & i }       ",
+"      . | b % & * 2 - c a d ) ! ~ ] ^ / : < [ 6 7 0 e e f f f e f f f f f e e 0 7 6 [ < : / ^ ] ~ g ) h a c - 2 * & % b }       ",
+"      . @ | $ % 1 * 2 - ; 3 4 ' ! ~ { ] ^ / _ < 5 [ 6 7 7 8 9 7 0 0 9 8 7 7 6 [ 5 < _ / ^ ] { ~ ! , 4 a ; - 2 * 1 % $ | }       ",
+"      . + @ # $ % & * = - $+> , ' ) ! ~ { ] ^ / ( _ : < < [ [ %+[ [ [ [ < < : _ ( / ^ ] { ~ ! ) ' a > ; - = * & % $ # @ }       ",
+"      . &++ @ # $ % & * = N V c a 4 ' q ! ~ e.] j ^ ^ / ( ( _ _ _ _ _ ( ( / ^ ^ j ] e.~ ! q ' 4 a c V N = * & % $ # @ + }       ",
+"      . } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } }       ",
+"        *+      *+  *+  *+    *+  *+*+*+  *+*+*+                                                                                ",
+"        *+*+  *+*+  *+  *+    *+  *+      *+    *+                                                              *+*+*+*+        ",
+"        *+  *+  *+  *+    *+*+    *+*+*+  *+*+*+                                                                *+=+=+=+        ",
+"        *+      *+  *+  *+    *+  *+      *+    *+                                                              *+=+=+=+        ",
+"        *+      *+  *+  *+    *+  *+*+*+  *+    *+                                                                              ",
+"                                                                                                                                ",
+"                                                                                                                                "};
diff --git a/AlsaMixer.app/skins/default/mutebutton.xpm b/AlsaMixer.app/skins/default/mutebutton.xpm
new file mode 100644 (file)
index 0000000..cce72e0
--- /dev/null
@@ -0,0 +1,30 @@
+/* XPM */
+static char * mutebutton_xpm[] = {
+"16 9 18 1",
+"      c None",
+".     c #B7BAC7",
+"+     c #848694",
+"@     c #838593",
+"#     c #828392",
+"$     c #808290",
+"%     c #7F818F",
+"&     c #7E808E",
+"*     c #7C7E8C",
+"=     c #7B7D8B",
+"-     c #7A7C8A",
+";     c #787A88",
+">     c #777987",
+",     c #767886",
+"'     c #747784",
+")     c #737583",
+"!     c #000000",
+"~     c #FF0000",
+"................",
+".+@#$%&*=-;>,')!",
+".!!!!!!!!!!!!!!!",
+"...............!",
+".+@#$%&*=-;>,')!",
+".!!!!!!!!!!!!!!!",
+"...........!~~~!",
+".+@#$%&*=-;!~~~!",
+".!!!!!!!!!!!!!!!"};
diff --git a/AlsaMixer.app/skins/default/redlight.xpm b/AlsaMixer.app/skins/default/redlight.xpm
new file mode 100644 (file)
index 0000000..0e3791b
--- /dev/null
@@ -0,0 +1,7 @@
+/* XPM */
+static char * redlight_xpm[] = {
+"3 2 2 1",
+"      c None",
+".     c #FF0000",
+"...",
+"..."};