/**********************************************************/
/* SB Audigy 2 Platinum                                   */
/**********************************************************/
#include "uniaud.h"
#include "umix.h"
#include "uniprn.h"

int card_id=-1, ii;

UniaudCardInfo CardInfo;

int ctrl_id    [CONTROLS];
int check_id   [CONTROLS];
int panel_limit[CONTROLS];

// init arrays
for (ii=0;ii<CONTROLS;ii++) { ctrl_id[ii]=-1; check_id[ii]=-1; panel_limit[ii]=0; }


int CaptVol=-1;
int CaptSwt=-1;
int CaptPin=-1;
int MicPin =-1;
int CDPin  =-1;
int LinePin=-1;

int CaptMax=-1;

int CheckControl(UniaudControl *pCtl, UniaudControlInfo *ctl_info,
   UniaudControlValue *ctl_val, int panel, char *name ,int index) 
{
//printf("%s %d, %d==2\n",ctl_info->id.name,ctl_info->id.index,ctl_info->count);
   if (strcmp(pCtl->name,name)==0&&(index<0||ctl_info->id.index==index)) {
     if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER) {
       ctrl_id[panel]=pCtl->numid;
       panel_limit[panel]=ctl_info->value.integer.max;
       return 1;
     }
   }
   return 0;
}

int CheckButton(UniaudControl *pCtl, UniaudControlInfo *ctl_info,
   UniaudControlValue *ctl_val, int panel, char *name ,int index) 
{
   if (strcmp(pCtl->name,name)==0&&(index<0||ctl_info->id.index==index)) {
     if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER) {
       check_id[panel]=pCtl->numid;
       return 1;
     }
   }
   return 0;
}


