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

#define SEG_LEN 1

static char rcsid[] = "$Id: ogg.c,v 1.3 2002/04/02 22:47:47 root Exp root $";

/*
 * $Log: ogg.c,v $
 * Revision 1.3  2002/04/02 22:47:47  root
 * #
 *
 * Revision 1.2  2002/04/02 22:44:31  root
 * #
 *
 * Revision 1.1  2002/04/02 15:31:37  root
 * #
 *
 * Revision 1.10  2001/10/12 13:51:16  root
 * #
 *
 * Revision 1.9  2001/01/30 06:16:26  root
 * #
 *
 * Revision 1.8  2000/10/07 18:30:06  root
 * #
 *
 * Revision 1.7  2000/10/07 17:57:01  root
 * #
 *
 * Revision 1.6  2000/10/06 19:52:20  root
 * #
 *
 * Revision 1.5  2000/09/24 01:37:11  root
 * #
 *
 * Revision 1.4  2000/09/24 01:12:47  root
 * #
 *
 * Revision 1.3  2000/09/19 06:09:00  root
 * #
 *
 * Revision 1.2  2000/09/19 05:39:42  root
 * #
 *
 * Revision 1.1  2000/09/19 05:08:18  root
 * #
 *
 */

#include <pthread.h>

#include "project.h"

extern void *msglib;

static int newtime = 1;
static double lasttime, basetime;


typedef struct
{
  int running;
  pthread_t thread;
  char *wot;
}
ogg_t;
ogg_t ogg = { 0 };


float
mult_to_vol (float m)
{
  if (m == 0.0)
    return 0.0;

  m = log10 (m);
  m += 2.5;
  m = m / 3.0;

  return m;
}

float
vol_to_mult (float m)
{
  if (m == 0.0)
    return 0.0;

  m *= 3.0;
  m -= 2.5;

  m = pow (10.0, m);

  return m;
}


void
ogg_init (void)
{
  extern int ogg123_init (void);
  ogg123_init ();
}

static void *
ogg_thread_func (void *arg)
{
  extern int ogg123_play (char *);

  ogg_t *o = (ogg_t *) arg;
  ogg123_play (o->wot);
  pthread_exit (0);
}


void
ogg_stop (void)
{
  extern void ogg123_stop (void);
  printf ("Ogg stop: %d\n", ogg.running);
  if (!ogg.running)
    return;
  ogg123_stop ();
  pthread_join (ogg.thread, NULL);
  ogg.running = 0;
  free (ogg.wot);
  printf ("Stop done\n");
}

void
ogg_start (char *wot)
{
  extern void ogg123_unstop (void);
  printf ("Ogg start: %d %s\n", ogg.running, wot);
  ogg_stop ();
  ogg123_unstop ();
  ogg.running = 1;
  ogg.wot = strdup (wot);
  {
    double extern ogg123_current_time;
    newtime++;
    ogg123_current_time = -1;
  }

  pthread_create (&ogg.thread, NULL, ogg_thread_func, &ogg);
  printf ("Start done\n");
}

static void ogg_play_from_time_t(time_t t)
{
	char buf[1024];

	struct tm tm;

        tm = *localtime (&t);
        tm.tm_isdst = -1;

        tm.tm_min = SEG_LEN * (tm.tm_min / SEG_LEN);
        tm.tm_sec = 0;

        sprintf (buf,
                 "http://reith.southeast.local:3000/cgi-bin/radio_player?%04d_%02d_%02d_%02d_%02d",
                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
                 tm.tm_min);

        t = mktime (&tm);

        basetime = (double) t;

        ogg_start (buf);
}


