/*
 * system.c:
 *
 * Copyright (c) 2000 James McKenzie <james@fishsoup.dhs.org>,
 * All rights reserved.
 *
 */

static char rcsid[] = "$Id: mpeg.c,v 1.7 2001/10/12 13:51:19 root Exp root $";

/*
 * $Log: mpeg.c,v $
 * Revision 1.7  2001/10/12 13:51:19  root
 * #
 *
 * Revision 1.6  2001/01/30 06:16:33  root
 * #
 *
 * Revision 1.5  2000/11/23 23:45:30  root
 * #
 *
 * Revision 1.4  2000/10/07 18:30:11  root
 * #
 *
 * Revision 1.3  2000/10/07 16:41:53  root
 * #
 *
 * Revision 1.2  2000/10/06 19:52:46  root
 * #
 *
 * Revision 1.1  2000/10/06 06:21:36  root
 * #
 *
 */

#include "project.h"

static Panel_item volumeitem, listitem, statusitem, progitem, textitem,
  titleitem, buffitem,geweitem,eweitem;
static Menu histmenu, favmenu, histbut;

static Word current_length;
static int num = -1;

static int selected = -2;

static Eweid *eweids = NULL;

static int where = 0;

#define HNUM 20
char history[HNUM][1024];

static void do_history (char *);

static void
do_search (char *s, int j)
{
  int i = strlen (s);
  char *buf, *ptr, *cptr;

  if (j)
    do_history (s);

  buf = ptr = hifi_getbuf ();
  ptr =
    hifipkt_new_rel (ptr, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
                     mpegunit);
  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_MPEG_SEARCH);

  i++;
  bcopy (s, ptr, i);
  ptr += i;

  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);




}


static void
mproc (Menu menu, Menu_item menu_item)
{
  char *s = (char *) xv_get (menu_item, MENU_STRING);
  if (s)
    {
      xv_set (textitem, PANEL_VALUE, s, 0);
      do_search ((char *) xv_get (menu_item, MENU_STRING), 0);
      xv_set (textitem, PANEL_TEXT_SELECT_LINE, 0);
    }
}

static void
sethmenu (void)
{
  int i;

  xv_destroy (histmenu);

  histmenu = xv_create (0, MENU, MENU_NOTIFY_PROC, mproc, 0);

  for (i = 0; i < HNUM; ++i)
    {
      if (strlen (history[i]))
        xv_set (histmenu, MENU_STRING_ITEM, history[i], 0, 0);
    }

  xv_set (histbut, PANEL_ITEM_MENU, histmenu, 0);

}


static void
savehistory (void)
{
  FILE *f;
  char foo[1024];
  int i = 0;

  sprintf (foo, "%s/.hifi/history", getenv ("HOME"));

  f = fopen (foo, "w");
  if (!f)
    {
      printf ("Couldn't open %s\n", foo);
      return;
    }

  for (i = 0; i < HNUM; ++i)
    {
      if (strlen (history[i]))
        fprintf (f, "%s\n", history[i]);
    }

  fclose (f);


}
static void
loadhistory (void)
{
  FILE *f;
  char foo[1024];
  int i = 0;

  for (i = 0; i < HNUM; ++i)
    history[i][0] = 0;

  sprintf (foo, "%s/.hifi/history", getenv ("HOME"));
  f = fopen (foo, "r");
  if (!f)
    {
      printf ("Couldn't open %s\n", foo);
      return;
    }

  i = 0;
  fgets (foo, sizeof (foo), f);
  while ((!feof (f)) && (i < HNUM))
    {

      strcpy (history[i], foo);
      fgets (foo, sizeof (foo), f);
      i++;
    }

  fclose (f);




}

static void
do_history (char *s)
{
  int i;

  for (i = HNUM - 1; i > 0; i--)
    strcpy (history[i], history[i - 1]);
  strcpy (history[0], s);

  savehistory ();

  sethmenu ();

}



static void
tp (void)
{
  char *s = (char *) xv_get (textitem, PANEL_VALUE);

  do_search (s, 1);

  xv_set (textitem, PANEL_TEXT_SELECT_LINE, 0);

}


static void
list_lookup (char *ie)
{
  int i, j = -1;
  if (!eweids)
    return;


  for (i = 0; i < num; ++i)
    {
      if (!bcmp (eweids[i]->e, ie, sizeof (eweids[i]->e)))
        {
          j = i;
        }
    }



  if (j != -1)
    {
//Alpha and old xview has some problem with this attr
      /*      if (xv_get (listitem, PANEL_LIST_SELECTED, j) == FALSE) */
      if (selected != j)
        {
          xv_set (listitem, PANEL_LIST_SELECT, j, TRUE, 0);
          selected = j;
        }
    }
  else
    {
      if (selected != j) {
         selected = -1;
        xv_set (listitem, PANEL_LIST_SELECT, 0, FALSE, 0);
      }
    }


   

}