int unimix_show_controls(int card_id, int ctl_id) {
    int ctls, i;
    UniaudControlValue *ctl_val = NULL;
    UniaudControlInfo *ctl_info = NULL;
    UniaudControl *pCtl = NULL;

    ctls = uniaud_mixer_get_ctls_number(card_id);

    pCtl = (UniaudControl * )uniaud_mixer_get_ctl_list(card_id);

    if (pCtl!=NULL) {
        ctl_val = (UniaudControlValue *)malloc(sizeof(UniaudControlValue));
        ctl_info = (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
        for(i=1; i<=ctls; i++) {
            memset(ctl_val,0,sizeof(UniaudControlValue));
            memset(ctl_info,0,sizeof(UniaudControlInfo));
            uniaud_mixer_get_ctl_info(card_id, pCtl->numid, ctl_info);
            uniaud_mixer_get_ctl_val(card_id, pCtl->numid, ctl_val);

            if ((ctl_id && pCtl->numid == ctl_id) ||
                (ctl_id == 0))
            {
                PrintControl(card_id, ctl_info, ctl_val);

                if (strcmp(pCtl->name,"Master Playback Volume")==0) {
                  if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER) {
                    ctrl_id[PANEL_MAIN]=pCtl->numid; 
                    panel_limit[PANEL_MAIN]=ctl_info->value.integer.max;
                  }
                }
                if (strcmp(pCtl->name,"Master Playback Switch")==0)
                  if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER)
                    check_id[PANEL_MAIN]=pCtl->numid; 

                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_WAVE,
                             "Wave Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CENTER,
                             "Center Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_SPACE,
                             "Surround Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_MIDI,
                             "Synth Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CD,
                             "Audigy CD Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_LINE,
                             "Aux2 Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_MIC,
                             "AMic Playback Volume", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CUSTOMA,
                             "Tone Control - Bass", -1))
                if (!CheckButton(pCtl, ctl_info, ctl_val, PANEL_CUSTOMA,
                             "Tone Control - Switch", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CUSTOMB,
                             "Tone Control - Treble", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CUSTOMC,
                             "3D Control Sigmatel - Depth", -1))
                if (!CheckButton(pCtl, ctl_info, ctl_val, PANEL_CUSTOMC,
                             "3D Control - Switch", -1))
                if (!CheckControl(pCtl, ctl_info, ctl_val, PANEL_CUSTOMD,
                             "3D Control Sigmatel - Rear Depth", -1))

                if (strcmp(pCtl->name,"HD source Capture]")==0)
                  if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER&&
                      ctl_info->type==SNDRV_CTL_ELEM_TYPE_ENUMERATED) 
                  {
                    UniaudControlInfo *ctl_info2 =
                      (UniaudControlInfo *)malloc(sizeof(UniaudControlInfo));
                    CaptPin=pCtl->numid;

                    int ii;
                    for (ii=0; ii < ctl_info->value.enumerated.items; ii++) {
                      int id=ctl_info->id.numid;
                      memset(ctl_info2,0,sizeof(UniaudControlInfo));
                      ctl_info2->value.enumerated.item=ii;
                      uniaud_mixer_get_ctl_info(card_id, id, ctl_info2);
                      if (strcmp(ctl_info2->value.enumerated.name,"Mic")==0) MicPin=ii; else
                      if (strcmp(ctl_info2->value.enumerated.name,"CD")==0) CDPin=ii; else
                      if (strcmp(ctl_info2->value.enumerated.name,"Line")==0) LinePin=ii;
                    }
                    free(ctl_info2);
                  }
                if (strcmp(pCtl->name,"Master Capture Volume")==0)
                  if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER) {
                    CaptVol=pCtl->numid;
                    CaptMax=ctl_info->value.integer.max;
                  }
                if (strcmp(pCtl->name,"Master Capture Switch")==0)
                  if (ctl_info->id.iface==SNDRV_CTL_ELEM_IFACE_MIXER)
                    CaptSwt=pCtl->numid;
            }
            pCtl++;
        }
        free(ctl_info);
        free(ctl_val);

        printf("CaptVol: %d, CaptSwt: %d, MicPin: %d, CDPin: %d, LinePin: %d\n",CaptVol,CaptSwt,MicPin,CDPin,LinePin);
        if (CaptVol>=0) {
          if (MicPin >=0) { ctrl_id[PANEL_RECMIC ]=CaptVol; panel_limit[PANEL_RECMIC ]=CaptMax; }
          if (CDPin  >=0) { ctrl_id[PANEL_RECCD  ]=CaptVol; panel_limit[PANEL_RECCD  ]=CaptMax; }
          if (LinePin>=0) { ctrl_id[PANEL_RECLINE]=CaptVol; panel_limit[PANEL_RECLINE]=CaptMax; }
        }
        // master switch second channel is something strange on SbLive
        check_show(PANEL_MAINRIGHT,0);

// there is no "switches" for some wave controls, it must be implemented manually
// but now we are only disable checks
        check_show(PANEL_WAVE,0);
        check_show(PANEL_CENTER,0);
        check_show(PANEL_SPACE,0);

        printf("Bass: %d, Treble: %d, Switch: %d, 3D: %d, 3DRear: %d, 3D Switch:%d\n",
           ctrl_id[PANEL_CUSTOMA],ctrl_id[PANEL_CUSTOMB],check_id[PANEL_CUSTOMA],
           ctrl_id[PANEL_CUSTOMC],ctrl_id[PANEL_CUSTOMD],check_id[PANEL_CUSTOMC]);
        check_show(PANEL_CUSTOMB,0);
        check_show(PANEL_CUSTOMD,0);
    }
    return 0;
}




int detect() { // check adapter presence
    int cards_num = uniaud_get_cards(), ii;
    if (!cards_num) {
        printf("No audio cards detected\n");
        return 0;
    }
    printf("Detected %i audio adapter(s)\n", cards_num);
    for (ii=0;ii<cards_num;ii++) {
        if (uniaud_get_card_info(ii, &CardInfo) < 0) {
            printf("Error: unable to get card info\n");
            continue;
        }
        printf("Card info:\n");
        printf("  num: %i\n",CardInfo.card);
        printf("  id: %s\n",CardInfo.id);
        printf("  driver: %s\n",CardInfo.driver);
        printf("  name: %s\n",CardInfo.name);
        printf("  longname: %s\n",CardInfo.longname);
        printf("  mixer: %s\n",CardInfo.mixername);
        printf("  componenets: %s\n",CardInfo.components);

        if ((strstr((char*)&CardInfo.longname,"SB Audigy 2 Platinum")!=NULL))
        {
          printf("Detected ID: %d\n",CardInfo.id);
          card_id=ii;
          unimix_show_controls(card_id, 0);
          break;
        }
    }
    return card_id>=0?1:0;
}

