#include "avolctl.h"

extern int 		perc;
extern alsa		*alsamixer;
extern mixerlist	*mixer;

// --- constructor ---
alsa::alsa()
{
 if(!snd_mixer_open(&handle,0))
 {
  printf("[avolctl] snd_mixer_open() OK!\n");
  if(!snd_mixer_attach(handle,"default"))
  {
   printf("[avolctl] snd_mixer_attach() OK!\n");
   if(!snd_mixer_selem_register(handle,NULL,NULL))
   {
    printf("[avolctl] snd_mixer_selem_register() OK!\n");
    if(!snd_mixer_load(handle))printf("[avolctl] snd_mixer_load OK!\n");
    else printf("[avolctl] snd_mixer_load() failed\n");
   }
   else printf("[avolctl] snd_mixer_selem_register() failed\n");
  }
  else printf("[avolctl] snd_mixer_attach() failed\n");
 }
 else printf("[avolctl] snd_mixer_open() failed\n");
}

// --- destructor ---
alsa::~alsa()
{
 snd_mixer_close(handle);
}

// --- gives back a linked list with info's about mixers ---
mixerlist* alsa::List()
{
 long	vmin,vmax;
 list=new mixerlist;
 int i=0;
 
 snd_mixer_selem_id_malloc(&sid);
 
 for(elem=snd_mixer_first_elem(handle);elem;elem=snd_mixer_elem_next(elem))
 {
  snd_mixer_selem_get_id(elem,sid);
  if(snd_mixer_selem_is_active(elem)&&(snd_mixer_selem_has_playback_volume(elem)||snd_mixer_selem_has_playback_switch(elem)))
  {
   i++;
   list->setName(snd_mixer_selem_id_get_name(sid));
   snd_mixer_selem_get_playback_volume_range(elem,&vmin,&vmax);
   list->setVolume(snd_mixer_selem_has_playback_volume(elem));
   list->setSwitch(snd_mixer_selem_has_playback_switch(elem));
   list->setVmin(vmin);
   list->setVmax(vmax);
   list->addElem();
  }
 }
 printf("[avolctl] number of controls and switches: %d\n",i);

 snd_mixer_selem_id_free(sid);

 return list;
}

// --- sets the volume of a given mixer ---
void alsa::setVolume(char* name,long vol)
{
 int	svalue;
 long	vmin,vmax,value;

 snd_mixer_selem_id_malloc(&sid);

 snd_mixer_selem_id_set_index(sid,0);
 snd_mixer_selem_id_set_name(sid,name);
 if(!(elem=snd_mixer_find_selem(handle,sid)));
 else
 {
  snd_mixer_selem_get_playback_volume_range(elem,&vmin,&vmax);
  value=(vmax-vmin)*vol/100;
  if(value>=vmin&&value<=vmax)snd_mixer_selem_set_playback_volume_all(elem,value);
  // --- unmute if muted ---
  snd_mixer_selem_get_playback_switch(elem,SND_MIXER_SCHN_MONO,&svalue);
  if(snd_mixer_selem_has_playback_switch(elem)&&!svalue)
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_MONO,1);
 }

 snd_mixer_selem_id_set_index(sid,1);
 snd_mixer_selem_id_set_name(sid,name);
 if(!(elem=snd_mixer_find_selem(handle,sid)));
 else
 {
  snd_mixer_selem_get_playback_volume_range(elem,&vmin,&vmax);
  value=(vmax-vmin)*vol/100;
  if(value>=vmin&&value<=vmax)snd_mixer_selem_set_playback_volume_all(elem,value);
  // --- unmute if muted ---
  snd_mixer_selem_get_playback_switch(elem,SND_MIXER_SCHN_MONO,&svalue);
  if(snd_mixer_selem_has_playback_switch(elem)&&!svalue)
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_MONO,1);
 }


 snd_mixer_selem_id_free(sid);
}

void alsa::setSwitch(char* name,int value)
{
 snd_mixer_selem_id_malloc(&sid);
 
 snd_mixer_selem_id_set_index(sid,0);
 snd_mixer_selem_id_set_name(sid,name);
 if(!(elem=snd_mixer_find_selem(handle,sid)))fprintf(stderr,"[avolctl] can't find mixer %s\n",name);
 else
 {
  if(value==0)
  {
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_FRONT_LEFT,0);
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_FRONT_RIGHT,0);
  }
  else
  {
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_FRONT_LEFT,1);
   snd_mixer_selem_set_playback_switch(elem,SND_MIXER_SCHN_FRONT_RIGHT,1);
  }
 }
 snd_mixer_selem_id_free(sid);
}
