#include "movieIO.h"
#include <malloc.h>

movieIO::movieIO()
  : filename_(0), basename_(0), extension_(0),
    width_(-1), height_(-1), length_(-1), playRate_(30.0f),
    bwFrameList_(0), bwFrameListSize_(0),
    rgbFrameList_(0), rgbFrameListSize_(0)
{
}

movieIO::movieIO( int width, int height, int length )
  : filename_(0), basename_("temp"), extension_(0),
    width_(width), height_(height), length_(length), playRate_(30.0f),
    bwFrameList_(0), bwFrameListSize_(0),
    rgbFrameList_(0), rgbFrameListSize_(0)
{
}

movieIO::~movieIO()
{
  if ( (bwFrameList_!=0) && (bwFrameListSize_>0) )
  {
    for ( int i=0; i<bwFrameListSize_; i++ )
    {
      if ( bwFrameList_[i]!=0 ) delBWFrame( bwFrameList_[i] );
    }
    free( bwFrameList_ );
  }
  if ( (rgbFrameList_!=0) && (rgbFrameListSize_>0) )
  {
    for ( int i=0; i<rgbFrameListSize_; i++ )
    {
      if ( rgbFrameList_[i]!=0 ) delRGBFrame( rgbFrameList_[i] );
    }
    free( rgbFrameList_ );
  }
  if ( filename_!=0 )
    free( filename_ );
  if ( basename_!=0 )
    free( basename_ );
  if ( extension_!=0 )
    free( extension_ );
}

void
movieIO::splitFilename( const char *filename, char *basename, char *extension )
{
  if ( strrchr(filename,'.')!=0 )
  {
    strncpy( basename, filename, strrchr(filename,'.')-filename );
    strcpy( extension,  strrchr(filename,'.')+1 );
  }
  else
  {
    strcpy( basename, filename );
    extension[0]=0;
  }
}

bwImage *
movieIO::getBWFrame( int frameNum )
{
  if ( bwFrameList_==0 )
  { // first run
    bwFrameList_ = (bwImage**)calloc( 10, sizeof(bwImage*) );
    if ( bwFrameList_==0 ) return 0;
    bwFrameListSize_ = 10;
  }
  
  for ( int i=0; i<bwFrameListSize_; i++ )
  {
    if ( bwFrameList_[i]==0 )
    {
      bwFrameList_[i] = deepBWFrame(frameNum);
      return bwFrameList_[i];
    }
  }
  
  // Cache too small
  int newFrameListSize_ = bwFrameListSize_ * 1.5;
  bwImage **newFrameList_ =
    (bwImage**)realloc( bwFrameList_, newFrameListSize_*sizeof(bwImage*) );
  if ( newFrameList_==0 ) return 0;
  for ( i=bwFrameListSize_; i<newFrameListSize_; i++ )
  {
    newFrameList_[i] = 0;
  }
  i = bwFrameListSize_;
  bwFrameList_ = newFrameList_;
  bwFrameListSize_ = newFrameListSize_;
  bwFrameList_[i] = deepBWFrame(frameNum);
  return bwFrameList_[i];
}

void
movieIO::releaseBWFrame( bwImage *framePtr )
{
  for ( int i=0; i<bwFrameListSize_; i++ )
  {
    if ( bwFrameList_[i]==framePtr )
    {
      delBWFrame( bwFrameList_[i] );
      bwFrameList_[i] = 0;
      return;
    }
  }
}

rgbImage *
movieIO::getRGBFrame( int frameNum )
{
  if ( rgbFrameList_==0 )
  { // first run
    rgbFrameList_ = (rgbImage**)calloc( 10, sizeof(rgbImage*) );
    if ( rgbFrameList_==0 ) return 0;
    rgbFrameListSize_ = 10;
  }
  
  for ( int i=0; i<rgbFrameListSize_; i++ )
  {
    if ( rgbFrameList_[i]==0 )
    {
      rgbFrameList_[i] = deepRGBFrame(frameNum);
      return rgbFrameList_[i];
    }
  }
  
  // Cache too small
  int newFrameListSize_ = rgbFrameListSize_ * 1.5;
  rgbImage **newFrameList_ =
    (rgbImage**)realloc( rgbFrameList_, newFrameListSize_*sizeof(rgbImage*) );
  if ( newFrameList_==0 ) return 0;
  for ( i=rgbFrameListSize_; i<newFrameListSize_; i++ )
  {
    newFrameList_[i] = 0;
  }
  i = rgbFrameListSize_;
  rgbFrameList_ = newFrameList_;
  rgbFrameListSize_ = newFrameListSize_;
  rgbFrameList_[i] = deepRGBFrame(frameNum);
  return rgbFrameList_[i];
}

void
movieIO::releaseRGBFrame( rgbImage *framePtr )
{
  for ( int i=0; i<rgbFrameListSize_; i++ )
  {
    if ( rgbFrameList_[i]==framePtr )
    {
      delRGBFrame( rgbFrameList_[i] );
      rgbFrameList_[i] = 0;
      return;
    }
  }
}

// platform specific movie IO
#ifdef IRIX
#  include "movieIO_IRIX.C"
#elif defined (WIN32)
#  include "movieIO_Win32.C"
#elif defined (LINUX)
#  include "movieIO_Linux.C"
#else
#  error "No platform specification.  Couldn't compile movieIO"
#endif

