//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: dummyaudio.cpp,v 1.3.2.1 2004/12/17 21:09:30 spamatica Exp $
//  (C) Copyright 2002-2003 Werner Schweer (ws@seh.de)
//=========================================================

#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <pthread.h>
#include <sys/poll.h>

#include "config.h"
#include "audio.h"
#include "audiodev.h"
#include "globals.h"
#include "song.h"
#include "driver/alsatimer.h"

#define DEBUG_DUMMY 0
//---------------------------------------------------------
//   DummyAudioDevice
//---------------------------------------------------------

class DummyAudioDevice : public AudioDevice {
      pthread_t dummyThread;
      float buffer[1024];

   public:
      Audio::State state;
      int _framePos;
      int playPos;
      
      DummyAudioDevice() {
            state = Audio::STOP;
            _framePos = 0;
            playPos = 0;
            }
      virtual ~DummyAudioDevice() {}

      virtual void start();
      virtual void stop ();
      virtual int framePos() const { 
            if(DEBUG_DUMMY)
                printf("DummyAudioDevice::framePos %d\n", _framePos);
            return _framePos; 
            }

      virtual float* getBuffer(void* /*port*/, unsigned long nframes)
            {
            if (nframes > 1024) {
                  printf("error: segment size > 1024\n");
                  exit(-1);
                  }
            return buffer;
            }

      virtual std::list<QString> outputPorts();
      virtual std::list<QString> inputPorts();

      virtual void registerClient() {}

      virtual void* registerOutPort(const char*) {
            return (void*)1;
            }
      virtual void* registerInPort(const char*) {
            return (void*)2;
            }
      virtual void unregisterPort(void*) {}
      virtual void connect(void*, void*) {}
      virtual void disconnect(void*, void*) {}
      virtual void setPortName(void*, const char*) {}
      virtual void* findPort(const char*) { return 0;}
      virtual QString portName(void*) {
            return QString("mops");
            }
      virtual int getState() { 
//            if(DEBUG_DUMMY)
//                printf("DummyAudioDevice::getState %d\n", state);
      
      return state; }
      virtual unsigned getCurFrame() { 
            if(DEBUG_DUMMY)
                printf("DummyAudioDevice::getCurFrame %d\n", _framePos);
      
      return _framePos; }
      virtual bool isRealtime() { return false; }
      virtual void startTransport() {
            if(DEBUG_DUMMY)
                printf("DummyAudioDevice::startTransport playPos=%d\n", playPos);
            state = Audio::START_PLAY;
            audio->sync(state, playPos);            
            state = Audio::PLAY;
            }
      virtual void stopTransport() {
            if(DEBUG_DUMMY)
                printf("DummyAudioDevice::stopTransport, playPos=%d\n", playPos);
            state = Audio::STOP;
            }
      virtual void seekTransport(unsigned pos) {
            if(DEBUG_DUMMY)
                printf("DummyAudioDevice::seekTransport frame =%d topos=%d\n",playPos,pos);
            playPos = pos;
            Audio::State tempState = state;
            state = Audio::START_PLAY;
            audio->sync(state, playPos);            
            state = tempState;
            }
      virtual void setFreewheel(bool) {}
      };

DummyAudioDevice* dummyAudio;

//---------------------------------------------------------
//   initDummyAudio
//---------------------------------------------------------

bool initDummyAudio()
      {
      dummyAudio = new DummyAudioDevice();
      audioDevice = dummyAudio;
      return false;
      }

//---------------------------------------------------------
//   outputPorts
//---------------------------------------------------------

std::list<QString> DummyAudioDevice::outputPorts()
      {
      std::list<QString> clientList;
      clientList.push_back(QString("output1"));
      clientList.push_back(QString("output2"));
      return clientList;
      }

//---------------------------------------------------------
//   inputPorts
//---------------------------------------------------------

std::list<QString> DummyAudioDevice::inputPorts()
      {
      std::list<QString> clientList;
      clientList.push_back(QString("input1"));
      clientList.push_back(QString("input2"));
      return clientList;
      }

//---------------------------------------------------------
//   dummyLoop
//---------------------------------------------------------

static void* dummyLoop(void* ptr)
      {
      const int tickRate = 32;
      sampleRate = 32768;
      segmentSize = 1024;
      AlsaTimer timer;
      int fd = timer.initTimer();
      timer.setTimerTicks(tickRate);
      timer.startTimer();
      
      //fd_set pFd;
      //FD_SET(fd, &pFd);
      pollfd myPollFd;
      
      myPollFd.fd = fd;
      myPollFd.events = POLLIN;
      
      //int counter=0;
      DummyAudioDevice *drvPtr = (DummyAudioDevice *)ptr;
      for (;;) {
                  
            int _pollWait = 10;   // ms

            int n = poll(&myPollFd, 1 /* npfd */, _pollWait);
            
            timer.getTimerTicks();
            
            /*if (counter == 32) */{
            //      counter=0;
      
                  audio->process(segmentSize);
      
                  //usleep(1000*100); 
                  //                44100   / 1024
                  int increment = 1; //tickRate / sampleRate * segmentSize;
                  //printf("sampleRate =%d, segmentSize=%d increment=%d\n",sampleRate, segmentSize, increment); 
                  
                  drvPtr->_framePos+=increment;
                  if (drvPtr->state == Audio::PLAY) 
                        {
                        //if(DEBUG_DUMMY)
                        //    printf("dummyLoop - play!\n");
                        drvPtr->playPos+=increment;
                        }
                  }
            }
      timer.stopTimer();
      pthread_exit(0);
      }

void DummyAudioDevice::start()
      {
      pthread_attr_t* attributes = (pthread_attr_t*) malloc(sizeof(pthread_attr_t));
      pthread_attr_init(attributes);
      if (pthread_create(&dummyThread, attributes, ::dummyLoop, this))
            perror("creating thread failed:");
      pthread_attr_destroy(attributes);
      }

void DummyAudioDevice::stop ()
      {
      pthread_cancel(dummyThread);
      pthread_join(dummyThread, 0);
      }

