1 /*
2  Copyright (C) 2001 Paul Davis
3  Copyright (C) 2004-2008 Grame
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 
19 */
20 
21 #include "JackSystemDeps.h"
22 #include "JackThreadedDriver.h"
23 #include "JackError.h"
24 #include "JackTools.h"
25 #include "JackGlobals.h"
26 #include "JackEngineControl.h"
27 
28 namespace Jack
29 {
30 
JackThreadedDriver(JackDriver * driver)31 JackThreadedDriver::JackThreadedDriver(JackDriver* driver):fThread(this),fDriver(driver)
32 {}
33 
~JackThreadedDriver()34 JackThreadedDriver::~JackThreadedDriver()
35 {
36     delete fDriver;
37 }
38 
Open()39 int JackThreadedDriver::Open()
40 {
41     return fDriver->Open();
42 }
43 
Open(jack_nframes_t buffer_size,jack_nframes_t samplerate,bool capturing,bool playing,int inchannels,int outchannels,bool monitor,const char * capture_driver_name,const char * playback_driver_name,jack_nframes_t capture_latency,jack_nframes_t playback_latency)44 int JackThreadedDriver::Open(jack_nframes_t buffer_size,
45                              jack_nframes_t samplerate,
46                              bool capturing,
47                              bool playing,
48                              int inchannels,
49                              int outchannels,
50                              bool monitor,
51                              const char* capture_driver_name,
52                              const char* playback_driver_name,
53                              jack_nframes_t capture_latency,
54                              jack_nframes_t playback_latency)
55 {
56     return fDriver->Open(buffer_size,
57                         samplerate, capturing,
58                         playing, inchannels,
59                         outchannels, monitor,
60                         capture_driver_name, playback_driver_name,
61                         capture_latency, playback_latency);
62 }
63 
Close()64 int JackThreadedDriver::Close()
65 {
66     return fDriver->Close();
67 }
68 
Process()69 int JackThreadedDriver::Process()
70 {
71     return fDriver->Process();
72 }
73 
Attach()74 int JackThreadedDriver::Attach()
75 {
76     return fDriver->Attach();
77 }
78 
Detach()79 int JackThreadedDriver::Detach()
80 {
81     return fDriver->Detach();
82 }
83 
Read()84 int JackThreadedDriver::Read()
85 {
86     return fDriver->Read();
87 }
88 
Write()89 int JackThreadedDriver::Write()
90 {
91     return fDriver->Write();
92 }
93 
IsFixedBufferSize()94 bool JackThreadedDriver::IsFixedBufferSize()
95 {
96     return fDriver->IsFixedBufferSize();
97 }
98 
SetBufferSize(jack_nframes_t buffer_size)99 int JackThreadedDriver::SetBufferSize(jack_nframes_t buffer_size)
100 {
101     return fDriver->SetBufferSize(buffer_size);
102 }
103 
SetSampleRate(jack_nframes_t sample_rate)104 int JackThreadedDriver::SetSampleRate(jack_nframes_t sample_rate)
105 {
106     return fDriver->SetSampleRate(sample_rate);
107 }
108 
SetMaster(bool onoff)109 void JackThreadedDriver::SetMaster(bool onoff)
110 {
111     fDriver->SetMaster(onoff);
112 }
113 
GetMaster()114 bool JackThreadedDriver::GetMaster()
115 {
116     return fDriver->GetMaster();
117 }
118 
AddSlave(JackDriverInterface * slave)119 void JackThreadedDriver::AddSlave(JackDriverInterface* slave)
120 {
121     fDriver->AddSlave(slave);
122 }
123 
RemoveSlave(JackDriverInterface * slave)124 void JackThreadedDriver::RemoveSlave(JackDriverInterface* slave)
125 {
126     fDriver->RemoveSlave(slave);
127 }
128 
ProcessReadSlaves()129 int JackThreadedDriver::ProcessReadSlaves()
130 {
131     return fDriver->ProcessReadSlaves();
132 }
133 
ProcessWriteSlaves()134 int JackThreadedDriver::ProcessWriteSlaves()
135 {
136     return fDriver->ProcessWriteSlaves();
137 }
138 
ProcessRead()139 int JackThreadedDriver::ProcessRead()
140 {
141     return fDriver->ProcessRead();
142 }
143 
ProcessWrite()144 int JackThreadedDriver::ProcessWrite()
145 {
146     return fDriver->ProcessWrite();
147 }
148 
ProcessReadSync()149 int JackThreadedDriver::ProcessReadSync()
150 {
151     return fDriver->ProcessReadSync();
152 }
153 
ProcessWriteSync()154 int JackThreadedDriver::ProcessWriteSync()
155 {
156     return fDriver->ProcessWriteSync();
157 }
158 
ProcessReadAsync()159 int JackThreadedDriver::ProcessReadAsync()
160 {
161     return fDriver->ProcessReadAsync();
162 }
163 
ProcessWriteAsync()164 int JackThreadedDriver::ProcessWriteAsync()
165 {
166     return fDriver->ProcessWriteAsync();
167 }
168 
GetSlaves()169 std::list<JackDriverInterface*> JackThreadedDriver::GetSlaves()
170 {
171     return fDriver->GetSlaves();
172 }
173 
ClientNotify(int refnum,const char * name,int notify,int sync,const char * message,int value1,int value2)174 int JackThreadedDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
175 {
176     return fDriver->ClientNotify(refnum, name, notify, sync, message, value1, value2);
177 }
178 
GetClientControl() const179 JackClientControl* JackThreadedDriver::GetClientControl() const
180 {
181     return fDriver->GetClientControl();
182 }
183 
IsRealTime() const184 bool JackThreadedDriver::IsRealTime() const
185 {
186     return fDriver->IsRealTime();
187 }
188 
IsRunning() const189 bool JackThreadedDriver::IsRunning() const
190 {
191     return fDriver->IsRunning();
192 }
193 
Start()194 int JackThreadedDriver::Start()
195 {
196     jack_log("JackThreadedDriver::Start");
197 
198     if (fDriver->Start() < 0) {
199         jack_error("Cannot start driver");
200         return -1;
201     }
202     if (fThread.StartSync() < 0) {
203         jack_error("Cannot start thread");
204         return -1;
205     }
206 
207     return 0;
208 }
209 
Stop()210 int JackThreadedDriver::Stop()
211 {
212     jack_log("JackThreadedDriver::Stop");
213 
214     switch (fThread.GetStatus()) {
215 
216         // Kill the thread in Init phase
217         case JackThread::kStarting:
218         case JackThread::kIniting:
219             if (fThread.Kill() < 0) {
220                 jack_error("Cannot kill thread");
221             }
222             break;
223 
224         // Stop when the thread cycle is finished
225         case JackThread::kRunning:
226             if (fThread.Stop() < 0) {
227                 jack_error("Cannot stop thread");
228             }
229             break;
230 
231         default:
232             break;
233     }
234 
235     if (fDriver->Stop() < 0) {
236         jack_error("Cannot stop driver");
237         return -1;
238     }
239     return 0;
240 }
241 
Execute()242 bool JackThreadedDriver::Execute()
243 {
244     return (Process() == 0);
245 }
246 
Init()247 bool JackThreadedDriver::Init()
248 {
249     if (fDriver->Initialize())  {
250         SetRealTime();
251         return true;
252     } else {
253         return false;
254     }
255 }
256 
SetRealTime()257 void JackThreadedDriver::SetRealTime()
258 {
259     if (fDriver->IsRealTime()) {
260         jack_log("JackThreadedDriver::Init real-time");
261         // Will do "something" on OSX only...
262         GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
263         GetEngineControl()->fComputation = JackTools::ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000;
264         fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
265         if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
266             jack_error("AcquireSelfRealTime error");
267         } else {
268             set_threaded_log_function();
269         }
270     } else {
271         jack_log("JackThreadedDriver::Init non-realtime");
272     }
273 }
274 
275 
276 } // end of namespace
277