1 /*
2   ZynAddSubFX - a software synthesizer
3 
4   OSSaudiooutput.C - Audio output for Open Sound System
5   Copyright (C) 2002-2005 Nasca Octavian Paul
6   Author: Nasca Octavian Paul
7 
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License
10   as published by the Free Software Foundation; either version 2
11   of the License, or (at your option) any later version.
12 */
13 
14 #include "NulEngine.h"
15 #include "../globals.h"
16 #include "../Misc/Util.h"
17 
18 #include <iostream>
19 using namespace std;
20 
21 namespace zyn {
22 
NulEngine(const SYNTH_T & synth_)23 NulEngine::NulEngine(const SYNTH_T &synth_)
24     :AudioOut(synth_), pThread(NULL)
25 {
26     name = "NULL";
27     playing_until.tv_sec  = 0;
28     playing_until.tv_usec = 0;
29 }
30 
_AudioThread(void * arg)31 void *NulEngine::_AudioThread(void *arg)
32 {
33     return (static_cast<NulEngine *>(arg))->AudioThread();
34 }
35 
AudioThread()36 void *NulEngine::AudioThread()
37 {
38     while(pThread) {
39         getNext();
40 
41         struct timeval now;
42         int remaining = 0;
43         gettimeofday(&now, NULL);
44         if((playing_until.tv_usec == 0) && (playing_until.tv_sec == 0)) {
45             playing_until.tv_usec = now.tv_usec;
46             playing_until.tv_sec  = now.tv_sec;
47         }
48         else {
49             remaining = (playing_until.tv_usec - now.tv_usec)
50                         + (playing_until.tv_sec - now.tv_sec) * 1000000;
51             if(remaining > 10000) //Don't sleep() less than 10ms.
52                 //This will add latency...
53                 os_usleep(remaining  - 10000);
54             if(remaining < 0)
55                 cerr << "WARNING - too late" << endl;
56         }
57         playing_until.tv_usec += synth.buffersize * 1000000
58                                  / synth.samplerate;
59         if(remaining < 0)
60             playing_until.tv_usec -= remaining;
61         playing_until.tv_sec  += playing_until.tv_usec / 1000000;
62         playing_until.tv_usec %= 1000000;
63     }
64     return NULL;
65 }
66 
~NulEngine()67 NulEngine::~NulEngine()
68 {}
69 
Start()70 bool NulEngine::Start()
71 {
72     setAudioEn(true);
73     return getAudioEn();
74 }
75 
Stop()76 void NulEngine::Stop()
77 {
78     setAudioEn(false);
79 }
80 
setAudioEn(bool nval)81 void NulEngine::setAudioEn(bool nval)
82 {
83     if(nval) {
84         if(!getAudioEn()) {
85             pthread_t     *thread = new pthread_t;
86             pthread_attr_t attr;
87             pthread_attr_init(&attr);
88             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
89             pThread = thread;
90             pthread_create(pThread, &attr, _AudioThread, this);
91         }
92     }
93     else
94     if(getAudioEn()) {
95         pthread_t *thread = pThread;
96         pThread = NULL;
97         pthread_join(*thread, NULL);
98         delete thread;
99     }
100 }
101 
getAudioEn() const102 bool NulEngine::getAudioEn() const
103 {
104     return pThread;
105 }
106 
107 }
108