/* MPEG/WAVE Sound library

   (C) 1997 by Jung woo-jae */

// Fileplayer.cc
// It's an example for how to use MPEG/WAVE Sound library

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <unistd.h>

#include "mpegsound.h"

// File player superclass
Fileplayer::Fileplayer()
{
  __errorcode=SOUND_ERROR_OK;
  player=NULL;
};

Fileplayer::~Fileplayer()
{
  delete player;
};


// Wave file player
Wavefileplayer::Wavefileplayer()
{
  loader=NULL;
  server=NULL;
}

Wavefileplayer::~Wavefileplayer()
{
  if(loader)delete loader;
  if(server)delete server;
}

bool Wavefileplayer::openfile(char *filename,const char *device)
{
// Player
  if(device==NULL)device=Rawplayer::defaultdevice;

  if(device[0]=='/')player=new Rawplayer;
  else 
  {
    if(strstr(device,".WAV") || strstr(device,".wav"))
      player=new Rawtowav;
    else
      player=new Rawtofile;
    if(device[0]=='-')device=NULL;
  }

  if(player==NULL)
    return seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH);
  if(!player->initialize(device))return seterrorcode(player->geterrorcode());

// Loader
  {
    int err;

    if((loader=Soundinputstream::hopen(filename,&err))==NULL)
      return seterrorcode(err);
  }

// Server
  if((server=new Wavetoraw(loader,player))==NULL)
    return seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH);
  return server->initialize();
}

void Wavefileplayer::setforcetomono(bool flag)
{
  server->setforcetomono(flag);
};

bool Wavefileplayer::playing(int verbose)
{
  if(!server->run())return false; // Read first time

  if(verbose>0)
  {
    fprintf(stderr,
	    "Verbose : %dbits, "
	    "%dHz, "
	    "%s\n",
	    server->getsamplesize(),
	    server->getfrequency(),
	    server->isstereo()?"Stereo":"Mono");
  }

  while(server->run());           // Playing

  seterrorcode(server->geterrorcode());
  if(geterrorcode()==SOUND_ERROR_FINISH)return true;
  return false;
}




// Mpegfileplayer
Mpegfileplayer::Mpegfileplayer()
{
  loader=NULL;
  server=NULL;
};

Mpegfileplayer::~Mpegfileplayer()
{
  if(loader)delete loader;
  if(server)delete server;
}

bool Mpegfileplayer::openfile(char *filename,const char *device)
{
// Player
  if(device==NULL)device=Rawplayer::defaultdevice;

  if(device[0]=='/')player=new Rawplayer;
  else 
  {
    if(strstr(device,".WAV") || strstr(device,".wav"))
      player=new Rawtowav;
    else
      player=new Rawtofile;
    if(device[0]=='-')device=NULL;
  }

  if(player==NULL)
    return seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH);
  if(!player->initialize(device))
    return seterrorcode(player->geterrorcode());

// Loader
  {
    int err;
    if((loader=Soundinputstream::hopen(filename,&err))==NULL)
      return seterrorcode(err);
  }

// Server
  if((server=new Mpegwavtoraw(loader,player))==NULL)
    return seterrorcode(SOUND_ERROR_MEMORYNOTENOUGH);

// Initialize server
  server->initialize(filename);
  return true;
}

void Mpegfileplayer::setforcetomono(bool flag)
{
  server->setforcetomono(flag);
};

void Mpegfileplayer::setdownfrequency(int value)
{
  server->setdownfrequency(value);
};

#ifdef __DJGPP__
#include <dpmi.h>
#define ReleaseCPU() __dpmi_yield()
#else
#define ReleaseCPU() usleep(10)
#endif

bool Mpegfileplayer::playing(int verbose)
{
  if(!server->startplay())return false;       // Initialize MPEG Layer 3
  if(verbose>0)showverbose(verbose);
  do
    {
     while(!server->callformore()) ReleaseCPU();
    }
  while(server->run(1));                // Playing

  seterrorcode(server->geterrorcode());
  if(seterrorcode(SOUND_ERROR_FINISH))return true;
  return false;
}

#ifdef PTHREADEDMPEG
bool Mpegfileplayer::playingwiththread(int verbose,int framenumbers)
{
  if(framenumbers<20)return playing(verbose);

  server->makethreadedplayer(framenumbers);

  if(!server->run(-1))return false;       // Initialize MPEG Layer 3
  if(verbose>0)showverbose(verbose);
  while(server->run(100));                // Playing
  server->freethreadedplayer();
  
  seterrorcode(server->geterrorcode());
  if(seterrorcode(SOUND_ERROR_FINISH))return true;
  return false;
}
#endif

void Mpegfileplayer::showverbose(int verbose)
{
  static const char *modestring[4]={"stereo","joint stereo","dual channel","mono"};

  fprintf(stderr,"Verbose: MPEG-%d Layer %d, %s,\n\t%dHz%s, %dkbit/s, ",
	  server->getversion()+1,
	  server->getlayer(),modestring[server->getmode()],
	  server->getfrequency(),server->getdownfrequency()?"/2":"",
	  server->getbitrate());
  fprintf(stderr,server->getcrccheck() 
	  ? "with crc check\n" 
	  : "without crc check\n");
  if(verbose>1)
  {
    fprintf(stderr,
	    "Songname : %s\n"
	    "Artist   : %s\n"
	    "Album    : %s\n"
	    "Year     : %s\n"
	    "Comment  : %s\n"
       "Genre    : %s\n",
	    server->getname(),
	    server->getartist(),
	    server->getalbum(),
	    server->getyear(),
	    server->getcomment(),
       server->getgenre());
  }
}

bool Mpegfileplayer::startplay(void)
{
  return server->startplay();
}

bool Mpegfileplayer::callformore(void)
{
  return server->callformore();
}

bool Mpegfileplayer::playmore(void)
{
  server->run(1);
  seterrorcode(server->geterrorcode());
  if(seterrorcode(SOUND_ERROR_FINISH))return false;
  return true;
}

