21 #include "JackTransportEngine.h"
22 #include "JackClientInterface.h"
23 #include "JackClientControl.h"
24 #include "JackEngineControl.h"
25 #include "JackGlobals.h"
26 #include "JackError.h"
37 JackTransportEngine::JackTransportEngine(): JackAtomicArrayState<
jack_position_t>()
39 fTransportState = JackTransportStopped;
40 fTransportCmd = fPreviousCmd = TransportCommandStop;
41 fSyncTimeout = 10000000;
46 fConditionnal =
false;
52 void JackTransportEngine::SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size)
54 long buf_usecs = (long)((buffer_size * (jack_time_t)1000000) / frame_rate);
55 fSyncTimeLeft = fSyncTimeout / buf_usecs;
56 jack_log(
"SyncTimeout fSyncTimeout = %ld fSyncTimeLeft = %ld", (
long)fSyncTimeout, (
long)fSyncTimeLeft);
60 int JackTransportEngine::ResetTimebase(
int refnum)
62 if (fTimeBaseMaster == refnum) {
64 request->
valid = (jack_position_bits_t)0;
74 int JackTransportEngine::SetTimebaseMaster(
int refnum,
bool conditionnal)
76 if (conditionnal && fTimeBaseMaster > 0) {
77 if (refnum != fTimeBaseMaster) {
78 jack_log(
"conditional timebase for ref = %ld failed: %ld is already the master", refnum, fTimeBaseMaster);
81 jack_log(
"ref = %ld was already timebase master", refnum);
85 fTimeBaseMaster = refnum;
86 fConditionnal = conditionnal;
87 jack_log(
"new timebase master: ref = %ld", refnum);
93 bool JackTransportEngine::CheckAllRolling(JackClientInterface** table)
95 for (
int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
96 JackClientInterface* client = table[i];
97 if (client && client->GetClientControl()->fTransportState != JackTransportRolling) {
98 jack_log(
"CheckAllRolling ref = %ld is not rolling", i);
107 void JackTransportEngine::MakeAllStartingLocating(JackClientInterface** table)
109 for (
int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
110 JackClientInterface* client = table[i];
112 JackClientControl* control = client->GetClientControl();
114 control->fTransportState = (control->fActive && control->fCallback[kRealTimeCallback]) ? JackTransportStarting : JackTransportRolling;
115 control->fTransportSync =
true;
116 control->fTransportTimebase =
true;
117 jack_log(
"MakeAllStartingLocating ref = %ld", i);
123 void JackTransportEngine::MakeAllStopping(JackClientInterface** table)
125 for (
int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
126 JackClientInterface* client = table[i];
128 JackClientControl* control = client->GetClientControl();
129 control->fTransportState = JackTransportStopped;
130 control->fTransportSync =
false;
131 control->fTransportTimebase =
false;
132 jack_log(
"MakeAllStopping ref = %ld", i);
138 void JackTransportEngine::MakeAllLocating(JackClientInterface** table)
140 for (
int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
141 JackClientInterface* client = table[i];
143 JackClientControl* control = client->GetClientControl();
144 control->fTransportState = JackTransportStopped;
145 control->fTransportSync =
true;
146 control->fTransportTimebase =
true;
147 jack_log(
"MakeAllLocating ref = %ld", i);
153 void JackTransportEngine::CycleBegin(jack_nframes_t frame_rate, jack_time_t time)
156 pending->
usecs = time;
162 void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t frame_rate, jack_nframes_t buffer_size)
167 transport_command_t cmd = fTransportCmd;
168 if (cmd != fPreviousCmd) {
170 jack_log(
"transport command: %s", (cmd == TransportCommandStart ?
"Transport start" :
"Transport stop"));
172 cmd = TransportCommandNone;
176 switch (fTransportState) {
178 case JackTransportStopped:
180 if (cmd == TransportCommandStart) {
182 fTransportState = JackTransportStarting;
183 MakeAllStartingLocating(table);
184 SyncTimeout(frame_rate, buffer_size);
185 }
else if (fPendingPos) {
187 MakeAllLocating(table);
191 case JackTransportStarting:
192 if (cmd == TransportCommandStop) {
194 fTransportState = JackTransportStopped;
195 MakeAllStopping(table);
196 }
else if (fPendingPos) {
198 fTransportState = JackTransportStarting;
199 MakeAllStartingLocating(table);
200 SyncTimeout(frame_rate, buffer_size);
201 }
else if (--fSyncTimeLeft == 0 || CheckAllRolling(table)) {
203 jack_log(
"transport starting ==> netstarting frame = %d");
204 fTransportState = JackTransportNetStarting;
206 jack_log(
"transport starting ==> rolling fSyncTimeLeft = %ld", fSyncTimeLeft);
207 fTransportState = JackTransportRolling;
212 case JackTransportRolling:
213 if (cmd == TransportCommandStop) {
214 jack_log(
"transport rolling ==> stopped");
215 fTransportState = JackTransportStopped;
216 MakeAllStopping(table);
217 }
else if (fPendingPos) {
218 jack_log(
"transport rolling ==> starting");
219 fTransportState = JackTransportStarting;
220 MakeAllStartingLocating(table);
221 SyncTimeout(frame_rate, buffer_size);
225 case JackTransportNetStarting:
229 jack_error(
"Invalid JACK transport state: %d", fTransportState);
233 if (fTransportState == JackTransportRolling) {
235 pending->
frame += buffer_size;
244 CopyPosition(request, pending);
255 cur_index = next_index;
258 }
while (cur_index != next_index);
265 CopyPosition(pos, request);
270 jack_transport_state_t JackTransportEngine::Query(
jack_position_t* pos)
277 jack_nframes_t JackTransportEngine::GetCurrentFrame()
280 ReadCurrentPos(&pos);
282 if (fTransportState == JackTransportRolling) {
283 float usecs = GetMicroSeconds() - pos.
usecs;
284 jack_nframes_t elapsed = (jack_nframes_t)floor((((
float) pos.
frame_rate) / 1000000.0f) * usecs);
285 return pos.
frame + elapsed;
307 if (--timeout == 0) {
308 jack_error(
"hung in loop copying position B");
UInt16 GetCurrentIndex()
Returns the current switch counter.
SERVER_EXPORT void jack_error(const char *fmt,...)
jack_position_bits_t valid
jack_position_t * ReadCurrentState()
Returns the current state : only valid in the RT reader thread.
jack_nframes_t frame_rate
jack_position_t * TrySwitchState(int state)
Tries to switch to the next state and returns the new current state (either the same as before if cas...
void WriteNextStateStop(int state)
Stop write operation : make the next state ready to be used by the RT thread.
jack_position_t * WriteNextStateStart(int state)
Start write operation : setup and returns the next state to update, check for recursive write calls...
SERVER_EXPORT void jack_log(const char *fmt,...)