void
ogg_cmdst_message (Byte dunit, Word cmd, Byte * data, Word len)
{

  if ((dunit != oggunit) && (dunit != HIFI_UNIT_ALL))
    return;


  switch (cmd)
    {
    case HIFI_CMD_VOL:
      {
        extern double ogg123_voll;
        extern double ogg123_volr;
        float voll = 0.01 * (float) data[0];
        float volr = 0.01 * (float) data[1];
        ogg123_voll = vol_to_mult(voll);
        ogg123_volr = vol_to_mult(volr);
	printf("Mults %f %f\n",ogg123_voll,ogg123_volr);
      }
      break;
    case HIFI_CMD_OGG_PLAY_S:
    case HIFI_CMD_OGG_PLAY_MS:
    case HIFI_CMD_OGG_PLAY_HMS:
      {
        time_t t,nt;
        struct tm tm;
        SDWord sd;

        time (&t);
        tm = *localtime (&t);

        tm.tm_isdst = -1;
        switch (cmd)
          {
          case HIFI_CMD_OGG_PLAY_HMS:
            tm.tm_hour = 0;
          case HIFI_CMD_OGG_PLAY_MS:
            tm.tm_min = 0;
          case HIFI_CMD_OGG_PLAY_S:
            tm.tm_sec = 0;
          }

        t = mktime (&tm);

        hifipkt_dsdword (data, &sd);

        t += sd;

	time(&nt);

	if (t>nt) {
		t-=24*60*60;
	}

	ogg_play_from_time_t(t);
      }
      break;
     case HIFI_CMD_OGG_SEEK:
      {
        time_t t;
        struct tm tm;
        SDWord sd;

        t = (time_t) basetime;
        hifipkt_dsdword (data, &sd);
        t += sd;

	ogg_play_from_time_t(t);
      }
      break;
    case HIFI_CMD_OGG_PLAY:
      {
        struct tm tm;
        time_t t;
        Word w;

        // data[0] is stream id

        hifipkt_dword (data + 1, &w);

        tm.tm_isdst = -1;
        tm.tm_year = w - 1900;
        tm.tm_mon = data[3] - 1;
        tm.tm_mday = data[4];
        tm.tm_hour = data[5];
        tm.tm_min = data[6];
        tm.tm_sec = data[7];


        t = mktime (&tm);

	ogg_play_from_time_t(t);
      }
      break;
    case HIFI_CMD_STOP:
      ogg_stop ();
      break;
    }


}


void
ogg_status (void)
{
  Byte *buf = hifi_getbuf ();
  Byte *ptr = buf, *cptr;
  double extern ogg123_current_time;
  double extern ogg123_buffer_fill;
  int i;

  struct tm *tm;
  time_t t;

  double ogg_time = ogg123_current_time;

  if (ogg_time > 0)
    {
      if (newtime || (lasttime > ogg_time))
        lasttime = ogg_time;
      newtime = 0;
      basetime += (ogg_time - lasttime);
      lasttime = ogg_time;
    }

  t = (time_t) basetime;
  tm = localtime (&t);


  ptr = hifipkt_new_brd (ptr, HIFI_CLASS_OGG, oggunit);

  ptr = hifipkt_est (cptr = ptr, HIFI_ST_OGG_STATE);

  if (ogg.running)
    {
      ptr = hifipkt_ebyte (ptr, HIFI_OGG_State_Playing);
    }
  else
    {
      ptr = hifipkt_ebyte (ptr, HIFI_OGG_State_Stopped);
    }

  ptr = hifipkt_ebyte (ptr, 0); //stream

  ptr = hifipkt_eword (ptr, tm->tm_year + 1900);
  ptr = hifipkt_ebyte (ptr, tm->tm_mon + 1);
  ptr = hifipkt_ebyte (ptr, tm->tm_mday);
  ptr = hifipkt_ebyte (ptr, tm->tm_hour);
  ptr = hifipkt_ebyte (ptr, tm->tm_min);
  ptr = hifipkt_ebyte (ptr, tm->tm_sec);
  ptr = hifipkt_ebyte (ptr, (int) ogg123_buffer_fill);

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

  {
    extern double ogg123_voll;
    extern double ogg123_volr;
    int l, r;

    l = (int) (mult_to_vol(ogg123_voll) * 100.0);
    r = (int) (mult_to_vol(ogg123_volr) * 100.0);

    ptr = hifipkt_est (cptr = ptr, HIFI_ST_VOL);
    ptr = hifipkt_ebyte (ptr, l);
    ptr = hifipkt_ebyte (ptr, r);
    hifipkt_elen (cptr, HIFI_PTR_DIFF (ptr, cptr));

  }
  ptr = hifipkt_eeof (ptr);

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

}
