mirror of
https://github.com/gryf/wmamixer.git
synced 2025-12-17 11:30:21 +01:00
Implemeneted read functions
This commit is contained in:
777
wmamixer.c
777
wmamixer.c
@@ -11,7 +11,7 @@
|
||||
#include "wmamixer.h"
|
||||
|
||||
// global mixer struct
|
||||
struct Mixer *mixer_ctrl;
|
||||
struct Mixer *mix;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int i;
|
||||
@@ -32,24 +32,6 @@ int main(int argc, char **argv) {
|
||||
scanArgs(argc, argv);
|
||||
initXWin(argc, argv);
|
||||
|
||||
xpmattr.numsymbols = 4;
|
||||
xpmattr.colorsymbols = xpmcsym;
|
||||
xpmattr.exactColors = false;
|
||||
xpmattr.closeness = 40000;
|
||||
xpmattr.valuemask = XpmColorSymbols | XpmExactColors | XpmCloseness;
|
||||
XpmCreatePixmapFromData(d_display, w_root, wmsmixer_xpm, &pm_main,
|
||||
&pm_mask, &xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, tile_xpm, &pm_tile, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, icons_xpm, &pm_icon, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, digits_xpm, &pm_digits, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, chars_xpm, &pm_chars, NULL,
|
||||
&xpmattr);
|
||||
pm_disp = XCreatePixmap(d_display, w_root, 64, 64, DefaultDepth(d_display,
|
||||
DefaultScreen(d_display)));
|
||||
|
||||
gcm = GCGraphicsExposures;
|
||||
gcv.graphics_exposures = false;
|
||||
gc_gc = XCreateGC(d_display, w_root, gcm, &gcv);
|
||||
@@ -59,6 +41,24 @@ int main(int argc, char **argv) {
|
||||
color[2] = mixColor(ledcolor, 60, backcolor, 40);
|
||||
color[3] = mixColor(ledcolor, 25, backcolor, 75);
|
||||
|
||||
xpmattr.numsymbols = 4;
|
||||
xpmattr.colorsymbols = xpmcsym;
|
||||
xpmattr.exactColors = false;
|
||||
xpmattr.closeness = 40000;
|
||||
xpmattr.valuemask = XpmColorSymbols | XpmExactColors | XpmCloseness;
|
||||
XpmCreatePixmapFromData(d_display, w_root, wmsmixer_xpm, &pm_main,
|
||||
&pm_mask, &xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, tile_xpm, &pm_tile, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, icons_xpm, &pm_icon, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, digits_xpm, &pm_digits, NULL,
|
||||
&xpmattr);
|
||||
XpmCreatePixmapFromData(d_display, w_root, chars_xpm, &pm_chars, NULL,
|
||||
&xpmattr);
|
||||
pm_disp = XCreatePixmap(d_display, w_root, 64, 64, DefaultDepth(d_display,
|
||||
DefaultScreen(d_display)));
|
||||
|
||||
if (wmaker || ushape || astep) {
|
||||
XShapeCombineMask(d_display, w_activewin, ShapeBounding, winsize/2-32,
|
||||
winsize/2-32, pm_mask, ShapeSet);
|
||||
@@ -70,26 +70,12 @@ int main(int argc, char **argv) {
|
||||
XCopyArea(d_display, pm_main, pm_disp, gc_gc, 0, 0, 64, 64, 0, 0);
|
||||
XSetClipMask(d_display, gc_gc, None);
|
||||
|
||||
mixer_ctrl = Mixer_create(mixer_device);
|
||||
|
||||
if (mixer_ctrl->openOK != 0) {
|
||||
fprintf(stderr, "%s : Unable to open mixer device '%s'.\n", NAME,
|
||||
mixer_device);
|
||||
} else {
|
||||
for (i=0; i <mixer_ctrl->devices_no; i++) {
|
||||
if (i > 24) {
|
||||
fprintf(stderr,"%s : Sorry, can only use channels 0-24\n", NAME);
|
||||
break;
|
||||
}
|
||||
channel[channels] = i;
|
||||
channels++;
|
||||
}
|
||||
}
|
||||
mix = Mixer_create(card);
|
||||
|
||||
readFile();
|
||||
|
||||
if (channels==0)
|
||||
fprintf(stderr,"%s : Sorry, no supported channels found.\n", NAME);
|
||||
if (mix->devices_no == 0)
|
||||
fprintf(stderr,"%s: Sorry, no supported channels found.\n", NAME);
|
||||
else {
|
||||
checkVol(true);
|
||||
|
||||
@@ -129,8 +115,8 @@ int main(int argc, char **argv) {
|
||||
else
|
||||
curchannel--;
|
||||
if (curchannel < 0)
|
||||
curchannel = channels - 1;
|
||||
if (curchannel >= channels)
|
||||
curchannel = mix->devices_no - 1;
|
||||
if (curchannel >= mix->devices_no)
|
||||
curchannel = 0;
|
||||
checkVol(true);
|
||||
rpttimer = 0;
|
||||
@@ -145,7 +131,7 @@ int main(int argc, char **argv) {
|
||||
drawVolLevel();
|
||||
repaint();
|
||||
}
|
||||
// printf("%c", text_counter);
|
||||
// printf("%c", text_counter);
|
||||
}
|
||||
|
||||
XFlush(d_display);
|
||||
@@ -163,19 +149,290 @@ int main(int argc, char **argv) {
|
||||
XFreePixmap(d_display, pm_digits);
|
||||
XFreePixmap(d_display, pm_chars);
|
||||
freeXWin();
|
||||
Mixer_destroy(mixer_ctrl);
|
||||
Mixer_destroy(mix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Mixer struct support functions */
|
||||
struct Mixer *Mixer_create(char *device) {
|
||||
struct Mixer *mixer_ctrl = malloc(sizeof(struct Mixer));
|
||||
assert(mixer_ctrl != NULL);
|
||||
mixer_ctrl->openOK = 0;
|
||||
mixer_ctrl->devices_no = 0;
|
||||
mixer_ctrl->devices_no = 0;
|
||||
return mixer_ctrl;
|
||||
struct Mixer *Mixer_create(char *devicename) {
|
||||
struct Mixer *mixer = malloc(sizeof(struct Mixer));
|
||||
int err;
|
||||
const char *name;
|
||||
slideCaptureMono capabilities;
|
||||
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *elem;
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
|
||||
assert(mixer != NULL);
|
||||
mixer->devices_no = 0;
|
||||
|
||||
if ((err = snd_mixer_open(&mixer->handle, 0)) < 0) {
|
||||
fprintf(stderr, "Mixer %s open error: %s", card, snd_strerror(err));
|
||||
exit(err);
|
||||
}
|
||||
|
||||
if (smixer_level == 0 &&
|
||||
(err = snd_mixer_attach(mixer->handle, card)) < 0) {
|
||||
fprintf(stderr, "Mixer attach %s error: %s", card, snd_strerror(err));
|
||||
snd_mixer_close(mixer->handle);
|
||||
exit(err);
|
||||
}
|
||||
|
||||
if ((err = snd_mixer_selem_register(mixer->handle,
|
||||
smixer_level > 0 ? &smixer_options : NULL, NULL)) < 0) {
|
||||
fprintf(stderr, "Mixer register error: %s", snd_strerror(err));
|
||||
snd_mixer_close(mixer->handle);
|
||||
exit(err);
|
||||
}
|
||||
|
||||
err = snd_mixer_load(mixer->handle);
|
||||
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Mixer %s load error: %s", card, snd_strerror(err));
|
||||
snd_mixer_close(mixer->handle);
|
||||
exit(err);
|
||||
}
|
||||
for (elem = snd_mixer_first_elem(mixer->handle); elem;
|
||||
elem = snd_mixer_elem_next(elem)) {
|
||||
snd_mixer_selem_get_id(elem, sid);
|
||||
|
||||
if (!snd_mixer_selem_is_active(elem))
|
||||
continue;
|
||||
|
||||
capabilities = Mixer_getcapabilities(elem);
|
||||
|
||||
if (!capabilities.isvolume)
|
||||
continue;
|
||||
name = snd_mixer_selem_id_get_name(sid);
|
||||
printf("DEBUG: capabilities cap: %d\n", capabilities.capture);
|
||||
selems[mixer->devices_no] = malloc(sizeof(struct Selem));
|
||||
selems[mixer->devices_no]->elem = elem;
|
||||
selems[mixer->devices_no]->capture = capabilities.capture;
|
||||
Mixer_set_limits(elem, selems[mixer->devices_no]);
|
||||
Mixer_set_selem_props(selems[mixer->devices_no], name);
|
||||
mixer->devices_no++;
|
||||
printf("DEBUG: Simple mixer control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
|
||||
if (mixer->devices_no == 32) {
|
||||
// stop here. This is ridiculous anyway
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mixer;
|
||||
}
|
||||
|
||||
/* Guess and return short name for the mixer simple element */
|
||||
void Mixer_set_selem_props(struct Selem *selem, const char *name) {
|
||||
const char *pcm = "PCM",
|
||||
*mic = "Mic",
|
||||
*cap = "Capture",
|
||||
*boost = "Boost",
|
||||
*line = "Line";
|
||||
|
||||
snd_mixer_selem_channel_id_t chn;
|
||||
char variable[4];
|
||||
int idx;
|
||||
|
||||
// Get the name. Simple match.
|
||||
if (strcmp("Master", name) == 0) {
|
||||
selem->name = "mstr";
|
||||
} else if (strstr(pcm, name)) {
|
||||
selem->iconIndex = 1;
|
||||
if (strcmp(pcm, name) == 0) {
|
||||
selem->name = "pcm ";
|
||||
} else {
|
||||
sprintf(variable, "pcm%d", namesCount.pcm);
|
||||
selem->name = variable;
|
||||
namesCount.pcm++;
|
||||
}
|
||||
} else if (strstr("Headphone", name)) {
|
||||
selem->name = "hdph";
|
||||
selem->iconIndex = 8;
|
||||
} else if (strstr("Beep", name)) {
|
||||
selem->name = "beep";
|
||||
selem->iconIndex = 7;
|
||||
} else if (strstr("Digital", name)) {
|
||||
selem->iconIndex = selem->capture ? 3 : 6;
|
||||
selem->name = "digt";
|
||||
} else if (strstr(mic, name)) {
|
||||
if (strcmp(mic, name) == 0) {
|
||||
selem->name = "mic ";
|
||||
} else {
|
||||
if (strstr(boost, name)) {
|
||||
sprintf(variable, "mib%d", namesCount.micb);
|
||||
namesCount.micb++;
|
||||
} else {
|
||||
sprintf(variable, "mib%d", namesCount.mic);
|
||||
namesCount.mic++;
|
||||
}
|
||||
selem->name = variable;
|
||||
}
|
||||
selem->iconIndex = 4;
|
||||
} else if (strstr(line, name)) {
|
||||
if (strcmp(line, name) == 0) {
|
||||
selem->name = "line";
|
||||
} else {
|
||||
if (strstr(boost, name)) {
|
||||
sprintf(variable, "lnb%d", namesCount.lineb);
|
||||
namesCount.lineb++;
|
||||
} else {
|
||||
sprintf(variable, "lin%d", namesCount.line);
|
||||
namesCount.line++;
|
||||
}
|
||||
selem->name = variable;
|
||||
}
|
||||
selem->iconIndex = 5;
|
||||
} else if (strstr(cap, name)) {
|
||||
if (strcmp(cap, name) == 0) {
|
||||
selem->name = "cap ";
|
||||
} else {
|
||||
sprintf(variable, "cap%d", namesCount.capt);
|
||||
selem->name = variable;
|
||||
namesCount.capt++;
|
||||
}
|
||||
selem->iconIndex = 3;
|
||||
} else {
|
||||
/* defaults */
|
||||
sprintf(variable, "vol%d", namesCount.vol);
|
||||
selem->name = variable;
|
||||
namesCount.pcm++;
|
||||
selem->iconIndex = 6;
|
||||
}
|
||||
|
||||
|
||||
if (snd_mixer_selem_has_playback_volume(selem->elem)) {
|
||||
if (snd_mixer_selem_is_playback_mono(selem->elem)) {
|
||||
printf("DEBUG: playback mono\n");
|
||||
selem->stereo = false;
|
||||
selem->channels[0] = SND_MIXER_SCHN_MONO;
|
||||
selem->channels[1] = SND_MIXER_SCHN_MONO;
|
||||
} else {
|
||||
printf("DEBUG: playback stereo\n");
|
||||
idx = 0;
|
||||
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++){
|
||||
if (!snd_mixer_selem_has_playback_channel(selem->elem, chn))
|
||||
continue;
|
||||
selem->channels[idx] = chn;
|
||||
idx++;
|
||||
if (idx == 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_capture_volume(selem->elem)) {
|
||||
printf("Capture channels: ");
|
||||
if (snd_mixer_selem_is_capture_mono(selem->elem)) {
|
||||
printf("DEBUG: playback mono\n");
|
||||
selem->stereo = false;
|
||||
selem->channels[0] = SND_MIXER_SCHN_MONO;
|
||||
selem->channels[1] = SND_MIXER_SCHN_MONO;
|
||||
} else {
|
||||
idx = 0;
|
||||
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++){
|
||||
if (!snd_mixer_selem_has_capture_channel(selem->elem, chn))
|
||||
continue;
|
||||
selem->channels[idx] = chn;
|
||||
idx++;
|
||||
if (idx == 2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slideCaptureMono Mixer_getcapabilities(snd_mixer_elem_t *elem) {
|
||||
slideCaptureMono retval;
|
||||
retval.mono = false;
|
||||
retval.capture = false;
|
||||
retval.isvolume = false;
|
||||
|
||||
if (snd_mixer_selem_has_common_volume(elem)) {
|
||||
retval.isvolume = true;
|
||||
|
||||
if (snd_mixer_selem_has_playback_volume_joined(elem) ||
|
||||
snd_mixer_selem_is_playback_mono(elem) )
|
||||
retval.mono = true;
|
||||
} else {
|
||||
|
||||
if (snd_mixer_selem_has_playback_volume(elem)) {
|
||||
retval.isvolume = true;
|
||||
if (snd_mixer_selem_has_playback_volume_joined(elem) ||
|
||||
snd_mixer_selem_is_playback_mono(elem))
|
||||
retval.mono = true;
|
||||
}
|
||||
|
||||
if (snd_mixer_selem_has_capture_volume(elem)) {
|
||||
retval.isvolume = true;
|
||||
retval.capture = true;
|
||||
if (snd_mixer_selem_has_capture_volume_joined(elem) ||
|
||||
snd_mixer_selem_is_playback_mono(elem))
|
||||
retval.mono = true;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Mixer_set_limits(snd_mixer_elem_t *elem, struct Selem *selem) {
|
||||
long min = 0, max = 0;
|
||||
|
||||
if (snd_mixer_selem_has_common_volume(elem)) {
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
||||
} else {
|
||||
if (snd_mixer_selem_has_capture_volume(elem))
|
||||
snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
|
||||
if (snd_mixer_selem_has_playback_volume(elem))
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
||||
}
|
||||
|
||||
selem->min = min;
|
||||
selem->max = max;
|
||||
}
|
||||
|
||||
static int convert_prange(long val, long min, long max) {
|
||||
long range = max - min;
|
||||
int tmp;
|
||||
|
||||
if (range == 0)
|
||||
return 0;
|
||||
|
||||
val -= min;
|
||||
tmp = rint((double)val/(double)range * 100);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
vol_ops = [
|
||||
{"has_volume": snd_mixer_selem_has_playback_volume,
|
||||
"v": [
|
||||
[snd_mixer_selem_get_playback_volume_range,
|
||||
snd_mixer_selem_get_playback_volume,
|
||||
set_playback_raw_volume],
|
||||
[snd_mixer_selem_get_playback_dB_range,
|
||||
snd_mixer_selem_get_playback_dB,
|
||||
set_playback_dB],
|
||||
[get_mapped_volume_range,
|
||||
get_playback_mapped_volume,
|
||||
set_playback_mapped_volume]]
|
||||
},
|
||||
// capt
|
||||
{...}
|
||||
]
|
||||
*/
|
||||
|
||||
long get_volume(snd_mixer_elem_t *elem,
|
||||
snd_mixer_selem_channel_id_t chn,
|
||||
long min, long max, bool capt) {
|
||||
long raw;
|
||||
int volume;
|
||||
|
||||
if (!capt) {
|
||||
snd_mixer_selem_get_playback_volume(elem, chn, &raw);
|
||||
} else {
|
||||
snd_mixer_selem_get_capture_volume(elem, chn, &raw);
|
||||
}
|
||||
volume = convert_prange(raw, min, max);
|
||||
return volume;
|
||||
}
|
||||
|
||||
void Mixer_set_left(int current, int value) {
|
||||
@@ -188,25 +445,25 @@ void Mixer_write_volume(int current) {
|
||||
}
|
||||
|
||||
int Mixer_read_left(int current) {
|
||||
return 50;
|
||||
struct Selem *selem = selems[current];
|
||||
return get_volume(selem->elem, selem->channels[0],
|
||||
selem->min, selem->max, selem->capture);
|
||||
}
|
||||
|
||||
int Mixer_read_right(int current) {
|
||||
struct Selem *selem = selems[current];
|
||||
return get_volume(selem->elem, selem->channels[1],
|
||||
selem->min, selem->max, selem->capture);
|
||||
}
|
||||
|
||||
int Mixer_read_volume(int current, bool read) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
int Mixer_read_volume(int channel, bool read) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
bool Mixer_get_stereo(int channel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mixer_destroy(struct Mixer *mix) {
|
||||
assert(mix != NULL);
|
||||
//free(mix->name);
|
||||
free(mix);
|
||||
void Mixer_destroy(struct Mixer *mixer) {
|
||||
assert(mixer != NULL);
|
||||
snd_mixer_close(mixer->handle);
|
||||
free(mixer);
|
||||
}
|
||||
|
||||
void initXWin(int argc, char **argv)
|
||||
@@ -214,7 +471,7 @@ void initXWin(int argc, char **argv)
|
||||
winsize=astep ? ASTEPSIZE : NORMSIZE;
|
||||
|
||||
if ((d_display=XOpenDisplay(display))==NULL ) {
|
||||
fprintf(stderr,"%s : Unable to open X display '%s'.\n", NAME, XDisplayName(display));
|
||||
fprintf(stderr,"%s: Unable to open X display '%s'.\n", NAME, XDisplayName(display));
|
||||
exit(1);
|
||||
}
|
||||
_XA_GNUSTEP_WM_FUNC=XInternAtom(d_display, "_GNUSTEP_WM_FUNCTION", false);
|
||||
@@ -228,7 +485,7 @@ void initXWin(int argc, char **argv)
|
||||
shints.y=0;
|
||||
shints.flags=0;
|
||||
bool pos=(XWMGeometry(d_display, DefaultScreen(d_display), position, NULL, 0, &shints, &shints.x, &shints.y,
|
||||
&shints.width, &shints.height, &shints.win_gravity) & (XValue | YValue));
|
||||
&shints.width, &shints.height, &shints.win_gravity) & (XValue | YValue));
|
||||
shints.min_width=winsize;
|
||||
shints.min_height=winsize;
|
||||
shints.max_width=winsize;
|
||||
@@ -279,18 +536,6 @@ void createWin(Window *win, int x, int y)
|
||||
XSetClassHint(d_display, *win, &classHint);
|
||||
}
|
||||
|
||||
unsigned long getColor(char *colorname)
|
||||
{
|
||||
XColor color;
|
||||
XWindowAttributes winattr;
|
||||
XGetWindowAttributes(d_display, w_root, &winattr);
|
||||
color.pixel=0;
|
||||
XParseColor(d_display, winattr.colormap, colorname, &color);
|
||||
color.flags=DoRed | DoGreen | DoBlue;
|
||||
XAllocColor(d_display, winattr.colormap, &color);
|
||||
return color.pixel;
|
||||
}
|
||||
|
||||
unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2)
|
||||
{
|
||||
XColor color, color1, color2;
|
||||
@@ -309,67 +554,97 @@ unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2)
|
||||
|
||||
void scanArgs(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
|
||||
usage();
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
if (strcmp(argv[i], "-v")==0 || strcmp(argv[i], "--version")==0) {
|
||||
fprintf(stderr, "wmsmixer version %s\n", VERSION);
|
||||
exit(0);
|
||||
|
||||
if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
|
||||
fprintf(stderr, "%s version %s\n", NAME, VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-w") == 0)
|
||||
wmaker = !wmaker;
|
||||
|
||||
if (strcmp(argv[i], "-s") == 0)
|
||||
ushape = !ushape;
|
||||
|
||||
if (strcmp(argv[i], "-a") == 0)
|
||||
astep = !astep;
|
||||
|
||||
if (strcmp(argv[i], "-novol") == 0)
|
||||
no_volume_display = 1;
|
||||
|
||||
if (strcmp(argv[i], "-d") == 0) {
|
||||
if (i < argc - 1) {
|
||||
i++;
|
||||
if (strlen(argv[i]) > 255) {
|
||||
fprintf(stderr, "%s: Illegal device name.\n", NAME);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(card, "%s", argv[i]);
|
||||
smixer_options.device = card;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-l") == 0) {
|
||||
if ( i < argc - 1) {
|
||||
i++;
|
||||
if (strlen(argv[i]) > 255) {
|
||||
fprintf(stderr, "%s: Illegal color name.\n", NAME);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(ledcolor, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-b") == 0) {
|
||||
if (i < argc - 1) {
|
||||
i++;
|
||||
if (strlen(argv[i]) > 255) {
|
||||
fprintf(stderr, "%s: Illegal color name.\n", NAME);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(backcolor, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-position") == 0) {
|
||||
if (i < argc - 1) {
|
||||
i++;
|
||||
if (strlen(argv[i]) > 255) {
|
||||
fprintf(stderr, "%s: Illegal position.\n", NAME);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(position, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "-display") == 0) {
|
||||
if (i < argc - 1) {
|
||||
i++;
|
||||
if (strlen(argv[i]) > 255) {
|
||||
fprintf(stderr, "%s: Illegal display name.\n", NAME);
|
||||
exit(1);
|
||||
}
|
||||
sprintf(display, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (strcmp(argv[i], "-w")==0)
|
||||
wmaker=!wmaker;
|
||||
if (strcmp(argv[i], "-s")==0)
|
||||
ushape=!ushape;
|
||||
if (strcmp(argv[i], "-a")==0)
|
||||
astep=!astep;
|
||||
if (strcmp(argv[i], "-novol")==0)
|
||||
no_volume_display = 1;
|
||||
if (strcmp(argv[i], "-d")==0 ) {
|
||||
if (i<argc-1 ) {
|
||||
i++;
|
||||
sprintf(mixer_device, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "-l")==0 ) {
|
||||
if (i<argc-1 ) {
|
||||
i++;
|
||||
sprintf(ledcolor, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "-b")==0 ) {
|
||||
if (i<argc-1 ) {
|
||||
i++;
|
||||
sprintf(backcolor, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "-position")==0 ) {
|
||||
if (i<argc-1 ) {
|
||||
i++;
|
||||
sprintf(position, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strcmp(argv[i], "-display")==0 ) {
|
||||
if (i<argc-1 ) {
|
||||
i++;
|
||||
sprintf(display, "%s", argv[i]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void readFile() {
|
||||
FILE *rcfile;
|
||||
char buf[256];
|
||||
int done;
|
||||
int current=-1;
|
||||
char *confpath;
|
||||
int done, current = -1;
|
||||
char *confpath, buf[256];
|
||||
|
||||
if (getenv("XDG_CONFIG_HOME")) {
|
||||
confpath = malloc(snprintf(NULL, 0, "%s%s", getenv("XDG_CONFIG_HOME"),
|
||||
@@ -382,59 +657,35 @@ void readFile() {
|
||||
}
|
||||
|
||||
if(access(confpath, 0) != 0) {
|
||||
printf("no conf file\n");
|
||||
fprintf(stderr, "%s: No config file found.\n", NAME);
|
||||
free(confpath);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rcfile = fopen(confpath, "r")) == NULL) {
|
||||
printf("cannot open conf file\n");
|
||||
fprintf(stderr, "%s: Cannot open config file. Using defaults.\n",
|
||||
NAME);
|
||||
free(confpath);
|
||||
return;
|
||||
}
|
||||
|
||||
channels=0;
|
||||
do {
|
||||
fgets(buf, 250, rcfile);
|
||||
if ((done=feof(rcfile)) == 0) {
|
||||
buf[strlen(buf) - 1] = 0;
|
||||
|
||||
if (strncmp(buf, "addchannel ", strlen("addchannel ")) == 0) {
|
||||
sscanf(buf, "addchannel %i", ¤t);
|
||||
if (current >= mixer_ctrl->devices_no ) {
|
||||
fprintf(stderr, "%s : Sorry, this channel (%i) is "
|
||||
"not supported.\n", NAME, current);
|
||||
current = -1;
|
||||
}
|
||||
else{
|
||||
channel[channels]=current;
|
||||
channels++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(buf, "setchannel ", strlen("setchannel ")) == 0) {
|
||||
sscanf(buf, "setchannel %i", ¤t);
|
||||
if (current >= mixer_ctrl->devices_no ) {
|
||||
fprintf(stderr,"%s : Sorry, this channel (%i) is "
|
||||
if (current >= mix->devices_no ) {
|
||||
fprintf(stderr,"%s: Sorry, this channel (%i) is "
|
||||
"not supported.\n", NAME, current);
|
||||
current = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(buf, "setname ", strlen("setname ")) == 0) {
|
||||
if (current == -1) {
|
||||
fprintf(stderr, "%s : Sorry, no current channel.\n",
|
||||
NAME);
|
||||
} else {
|
||||
small_labels[current] = (char *) malloc(sizeof(char) *
|
||||
5);
|
||||
sscanf(buf, "setname %4s", small_labels[current]);
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(buf, "setmono ", strlen("setmono ")) == 0) {
|
||||
if (current == -1) {
|
||||
fprintf(stderr,"%s : Sorry, no current channel.\n",
|
||||
fprintf(stderr,"%s: Sorry, no current channel.\n",
|
||||
NAME);
|
||||
} else {
|
||||
int value;
|
||||
@@ -447,7 +698,7 @@ void readFile() {
|
||||
|
||||
if (strncmp(buf, "setleft ", strlen("setleft ")) == 0 ) {
|
||||
if (current == -1) {
|
||||
fprintf(stderr, "%s : Sorry, no current channel.\n",
|
||||
fprintf(stderr, "%s: Sorry, no current channel.\n",
|
||||
NAME);
|
||||
} else {
|
||||
int value;
|
||||
@@ -459,7 +710,7 @@ void readFile() {
|
||||
|
||||
if (strncmp(buf, "setright ", strlen("setright ")) == 0 ) {
|
||||
if (current == -1) {
|
||||
fprintf(stderr, "%s : Sorry, no current channel.\n",
|
||||
fprintf(stderr, "%s: Sorry, no current channel.\n",
|
||||
NAME);
|
||||
} else{
|
||||
int value;
|
||||
@@ -475,9 +726,9 @@ void readFile() {
|
||||
}
|
||||
|
||||
void checkVol(bool forced) {
|
||||
Mixer_read_volume(channel[curchannel], true);
|
||||
int nl = Mixer_read_left(channel[curchannel]);
|
||||
int nr = Mixer_read_right(channel[curchannel]);
|
||||
Mixer_read_volume(curchannel, true);
|
||||
int nl = Mixer_read_left(curchannel);
|
||||
int nr = Mixer_read_right(curchannel);
|
||||
if (forced ) {
|
||||
curleft=nl;
|
||||
curright=nr;
|
||||
@@ -487,81 +738,85 @@ void checkVol(bool forced) {
|
||||
else{
|
||||
if (nl!=curleft || nr!=curright ) {
|
||||
if (nl!=curleft ) {
|
||||
curleft=nl;
|
||||
if (Mixer_get_stereo(channel[curchannel]))
|
||||
drawLeft();
|
||||
else
|
||||
drawMono();
|
||||
curleft=nl;
|
||||
if (selems[curchannel]->stereo)
|
||||
drawLeft();
|
||||
else
|
||||
drawMono();
|
||||
}
|
||||
if (nr!=curright ) {
|
||||
curright=nr;
|
||||
if (Mixer_get_stereo(channel[curchannel]))
|
||||
drawRight();
|
||||
else
|
||||
drawMono();
|
||||
curright=nr;
|
||||
if (selems[curchannel]->stereo)
|
||||
drawRight();
|
||||
else
|
||||
drawMono();
|
||||
}
|
||||
if (!no_volume_display)
|
||||
drawVolLevel();
|
||||
drawVolLevel();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pressEvent(XButtonEvent *xev)
|
||||
{
|
||||
if (xev->button == Button4 || xev->button == Button5) {
|
||||
int inc;
|
||||
if (xev->button == Button4) inc = 4;
|
||||
else inc = -4;
|
||||
void pressEvent(XButtonEvent *xev) {
|
||||
int inc, x, y, v;
|
||||
|
||||
Mixer_read_volume(channel[curchannel], false);
|
||||
Mixer_set_left(channel[curchannel],
|
||||
CLAMP(Mixer_read_left(channel[curchannel]) + inc, 0, 100));
|
||||
Mixer_set_right(channel[curchannel],
|
||||
CLAMP(Mixer_read_right(channel[curchannel]) + inc, 0, 100));
|
||||
Mixer_write_volume(channel[curchannel]);
|
||||
checkVol(false);
|
||||
return;
|
||||
}
|
||||
if (xev->button == Button4 || xev->button == Button5) {
|
||||
if (xev->button == Button4) {
|
||||
printf("inc\n");
|
||||
inc = 4;
|
||||
} else {
|
||||
printf("dec\n");
|
||||
inc = -4;
|
||||
}
|
||||
|
||||
int x=xev->x-(winsize/2-32);
|
||||
int y=xev->y-(winsize/2-32);
|
||||
if (x>=5 && y>=47 && x<=17 && y<=57 ) {
|
||||
curchannel--;
|
||||
if (curchannel<0)
|
||||
curchannel=channels-1;
|
||||
btnstate |= BTNPREV;
|
||||
rpttimer=0;
|
||||
drawBtns(BTNPREV);
|
||||
checkVol(true);
|
||||
return;
|
||||
}
|
||||
if (x>=18 && y>=47 && x<=30 && y<=57 ) {
|
||||
curchannel++;
|
||||
if (curchannel>=channels)
|
||||
curchannel=0;
|
||||
btnstate|=BTNNEXT;
|
||||
rpttimer=0;
|
||||
drawBtns(BTNNEXT);
|
||||
checkVol(true);
|
||||
return;
|
||||
}
|
||||
if (x>=37 && x<=56 && y>=8 && y<=56 ) {
|
||||
int v=((60-y)*100)/(2*25);
|
||||
dragging=true;
|
||||
if (x<=50)
|
||||
Mixer_set_left(channel[curchannel], v);
|
||||
if (x>=45)
|
||||
Mixer_set_right(channel[curchannel], v);
|
||||
Mixer_write_volume(channel[curchannel]);
|
||||
checkVol(false);
|
||||
return;
|
||||
}
|
||||
if (x>=5 && y>=21 && x<=30 && y<=42) {
|
||||
drawText(small_labels[channel[curchannel]]);
|
||||
return;
|
||||
}
|
||||
Mixer_read_volume(curchannel, false);
|
||||
Mixer_set_left(curchannel,
|
||||
CLAMP(Mixer_read_left(curchannel) + inc, 0, 100));
|
||||
Mixer_set_right(curchannel,
|
||||
CLAMP(Mixer_read_right(curchannel) + inc, 0, 100));
|
||||
Mixer_write_volume(curchannel);
|
||||
checkVol(false);
|
||||
return;
|
||||
}
|
||||
|
||||
x = xev->x - (winsize / 2 - 32);
|
||||
y = xev->y - (winsize / 2 - 32);
|
||||
if (x >= 5 && y >= 47 && x <= 17 && y <= 57) {
|
||||
curchannel--;
|
||||
if (curchannel < 0)
|
||||
curchannel = mix->devices_no -1;
|
||||
btnstate |= BTNPREV;
|
||||
rpttimer = 0;
|
||||
drawBtns(BTNPREV);
|
||||
checkVol(true);
|
||||
return;
|
||||
}
|
||||
if (x >= 18 && y >= 47 && x <= 30 && y <= 57) {
|
||||
curchannel++;
|
||||
if (curchannel >= mix->devices_no)
|
||||
curchannel = 0;
|
||||
btnstate|=BTNNEXT;
|
||||
rpttimer = 0;
|
||||
drawBtns(BTNNEXT);
|
||||
checkVol(true);
|
||||
return;
|
||||
}
|
||||
if (x >= 37 && x <= 56 && y >= 8 && y <= 56) {
|
||||
v = ((60 - y) * 100) / (2 * 25);
|
||||
dragging = true;
|
||||
if (x <= 50)
|
||||
Mixer_set_left(curchannel, v);
|
||||
if (x >= 45)
|
||||
Mixer_set_right(curchannel, v);
|
||||
Mixer_write_volume(curchannel);
|
||||
checkVol(false);
|
||||
return;
|
||||
}
|
||||
if (x >= 5 && y >= 21 && x <= 30 && y <= 42) {
|
||||
drawText(selems[curchannel]->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void releaseEvent() {
|
||||
@@ -580,10 +835,10 @@ void motionEvent(XMotionEvent *xev)
|
||||
if (v<0)
|
||||
v=0;
|
||||
if (x<=50)
|
||||
Mixer_set_left(channel[curchannel], v);
|
||||
Mixer_set_left(curchannel, v);
|
||||
if (x>=45)
|
||||
Mixer_set_right(channel[curchannel], v);
|
||||
Mixer_write_volume(channel[curchannel]);
|
||||
Mixer_set_right(curchannel, v);
|
||||
Mixer_write_volume(curchannel);
|
||||
checkVol(false);
|
||||
}
|
||||
}
|
||||
@@ -595,50 +850,48 @@ void repaint()
|
||||
while(XCheckTypedEvent(d_display, Expose, &xev));
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
drawText(small_labels[channel[curchannel]]);
|
||||
void update() {
|
||||
drawText(selems[curchannel]->name);
|
||||
|
||||
XCopyArea(d_display, pm_icon, pm_disp, gc_gc, icon[channel[curchannel]]*26, 0, 26, 24, 5, 19);
|
||||
if (Mixer_get_stereo(channel[curchannel])) {
|
||||
drawLeft();
|
||||
drawRight();
|
||||
}
|
||||
else {
|
||||
drawMono();
|
||||
}
|
||||
XCopyArea(d_display, pm_icon, pm_disp, gc_gc,
|
||||
selems[curchannel]->iconIndex * 26, 0, 26, 24, 5, 19);
|
||||
if (selems[curchannel]->stereo) {
|
||||
drawLeft();
|
||||
drawRight();
|
||||
} else {
|
||||
drawMono();
|
||||
}
|
||||
}
|
||||
|
||||
void drawText(char *text)
|
||||
{
|
||||
char *p = text;
|
||||
char p2;
|
||||
int i;
|
||||
void drawText(char *text) {
|
||||
char *p = text;
|
||||
char p2;
|
||||
int i;
|
||||
|
||||
for (i=0; i<4; i++, p++) {
|
||||
p2 = toupper(*p);
|
||||
if (p2 >= 'A' && p2 <= 'Z') {
|
||||
XCopyArea(d_display, pm_chars, pm_disp, gc_gc, 6*((int)p2-65), 0, 6, 9, 5+(i*6), 5);
|
||||
for (i = 0; i < 4; i++, p++) {
|
||||
p2 = toupper(*p);
|
||||
if (p2 >= 'A' && p2 <= 'Z') {
|
||||
XCopyArea(d_display, pm_chars, pm_disp, gc_gc,
|
||||
6 * ((int)p2 - 65), 0, 6, 9, 5 + (i * 6), 5);
|
||||
} else if (p2 >= '0' && p2 <= '9') {
|
||||
XCopyArea(d_display, pm_digits, pm_disp, gc_gc,
|
||||
6 * ((int)p2 - 48), 0, 6, 9, 5 + (i * 6), 5);
|
||||
} else {
|
||||
if (p2 == '\0')
|
||||
p--;
|
||||
XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 60, 0, 6, 9,
|
||||
5 + (i * 6), 5);
|
||||
}
|
||||
}
|
||||
else if (p2 >= '0' && p2 <= '9') {
|
||||
XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 6*((int)p2-48), 0, 6, 9, 5+(i*6), 5);
|
||||
}
|
||||
else {
|
||||
if (p2 == '\0')
|
||||
p--;
|
||||
XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 60, 0, 6, 9, 5+(i*6), 5);
|
||||
}
|
||||
}
|
||||
if (!no_volume_display)
|
||||
text_counter = 10;
|
||||
if (!no_volume_display)
|
||||
text_counter = 10;
|
||||
}
|
||||
|
||||
void drawVolLevel() {
|
||||
int i;
|
||||
int digits[4];
|
||||
|
||||
int vol = (Mixer_read_left(channel[curchannel]) +
|
||||
Mixer_read_right(channel[curchannel])) / 2;
|
||||
int vol = (Mixer_read_left(curchannel) + Mixer_read_right(curchannel)) / 2;
|
||||
|
||||
digits[0] = (vol/100) ? 1 : 10;
|
||||
digits[1] = (vol/10) == 10 ? 0 : (vol/10);
|
||||
@@ -730,7 +983,7 @@ See the README file for a more complete notice.\n\n", stdout);
|
||||
-a use smaller window (for AfterStep Wharf)\n\
|
||||
-l led_color use the specified color for led display\n\
|
||||
-b back_color use the specified color for backgrounds\n\
|
||||
-d mix_device use specified device (rather than /dev/mixer)\n\
|
||||
-d alsa_device use specified device (rather than 'default')\n\
|
||||
-position position set window position (see X manual pages)\n\
|
||||
-display display select target display (see X manual pages)\n\n",
|
||||
stdout);
|
||||
|
||||
65
wmamixer.h
65
wmamixer.h
@@ -18,6 +18,7 @@
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
@@ -46,6 +47,10 @@
|
||||
#undef CLAMP
|
||||
#define CLAMP(v, l, h) (((v) > (h)) ? (h) : (((v) < (l)) ? (l) : (v)))
|
||||
|
||||
/* Function to convert from percentage to volume. val = percentage */
|
||||
#define convert_prange1(val, min, max) \
|
||||
ceil((val) * ((max) - (min)) * 0.01 + (min))
|
||||
|
||||
|
||||
// Pixmaps - standard
|
||||
Pixmap pm_main;
|
||||
@@ -77,7 +82,7 @@ int winsize;
|
||||
bool no_volume_display = 0;
|
||||
|
||||
// Variables for command-line arguments - custom
|
||||
char mixer_device[256] = "default";
|
||||
char card[256] = "default";
|
||||
char backcolor[256] = BACKCOLOR;
|
||||
char ledcolor[256] = LEDCOLOR;
|
||||
|
||||
@@ -96,7 +101,7 @@ unsigned long color[4];
|
||||
|
||||
int text_counter = 0;
|
||||
|
||||
// Misc custom global variables
|
||||
// Misc custom global variables
|
||||
// ----------------------------
|
||||
|
||||
// Current state information
|
||||
@@ -116,27 +121,49 @@ int rpttimer = 0;
|
||||
// For draggable volume control
|
||||
bool dragging = false;
|
||||
|
||||
int channels = 2;
|
||||
int channel[25];
|
||||
int icon[25] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24};
|
||||
char *small_labels[25] = {"vol ", "bass", "trbl", "synt", "pcm ",
|
||||
"spkr", "line", "mic ", "cd ", "mix ", "pcm2", "rec ", "igai", "ogai",
|
||||
"lin1", "lin2", "lin3", "dig1", "dig2", "dig3", "phin", "phou", "vid ",
|
||||
"rad ", "mon "};
|
||||
int channel[32];
|
||||
int icon[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
struct Selem {
|
||||
char *name;
|
||||
bool stereo;
|
||||
int currentVolRight;
|
||||
int currentVolLeft;
|
||||
short int iconIndex;
|
||||
snd_mixer_elem_t *elem;
|
||||
long min;
|
||||
long max;
|
||||
bool capture;
|
||||
snd_mixer_selem_channel_id_t channels[2];
|
||||
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool isvolume;
|
||||
bool capture;
|
||||
bool mono;
|
||||
} slideCaptureMono;
|
||||
|
||||
struct NamesCount {
|
||||
short int pcm, line, lineb, mic, micb, capt, vol;
|
||||
} namesCount = {1, 1, 1, 1, 1, 1, 1};
|
||||
|
||||
struct Selem *selems[32];
|
||||
|
||||
struct Mixer {
|
||||
int openOK;
|
||||
int devices_no;
|
||||
snd_mixer_t * handle;
|
||||
void *elems[32];
|
||||
};
|
||||
|
||||
static int smixer_level = 0;
|
||||
static struct snd_mixer_selem_regopt smixer_options;
|
||||
|
||||
// Procedures and functions - standard
|
||||
void initXWin(int argc, char **argv);
|
||||
void freeXWin();
|
||||
void createWin(Window *win, int x, int y);
|
||||
unsigned long getColor(char *colorname);
|
||||
unsigned long mixColor(char *colorname1, int prop1, char *colorname2,
|
||||
int prop2);
|
||||
unsigned long mixColor(char *color1, int prop1, char *color2, int prop2);
|
||||
|
||||
// Procedures and functions - custom
|
||||
void scanArgs(int argc, char **argv);
|
||||
@@ -156,14 +183,18 @@ void drawText(char *text);
|
||||
void drawBtns(int btns);
|
||||
void drawBtn(int x, int y, int w, int h, bool down);
|
||||
|
||||
struct Mixer *Mixer_create(char *device);
|
||||
void Mixer_set_selem_props(struct Selem *selem, const char *name);
|
||||
slideCaptureMono Mixer_getcapabilities(snd_mixer_elem_t *elem);
|
||||
|
||||
struct Mixer *Mixer_create(char *devicename);
|
||||
void Mixer_set_left(int current, int value);
|
||||
void Mixer_set_right(int current, int value);
|
||||
void Mixer_write_volume(int current);
|
||||
int Mixer_read_left(int current);
|
||||
int Mixer_read_right(int current);
|
||||
int Mixer_read_volume(int channel, bool read);
|
||||
bool Mixer_get_stereo(int channel);
|
||||
int Mixer_read_volume(int current, bool read);
|
||||
|
||||
void Mixer_set_limits(snd_mixer_elem_t *elem, struct Selem *selem);
|
||||
|
||||
void Mixer_destroy(struct Mixer *mix);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user