#include "mmix.h"

int mmix_updates;    /* what needs to be updated */
int mmix_found=0;    /* found mixer devices */
char *mmix_config=0; /* config file - resists in memory */

int
 c_mix=1, /* current mixer */
 c_res=1, /* current resource (1,2,3,4,..,m->nrdevs) */
 r_res=1, /* current real resource */
 c_cfg=1; /* current configuration */

bool
 _q=FALSE, /* quit after loading */
 _i=FALSE, /* setting number # */
 _r=FALSE, /* resource number # */
 _d=FALSE; /* print debug information */

int main(int argc, char **argv, char **environ) {
 vol_t clipboard[SOUND_MIXER_NRDEVICES]; /* sth. like a clipboard */
 int clipboard_dev=c_mix; /* we don't copy/paste between diff. mixers! */
 struct mmix *first, *m; /* m == current mixer, first saves the first one */
 bool mute_all=FALSE; /* mute_all variable */
 bool quit=FALSE; /* my quit variable */
 char ch; /* input char */
 int i; /* counter */

/*
-s#@load setting number # of all mixers (default, use current mixer settings)
-r#@load settings only from resource number # (default, all mixers)
-d@write some debugging information to stderr
-v@print version and exit
-q@quit, after loading settings
*/
 for (i=1;i<argc;i++) if (argv[i][0]=='-') {
  int i2;
  for (i2=1; i2<str_len((unsigned char *)argv[i]); i2++) {
   switch (argv[i][i2]) {
    case 'q': _q=TRUE; break;
    case 'f':
     if (argv[i+1]) mmix_config=(char*)str_dup((unsigned char *)argv[i+1]);
     break;
    case 'i':
     _i=TRUE;
     if (argv[i+1]) c_cfg=strtol(argv[i+1], (char **)NULL, 10);
     if (c_cfg<1 || c_cfg>9) c_cfg=1;
     break;
    case 'r':
     _r=TRUE;
     if (argv[i+1]) c_res=strtol(argv[i+1], (char **)NULL, 10);
     if (c_res<1 || c_res>9) c_res=1;
     break;
    case 'v':
     draw_exit((unsigned char *)"mmix version " VERSION "\n", 0);
     break;
    case 'd': _d=TRUE; break;
   } /* switch */
  } /* for2 */
 } /* for1 */


 /* set the default signal handling */
 sig_set(SIGWINCH,tty_resize);
 sig_set(SIGINT, mmix_quit);
 sig_set(SIGQUIT,mmix_quit);
 sig_set(SIGTERM,mmix_quit);

 /* init the mixer(s) */
 first=m=mixer_init();

 /* find confguration */
 if (!mmix_config)
  if (!(mmix_config=getenv("MMIXRC")))
   mmix_config=(char*)str_concat(get_user_home(), "/.mmixrc", NULL);
 draw("reading configuration %d from %s ...\n", c_cfg, mmix_config); draw_flush();
 if (defaults_loadconfig(&first[0])!=OK) mmix_error(ERR_CONF);

 if (_i)  {
  for (m=first;m!=NULL;m=m->next) for (i=0;i<SOUND_MIXER_NRDEVICES;i++) if ((m->devmask&(1<<i)) == (1<<i)) {
   m->v[0][i].right=m->v[c_cfg][i].right;
   m->v[0][i].left =m->v[c_cfg][i].left;
   m->v[0][i].m=m->v[c_cfg][i].m;
   m->v[0][i].r=m->v[c_cfg][i].r;
   mixer_write_it(&m[0], i, m->v[c_cfg][i].right<<8, m->v[c_cfg][i].left);
  }
 }
 /* just use the default setttings from all mixer devs + exit then */
 if (_i) { exit(ERR_NO); }

 /* init our terminal */
 tty_mode_init();

 while (!quit) {
  draw_update(&m[0]);
  if (select_wait(0, MIXER_UPDATES) == 1) {
   read(0,&ch,1);
   switch (ch) {

   /* cursors */
   case '\033':
    read(0,&ch,1);read(0,&ch,1); /* should be done in another way ? */
    switch (ch) {
     case 'A': /* up */
      if (c_res>1) { c_res--; } else c_res=m->nrdevs;
      set(U_MIXRES); break;
     case 'B': /* down */
      if (c_res<m->nrdevs) { c_res++; } else c_res=1;
      set(U_MIXRES); break;
     case 'C': mixer_write(&m[0], r_res, +5,  +5); break; /* right */
     case 'D': mixer_write(&m[0], r_res, -5,  -5); break; /* left */
    }
    break;
   case '+': /* to right */
    if ((m->devmask&(1<<r_res)) == (1<<r_res))
     if (m->v[0][r_res].s == R_ON)
      mixer_write(&m[0], r_res, -1,  1);
    break;

   case '-': /* to left */
    if ((m->devmask&(1<<r_res)) == (1<<r_res))
     if (m->v[0][r_res].s == R_ON)
      mixer_write(&m[0], r_res,  1, -1);
    break;

   case '0': /* special thing: mute/unmute all */
    mute_all=(mute_all==FALSE)?TRUE:FALSE;
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
    if ((m->devmask&(1<<i)) == (1<<i)) {
     if (mute_all==TRUE) {
      m->v[0][i].m=m->v[c_cfg][r_res].m=R_ON;  /* mute it */
     } else {
      m->v[0][i].m=m->v[c_cfg][r_res].m=R_OFF; /* unmute it */
     }
     mixer_write(&m[0], i, 0, 0); /* apply */
    }
    break;

   case '1': /* configuration witching */
   case '2': case '3': case '4': case '5':
   case '6': case '7': case '8': case '9':
    c_cfg=ch-48; set(U_MIXCFG);
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
    if ((m->devmask&(1<<i)) == (1<<i)) {
     m->v[0][i].right=m->v[c_cfg][i].right;
     m->v[0][i].left =m->v[c_cfg][i].left;
     m->v[0][i].m=m->v[c_cfg][i].m;
     m->v[0][i].r=m->v[c_cfg][i].r;
     mixer_write_it(&m[0], i, m->v[c_cfg][i].right<<8, m->v[c_cfg][i].left);
    }
    break;

   /* volume changing */
   case ']': mixer_write(&m[0], r_res, 25,  25); break;
   case ')': mixer_write(&m[0], r_res, 10,  10); break;
   case '>': mixer_write(&m[0], r_res,  1,   1); break;
   case '[': mixer_write(&m[0], r_res,-25, -25); break;
   case '(': mixer_write(&m[0], r_res,-10, -10); break;
   case '<': mixer_write(&m[0], r_res, -1,  -1); break;

   case 'y':
   /* copy current settings to a (own) clipboard */
    clipboard_dev=c_mix;
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++) {
     clipboard[i].right=m->v[0][i].right;
     clipboard[i].left =m->v[0][i].left;
     clipboard[i].m=m->v[0][i].m;
     clipboard[i].r=m->v[0][i].r;
    }
    break;

   case 'p':
   /* paste content from clipboard to current configuration */
    if (clipboard_dev==c_mix) {
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
    if ((m->devmask&(1<<i)) == (1<<i)) {
      m->v[0][i].right=clipboard[i].right;
      m->v[0][i].left =clipboard[i].left;
      m->v[0][i].m=clipboard[i].m;
      m->v[0][i].r=clipboard[i].r;
      mixer_write_it(&m[0], i,
       clipboard[i].right<<8, clipboard[i].left); /* set it */
     }
    }
    break;

   case 'e':
   /* edit .mmixrc file via vim|$EDITOR */
    tty_mode_restore();
    {
     char *l,*e=getenv("EDITOR");
     if (!e) e="vim";
     l=(char*)str_concat(e, " ", mmix_config, NULL);
     my_system(l); /* no errors or signals are fetched!! */
     xfree(l);
    }
    tty_mode_init();

   case 'l':
    /* load settings - xxx doesn't work as expected */
    defaults_loadconfig(&first[0]);
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++)
    if ((m->devmask&(1<<i)) == (1<<i)) {
     m->v[0][i].right=m->v[c_cfg][i].right;
     m->v[0][i].left=m->v[c_cfg][i].left;
     m->v[0][i].m=m->v[c_cfg][i].m;
     m->v[0][i].r=m->v[c_cfg][i].r;
    }
    set(U_MIXVOL);
    break;

    break;

   case 'h': case '?':
   /* show helping stuff */
    tty_mode_restore();
    my_system("man mmix");
    tty_mode_init();
    break;

   case 'm':
   /* mute/unmute */
    if (m->v[0][r_res].m==R_ON) {
     m->v[c_cfg][r_res].m=m->v[0][r_res].m=R_OFF;
     mute_all=FALSE;
    } else {
     m->v[c_cfg][r_res].m=m->v[0][r_res].m=R_ON;
    }
    mixer_write(&m[0], r_res, 0, 0);
    break;

   case CTRL_X('l'): /* ctrl-l */
   /* redraw screen */
    set(U_ALL);
    break;

   case 'q':
   /* quit */
    quit=TRUE;
    break;

   case 'r':
   /* recording on/off */
    if ((m->recmask&(1<<r_res)) == (1<<r_res))
     mixer_write_res(&m[0], r_res);
    break;

   case 's':
   /* save settings */
    for (i=0;i<SOUND_MIXER_NRDEVICES;i++) {
     m->v[c_cfg][i].left=m->v[0][i].left;
     m->v[c_cfg][i].right=m->v[0][i].right;
     m->v[c_cfg][i].m=m->v[0][i].m;
     m->v[c_cfg][i].r=m->v[0][i].r;
    }
    if (defaults_saveconfig(&first[0])!=OK)
     mmix_error(ERR_CONF);
    break;

   case ' ': /* space */
    /* balance to middle (left=right) */
    if (m->v[0][r_res].s == R_OFF) break; /* no stereo */
    {
     int b=(m->v[0][r_res].left+m->v[0][r_res].right)/2;
     m->v[0][r_res].left=m->v[0][r_res].right=b;
     mixer_write_it(&m[0], r_res, b<<8, b);
    }
    break;

   case '\t': /* tab */
   /* change mixer device */
    if (mmix_found==1) break; /* we have only one mixer */
    if (c_mix<mmix_found) {
     c_mix++; m=m->next;
    } else {
     c_mix=1; m=first;
    }
    c_cfg=c_res=1;
    set(U_ALL);
    break;
   } /* switch */
  } /* select */
  mixer_read(&m[0]); /* is it okay ? */
 } /* while */
 mmix_quit(0); /* cleanup */
 exit(0);
}

void mmix_quit(int unused) {
 draw_exit((unsigned char *)T_HOME T_CLEAR T_BOLD "ByeBye..." T_NORMAL "\n\n", ERR_NO);
}

void mmix_error(int nr) {
 char *s[]={
/* 1 */  "No mixer device found.\n",
/* 2 */  "Your configuration is buggy.\n",
/* 3 */  "Setting Terminal failed.\n",
/* 4 */  "You really want to start interactive mode -q ... not with ME!\n"
 };
 if (nr>4) nr=1;_q=0;
 draw_exit((unsigned char *)s[nr-1], nr);
}

#ifndef __dietlibc__
#warning "!!! get dietlibc from www.fefe.de !!!"
#endif
