//=========================================================
//  MusE
//  Linux Music Editor
//  $Id: audioprefetch.cpp,v 1.1.1.1 2003/10/29 10:05:00 wschweer Exp $
//
//  (C) Copyright 2001 Werner Schweer (ws@seh.de)
//=========================================================

#include <poll.h>
#include <stdio.h>
#include <unistd.h>

#include "audioprefetch.h"
#include "globals.h"
#include "track.h"
#include "song.h"
#include "audio.h"

AudioPrefetch* audioPrefetch;

//---------------------------------------------------------
//   AudioPrefetch
//---------------------------------------------------------

AudioPrefetch::AudioPrefetch(int prio, const char* name)
   : Thread(prio,name)
      {
      readSamplePos = 0;
      seekpos = -1;
      }

//---------------------------------------------------------
//   readMsg
//---------------------------------------------------------

static void readMsgP(void* p, void*)
      {
      AudioPrefetch* at = (AudioPrefetch*)p;
      at->readMsg1(sizeof(PrefetchMsg));
      }

//---------------------------------------------------------
//   start
//---------------------------------------------------------

void AudioPrefetch::start()
      {
      clearPollFd();
      addPollFd(toThreadFdr, POLLIN, ::readMsgP, this, 0);
      Thread::start();
      }

//---------------------------------------------------------
//   ~AudioPrefetch
//---------------------------------------------------------

AudioPrefetch::~AudioPrefetch()
      {
      }

//---------------------------------------------------------
//   processMsg
//---------------------------------------------------------

void AudioPrefetch::processMsg1(const void* m)
      {
      const PrefetchMsg* msg = (PrefetchMsg*)m;
      switch(msg->id) {
            case PREFETCH_TICK:
                  prefetch();
                  break;
            case PREFETCH_SEEK:
                  seek(msg->pos);
                  {
                  int rv = write(fromThreadFdw, m, 4);
                  if (rv != 4)
                        perror("Thread::readMessage(): write pipe failed");
                  }
                  break;
            default:
                  printf("AudioPrefetch::processMsg1: unknown message\n");
            }
      }

//---------------------------------------------------------
//   msgTick
//---------------------------------------------------------

void AudioPrefetch::msgTick()
      {
      if (noAudio)
            return;
      PrefetchMsg msg;
      msg.id  = PREFETCH_TICK;
      while (sendMsg1(&msg, sizeof(msg))) {
            printf("AudioPrefetch::msgTick::sleep(1)\n");
            sleep(1);
            }
      }

//---------------------------------------------------------
//   msgSeek
//---------------------------------------------------------

void AudioPrefetch::msgSeek(int samplePos)
      {
      if (noAudio)
            return;
      PrefetchMsg msg;
      msg.id  = PREFETCH_SEEK;
      msg.pos = samplePos;
      while (sendMsg1(&msg, sizeof(msg)))
            sleep(1);
      // wait for answer
      int rv = read(fromThreadFdr, &msg, 4);
      if (rv != 4) {
            perror("AudioPrefetch:: read pipe failed");
            }
      }

//---------------------------------------------------------
//   prefetch
//---------------------------------------------------------

void AudioPrefetch::prefetch()
      {
      seekpos = -1;
      if (song->record())
            audio->writeTick();
      TrackList* tl = song->tracks();
      for (iTrack it = tl->begin(); it != tl->end(); ++it) {
            if ((*it)->type() != Track::WAVE)
                  continue;
            WaveTrack* track = (WaveTrack*)(*it);
// printf("prefetch %d\n", readSamplePos);
            track->fetchData(readSamplePos, segmentSize);
            }
      readSamplePos += segmentSize;
      }

//---------------------------------------------------------
//   seek
//---------------------------------------------------------

void AudioPrefetch::seek(int pos)
      {
      if (pos == seekpos)
            return;
      readSamplePos = pos;
      TrackList* tl = song->tracks();
// printf("AudioPrefetch::seek(%d)\n", pos);
      for (iTrack it = tl->begin(); it != tl->end(); ++it) {
            if ((*it)->type() != Track::WAVE)
                  continue;
            WaveTrack* track = (WaveTrack*)(*it);
            track->clearPrefetchFifo();
            for (int i = 0; i < FIFO_BUFFER; ++i) {
                  track->fetchData(readSamplePos + i * segmentSize, segmentSize);
                  }
            }
      seekpos = pos;
      readSamplePos += FIFO_BUFFER * segmentSize;
      }