static int
lnp (Panel_item i, char *s, char *cd, Panel_list_op op, Event * event,
     int row)
{
  char *ptr, *buf, *cptr;
  char *a;

  selected = -2;

/*
   if (op != PANEL_LIST_OP_SELECT)
   return XV_OK;
 */


  if (!eweids)
    return XV_OK;



  buf = ptr = hifi_getbuf ();
  ptr =
    hifipkt_new_rel (ptr, HIFI_CLASS_DISPLAY, clientunit,
                     HIFI_CLASS_MPEG, mpegunit);
  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_MPEG_PLAY);
  bcopy (eweids[row]->e, ptr, 8);
  ptr += 8;


  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);





  return XV_OK;
}



static void
listnew (void)
{
  int x, y, h, w;
  int i;
  h = xv_get (listitem, PANEL_LIST_DISPLAY_ROWS);
  w = xv_get (listitem, PANEL_LIST_WIDTH);
  x = xv_get (listitem, XV_X);
  y = xv_get (listitem, XV_Y);



  xv_destroy (listitem);

  selected = -2;

  listitem = xv_create (panels[TAB_MPEG], PANEL_LIST,
                        XV_X, x,
                        XV_Y, y,
                        PANEL_LIST_WIDTH, w,
                        PANEL_LIST_DISPLAY_ROWS, h,
                        PANEL_LIST_NROWS, num,
                        PANEL_READ_ONLY, TRUE,
                        PANEL_NOTIFY_PROC, lnp,
                        PANEL_CHOOSE_ONE, TRUE, PANEL_CHOOSE_NONE, TRUE, 0);

  for (i = 0; i < num; ++i)
    {
      xv_set (listitem, PANEL_LIST_STRING, i, "Please wait...", 0);
    }

}



static void
maintain_list (int j, int n, char *ie, char *name)
{


  if (n != num)
    {
      int i;

      if (eweids)
        {
          for (i = 0; i < num; ++i)
            {
              Obj_Delete (eweids[i]);
            }
          free (eweids);
        }

      num = n;
      listnew ();
      eweids = (Eweid *) malloc (sizeof (Eweid) * num);

      for (i = 0; i < num; ++i)
        {
          eweids[i] = CREATE_OBJ (Eweid);
        }


    }



  if (j < num)
    {
      char *p;
      char mname[1024];
      int k;

      if (ie)
        {
          bcopy (ie, eweids[j]->e, sizeof (eweids[j]->e));

          for (k = 0; k < 4; ++k)
            {
              mname[k] = isgraph (eweids[j]->e[k]) ? (eweids[j]->e[k]) : '.';
            }
          mname[4] = ':';

          strcpy (mname + 5, name);
        }
      else
        {
          strcpy (mname, name);
        }


      p = (char *) xv_get (listitem, PANEL_LIST_STRING, j);

      if ((!p) || strcmp (p, mname))
        xv_set (listitem, PANEL_LIST_STRING, j, mname, 0);

    }





}

static void
rs (void)
{
  char *cptr, *buf, *ptr;
  hifi_cmd (msglib, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
            mpegunit, HIFI_CMD_MPEG_RESCAN);

  maintain_list (0, -1, NULL, "Rescanning...");


}
static void
rnd (void)
{
  char *cptr, *buf, *ptr;
  hifi_cmd (msglib, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
            mpegunit, HIFI_CMD_RANDOM);

}

static void
mstop (void)
{
  hifi_cmd_rel (msglib, HIFI_CLASS_DISPLAY, clientunit,
                HIFI_CLASS_MPEG, mpegunit, HIFI_CMD_STOP);
}

static void
jp30 (Panel_item p, int i)
{
  Byte *buf, *ptr, *cptr;

  buf = ptr = hifi_getbuf ();
  ptr =
    hifipkt_new (ptr, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
                 mpegunit);
  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_MPEG_SEEK);
  ptr = hifipkt_eword (ptr, where + 30);

  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);
}

static void
jm30 (Panel_item p, int i)
{
  Byte *buf, *ptr, *cptr, q;

  buf = ptr = hifi_getbuf ();
  ptr =
    hifipkt_new (ptr, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
                 mpegunit);
  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_MPEG_SEEK);

  q = where - 30;
  if (q < 30)
    q = 0;
  ptr = hifipkt_eword (ptr, q);

  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);
}

static void
doprog (Panel_item p, int i)
{
  Byte *buf, *ptr, *cptr;

  buf = ptr = hifi_getbuf ();
  ptr =
    hifipkt_new (ptr, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
                 mpegunit);
  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_MPEG_SEEK);
  ptr = hifipkt_eword (ptr, i);

  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);


}


