#include "replay.h"
#include <unistd.h>
#include <vdr/osdcontroller.h>
#include <vdr/ringbuffer.h>
#include <vdr/device.h>
#include <vdr/thread.h>
#include "page.h"
#include "sync.h"
#define RINGBUFFERSIZE 1024*100
#define ORIGINAL_OR_COPY_MASK 0x01
#define PRIVATE_STREAM_1 0xBD

using namespace NonInteractiveOsdPatch;

cDvbSubtitlesReplay::cDvbSubtitlesReplay(int Priority, int DataId)
    :  viewer(), decoder(), clearTime(0), dataId(DataId),priority(Priority)

{
  subscribed = false;
  mutex = new cMutex();
  ringBuffer = new cRingBufferFrame(RINGBUFFERSIZE);  
  RecordingController.Subscribe( DataId, this );    
  syncer = GetSynchronizer();
  Start();
}
cDvbSubtitlesReplay::~cDvbSubtitlesReplay()
{
  active = false;
  RecordingController.Unsubscribe( dataId, this );    
  syncer->stop();

  mutex->Lock();
  if (subscribed)
    OsdController.Unsubscribe( &viewer );
  mutex->Unlock();

  Cancel(3);
  delete ringBuffer;
  delete syncer;
  delete mutex;
}
void cDvbSubtitlesReplay::Receive(unsigned char DataIdentifier, unsigned char* Data, int Length)
{

  cFrame* frame = new cFrame( Data, Length );
  if ( !ringBuffer->Put( frame ) )
    delete frame;

}

void cDvbSubtitlesReplay::Action()
{
  active = true;
  while (active)
  {
    cFrame* frame = ringBuffer->Get();
    if (frame)
      {
      unsigned char* data = frame->Data();
      int length = frame->Count();
      //      for (int i = 0; i < 16; i ++)
      //	fprintf(stderr,"%02X ", data[i]);
      //    fprintf(stderr, "\n");
      if ( length >= 9 
	   && data[0] == 0x00 
	   && data[1] == 0x00 
	   && data[2] == 0x01 
	   && data[3] == PRIVATE_STREAM_1 )
      {
	
	if ( data[6] & ORIGINAL_OR_COPY_MASK )
	{
	  decoder.addPesData(data, length, true );
	}
	else
	{
	  int hlength = data[8];
	  length -= 9 + hlength;
	  decoder.addPesData( &data[9+hlength], length, false );
	}
	  
      }
      ringBuffer->Drop( frame );
    }

    if (active && decoder.PageAvailable() )
    {

	mutex->Lock();
	if (!subscribed)
	{
	  OsdController.Subscribe(priority, &viewer);
	  subscribed = true;
	}
	mutex->Unlock();

	cSubtitlesPage* page = decoder.GetPage();
	
	syncer->sync(page->GetPts());

	viewer.SetPage( page );

	if (page->GetTimeout())
	    clearTime = msectime()+page->GetTimeout()*1000;
	else
	    clearTime = 0;
//	delete page;
    }
    
    // page timeout
    if (clearTime > 0 && msectime() > clearTime)
    {
      viewer.Clear();
      clearTime = 0;
    }
    usleep(10000);
  }

}


