wmix-3.1/0040755000175000001440000000000010050541574011725 5ustar timecopuserswmix-3.1/AUTHORS0100644000175000001440000000140607303433722012775 0ustar timecopuserstimecop [timecop@japan.co.jp] the main author of wmix Daniel Richard G. [skunk@mit.edu] author of volume.app, where I got the knob math and mixer routines from (which was in turn based on mixer routines in wmix 2.x) /* the people below have contributed code in the past, though most of the code has been rewritten in 3.0 */ gilles querret [gilles.querret@free.fr] author of the mousewheel patch for wmix Travis Whitton [travis@atlantic.net] submitted a patch to restore volume and balance when pressing mute button, and also did changes in the Makefile to make sure it works on systems other than my own. Vinnie Yesue [vinnie@fizz.sonicity.com] Did the work on changing mixermax stuff, because he had one of those broken soundcards that made things break (see BUGS) wmix-3.1/BUGS0100644000175000001440000000025407303434042012404 0ustar timecopusersIf you find any, make sure and let me know. Since this is almost a complete rewrite, I am sure I missed something somewhere. If you find any problems, please let me know. wmix-3.1/COPYING0100644000175000001440000000006207303433722012755 0ustar timecopusers#ifndef GNU_GPL_V2 #include #endif wmix-3.1/INSTALL0100644000175000001440000000042107303433722012752 0ustar timecopusersSince your reading this, you are probably done with the tar zxvf part. 1. make 2. become root 3. make install 4. wmix pretty easy. See README for instructions on how to use the mixer and about some information on the programming involved. timecop [timecop@japan.co.jp] wmix-3.1/Makefile0100644000175000001440000000057707303427510013373 0ustar timecopusersCC = gcc CFLAGS = -O3 -W -Wall LDFLAGS = -L/usr/X11R6/lib OBJECTS = misc.o mixer-oss.o ui_x.o wmix.o # where to install this program (also for packaging stuff) DESTDIR = PREFIX = $(DESTDIR)/usr/X11R6 INSTALL = -m 755 wmix: $(OBJECTS) $(CC) -o $@ $(LDFLAGS) $(OBJECTS) -lXpm -lXext -lX11 -lm clean: rm -rf *.o wmix *~ install: wmix install $(INSTALL) wmix $(PREFIX)/bin wmix-3.1/NEWS0100644000175000001440000001211010050541573012413 0ustar timecopusers3.1 NEWS: Fixed a 3 years old bug about volume level showing up as "0" when it's actually set to 10. Thank to all 20 or so people who e-mailed me about this. Changed struct mixer_info name to allow compiling wmix under 2.6.1+ kernels. Thanks Neil Burch for the patch. Added a patch to enable exclusion of channels from display - allows you to remove mixer channels you never use. adds '-e ' command line option which can be repeated any number of times. Thanks to Nicolas Descomps . Added #include since glibc finally fixed most of the includes since 2001. 3.0 NEWS: Major code rewrite. Now uses much better mixer library. New knob drawing code. New config parsing code - no more segfaults. New mouse control code for knob and slider dragging - more intuitive. Documentation updates. Removed runtime config parsing, only reading config file once on startup. New command line options to specify X display, config file, and mixer device. Removed "mixermax" code until someone complains. Current channel title scrolling is now configurable. 2.2 NEWS: This is a bugfix release. On-Screen-Display code now looks for some common large bitmap font. Check that $HOME is set before trying to write a config file. Wmix makes a pid file for use with signal changing volume up/down. Minor code reorganization. 2.11 NEWS: Mostly bugfixes and other random stuff. OSD now really stays on top provided you run a GNOME-compliant window manager (wmaker/E/saw-what-ever,etc) 2.1 NEWS: Configuration file implemented. Mousewheel functionality, OSD display, OSD color, main mixer device, and OSS bug work-around can now be selected through WMixer rc file, by default placed in ~/.wmixrc Changes to the rc file are loaded dynamically, while the mixer is running - you can change the OSD color, for example, and see the results right away. 2.04 NEWS: New feature: Volume of the current channel can be controlled using signals. Sending SIGUSR1 will increase the volume by 1 step, and SIGUSR2 will decrase the volume by 1 step. This could be useful if you have a newer style keyboard with volume buttons and all the other extra shit. You can tell your favorite window manager to run a program on keypress, and that program could be something like "killall -USR1 wmix" for volume up key, and "killall -USR2 wmix" for volume down. How to assign programs to specific keys is up to you. I know Blackbox and WindowMaker can both do it. Keep in mind most X-servers don't automatically support those extra keys, so some hacking might be required. Usually they are sent as a Win95 key scancode plus another scancode. I don't have one of these keyboards so I don't know. If enough people ask for it I will add 2 more signal handlers to switch the current "channel" back and forth. 2.02 NEWS: Version 2.02 adds mouse wheel support to adjust volume, thanks to the patch from Gilles QUERRET . Now instead of dragging the knob, you can use your mouse wheel to adjust the current channel volume. Position the cursor anywhere on the dockapp, and move the wheel. This behaviour is off by default, but you can compile wmix with -DMOUSEWHEEL in the Makefile to enable this feature. Incase your mouse has more than 2 buttons and a wheel, you can set which button signals the wheel generates as "up" and "down" in mix.c, lines 45 and 46. The default is for a standard mouse with 2 buttons and a wheel. WHEEL_STEP is the amount to adjust the knob. The default of 3 should be good for everyone. Changing the volume using the wheel also brings up OSD for the current channel following same rules as if the knob was used directly. 2.01 NEWS: New feature, which isn't really new, but a feature move from WMixer 1.5, is the On-Screen-Display (OSD), just like the one you probably have on your TV. The concept was the only thing copied from Wmixer 1.5 though, the code has been rewritten to use a modeless window instead of drawing on the root window, and draw code has been optimized not to draw any unnecessary stuff. The OSD only comes up when the Knob is turned, i.e. during manual adjustment. OSD stays hidden during automatic updates due to mixer reads or changing rec/balance etc. However, due to the way the OSD timer is done, as long as you are moving inside the dockapp (adjusting balance, or just generally moving the mouse inside the dockapp window, the OSD will stay lit. After all movement is gone, and in approximately 1.5 seconds, the OSD fades out. If some Xlib programmer knows a /NON GAY/ way to handle always-on-top, feel free to mail me a diff that makes the OSD continuously on top while being displayed. Right now, it comes up on top, but if you move a window over it or something, it gets hidden. Not too much of a loss, but still could be improved. OSD follows the same low-CPU use guidelines as the rest of the code. No updates happen unless something changes that requires an update. Also, expose events after uncovering the OSD window are not handled - if you can manage to obscure it in 1.5 seconds and want to see it again after that, you can always go back and twiddle the knob or something. wmix-3.1/README0100644000175000001440000001030607303433722012604 0ustar timecopusers _ _____ ___ __ ___ __ ___ (_)_ __ |___ / / _ \ timecop@japan.co.jp \ \ /\ / / '_ ` _ \| \ \/ / |_ \| | | | skunk@mit.edu \ V V /| | | | | | |> < ___) | |_| | \_/\_/ |_| |_| |_|_/_/\_\ |____(_)___/ ______________________________________________________________________________ * This is a complete dockapp mixer utilizing the OSS mixer API * Has a nice On-Screen-Display to visualize current volume levels * Can adjust main volume, balance, recording status, and mute/unmute channels * Supports mousewheel to adjust the volume settings * Supports user specified signals to adjust the volume remotely * User configuration file can be used to set options How to use it: .---------------------------. | Message Area Message Area | <- (1) | [ Rec ] [ ST ] [ Mute ] | <- (2) (3) (4) | <- -> xxx | <- (5) (6) (7) | L R ___ | | | ||| | /the\ | | |--|||---| |K NOB| | <- (8) (9) | ||| <- slider \___/ | `---------------------------' 1) Current channel name is displayed in this area. If scrolling messages are enabled in config, the text will scroll every 30 seconds or so, using long sound channel names. If scrolling is disabled, short 5-character channel names are used instead, and the message constantly stays on the screen. In scroll mode, clicking in this area will re-scroll current message. 2) Clicking REC will toggle record status for current channel, if the channel is capable of recording. Some sound cards will allow you to set multiple record sources. Some don't, so you can only have one selected at any time. If you click here and nothing happens, the channel is not record-capable. 3) ST indicator is lit if the current channel is stereo. 4) Clicking MUTE will mute the current channel. Old volume settings are remembered, so clicking it again will un-mute. Also see the knob section because there is more than one way to do it :) 5) Clicking <- will switch to previous channel 6) Clicking -> will switch to next channel 7) Numeric indicator of current volume from 0 to 100 percent. Doesn't change when the channel is muted, so you can still adjust the volume and then unmute. 8) If ST light is on (Stereo channel), you can move this slider left and right to set balance. Click on the slider, and drag the mouse left or right to adjust. Double-clicking on the slider will center the balance. If you are on a mono channel, the slider doesn't move or do anything. 9) Ah, yes, the knob. One of the biggest visual differences since version 2.x of WMix is that the knob now rendered in real-time opposed to switching pixmaps with various knob angles. Bow down to Daniel Richard G. for coming up with this awesome routine. Also utilizes new "cursor-hiding-and-moving" code which first appeared in volume.app by the same guy. Now you don't have to scroll the mouse off your desk to adjust the volume. Anyway, simply click on the knob and drag the mouse up or down to adjust the volume. After you release the button, your mouse cursor is right back where you started. Very Nifty! You can also double-click on the knob to mute the current channel. Red LED will turn off... Channel is muted! Most people have mice with wheels these days, to this support is enabled by default. Scrolling the mouse wheel up or down will adjust the volume by 3% up or down. Buttons and step size are configurable from the config file - see below. You can also check out ~/.wmix.pid, and use SIGUSR1/2 to adjust the volume up or down by the configured step size. The config file: 1 = yes, 0 = no mousewheel=1 # use mousewheel? scrolltext=1 # scroll the system messages? osd=1 # display OSD? osdcolor=green # color of the OSD (from rgb.txt) wheelbtn1=4 # which mousewheel button is "up" wheelbtn2=5 # which mousewheel button is "down" wheelstep=3 # the step for mousewheel adjustment Most defaults are good for normal use, and if there is no config file, the settings you see above are used. If you want to hack on a config file, copy sample.wmixrc to ~/.wmixrc and change it around. Comments are ignored, but don't put comments at the end of line like I did here. timecop [timecop@japan.co.jp] wmix-3.1/misc.c0100644000175000001440000000731007303426460013025 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include "include/common.h" #include "include/misc.h" typedef struct { int enable; int x; int y; int width; int height; } MRegion; MRegion mr[16]; extern Config config; /* Converts separate left and right channel volumes (each in [0, 1]) to * volume and balance values. (Volume is in [0, 1], balance is in [-1, 1]) */ void lr_to_vb(float left, float right, float *volume, float *balance) { assert((left >= 0.0) && (right >= 0.0)); *volume = MAX(left, right); if (left > right) *balance = -1.0 + right / left; else if (right > left) *balance = 1.0 - left / right; else *balance = 0.0; } /* Performs the reverse calculation of lr_to_vb() */ void vb_to_lr(float volume, float balance, float *left, float *right) { /* *left = volume; *right = volume; return; // XXX */ *left = volume * (1.0 - MAX(0.0, balance)); *right = volume * (1.0 + MIN(0.0, balance)); } double get_current_time(void) { struct timeval tv; double t; gettimeofday(&tv, NULL); t = (double)tv.tv_sec; t += (double)tv.tv_usec / 1.0e6; return t; } void add_region(int index, int x, int y, int width, int height) { mr[index].enable = 1; mr[index].x = x; mr[index].y = y; mr[index].width = width; mr[index].height = height; } int check_region(int x, int y) { register int i; bool found = false; for (i = 0; i < 16 && !found; i++) { if (mr[i].enable && x >= mr[i].x && x <= mr[i].x + mr[i].width && y >= mr[i].y && y <= mr[i].y + mr[i].height) found = true; } if (!found) return -1; return (i - 1); } void config_read(void) { FILE *fp; char buf[512]; char *ptr; if (config.file == NULL) return; fp = fopen(config.file, "r"); if (!fp) return; while (fgets(buf, 512, fp)) { if ((ptr = strstr(buf, "mousewheel="))) { ptr += 11; config.mousewheel = atoi(ptr); } if ((ptr = strstr(buf, "scrolltext="))) { ptr += 11; config.scrolltext = atoi(ptr); } if ((ptr = strstr(buf, "osd="))) { ptr += 4; config.osd = atoi(ptr); } if ((ptr = strstr(buf, "osdcolor="))) { char *end; ptr += 9; end = strchr(ptr, '\n'); ptr[end - ptr] = '\0'; if (config.osd_color) free(config.osd_color); config.osd_color = strdup(ptr); } if ((ptr = strstr(buf, "wheelstep="))) { ptr += 10; /* detect old style config */ if (atoi(ptr) > 1) config.scrollstep = (float)atoi(ptr) / 100.0; else config.scrollstep = atof(ptr); } if ((ptr = strstr(buf, "wheelbtn1="))) { ptr += 10; config.wheel_button_up = atoi(ptr); } if ((ptr = strstr(buf, "wheelbtn2="))) { ptr += 10; config.wheel_button_down = atoi(ptr); } } fclose(fp); } wmix-3.1/mixer-oss.c0100644000175000001440000002463110050540330014007 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include "include/common.h" #include "include/misc.h" #include "include/mixer.h" #define WMVOLUME_CHANNEL_NAMES \ "Master volume", \ "Bass", \ "Treble", \ "FM Synth volume", \ "PCM Wave volume", \ "PC Speaker", \ "Line In level", \ "Microphone level", \ "CD volume", \ "Recording monitor", \ "PCM Wave 2 volume", \ "Recording volume", \ "Input gain", \ "Output gain", \ "Line In 1", \ "Line In 2", \ "Line In 3", \ "Digital In 1", \ "Digital In 2", \ "Digital In 3", \ "Phone input", \ "Phone output", \ "Video volume", \ "Radio volume", \ "Monitor volume" #ifdef OSS_CHANNEL_NAMES #define CHANNEL_NAMES SOUND_DEVICE_LABELS #else #define CHANNEL_NAMES WMVOLUME_CHANNEL_NAMES #endif typedef struct { const char *name; /* name of channel */ const char *sname; /* short name of the channel */ int dev; /* channel device number */ int prev_dev_lr_volume; /* last known left/right volume * (in device format) */ float volume; /* volume, in [0, 1] */ float balance; /* balance, in [-1, 1] */ bool can_record; /* capable of recording? */ bool is_recording; /* is it recording? */ bool is_stereo; /* capable of stereo? */ bool is_muted; /* is it muted? */ } MixerChannel; static const char *channel_names[] = { CHANNEL_NAMES }; static const char *short_names[] = SOUND_DEVICE_LABELS; static int mixer_fd; static MixerChannel mixer[SOUND_MIXER_NRDEVICES]; static int n_channels = 0; static int cur_channel = 0; static int prev_modify_counter = -1; static bool get_mixer_state(void) { struct mixer_info m_info; int dev_lr_volume, dev_left_volume, dev_right_volume; float left, right; int srcmask; int ch; /* to really keep track of updates */ static MixerChannel oldmixer[SOUND_MIXER_NRDEVICES]; ioctl(mixer_fd, SOUND_MIXER_INFO, &m_info); if (m_info.modify_counter == prev_modify_counter) /* * Mixer state has not changed */ return false; /* Mixer state was changed by another program, so we need * to update. As OSS cannot tell us specifically which * channels changed, we read all of them in. * * prev_modify_counter was initialized to -1, so this part * is guaranteed to run the first time this routine is * called. */ if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &srcmask) == -1) { fprintf(stderr, "mixer read failed\n"); perror(NULL); exit(EXIT_FAILURE); } for (ch = 0; ch < n_channels; ch++) { if (ioctl(mixer_fd, MIXER_READ(mixer[ch].dev), &dev_lr_volume) == -1) { fprintf(stderr, "mixer read failed\n"); exit(EXIT_FAILURE); } if (dev_lr_volume != mixer[ch].prev_dev_lr_volume) { dev_left_volume = dev_lr_volume & 0xFF; dev_right_volume = dev_lr_volume >> 8; if ((dev_left_volume > 0) || (dev_right_volume > 0)) mixer[ch].is_muted = false; left = (float) dev_left_volume / 100.0; right = (float) dev_right_volume / 100.0; if (!mixer[ch].is_muted) { if (mixer[ch].is_stereo) lr_to_vb(left, right, &mixer[ch].volume, &mixer[ch].balance); else { mixer[ch].volume = left; mixer[ch].balance = 0.0; } mixer[ch].prev_dev_lr_volume = dev_lr_volume; } } mixer[ch].is_recording = ((1 << mixer[ch].dev) & srcmask) != 0; } prev_modify_counter = m_info.modify_counter; /* check if this was due to OSS stupidity or if we really changed */ if (!memcmp(&mixer, &oldmixer, sizeof(mixer))) { memcpy(&oldmixer, &mixer, sizeof(mixer)); return false; } memcpy(&oldmixer, &mixer, sizeof(mixer)); return true; } static void set_mixer_state(void) { float left, right; int dev_left_volume, dev_right_volume, dev_lr_volume; if (mixer[cur_channel].is_muted) { left = 0.0; right = 0.0; } else vb_to_lr(mixer[cur_channel].volume, mixer[cur_channel].balance, &left, &right); dev_left_volume = (int) (100.0 * left); dev_right_volume = (int) (100.0 * right); dev_lr_volume = (dev_right_volume << 8) | dev_left_volume; ioctl(mixer_fd, MIXER_WRITE(mixer[cur_channel].dev), &dev_lr_volume); } static void get_record_state(void) { int srcmask; int ch; if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &srcmask) == -1) { fprintf(stderr, "mixer read failed\n"); perror(NULL); exit(EXIT_FAILURE); } for (ch = 0; ch < n_channels; ch++) { mixer[ch].is_recording = ((1 << mixer[ch].dev) & srcmask) != 0; } } static void set_record_state(void) { int srcmask; if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &srcmask) == -1) { fputs("error: recording source mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } if (((1 << mixer[cur_channel].dev) & srcmask) == 0) srcmask |= (1 << mixer[cur_channel].dev); else srcmask &= ~(1 << mixer[cur_channel].dev); if (ioctl(mixer_fd, SOUND_MIXER_WRITE_RECSRC, &srcmask) == -1) { fputs("error: recording source mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } } void mixer_init(const char *mixer_device, bool verbose, const char * exclude[]) { int devmask, srcmask, recmask, stmask; struct mixer_info m_info; int count; int mask; mixer_fd = open(mixer_device, O_RDWR); if (mixer_fd == -1) { fprintf(stderr, "error: cannot open mixer device %s\n", mixer_device); exit(EXIT_FAILURE); } if (ioctl(mixer_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) { fputs("error: device mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } if (ioctl(mixer_fd, SOUND_MIXER_READ_RECSRC, &srcmask) == -1) { fputs("error: recording source mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } if (ioctl(mixer_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1) { fputs("error: recording mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } if (ioctl(mixer_fd, SOUND_MIXER_READ_STEREODEVS, &stmask) == -1) { fputs("error: stereo mask ioctl failed\n", stderr); exit(EXIT_FAILURE); } if (ioctl(mixer_fd, SOUND_MIXER_INFO, &m_info) == -1) { fputs("error: could not read mixer info\n", stderr); exit(EXIT_FAILURE); } if (verbose) { printf("%s (%s)\n", m_info.name, m_info.id); puts("Supported channels:"); } for (count = 0; count < SOUND_MIXER_NRDEVICES; count++) { mask = 1 << count; if ((mask & devmask) && (!is_exclude((short_names[count]),exclude))) { mixer[n_channels].name = channel_names[count]; mixer[n_channels].sname = short_names[count]; mixer[n_channels].dev = count; mixer[n_channels].prev_dev_lr_volume = -1; mixer[n_channels].can_record = (mask & recmask) != 0; mixer[n_channels].is_recording = (mask & srcmask) != 0; mixer[n_channels].is_stereo = (mask & stmask) != 0; mixer[n_channels].is_muted = false; ++n_channels; if (verbose) printf(" %d: %s \t(%s)\n", n_channels, channel_names[count], short_names[count]); } else if ((mask & devmask) && verbose) printf(" x: %s \t(%s) - disabled\n", channel_names[count], short_names[count]); } get_mixer_state(); } bool mixer_is_changed(void) { return get_mixer_state(); } int mixer_get_channel_count(void) { return n_channels; } int mixer_get_channel(void) { return cur_channel; } const char *mixer_get_channel_name(void) { return mixer[cur_channel].name; } const char *mixer_get_short_name(void) { return mixer[cur_channel].sname; } void mixer_set_channel(int channel) { assert((channel >= 0) && (channel < n_channels)); cur_channel = channel; get_record_state(); } void mixer_set_channel_rel(int delta_channel) { cur_channel = (cur_channel + delta_channel) % n_channels; if (cur_channel < 0) cur_channel += n_channels; get_record_state(); } float mixer_get_volume(void) { get_mixer_state(); return mixer[cur_channel].volume; } void mixer_set_volume(float volume) { assert((volume >= 0.0) && (volume <= 1.0)); mixer[cur_channel].volume = volume; set_mixer_state(); } void mixer_set_volume_rel(float delta_volume) { mixer[cur_channel].volume += delta_volume; mixer[cur_channel].volume = CLAMP(mixer[cur_channel].volume, 0.0, 1.0); set_mixer_state(); } float mixer_get_balance(void) { get_mixer_state(); return mixer[cur_channel].balance; } void mixer_set_balance(float balance) { assert((balance >= -1.0) && (balance <= 1.0)); if (mixer[cur_channel].is_stereo) { mixer[cur_channel].balance = balance; set_mixer_state(); } } void mixer_set_balance_rel(float delta_balance) { if (mixer[cur_channel].is_stereo) { mixer[cur_channel].balance += delta_balance; mixer[cur_channel].balance = CLAMP(mixer[cur_channel].balance, -1.0, 1.0); set_mixer_state(); } } void mixer_toggle_mute(void) { mixer[cur_channel].is_muted = !mixer[cur_channel].is_muted; set_mixer_state(); } void mixer_toggle_rec(void) { if (mixer[cur_channel].can_record) { mixer[cur_channel].is_recording = !mixer[cur_channel].is_recording; set_record_state(); get_record_state(); } } bool mixer_is_muted(void) { return mixer[cur_channel].is_muted; } bool mixer_is_stereo(void) { return mixer[cur_channel].is_stereo; } bool mixer_is_rec(void) { return mixer[cur_channel].is_recording; } bool mixer_can_rec(void) { return mixer[cur_channel].can_record; } bool is_exclude(const char *short_name, const char *exclude[]) { int count = 0; while (count < SOUND_MIXER_NRDEVICES && exclude[count] != NULL){ if ( strcmp(short_name, exclude[count]) == 0 ) return true; count++; } return false; } wmix-3.1/sample.wmixrc0100644000175000001440000000053207303433722014440 0ustar timecopusers# WMix configuration file # use mousewheel mousewheel=1 # scroll the system messages scrolltext=1 # display OSD osd=1 # color of the OSD (from rgb.txt or #xxxxxx) osdcolor=green # which mousewheel button is "up" wheelbtn1=4 # which mousewheel button is "down" wheelbtn2=5 # the step for mousewheel adjustment (in percent, 3 or 0.03) wheelstep=3 wmix-3.1/ui_x.c0100644000175000001440000003550710050540644013041 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "include/master.xpm" #include "include/led-on.xpm" #include "include/led-off.xpm" #include "include/common.h" #include "include/misc.h" #include "include/mixer.h" #include "include/ui_x.h" #ifndef PI #define PI M_PI #endif #define LED_POS_RADIUS 8 #define KNOB_CENTER_X 49 #define KNOB_CENTER_Y 48 #define LED_WIDTH 6 #define LED_HEIGHT 6 typedef struct _Dockapp Dockapp; struct _Dockapp { int width; int height; Pixmap pixmap; Pixmap mask; GC gc; int ctlength; Window osd; GC osd_gc; int osd_width; bool osd_mapped; }; extern Config config; static Pixmap led_on_pixmap; static Pixmap led_on_mask; static Pixmap led_off_pixmap; static Pixmap led_off_mask; #define copy_xpm_area(x, y, w, h, dx, dy) \ XCopyArea(display, dockapp.pixmap, dockapp.pixmap, dockapp.gc, \ x, y, w, h, dx, dy) /* local prototypes */ static Cursor create_null_cursor(Display *x_display); /* ui stuff */ static void draw_stereo_led(void); static void draw_rec_led(void); static void draw_mute_led(void); static void draw_percent(void); static void draw_knob(float volume); static void draw_slider(float offset); /* global variables */ static Dockapp dockapp; static Display *display; static Window win; static Window iconwin; static Cursor hand_cursor; static Cursor null_cursor; static Cursor norm_cursor; static Cursor bar_cursor; /* public methods */ void dockapp_init(Display *x_display) { display = x_display; } void redraw_window(void) { XCopyArea(display, dockapp.pixmap, iconwin, dockapp.gc, 0, 0, dockapp.width, dockapp.height, 0, 0); XCopyArea(display, dockapp.pixmap, win, dockapp.gc, 0, 0, dockapp.width, dockapp.height, 0, 0); } void ui_update(void) { draw_stereo_led(); draw_rec_led(); draw_mute_led(); draw_knob(mixer_get_volume()); draw_slider(mixer_get_balance()); redraw_window(); } void knob_turn(float delta) { mixer_set_volume_rel(delta); draw_knob(mixer_get_volume()); redraw_window(); } void slider_move(float delta) { mixer_set_balance_rel(delta); draw_slider(mixer_get_balance()); redraw_window(); } int blit_string(const char *text) { register int i; register int c; register int k; k = 0; copy_xpm_area(0, 87, 256, 9, 0, 96); for (i = 0; text[i] || i > 31; i++) { c = toupper(text[i]); if (c == '-') { copy_xpm_area(60, 67, 6, 8, k, 96); k += 6; } if (c == ' ') { copy_xpm_area(66, 67, 6, 8, k, 96); k += 6; } if (c == '.') { copy_xpm_area(72, 67, 6, 8, k, 96); k += 6; } if (c >= 'A' && c <= 'Z') { /* letter */ c = c - 'A'; copy_xpm_area(c * 6, 77, 6, 8, k, 96); k += 6; } else if (c >= '0' && c <= '9') { /* number */ c = c - '0'; copy_xpm_area(c * 6, 67, 6, 8, k, 96); k += 6; } } dockapp.ctlength = k; return k; } void scroll_text(int x, int y, int width, bool reset) { static int pos; static int first; static int stop; /* no text scrolling at all */ if (!config.scrolltext) { if (!reset) return; copy_xpm_area(0, 96, 58, 9, x, y); redraw_window(); return; } if (reset) { pos = 0; first = 0; stop = 0; copy_xpm_area(0, 87, width, 9, x, y); } if (stop) { return; } if ((first == 0) && pos == 0) { pos = width; first = 1; } if (pos < -(dockapp.ctlength)) { first = 1; pos = width; stop = 1; return; } pos -= 2; if (pos > 0) { copy_xpm_area(0, 87, pos, 9, x, y); /* clear */ copy_xpm_area(0, 96, width - pos, 9, x + pos, y); } else { /* don't need to clear, already in text */ copy_xpm_area(abs(pos), 96, width, 9, x, y); } redraw_window(); return; } void new_window(char *name, int width, int height) { XpmAttributes attr; Pixel fg, bg; XGCValues gcval; XSizeHints sizehints; XClassHint classhint; XWMHints wmhints; XTextProperty wname; dockapp.width = width; dockapp.height = height; sizehints.flags = USSize | USPosition; sizehints.x = 0; sizehints.y = 0; sizehints.width = width; sizehints.height = height; fg = BlackPixel(display, DefaultScreen(display)); bg = WhitePixel(display, DefaultScreen(display)); win = XCreateSimpleWindow(display, DefaultRootWindow(display), sizehints.x, sizehints.y, sizehints.width, sizehints.height, 1, fg, bg); iconwin = XCreateSimpleWindow(display, win, sizehints.x, sizehints.y, sizehints.width, sizehints.height, 1, fg, bg); XSetWMNormalHints(display, win, &sizehints); classhint.res_name = name; classhint.res_class = name; XSetClassHint(display, win, &classhint); #define INPUT_MASK \ ButtonPressMask \ | ExposureMask \ | ButtonReleaseMask \ | PointerMotionMask \ | LeaveWindowMask \ | StructureNotifyMask XSelectInput(display, win, INPUT_MASK); XSelectInput(display, iconwin, INPUT_MASK); #undef INPUT_MASk XStringListToTextProperty(&name, 1, &wname); XSetWMName(display, win, &wname); gcval.foreground = fg; gcval.background = bg; gcval.graphics_exposures = 0; dockapp.gc = XCreateGC(display, win, GCForeground | GCBackground | GCGraphicsExposures, &gcval); attr.exactColors = 0; attr.alloc_close_colors = 1; attr.closeness = 30000; attr.valuemask = (XpmExactColors | XpmAllocCloseColors | XpmCloseness); if ((XpmCreatePixmapFromData(display, DefaultRootWindow(display), master_xpm, &dockapp.pixmap, &dockapp.mask, &attr) != XpmSuccess) || (XpmCreatePixmapFromData(display, DefaultRootWindow(display), led_on_xpm, &led_on_pixmap, &led_on_mask, &attr) != XpmSuccess) || (XpmCreatePixmapFromData(display, DefaultRootWindow(display), led_off_xpm, &led_off_pixmap, &led_off_mask, &attr) != XpmSuccess)) { fputs("Cannot allocate colors for the dockapp pixmaps!\n", stderr); exit(EXIT_FAILURE); } XShapeCombineMask(display, win, ShapeBounding, 0, 0, dockapp.mask, ShapeSet); XShapeCombineMask(display, iconwin, ShapeBounding, 0, 0, dockapp.mask, ShapeSet); wmhints.initial_state = WithdrawnState; wmhints.icon_window = iconwin; wmhints.icon_x = sizehints.x; wmhints.icon_y = sizehints.y; wmhints.window_group = win; wmhints.flags = StateHint | IconWindowHint | IconPositionHint | WindowGroupHint; XSetWMHints(display, win, &wmhints); hand_cursor = XCreateFontCursor(display, XC_hand2); norm_cursor = XCreateFontCursor(display, XC_left_ptr); bar_cursor = XCreateFontCursor(display, XC_sb_up_arrow); null_cursor = create_null_cursor(display); XMapWindow(display, win); } void new_osd(int width, int height) { Window osd; Pixel fg, bg; XGCValues gcval; GC gc; XSizeHints sizehints; XSetWindowAttributes xattributes; int win_layer = 6; XFontStruct *fs = NULL; sizehints.flags = USSize | USPosition; sizehints.x = (DisplayWidth(display, 0) - width) / 2; sizehints.y = (DisplayHeight(display, 0) - 120); sizehints.width = width; sizehints.height = height; xattributes.save_under = True; xattributes.override_redirect = True; xattributes.cursor = None; fg = WhitePixel(display, DefaultScreen(display)); bg = BlackPixel(display, DefaultScreen(display)); osd = XCreateSimpleWindow(display, DefaultRootWindow(display), sizehints.x, sizehints.y, width, height, 0, fg, bg); XSetWMNormalHints(display, osd, &sizehints); XChangeWindowAttributes(display, osd, CWSaveUnder | CWOverrideRedirect, &xattributes); XStoreName(display, osd, "osd"); XSelectInput(display, osd, ExposureMask); XChangeProperty(display, osd, XInternAtom(display, "_WIN_LAYER", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&win_layer, 1); gcval.foreground = get_color(display, config.osd_color); gcval.background = bg; gcval.graphics_exposures = 0; /* * -sony-fixed-medium-r-normal--24-170-100-100-c-120-iso8859-1 * -misc-fixed-medium-r-normal--36-*-75-75-c-*-iso8859-* */ /* try our cool scaled 36pt fixed font */ fs = XLoadQueryFont(display, "-misc-fixed-medium-r-normal--36-*-75-75-c-*-iso8859-*"); if (fs == NULL) { /* they don't have it! */ /* try our next preferred font (100dpi sony) */ fprintf(stderr, "Trying alternate font\n"); fs = XLoadQueryFont(display, "-sony-fixed-medium-r-normal--24-*-100-100-c-*-iso8859-*"); /* they don't have the sony font either */ if (fs == NULL) { fprintf(stderr, "Trying \"fixed\" font\n"); fs = XLoadQueryFont(display, "fixed"); /* if they don't have the fixed font, we've got different kind * of problems */ if (fs == NULL) { fprintf(stderr, "Your X server is probably broken\n"); exit(1); } } } gc = XCreateGC(display, osd, GCForeground | GCBackground | GCGraphicsExposures, &gcval); XSetFont(display, gc, fs->fid); dockapp.osd = osd; dockapp.osd_gc = gc; dockapp.osd_width = width; dockapp.osd_mapped = false; } void update_osd(float volume, bool up) { int i; int foo; static int bar; if (config.osd) { foo = (((dockapp.osd_width / 100) * (volume * 100)) / 20) + 1; if ((foo != bar) || up) { XClearArea(display, dockapp.osd, ((bar - 1) * 20), 30, (foo * 20), 25, 1); for (i = 1; i < foo; i++) XFillRectangle(display, dockapp.osd, dockapp.osd_gc, i * 20, 30, 5, 25); } bar = foo; } } void unmap_osd(void) { if (config.osd) { XUnmapWindow(display, dockapp.osd); XFlush(display); dockapp.osd_mapped = false; } } void map_osd(void) { if (config.osd) { XMapRaised(display, dockapp.osd); XDrawString(display, dockapp.osd, dockapp.osd_gc, 1, 25, mixer_get_channel_name(), strlen(mixer_get_channel_name())); update_osd(mixer_get_volume(), true); XFlush(display); dockapp.osd_mapped = true; } } bool osd_mapped(void) { return dockapp.osd_mapped; } void set_cursor(int type) { static int oldtype; if (oldtype == type) return; switch (type) { case NULL_CURSOR: XDefineCursor(display, win, null_cursor); XDefineCursor(display, iconwin, null_cursor); break; case NORMAL_CURSOR: XDefineCursor(display, win, norm_cursor); XDefineCursor(display, iconwin, norm_cursor); break; case HAND_CURSOR: XDefineCursor(display, win, hand_cursor); XDefineCursor(display, iconwin, hand_cursor); break; case BAR_CURSOR: XDefineCursor(display, win, bar_cursor); XDefineCursor(display, iconwin, bar_cursor); break; } oldtype = type; } /* private */ static void draw_stereo_led(void) { if (mixer_is_stereo()) /* stereo capable */ copy_xpm_area(78, 0, 9, 7, 28, 14); /* light up LCD */ else /* mono channel */ copy_xpm_area(78, 7, 9, 7, 28, 14); /* turn off LCD */ } static void draw_rec_led(void) { if (mixer_is_rec()) /* record enabled */ copy_xpm_area(65, 0, 13, 7, 4, 14); /* Light up LCD */ else /* record disabled */ copy_xpm_area(65, 7, 13, 7, 4, 14); /* turn off LCD */ } static void draw_mute_led(void) { if (mixer_is_muted()) /* mute */ copy_xpm_area(65, 14, 20, 7, 39, 14); /* light up LCD */ else /* unmute */ copy_xpm_area(65, 21, 20, 7, 39, 14); /* turn off LCD */ } static void draw_percent(void) { int volume = (int)(mixer_get_volume() * 100); copy_xpm_area(0, 87, 18, 9, 41, 22); /* clear percentage */ if (volume < 100) { if (volume >= 10) copy_xpm_area((volume / 10) * 6, 67, 6, 9, 47, 22); copy_xpm_area((volume % 10) * 6, 67, 6, 9, 53, 22); } else { copy_xpm_area(6, 67, 6, 9, 41, 22); copy_xpm_area(0, 67, 6, 9, 47, 22); copy_xpm_area(0, 67, 6, 9, 53, 22); } } static void draw_knob(float volume) { float bearing, led_x, led_y; int led_topleft_x, led_topleft_y; Pixmap led_pixmap, led_mask; bearing = (1.25 * PI) - (1.5 * PI) * volume; led_x = KNOB_CENTER_X + LED_POS_RADIUS * cos(bearing); led_y = KNOB_CENTER_Y - LED_POS_RADIUS * sin(bearing); led_topleft_x = (int)(led_x - (LED_WIDTH / 2.0) + 0.5); led_topleft_y = (int)(led_y - (LED_HEIGHT / 2.0) + 0.5); /* clear previous knob picture */ copy_xpm_area(87, 0, 26, 26, 36, 35); if (mixer_is_muted()) { led_pixmap = led_off_pixmap; led_mask = led_off_mask; } else { led_pixmap = led_on_pixmap; led_mask = led_on_mask; } XCopyArea(display, led_pixmap, dockapp.pixmap, dockapp.gc, 0, 0, LED_WIDTH, LED_HEIGHT, led_topleft_x, led_topleft_y); draw_percent(); } static void draw_slider(float offset) { int x = (offset * 50) / 5; copy_xpm_area(65, 45, 27, 20, 4, 40); /* repair region. move */ copy_xpm_area(65, 29, 7, 15, 14 + x, 43); /* slider */ } static Cursor create_null_cursor(Display *x_display) { Pixmap cursor_mask; XGCValues gcval; GC gc; XColor dummy_color; Cursor cursor; cursor_mask = XCreatePixmap(x_display, DefaultRootWindow(x_display), 1, 1, 1); gcval.function = GXclear; gc = XCreateGC(x_display, cursor_mask, GCFunction, &gcval); XFillRectangle(x_display, cursor_mask, gc, 0, 0, 1, 1); dummy_color.pixel = 0; dummy_color.red = 0; dummy_color.flags = 04; cursor = XCreatePixmapCursor(x_display, cursor_mask, cursor_mask, &dummy_color, &dummy_color, 0, 0); XFreePixmap(x_display, cursor_mask); XFreeGC(x_display, gc); return cursor; } unsigned long get_color(Display *display, char *color_name) { XColor color; XWindowAttributes winattr; XGetWindowAttributes(display, RootWindow(display, DefaultScreen(display)), &winattr); color.pixel = 0; XParseColor(display, winattr.colormap, color_name, &color); color.flags = DoRed | DoGreen | DoBlue; XAllocColor(display, winattr.colormap, &color); return color.pixel; } wmix-3.1/wmix.c0100644000175000001440000002474410050540675013066 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 timecop@japan.co.jp * Mixer code in version 3.0 based on mixer api library by * Daniel Richard G. , which in turn was based on * the mixer code in WMix 2.x releases. * * 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 #include #include #include #include #include #include #include #include #include #include #include "include/common.h" #include "include/mixer.h" #include "include/misc.h" #include "include/ui_x.h" #define VERSION "3.0" static Display *display; static char *display_name = NULL; static char *mixer_device = NULL; static bool button_pressed = false; static bool slider_pressed = false; static double prev_button_press_time = 0.0; static float display_height; static float display_width; Config config; static int mouse_drag_home_x; static int mouse_drag_home_y; static int idle_loop; static bool verbose; static char *exclude[SOUND_MIXER_NRDEVICES]; /* local stuff */ static void parse_cli_options(int argc, char **argv); static void signal_catch(int sig); static void button_press_event(XButtonEvent *event); static void button_release_event(XButtonEvent *event); static void motion_event(XMotionEvent *event); #define HELP_TEXT \ "WMixer " VERSION " by timecop@japan.co.jp + skunk@mit.edu\n" \ "usage:\n" \ " -d connect to remote X display\n" \ " -f parse this config [~/.wmixrc]\n" \ " -m mixer device [/dev/mixer]\n" \ " -h print this help\n" \ " -v verbose -> id, long name, name\n" \ " -e exclude channel, can be used many times\n" \ static void parse_cli_options(int argc, char **argv) { int opt; int count_exclude = 0 ; verbose = false ; while ((opt = getopt(argc, argv, "d:f:hm:ve:")) != EOF) { switch (opt) { case 'd': if (optarg != NULL) display_name = strdup(optarg); break; case 'm': if (optarg != NULL) mixer_device = strdup(optarg); break; case 'f': if (optarg != NULL) if (config.file != NULL) free(config.file); config.file = strdup(optarg); break; case 'h': fputs(HELP_TEXT, stdout); exit(0); break; case 'v': verbose = true; break; case 'e': if (count_exclude < SOUND_MIXER_NRDEVICES) { exclude[count_exclude] = strdup(optarg); /* printf("exclude : %s\n", exclude[count_exclude]); */ count_exclude++; } else fprintf(stderr, "Warning: You can't exclude this many channels\n"); break; default: break; } } exclude[count_exclude] = NULL ; } int main(int argc, char **argv) { XEvent event; char *home; char *pid; FILE *fp; memset(&config, 0, sizeof(config)); /* we can theoretically live without a config file */ home = getenv("HOME"); if (home) { config.file = calloc(1, strlen(home) + 9); sprintf(config.file, "%s/.wmixrc", home); } /* handle writing PID file, silently ignore if we can't do it */ pid = calloc(1, strlen(home) + 10); sprintf(pid, "%s/.wmix.pid", home); fp = fopen(pid, "w"); if (fp) { fprintf(fp, "%d\n", getpid()); fclose(fp); } free(pid); /* default values */ config.mousewheel = 1; config.scrolltext = 1; config.wheel_button_up = 4; config.wheel_button_down = 5; config.scrollstep = 0.03; config.osd = 1; config.osd_color = strdup("green"); parse_cli_options(argc, argv); config_read(); if (mixer_device == NULL) mixer_device = "/dev/mixer"; mixer_init(mixer_device, verbose, (const char **)exclude); mixer_set_channel(0); if ((display = XOpenDisplay(display_name)) == NULL) { fprintf(stderr, "Unable to open display \"%s\"\n", display_name); return EXIT_FAILURE; } display_width = (float)DisplayWidth(display, DefaultScreen(display)) / 4.0; display_height = (float)DisplayHeight(display, DefaultScreen(display)) / 2.0; dockapp_init(display); new_window("wmix", 64, 64); new_osd(DisplayWidth(display, DefaultScreen(display)) - 200, 60); blit_string("wmix 3.0"); scroll_text(3, 4, 57, true); ui_update(); /* add click regions */ add_region(1, 37, 36, 25, 25); /* knob */ add_region(2, 4, 42, 27, 15); /* balancer */ add_region(3, 2, 26, 7, 10); /* previous channel */ add_region(4, 10, 26, 7, 10); /* next channel */ add_region(5, 39, 14, 20, 7); /* mute toggle */ add_region(6, 4, 14, 13, 7); /* rec toggle */ add_region(10, 3, 4, 56, 7); /* re-scroll current channel name */ /* setup up/down signal handler */ signal(SIGUSR1, (void *) signal_catch); signal(SIGUSR2, (void *) signal_catch); while (true) { if (button_pressed || slider_pressed || (XPending(display) > 0)) { XNextEvent(display, &event); switch (event.type) { case Expose: redraw_window(); break; case ButtonPress: button_press_event(&event.xbutton); idle_loop = 0; break; case ButtonRelease: button_release_event(&event.xbutton); idle_loop = 0; break; case MotionNotify: /* process cursor change, or drag events */ motion_event(&event.xmotion); idle_loop = 0; break; case LeaveNotify: /* go back to standard cursor */ if ((!button_pressed) && (!slider_pressed)) set_cursor(NORMAL_CURSOR); break; case DestroyNotify: XCloseDisplay(display); return EXIT_SUCCESS; default: break; } } else { usleep(100000); scroll_text(3, 4, 57, false); /* rescroll message after some delay */ if (idle_loop++ > 256) { scroll_text(3, 4, 57, true); idle_loop = 0; } /* get rid of OSD after a few seconds of idle */ if ((idle_loop > 15) && osd_mapped() && !button_pressed) { unmap_osd(); idle_loop = 0; } if (mixer_is_changed()) ui_update(); } } return EXIT_SUCCESS; } static void signal_catch(int sig) { switch (sig) { case SIGUSR1: mixer_set_volume_rel(config.scrollstep); if (!osd_mapped()) map_osd(); if (osd_mapped()) update_osd(mixer_get_volume(), false); ui_update(); idle_loop = 0; break; case SIGUSR2: mixer_set_volume_rel(-config.scrollstep); if (!osd_mapped()) map_osd(); if (osd_mapped()) update_osd(mixer_get_volume(), false); ui_update(); idle_loop = 0; break; } } static void button_press_event(XButtonEvent *event) { double button_press_time = get_current_time(); int x = event->x; int y = event->y; bool double_click = false; /* handle wheel scrolling to adjust volume */ if (config.mousewheel) { if (event->button == config.wheel_button_up) { mixer_set_volume_rel(config.scrollstep); if (!osd_mapped()) map_osd(); if (osd_mapped()) update_osd(mixer_get_volume(), false); ui_update(); return; } if (event->button == config.wheel_button_down) { mixer_set_volume_rel(-config.scrollstep); if (!osd_mapped()) map_osd(); if (osd_mapped()) update_osd(mixer_get_volume(), false); ui_update(); return; } } if ((button_press_time - prev_button_press_time) <= 0.5) { double_click = true; prev_button_press_time = 0.0; } else prev_button_press_time = button_press_time; switch (check_region(x, y)) { case 1: /* on knob */ button_pressed = true; slider_pressed = false; mouse_drag_home_x = x; mouse_drag_home_y = y; if (double_click) { mixer_toggle_mute(); ui_update(); } break; case 2: /* on slider */ button_pressed = false; slider_pressed = true; mouse_drag_home_x = x; mouse_drag_home_y = y; if (double_click) { mixer_set_balance(0.0); ui_update(); } break; case 3: /* previous channel */ mixer_set_channel_rel(-1); blit_string(config.scrolltext ? mixer_get_channel_name() : mixer_get_short_name()); scroll_text(3, 4, 57, true); unmap_osd(); map_osd(); ui_update(); break; case 4: /* next channel */ mixer_set_channel_rel(1); blit_string(config.scrolltext ? mixer_get_channel_name() : mixer_get_short_name()); scroll_text(3, 4, 57, true); unmap_osd(); map_osd(); ui_update(); break; case 5: /* toggle mute */ mixer_toggle_mute(); ui_update(); break; case 6: /* toggle rec */ mixer_toggle_rec(); ui_update(); break; case 10: scroll_text(3, 4, 57, true); break; default: printf("unknown region pressed\n"); break; } } static void button_release_event(XButtonEvent *event) { int x = event->x; int y = event->y; int region; region = check_region(x, y); if (region == 1) set_cursor(HAND_CURSOR); button_pressed = false; slider_pressed = false; } static void motion_event(XMotionEvent *event) { int x = event->x; int y = event->y; int region; if ((x == mouse_drag_home_x) && (y == mouse_drag_home_y)) return; region = check_region(x, y); if (button_pressed) { if (y != mouse_drag_home_y) { float delta; set_cursor(NULL_CURSOR); delta = (float)(mouse_drag_home_y - y) / display_height; knob_turn(delta); if (!osd_mapped()) map_osd(); if (osd_mapped()) update_osd(mixer_get_volume(), false); } XWarpPointer(display, None, event->window, x, y, 0, 0, mouse_drag_home_x, mouse_drag_home_y); return; } if (slider_pressed) { if (x != mouse_drag_home_x) { float delta; set_cursor(NULL_CURSOR); delta = (float)(x - mouse_drag_home_x) / display_width; slider_move(delta); } XWarpPointer(display, None, event->window, x, y, 0, 0, mouse_drag_home_x, mouse_drag_home_y); return; } if (region == 1) set_cursor(HAND_CURSOR); else if (region == 2) set_cursor(BAR_CURSOR); else set_cursor(NORMAL_CURSOR); } wmix-3.1/include/0040755000175000001440000000000010050540616013344 5ustar timecopuserswmix-3.1/include/common.h0100644000175000001440000000334707303426465015025 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ typedef unsigned int bool; #define false 0 #define true (!false) #define NULL_CURSOR 1 #define NORMAL_CURSOR 2 #define HAND_CURSOR 3 #define BAR_CURSOR 4 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) #define MAX_DOUBLE_CLICK_TIME 0.5 #define BUTTON_WHEEL_UP 4 #define BUTTON_WHEEL_DOWN 5 typedef struct _Config Config; struct _Config { char *file; /* full path to config file name */ unsigned int osd : 1; /* show OSD? */ unsigned int mousewheel : 1; /* mousewheel enabled? */ unsigned int scrolltext : 1; /* scroll channel names? */ unsigned int wheel_button_up; /* up button */ unsigned int wheel_button_down; /* down button */ float scrollstep; /* scroll mouse step adjustment */ char *osd_color; /* osd color */ }; wmix-3.1/include/led-off.xpm0100644000175000001440000000036607302302076015412 0ustar timecopusers/* XPM */ static char * led_off_xpm[] = { "6 6 9 1", " c None", ". c #494949", "+ c #414141", "@ c #484848", "# c #404040", "$ c #474747", "% c #C0C0C0", "& c #454545", "* c #464646", " .++@ ", ".####$", "+#%##+", "+####+", "$####&", " *++& "}; wmix-3.1/include/led-on.xpm0100644000175000001440000000052007302302076015244 0ustar timecopusers/* XPM */ static char * led_on_xpm[] = { "6 6 15 1", " c None", ". c #7D4141", "+ c #A02F2F", "@ c #9F2E2E", "# c #7A3E3E", "$ c #C81B1B", "% c #F50404", "& c #C71A1A", "* c #783C3C", "= c #FF0000", "- c #9C2B2B", "; c #9B2A2A", "> c #C61919", ", c #763A3A", "' c #793D3D", " .+@# ", ".$%%&*", "+%==%-", "@%==%;", "#&%%>,", " '--, "}; wmix-3.1/include/master.xpm0100644000175000001440000007053507302302076015376 0ustar timecopusers/* XPM */ static char * master_xpm[] = { "255 109 49 1", " c None", ". c #22B2AE", "+ c #202020", "@ c #C5C5C5", "# c #3A3B39", "$ c #2A3029", "% c #01564E", "& c #272A27", "* c #151614", "= c #1D1A1A", "- c #111012", "; c #000000", "> c #341F1E", ", c #4F5051", "' c #004941", ") c #3E4A46", "! c #2A2A29", "~ c #161612", "{ c #121212", "] c #161616", "^ c #121614", "/ c #1A1A1A", "( c #262626", "_ c #3A3632", ": c #37302E", "< c #2C2223", "[ c #241D1E", "} c #262222", "| c #212624", "1 c #222222", "2 c #1E1E1E", "3 c #1E1216", "4 c #121A17", "5 c #1D221F", "6 c #162622", "7 c #31322E", "8 c #1A1618", "9 c #161215", "0 c #2E2E2B", "a c #1E1A1A", "b c #3C3A36", "c c #43433D", "d c #1A1213", "e c #0A1612", "f c #DEDEEF", "g c #8494A5", "h c #027E72", "i c #ADBDC6", "j c #034A40", " ......................++@ ####$### ", " .%%..%%%.%%%...%%.%%%.+@ ##&+++*+++&$ ", " .%.%.%...%....%....%..@ ###$&=*-*=***-+# ", " ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .%%%.%%..%.....%%..%.. #>##&&-*===*****=& ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ .%%..%...%.......%.%.. ##&#&+&-=*-----**-*& ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ .%.%.%%%.%%%..%%%..%.. #&+$+=&=**--=-*--*===$ ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ...................... &++&===*&#,#$===*--*** ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '''''''''''''''''''''' #=*****&),$#$&&#$***-*=+ ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%%''%%%'%%%'''%%'%%%' &***-*&#$&&&=+++=&*-*=-= ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%'%'%'''%''''%''''%''#+-**-=#$+=&++#+&$#&*--**& ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%%%'%%''%'''''%%''%''#*----&&&+&$+&=+##++=*-*-+ ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%%''%'''%'''''''%'%''$*=*-*&=&&=&&&=+$&=&+-**-+ ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%'%'%%%'%%%''%%%''%''$-*-*=&=+=&&=&+&+=+&#=-*-* ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ ''''''''''''''''''''''!~{]^/(_:<[}[<|122111{{{34 ", " ;+.............+++++++++++.........++''''''''''''''''''''++@ .................... !/{]{]252|67_2(11111({]{8/ ", " ;+.%%..%%%.%%%.+++++++++++..%%.%%%.++'%'''%'%''%'%%%'%%%'++@ .%...%.%..%.%%%.%%%. :9]]]{12(210(1211(112]{a^1 ", " ;+.%.%.%...%...+++++++++++.%....%..++'%%'%%'%''%''%''%'''++@ .%%.%%.%..%..%..%... b9]{]^(c_(1121((1111]{{d^a ", " ;+.%%%.%%..%...+++++++++++..%%..%..++'%'%'%'%''%''%''%%''++@ .%.%.%.%..%..%..%%.. /9{{{2b!211112(11(1]{]98 ", " ;+.%%..%...%...+++++++++++....%.%..++'%'''%'%''%''%''%'''++@ .%...%.%..%..%..%... !{]{]{11(!(2111112]{]{{/ ", " ;+.%.%.%%%.%%%.+++++++++++.%%%..%..++'%'''%''%%'''%''%%%'++@ .%...%..%%...%..%%%. /9{]{]/2((1(((11]{{]{{ ", " ;+.............+++++++++++.........++''''''''''''''''''''++@ .................... 0~~{{{{]/((122]]{]]//a ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '''''''''''''''''''' 1]{]]{{{]{{{]{{{]{]/ ", " ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@ '%'''%'%''%'%%%'%%%' 2]{]{{]{{{{{{]{]{/ ", " ;;;;;;;;;;;;;;;;;;+++++++++++++++++++++++++++++++++++...+++@ '%%'%%'%''%''%''%''' 1~/d8^~~^d/99{^/ ", " ;++++++++++++++++++++++++++++++++++.+++.++@ '%'%'%'%''%''%''%%'' 58a9{{9^9e{^ ", " ;++++++++++++++++++++++++++++++++++.+++.++@ '%'''%'%''%''%''%''' 2~^33^^2 ", " ffffffg ffffffg ;++++++++++++++++++++++++++++++++++h+++h++@ '%'''%''%%'''%''%%%' ", " fiiiii; fiiiii; ;++++++++++++++++++++++++++++++++++.+++.++@ '''''''''''''''''''' ", " fiii;i; fi;iii; ;++++++++++++++++++++++++++++++++++.+++.++@ ", " fii;;i; fi;;ii; ;+++++++++++++++++++++++++++++++++++...+++@ ffffffg ffffffg+ffffffg ", " fi;;;i; fi;;;i; ;+++++++++++++++++++++++++++++++++++++++++@ fiiiii; fiiiii;+fiiiii; ", " fi;;;i; fi;;;i; ;+++++++++++++++++++++++++++++++++++++++++@ fiiiii; fiii;i;+fi;iii; ", " fii;;i; fi;;ii; ;+++++++++++++++++++++++@@@@@@@@@@@@@@@@@@@ fii;ii; fii;;i;+fi;;ii; ", " fiii;i; fi;iii; ;+++++++++++++++++++++@@ fii;ii; fi;;;i;+fi;;;i; ", " fiiiii; fiiiii; ;+++++++++++++++++++@@ fii;ii; fi;;;i;+fi;;;i; ", " g;;;;;; g;;;;;; ;++++++++++++++++++@ ####$### fii;ii; fii;;i;+fi;;ii; ", " ;+++++++++++++++++@ ##&+++*+++&$ fii;ii; fiii;i;+fi;iii; ", " ;++++++++++++++++@ ###$&=*-*=***-+# fii;ii; fiiiii;+fiiiii; ", " ;;;;;;;;;;;;;;;;;;+++++++++++++++@ #>##&&-*===*****=& fii;ii; g;;;;;;+g;;;;;; ", " ;++++++++++++++++++++++++++++++++@ ##&#&+&-=*-----**-*& fii;ii; ", " ;+.+++++++++++++++++++++++..++++@ #&+$+=&=**--=-*--*===$ fii;ii; ", " ;+.+++++++++++++++++++++++.+.+++@ &++&===*&#,#$===*--*** fiiiii; ", " ;+.+++++++++++++++++++++++..+++@ #=*****&),$#$&&#$***-*=+ fiiiii; ", " ;+.+++++++++ffffffg+++++++.+.++@ &***-*&#$&&&=+++=&*-*=-= g;;;;;; ", " ;+...+++++++fiiiii;+++++++.+.++@ #+-**-=#$+=&++#+&$#&*--**& ", " ;+++++++++++fiiiii;++++++++++++@ #*----&&&+&$+&=+##++=*-*-+ .+++++++++++++++++++++++..+ ", " ;++.++++++++fii;ii;++++++++.+++@ $*=*-*&=&&=&&&=+$&=&+-**-+ .+++++++++++++++++++++++.+. ", " ;++.+++.++++fii;ii;++++.+++.+++@ $-*-*=&=+=&&=&+&+=+&#=-*-* .+++++++++++++++++++++++..+ ", " ;++.+++.+++.fii;ii;.+++.+++.+++@ !~{]^/(_:<[}[<|122111{{{34 .+++++++++++++++++++++++.+. ", " ;++.+++.+++.fii;ii;.+++.+++.+++@ !/{]{]252|67_2(11111({]{8/ ...+++++++++++++++++++++.+. ", " ;+++++++++++fii;ii;++++++++++++@ :9]]]{12(210(1211(112]{a^1 +++++++++++++++++++++++++++ ", " ;++@@@@@@@@@fii;ii;@@@@@@@@@+++@ b9]{]^(c_(1121((1111]{{d^a +.+++++++++++++++++++++++.+ ", " ;++@++++++++fii;ii;++++++++;+++@ /9{{{2b!211112(11(1]{]98 +.+++.+++++++++++++++.+++.+ ", " ;++@++++++++fii;ii;++++++++;+++@ !{]{]{11(!(2111112]{]{{/ +.+++.+++.+++++++.+++.+++.+ ", " ;++;;;;;;;;;fii;ii;;;;;;;;;;+++@ /9{]{]/2((1(((11]{{]{{ +.+++.+++.+++.+++.+++.+++.+ ", " ;+++++++++++fiiiii;++++++++++++@ 0~~{{{{]/((122]]{]]//a +++++++++++++++++++++++++++ ", " ;+++++++++++fiiiii;++++++++++++@ 1]{]]{{{]{{{]{{{]{]/ +@@@@@@@@@@@@@@@@@@@@@@@@@+ ", " ;+++++++++++g;;;;;;++++++++++++@ 2]{]{{]{{{{{{]{]{/ +@+++++++++++++++++++++++;+ ", " ;++++++++++++++++++++++++++++++@ 1~/d8^~~^d/99{^/ +@+++++++++++++++++++++++;+ ", " ;++++++++++++++++++++++++++++++@ 58a9{{9^9e{^ +;;;;;;;;;;;;;;;;;;;;;;;;;+ ", " @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 2~^33^^2 +++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++ ", " +++++++++++++++++++++++++++ ", " ", " ", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", "++...++++++h+h...h+h...h+h+++h+h...h+h...h+h...h+h...h+h...h++++++++++++++++++++ ", "+.+++.+++++.+++++.+++++.+.+++.+.+++++.+++++++++.+.+++.+.+++.++++++++++++++++++++ ", "+.+++.+++++.+++++.+++++.+.+++.+.+++++.+++++++++.+.+++.+.+++.++++++++++++++++++++ ", "+h+++h+++++h+h...h++...h+h...h+h...h+h...h+++++h+j...j+h...h+h...h++++++++++++++ ", "+.+++.+++++.+.+++++++++.+++++.+++++.+.+++.+++++.+.+++.+++++.++++++++++++++++++++ ", "+.+++.+++++.+.+++++++++.+++++.+++++.+.+++.+++++.+.+++.+++++.+++++++++++++++hh+++ ", "++...++++++.+h...h+h...h+++++h+h...h+h...h+++++h+h...h+h...h+++++++++++++++..+++ ", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", "+j...j+h...++h...h+h...++h...h+h...h+h...h+h+++h+++h+++++++h+h+++h+h+++++.+++.+h...++h...h+h...h+h...h+h...h+h...h+h...h+h+++h+h+++h+h+++h+h+++h+h+++h+h...h++++ ", "+.+++.+.+++.+.+++++.+++.+.+++++.+++++.+++++.+++.+++.+++++++.+.+++.+.+++++..+..+.+++.+.+++.+.+++.+.+++.+.+++.+.+++++++.+++.+++.+.+++.+.+++.+.+++.+.+++.+++++.++++ ", "+.+++.+.+++.+.+++++.+++.+.+++++.+++++.+++++.+++.+++.+++++++.+.++.j+.+++++.+.+.+.+++.+.+++.+.+++.+.+++.+.+++.+.+++++++.+++.+++.+.+++.+.+++.+j.+.j+.+++.++++.j++++ ", "+h...h+h...++h+++++h+++h+h...++h...++hj..h+h...h+++h+++++++h+h..j++h+++++h+++h+h+++h+h+++h+h...h+h.++h+h...++h...h+++h+++h+++h+h+++h+h+++h++j.j++h...h++j.j+++++ ", "+.+++.+.+++.+.+++++.+++.+.+++++.+++++.+++.+.+++.+++.+++++++.+.++.j+.+++++.+++.+.+++.+.+++.+.+++++.+.+.+.+++.+++++.+++.+++.+++.+.+++.+.+.+.+j.+.j+++++.+j.+++++++ ", "+.+++.+.+++.+.+++++.+++.+.+++++.+++++.+++.+.+++.+++.+++++++.+.+++.+.+++++.+++.+.+++.+.+++.+.+++++.++..+.+++.+++++.+++.+++.+++.+.+++.+..+..+.+++.+++++.+.++++++++ ", "+h+++h+h...++h...h+....++h...h+.+++++h...h+h+++h+++.+++h...h+h++jh+h...j+h+++h+.+++.+h...h+h+++++h...h+h+++h+h...h+++h+++j....++...++.+++.+h+++.+h...h+h...h++++ ", "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ", " ", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}; wmix-3.1/include/misc.h0100644000175000001440000000222607303426465014463 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ void lr_to_vb (float left, float right, float *volume, float *balance); void vb_to_lr (float volume, float balance, float *left, float *right); double get_current_time(void); void add_region (int index, int x, int y, int width, int height); int check_region (int x, int y); void config_read (void); wmix-3.1/include/mixer.h0100644000175000001440000000701610050540615014641 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ /* WMVolume mixer interface * * Some notes: * * - The volume argument is a floating-point value between 0 (no sound) and * 1 (full sound) inclusively. * * - The balance argument is a floating-point value betwen -1 (full left) * and 1 (full right) inclusively. A value of 0 indicates centered sound. * If the device does not natively support a balance parameter, use the * lr_to_vb() and vb_to_lr() functions in misc.c. * * - The volume and balance arguments passed to these functions, given that * they are (usually 32-bit) floating-point values, may be capable of * specifying the audio parameters at a finer resolution than the * hardware itself. However, the mixer driver must not quantize the * volume and balance levels returned by the mixer_get_*() routines. * * Example: Suppose the mixer device supports specifying the volume as an * integer in the range of 0 to 100. If mixer_set_volume() is called with * an argument of 0.7351, then the device will be set to a volume of 74, * yet subsequent calls to mixer_get_volume() (assuming mixer state has * not changed since) will return 0.7351. Only if the mixer state is * changed by another program (that, say, sets the volume to 51) is the * value returned by this interface quantized (in such a case returning * 0.51). * * The reason why this quantization must be avoided whenever possible is * that otherwise, a large number of minuscule increases to the volume * level will have no cumulative effect. Calling mixer_set_volume_rel() * ten thousand times with an argument of 0.0001 should successfully * increase the volume to its maximum, even if the device actually * supports only 64 discrete volume levels. * * - Muting must occur independently of the volume level. */ void mixer_init (const char *mixer_device, bool verbose, const char *exclude[]); bool mixer_is_changed (void); int mixer_get_channel_count (void); int mixer_get_channel (void); const char * mixer_get_channel_name (void); const char * mixer_get_short_name (void); void mixer_set_channel (int channel); void mixer_set_channel_rel (int delta_channel); float mixer_get_volume (void); void mixer_set_volume (float volume); void mixer_set_volume_rel (float delta_volume); float mixer_get_balance (void); void mixer_set_balance (float balance); void mixer_set_balance_rel (float delta_balance); void mixer_toggle_mute (void); void mixer_toggle_rec (void); bool mixer_is_muted (void); bool mixer_is_stereo (void); bool mixer_is_rec (void); bool mixer_can_rec (void); bool is_exclude (const char *short_name, const char *exclude[]); wmix-3.1/include/ui_x.h0100644000175000001440000000262007303426465014472 0ustar timecopusers/* WMix 3.0 -- a mixer using the OSS mixer API. * Copyright (C) 2000, 2001 * Daniel Richard G. , * timecop * * 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. */ void dockapp_init (Display *x_display); void new_window (char *name, int width, int height); void new_osd (int width, int height); void update_osd (float volume, bool up); void map_osd (void); void unmap_osd (void); bool osd_mapped (void); void ui_update (void); void redraw_window (void); int blit_string (const char *text); void scroll_text (int x, int y, int width, bool reset); void set_cursor (int type); void knob_turn (float delta); void slider_move (float delta); unsigned long get_color (Display *display, char *color_name); wmix-3.1/wmix.1x.gz0100644000175000001440000000111007303436005013567 0ustar timecopusersm:wmix.1x}SMo@+F>k( jb[DJk`b7%= y09+g+lA;G$e&}\aIbKS@6YHt~nǧ_E.fmQ~SF) B"7r}ݯwz۝A*9{i 8,Ε8MTbVJDq e˵FOFv \rM2Iiej }>B\̤8"]|hŬJS%#et-$(;P!JP+L@za=e+jhq Ò'!MxFC4NZh1ImoR6XN;0)R!KӸl佬eW"2 :H7P[? dqwsrsk7n_kEi8$o)Td>=a {hޖ7gDH§≯s -DpVQnw9 BM! B[n 4$4t