static void
dovol (Panel_item p, int i)
{
  char *buf, *ptr, *cptr;


  buf = ptr = hifi_getbuf ();

  ptr =
    hifipkt_new (ptr, HIFI_CLASS_DISPLAY, clientunit, HIFI_CLASS_MPEG,
                 mpegunit);

  ptr = hifipkt_ecmd (cptr = ptr, HIFI_CMD_VOL);
  ptr = hifipkt_ebyte (ptr, i);
  ptr = hifipkt_ebyte (ptr, i);
  hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));
  ptr = hifipkt_eeof (ptr);

  hifi_send (msglib, buf, HIFI_PTR_DIFF (ptr, buf));
  hifi_freebuf (buf);
}


void
mpeg_cmdst (Byte class, Byte unit, Word cmd, unsigned char *data, int len)
{
  if (unit != mpegunit)
    return;



  switch (cmd)
    {
    case HIFI_ST_MPEG_GPNAME:
      {
	Eweid ge=CREATE_OBJ(Eweid);
	char *a;
	bcopy(data,ge->e,sizeof(ge->e));	
	if (EWEID_IS_NONE(ge)) {
        xv_set (geweitem, PANEL_VALUE, "", 0);
	} else {
	a=eweidtoa(ge);
        xv_set (geweitem, PANEL_VALUE, a, 0);
	free(a);
	}
	Obj_Delete(ge);	
        xv_set (titleitem, PANEL_LABEL_STRING, data+8, 0);
      }
      break;
    case HIFI_ST_MPEG_LIST:
      maintain_list (data[0], data[1], &data[2], data + 10);
      break;
    case HIFI_ST_MPEG_BUFFER:
      xv_set (buffitem, PANEL_VALUE, (int) data[0], 0);
      break;
    case HIFI_ST_VOL:
      xv_set (volumeitem, PANEL_VALUE, (int) *data, 0);
      break;

    case HIFI_ST_MPEG_STATE:
      {
        int current_state;
        int fl = 0;

        DWord d;
        Word length;

        char buf[80], *ptr;

        ptr = buf;


        current_state = data[0];

        switch (current_state)
          {
          case HIFI_MPEG_State_Stopped:
            ptr += sprintf (ptr, "Stop: ");
            break;
          case HIFI_MPEG_State_Playing:
            ptr += sprintf (ptr, "Play: ");
            fl++;
            break;
          case HIFI_MPEG_State_Paused:
            ptr += sprintf (ptr, "Paused: ");
            fl++;
            break;
          case HIFI_MPEG_State_Error:
            ptr += sprintf (ptr, "Error: ");
            break;
          case HIFI_MPEG_State_Unknown:
            ptr += sprintf (ptr, "???: ");
            break;
          }

        hifipkt_dword (&data[3], &current_length);


        if (fl)
          {
            sprintf (ptr, "%02d:%02d/%d:%02d", data[1], data[2],
                     current_length / 60, current_length % 60);

          }
        d = 0;
        if (current_length > 0)
          {
            d = data[1];
            d *= 60;
            d += data[2];
            where = d;
          }

        xv_set (progitem, PANEL_VALUE, d, PANEL_MAX_VALUE, current_length, 0);

        list_lookup (&data[5]);

	{
	  Eweid e=CREATE_OBJ(Eweid);
	  char *a;
	  bcopy(&data[5],e->e,sizeof(e->e));
	  if (EWEID_IS_NONE(e)) {
	  xv_set(eweitem,PANEL_VALUE,"",0);
	  } else {	
	  a=eweidtoa(e);
	  xv_set(eweitem,PANEL_VALUE,a,0);
	  free(a);
	  }
	  Obj_Delete(e);
	}

        xv_set (statusitem, PANEL_VALUE, buf, 0);
      }

      break;

    }




}


static void
do_fav_menu (void)
{
  FILE *f;
  char foo[1024];
  int i = 0, j = 1, l;

  favmenu = xv_create (0, MENU, MENU_NOTIFY_PROC, mproc, 0);

  sprintf (foo, "%s/.hifi/favorite", getenv ("HOME"));

  f = fopen (foo, "r");
  if (!f)
    {
      printf ("Couldn't open %s\n", foo);
      return;
    }


  fgets (foo, sizeof (foo), f);
  while (!feof (f))
    {

      l = strlen (foo);
      if (l)
        foo[l - 1] = 0;

      xv_set (favmenu, MENU_STRING_ITEM, strdup (foo), 0, 0);

      j++;
      fgets (foo, sizeof (foo), f);
    }

  fclose (f);


}