int panelpresent(int panel) { // check control presence (0..CONTROLS-1)
    // show detected panels only
    if (ctrl_id[panel]>=0) return 1;
    return 0;
}

int getlimit(int panel) { // get panel limit (0..CONTROLS-1)
    if (panel_limit[panel]) printf("getlimit(%d)=%d\n",panel,panel_limit[panel]);
    return panel_limit[panel];
}

int setvalue(int panel,int value) { // set value from panel 

   //printf("setvalue(%d,%d)\n", panel, value);

   if (panel==PANEL_MAIN||panel==PANEL_MAINRIGHT) {
     uniaud_mixer_put_value(card_id, ctrl_id[PANEL_MAIN], value, panel==0?0:1);
   } else {
     uniaud_mixer_put_value(card_id, ctrl_id[panel], value, 0);
     uniaud_mixer_put_value(card_id, ctrl_id[panel], value, 1);
   }
}

int getvalue(int panel) { // get value from system 
   if (panel==PANEL_MAIN||panel==PANEL_MAINRIGHT) {
     return uniaud_mixer_get_value(card_id, ctrl_id[PANEL_MAIN], panel==0?0:1);
   } else {
     return uniaud_mixer_get_value(card_id, ctrl_id[panel], 0);
   }
}

int getcheck(int panel) { // get check from system 
   if (panel==PANEL_MAIN) {
     return uniaud_mixer_get_value(card_id, check_id[PANEL_MAIN],0);
   } else 
   if (panel==PANEL_RECMIC||panel==PANEL_RECLINE||panel==PANEL_RECCD) {
     int value=uniaud_mixer_get_value(card_id, CaptPin, 0);
     int chkon=uniaud_mixer_get_value(card_id, CaptSwt, 0);
     if (!chkon) return 0;

     if (panel==PANEL_RECMIC  && value==MicPin ) return 1;
     if (panel==PANEL_RECLINE && value==LinePin) return 1;
     if (panel==PANEL_RECCD   && value==CDPin  ) return 1;
     return 0;
   } else {
     return uniaud_mixer_get_value(card_id, check_id[panel], 0);
   }
}

int setcheck(int panel,int state) { // set check from panel 
   printf("setcheck(%d,%d)\n", panel, state);

   if (panel==PANEL_MAIN) {
     uniaud_mixer_put_value(card_id, check_id[panel], state, 0);
   } else 
   if (panel==PANEL_RECMIC||panel==PANEL_RECLINE||panel==PANEL_RECCD) {
     int value;
     if (!state) {
       uniaud_mixer_put_value(card_id, CaptSwt, 0, 0);
       uniaud_mixer_put_value(card_id, CaptSwt, 0, 1);
     } else {
       if (panel==PANEL_RECMIC) value=MicPin; else
       if (panel==PANEL_RECLINE) value=LinePin; else
       if (panel==PANEL_RECCD) value=CDPin;

       uniaud_mixer_put_value(card_id, CaptSwt, 1, 0);
       uniaud_mixer_put_value(card_id, CaptSwt, 1, 1);

       uniaud_mixer_put_value(card_id, CaptPin, value, 0);
       uniaud_mixer_put_value(card_id, CaptPin, value, 1);
     }
     if (panel!=PANEL_RECMIC) check_set(PANEL_RECMIC,0);
     if (panel!=PANEL_RECCD) check_set(PANEL_RECCD,0);
     if (panel!=PANEL_RECLINE) check_set(PANEL_RECLINE,0);
   } else {
     uniaud_mixer_put_value(card_id, check_id[panel], state, 0);
     uniaud_mixer_put_value(card_id, check_id[panel], state, 1);
   }
}

void *getstate_all() { return 0; }

int setstate_all(void *) {}
