/*  mp3player hardware test

    15.05.2001: tk, initial implementation.

    Copyright (c)2000 by Thomas Kindler, thomas.kindler@gmx.de

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of
    the License, or (at your option) any later version. Read the
    full License at http://www.gnu.org/copyleft for more details.
*/

// include files -----
//
#include <alloc.h>
#include <stdio.h>
#include <dos.h>
#include <dir.h>
#include <io.h>
#include <time.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include <string.h>
#include "sc12/amd186.h"
#include "sc12/rtos.h"
#include "sc12/hwapi.h"
#include "checkbios.h"
#include "ztimer.h"
#include "sed1520.h"
#include "remote.h"
#include "gfxlcd.h"
#include "id3v1.h"
#include "vs1001.h"
#include "misc.h"
#include "inet/httpget.h"
#include "inet/url.h"
#include "mpbuf.h"
#include "mpeg.h"
#include "readline.h"

static BitmapFont  *bigfont, *smallfont;


void HttpTest()
{
  for(;;) {
    char str[80];
    printf("enter URL: ");
    readline(str, sizeof(str));
    printf("\n");
    if (strlen(str) == 0)
      break;
    http_get(str);
  }
}


/// \bug  divide by zero on 0-length files
void FileTest(char *filename)
{
  FILE *f = fopen(filename, "rb");
  if (!f) {
    perror("");
    return;
  }

  ID3v1Tag  tag;
  char title[128];
  if (ID3v1_ReadTag(f, &tag))
    sprintf( title, "%s - %s (%s)", tag.artist, tag.title, tag.comment );
  else
    strncpy( title, filename, sizeof(title) );

  int  vol        = 255;
  int  titlepos   =   0;
  int  titledir   =  -1;
  int  titlewidth = textwidth(title);
  if (titlewidth <= 122)
    titledir = 0;

  VS_Reset();
  BUF_Play();
  while (!(feof(f) && BUF_GetState() == BUF_STALLED))
  {
    // Read data from mp3 file
    //
    long  len, len1,  len2;
    char *buf1, *buf2;

    BUF_Lock( -1, min(16384L, BUF_GetFreeBytes()),
              &buf1, &len1, &buf2, &len2 );
    len = fread(buf1, 1, len1, f);
    if (buf2)
      len += fread(buf2, 1, len2, f);
    BUF_Unlock(len);

    // Update LCD display
    //
    cleardevice();
    titlepos += titledir;
    if (titlepos > 0)
      titledir = -1;
    if (titledir && (-titlepos > titlewidth-122))
      titledir =  1;
    setfont(bigfont);
    outtextxy( titlepos, 0, title );

    unsigned long header;
    FrameInfo     info;

    VS_GetMPEGHeader(&header);
    MPEG_ParseHeader(header, &info);

    setfont(smallfont);
    moveto(0, 8);
    gprintf(MPEG_HeaderToString(header));

    long tell = ftell(f);
    long size = filelength(fileno(f));

    setfillstyle(INTERLEAVE_FILL, 1);
    rectangle(0, 24, 121, 31);
    bar( 2, 26, 2+(float)tell/(float)size*117.0, 29 );
    moveto(0, 16);
    gprintf("%ld/%ld", tell, size);

    long bytepersec = info.bitrate/8;
    if (bytepersec > 0)
      gprintf("  %ld:%02ld/%ld:%02ld",
        (tell/bytepersec/60), (tell/bytepersec)%60,
        (size/bytepersec/60), (size/bytepersec)%60
      );

    size = BUF_GetSize();
    tell = BUF_GetCount();
    line( 0, 22, 2+(float)tell/(float)size*119.0, 22 );

    LCD_Update();

    // Process user input
    //
    if (kbhit()) {
      BUF_Clear;
      goto Exit;
    }
    while (RC_KeyAvail()) {
      unsigned long key = RC_GetKey();
      switch (key & (RCKEY_PROTO | RCKEY_CODE)) {
        case (RCKEY_RC5 | 0x0c):   // POWER
          BUF_Clear();
          goto Exit;
        case (RCKEY_RC5 | 0x37):   // FAST REWIND
          BUF_Clear(); BUF_Play();
          VS_Reset();
          fseek(f, -filelength(fileno(f))/20, SEEK_CUR);
          break;
        case (RCKEY_RC5 | 0x34):   // FAST FORWARD
          BUF_Clear(); BUF_Play();
          VS_Reset();
          fseek(f, filelength(fileno(f))/20, SEEK_CUR);
          break;
        case (RCKEY_RC5 | 0x11):   // VOLUME DOWN
          vol-=4;
          if (vol<128) vol = 128;
          VS_SetVolume(vol, vol);
          break;
        case (RCKEY_RC5 | 0x10):   // VOLUME UP
          vol+=4;
          if (vol>255) vol = 255;
          VS_SetVolume(vol, vol);
          break;
        default:
          printf("unknown RC code: %lx\n", key);
          break;
      }
    }

    // be nice to other apps
    //
    RTX_Sleep_Time(100);
  }

Exit:
  fclose(f);
}