void
mpeg_makepanel (Panel p)
{
  int y = 5;

  titleitem =
    xv_create (p, PANEL_MESSAGE, XV_X, 5, XV_Y, y, PANEL_LABEL_STRING,
               "Title", 0);


  y += 30;

  geweitem =
    xv_create (p, PANEL_TEXT, XV_X, 5, XV_Y, y, PANEL_LABEL_STRING,
               "Eweids: ",PANEL_VALUE,"", PANEL_READ_ONLY,TRUE,
		PANEL_VALUE_DISPLAY_LENGTH,17,0);
  eweitem =
    xv_create (p, PANEL_TEXT, 
               PANEL_VALUE,"", PANEL_READ_ONLY,TRUE,
		PANEL_VALUE_DISPLAY_LENGTH,17,0);

  y += 30;

  listitem = xv_create (p, PANEL_LIST,
                        XV_X, 5,
                        XV_Y, y,
                        PANEL_NOTIFY_PROC, lnp,
                        PANEL_READ_ONLY, TRUE,
                        PANEL_CHOOSE_ONE, TRUE,
                        PANEL_LIST_WIDTH, WIDTH - 30,
                        PANEL_LIST_DISPLAY_ROWS, 1, 0);


  xv_set (listitem, PANEL_LIST_DISPLAY_ROWS,
          110 / (int) xv_get (listitem, PANEL_LIST_ROW_HEIGHT), 0);


  y += 120 + xv_get (listitem, PANEL_LIST_ROW_HEIGHT);


  do_fav_menu ();

  histmenu = xv_create (0, MENU, 0);

  loadhistory ();

  xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "Favourites",
             PANEL_ITEM_MENU, favmenu, XV_X, 5, XV_Y, y, 0);

  histbut = xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "History",
                       PANEL_ITEM_MENU, histmenu, 0);

  sethmenu ();

  y += 25;


  textitem =
    xv_create (p, PANEL_TEXT, XV_X, 5, XV_Y, y, PANEL_LABEL_STRING, "Search:",
               PANEL_VALUE_DISPLAY_LENGTH, 40, PANEL_NOTIFY_PROC, tp, 0);
  y += 25;



  xv_create (p, PANEL_BUTTON,
             PANEL_LABEL_STRING, "Stop", XV_X, 5, XV_Y, y,
             PANEL_NOTIFY_PROC, mstop, 0);

  xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "Random",
             PANEL_NOTIFY_PROC, rnd, 0);
  xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "Rescan",
             PANEL_NOTIFY_PROC, rs, 0);
  xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "-30sec",
             PANEL_NOTIFY_PROC, jm30, 0);
  xv_create (p, PANEL_BUTTON, PANEL_LABEL_STRING, "+30sec",
             PANEL_NOTIFY_PROC, jp30, 0);
  y += 25;

  statusitem = xv_create (p, PANEL_TEXT,
                          PANEL_VALUE_DISPLAY_LENGTH, 40,
                          PANEL_READ_ONLY, TRUE,
                          PANEL_LABEL_STRING, "Status:", XV_X, 5, XV_Y, y, 0);
  y += 25;

  progitem = xv_create (p, PANEL_SLIDER,
                        PANEL_MIN_VALUE, 0,
                        PANEL_MAX_VALUE, 0, PANEL_SLIDER_WIDTH, SLW,
                        PANEL_SHOW_RANGE, FALSE,
                        PANEL_SHOW_VALUE, FALSE, PANEL_SLIDER_END_BOXES, TRUE,
                        PANEL_NOTIFY_PROC, doprog,
                        PANEL_NOTIFY_LEVEL, PANEL_DONE, XV_X, 5, XV_Y, y, 0);
  y += SLSEP;
  y += SLSEP;

  volumeitem = xv_create (p, PANEL_SLIDER,
                          PANEL_MIN_VALUE, 0,
                          PANEL_MAX_VALUE, 100, PANEL_SLIDER_WIDTH, SLW,
                          PANEL_LABEL_STRING, "Vol:",
                          PANEL_SHOW_VALUE, FALSE,
                          PANEL_SHOW_RANGE, FALSE,
                          PANEL_SLIDER_END_BOXES, TRUE,
                          PANEL_NOTIFY_PROC, dovol,
                          PANEL_NOTIFY_LEVEL, PANEL_ALL, XV_X, 5, XV_Y, y, 0);
  y += SLSEP;

  buffitem = xv_create (p, PANEL_GAUGE,
                        PANEL_MIN_VALUE, 0,
                        PANEL_MAX_VALUE, 100, PANEL_GAUGE_WIDTH, SLW,
                        PANEL_LABEL_STRING, "Buffer:",
                        PANEL_SHOW_VALUE, FALSE,
                        PANEL_SHOW_RANGE, FALSE, XV_X, 5, XV_Y, y, 0);
  y += SLSEP;
}
