/*
 * vol.c - Command-line volume getter/setter
 *
 * Copyright (c) 2005 Phillip Hellewell
 *
 * This program is licensed under GPL.
 */

#include <sys/ioctl.h>
#include <linux/soundcard.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

void getvol(int mixer_fd, int* vol_left, int* vol_right)
{
	unsigned char volsetting[4];
	if( ioctl( mixer_fd, SOUND_MIXER_READ_VOLUME, &volsetting[0]) == -1 ) {
		perror("getvol: ioctl failed");
		exit(1);
	}

	*vol_left = volsetting[0];
	*vol_right = volsetting[1];
}

void setvol(int mixer_fd, int vol_left, int vol_right)
{
	unsigned char volsetting[4];
	volsetting[0] = vol_left;
	volsetting[1] = vol_right;

	if( ioctl( mixer_fd, SOUND_MIXER_WRITE_VOLUME, &volsetting[0]) == -1 ) {
		perror("setvol: ioctl failed");
		exit(1);
	}
}

int parse1vol(const char* volstr, int oldvol)
{
	int vol;
	if( volstr[0] == '+' ) {
		vol = oldvol + atoi(volstr+1);
	} else if( volstr[0] == '-' ) {
		vol = oldvol - atoi(volstr+1);
	} else {
		vol = atoi(volstr);
	}

	if( vol < 0 ) vol = 0;
	if( vol > 100 ) vol = 100;
	return vol;
}

void parsevol(int mixer_fd, const char* volstr, int* vol_left, int* vol_right)
{
	const char* volstr_left;
	const char* volstr_right;
	int oldvol_left, oldvol_right;

	volstr_left = volstr;
	volstr_right = strchr(volstr, ',');
	if( volstr_right == NULL ) {
		volstr_right = volstr_left;
	} else {
		volstr_right++;
	}

	oldvol_left = oldvol_right = 0;
	if( volstr_left[0] == '+' || volstr_left[0] == '-' ||
		volstr_right[0] == '+' || volstr_right[0] == '-' ) {
		getvol(mixer_fd, &oldvol_left, &oldvol_right);
	}

	*vol_left = parse1vol(volstr_left, oldvol_left);
	*vol_right = parse1vol(volstr_right, oldvol_right);
}

int main(int argc, char* argv[])
{
	int vol_left, vol_right;

	int mixer_fd = open("/dev/mixer", O_RDWR, 0);
	if( mixer_fd < 0 ) {
		fprintf(stderr, "Error opening mixer device");
		exit(1);
	}
	
	if( argc > 1 ) {
		parsevol(mixer_fd, argv[1], &vol_left, &vol_right);
		setvol(mixer_fd, vol_left, vol_right);
	} else {
		getvol(mixer_fd, &vol_left, &vol_right);
		printf("%d,%d\n", vol_left, vol_right);
	}

	close(mixer_fd);

	return 0;
}