struct {
  char *filename;
  char *title;
} playlist[256] = {0};

int   numSongs = 0;


void DirTest()
{
  int done;
  struct ffblk ffblk;

  done = findfirst("*.mp3", &ffblk, 0);
  while (!done && numSongs<256)  {
    playlist[numSongs].filename = strdup(ffblk.ff_name);

    FILE *f = fopen(ffblk.ff_name, "rb");
    if (f) {
      ID3v1Tag  tag;
      if (ID3v1_ReadTag(f, &tag))
        playlist[numSongs].title = strdup(tag.title);
      else
        playlist[numSongs].title = strdup(ffblk.ff_name);
      fclose(f);
    } else{
      perror("");
    }
    numSongs++;

    done = findnext(&ffblk);
    cleardevice();
    moveto(0,0);
    gprintf("%d files..", numSongs);
    LCD_Update();
  }

  int currentSong = 0;
  int rcExit = 0;
  for(;;) {
    cleardevice();
    setfillstyle(SOLID_FILL, 1);
    bar(0,0,121,7);

    int j = currentSong;
    for (int i=0; i<4; i++) {
      moveto(1, i*8+1);
      if (i+j < numSongs) {
        setfont(bigfont);
        gprintf("%-03d ", i+j);
        setfont(smallfont);
        gprintf("%s", playlist[i+j].title);
      }
    }
    LCD_Update();

    if (kbhit()) return;
    while (RC_KeyAvail()) {
      unsigned long key = RC_GetKey();
      switch (key & (RCKEY_PROTO | RCKEY_CODE)) {
        case (RCKEY_RC5 | 0x0c):  // power
          goto Exit;
        case (RCKEY_RC5 | 0x36):  // play
          FileTest(playlist[currentSong].filename);
          break;
        case (RCKEY_RC5 | 0x11):  // volume down
          if (currentSong<numSongs-1)
            currentSong++;
          break;
        case (RCKEY_RC5 | 0x10): // volume up
          if (currentSong>0)
            currentSong--;
          break;
        default:
          printf("unknown code: %lx.\n", key);
          break;
      }
    }
  }
Exit:

}


int main(int argc, char* argv[])
{
  if (!CheckBIOS())
    return -1;

  SYS_SetSTDIOFocus(SYS_FOCUS_APP);
  printf("k/os mp3 player v2.0 pre-alpha\n"
         "(c)1999-2001 by thomas.kindler@gmx.de.\n");

  initgraph();
  smallfont = loadfont("a:\\fnt4x6.fnt");
  bigfont   = loadfont("a:\\fnt6x6.fnt");
  setfont(smallfont);
  RC_Init();

  VS_Init();
  BUF_Init(16*1024, 128*1024L);

  if (argc == 2)
    DirTest();
  else
    HttpTest();

  BUF_Done();
  VS_Done(); 
    
  RC_Done();
  closegraph();

  SYS_SetSTDIOFocus(SYS_FOCUS_BOTH);
  printf("done...\n");
  return 0;
}
