#include "thread.h"
#include "common.h"
#include <unistd.h>

cThreadEm84xx::cThreadEm84xx():
cThread("Em84xx replay"),
mActive(false)
{
}

cThreadEm84xx::~cThreadEm84xx()
{
   Stop();
}

void cThreadEm84xx::Start(void)
{
   if (pipe(mPipe) != 0) {
      LOG_ERROR;
      return;
   }
   fcntl(mPipe[1], F_SETFL, O_NONBLOCK);
   cThread::Start();
}

void cThreadEm84xx::Stop(void)
{
   if (mActive) {
      mActive = false;
      close(mPipe[1]);
      Cancel(3);
   }
}

void cThreadEm84xx::Action(void)
{
   em84MsgHeader header;
   cPoller poller;
   FMP_BUFFER buffer, *fmpbuf = NULL;
   DWORD flags = 0;

   mActive = true;
   FMPPlay();
   while (mActive) {
      poller.Add(mPipe[0], false);
      if (poller.Poll(150)) {
         int r;
         if ((r = safe_read(mPipe[0], &header, sizeof(em84MsgHeader))) == -1) {
            if (mActive) {
               LOG_ERROR;
               mActive = false;
            }
            break;
         }

         switch (header.msgtype) {
            case em84VideoPacket:
            case em84AudioPacket:
               while (header.msglen > 0) {
                  if (fmpbuf == NULL) {
                     DWORD rc;
                     if ((rc = FMPGetBuffer(&buffer, TRUE)) != FMPE_OK) {
                        esyslog("Couldn't allocate em8400 replaybuffer: %lu", rc);
                        mActive = false;
                        break;
                     }
                     fmpbuf = &buffer;
                  }

                  int bytes = min(buffer.dwBufferSize - buffer.dwDataSize, (DWORD)header.msglen);
                  if ((r = safe_read(mPipe[0], buffer.pBuffer + buffer.dwDataSize, bytes))
                      == -1) {
                     if (mActive) {
                        LOG_ERROR;
                        mActive = false;
                     }
                     break;
                  }
//					Dprintf("wanted %d, got %d\n", bytes, r);
                  buffer.dwDataSize += r;
                  header.msglen -= r;

                  if (buffer.dwDataSize == buffer.dwBufferSize) {
                     if (flags & FMP_TRICKMODE_END)
                        flags &= ~FMP_TRICKMODE_SAMPLE;

                     buffer.dwFlags = flags;
//						Dprintf("flags: %x, len = %d\n", flags, buffer.dwDataSize);
                     FMPPush(&buffer);
                     if (flags & FMP_TRICKMODE_START) {
                        flags &= ~FMP_TRICKMODE_START;
                        flags |= FMP_TRICKMODE_SAMPLE;
                     }
                     else if (flags & FMP_TRICKMODE_END) {
                        flags &= ~FMP_TRICKMODE_END;
                     }
                     fmpbuf = NULL;
                  }
               }
               break;

            case em84TrickMode:
               if (header.msglen)
                  flags |= FMP_TRICKMODE_START;
               else if (flags & FMP_TRICKMODE_SAMPLE)
                  flags |= FMP_TRICKMODE_END;
               break;

            default:
               Dprintf("SHOULDNT HAPPEN\n");
         }
      }
   }

   if (fmpbuf != NULL) {
      buffer.dwDataSize = 0;
      FMPPush(&buffer);
      FMPFlush(FALSE);
   }
   FMPStop();
   close(mPipe[0]);
   mActive = false;
}

int cThreadEm84xx::PlayPacket(const uchar *Data, int Length)
{
   uchar buffer[sizeof(em84MsgHeader) + Length];
   em84MsgHeader *header = (em84MsgHeader*)buffer;

   header->msgtype = em84VideoPacket;
   header->msglen  = Length;
   memcpy(buffer + sizeof(em84MsgHeader), Data, Length);

   int r = WriteAllOrNothing(mPipe[1], buffer, sizeof(em84MsgHeader) + Length, 1000, 10);
   return r;
}

void cThreadEm84xx::TrickSpeed(int Speed)
{
   FMPPlay();

   em84MsgHeader header = { em84TrickMode, 1};
   cPoller poller(mPipe[1], true);
   if (poller.Poll(500))
      safe_write(mPipe[1], &header, sizeof(em84MsgHeader));
   else
      esyslog("ERROR: Couldn't issue command on em84xx player thread");
}

void cThreadEm84xx::Play(void)
{
   FMPPlay();

   em84MsgHeader header = { em84TrickMode, 0};
   cPoller poller(mPipe[1], true);
   if (poller.Poll(500))
      safe_write(mPipe[1], &header, sizeof(em84MsgHeader));
   else
      esyslog("ERROR: Couldn't issue command on em84xx player thread");
}

void cThreadEm84xx::Freeze(void)
{
   FMPPause();
}

void cThreadEm84xx::AddPoller(cPoller &Poller)
{
   Poller.Add(mPipe[1], true);
}

