Browse Source

Transport timebase fix (in progress).

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2061 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/0.71
sletz 17 years ago
parent
commit
8b1f62a550
9 changed files with 200 additions and 177 deletions
  1. +4
    -1
      ChangeLog
  2. +39
    -86
      common/JackClient.cpp
  3. +4
    -0
      common/JackClientControl.h
  4. +2
    -2
      common/JackEngine.cpp
  5. +43
    -49
      common/JackTransportEngine.cpp
  6. +41
    -2
      common/JackTransportEngine.h
  7. +14
    -14
      common/jack/jack.h
  8. +0
    -1
      common/jack/transport.h
  9. +53
    -22
      common/transport_types.h

+ 4
- 1
ChangeLog View File

@@ -20,8 +20,11 @@ Fernando Lopez-Lezcano
Jackdmp changes log Jackdmp changes log
--------------------------- ---------------------------


2008-03-20 Stephane Letz <letz@grame.fr>
* Transport timebase fix (in progress).


2008-03-10 Stephane Letz <letz@grame.fr>
2008-03-19 Stephane Letz <letz@grame.fr>
* Synchronise transport.h with latest jackd version (Video handling). * Synchronise transport.h with latest jackd version (Video handling).




+ 39
- 86
common/JackClient.cpp View File

@@ -254,19 +254,15 @@ int JackClient::Activate()
if (StartThread() < 0) if (StartThread() < 0)
return -1; return -1;
/* seems just useless
if (fSync != NULL) // If a SyncCallback is pending...
SetSyncCallback(fSync, fSyncArg);

if (fTimebase != NULL) // If a TimebaseCallback is pending...
SetTimebaseCallback(fConditionnal, fTimebase, fTimebaseArg);
*/
/* /*
Insertion of client in the graph will cause a kGraphOrderCallback notification Insertion of client in the graph will cause a kGraphOrderCallback notification
to be delivered by the server, the client wants to receive it. to be delivered by the server, the client wants to receive it.
*/ */
GetClientControl()->fActive = true; GetClientControl()->fActive = true;
// Transport related callback become "active"
GetClientControl()->fTransportSync = true;
GetClientControl()->fTransportTimebase = true;


int result = -1; int result = -1;
fChannel->ClientActivate(GetClientControl()->fRefNum, &result); fChannel->ClientActivate(GetClientControl()->fRefNum, &result);
@@ -283,6 +279,11 @@ int JackClient::Deactivate()
return 0; return 0;


GetClientControl()->fActive = false; GetClientControl()->fActive = false;
// Transport related callback become "unactive"
GetClientControl()->fTransportSync = false;
GetClientControl()->fTransportTimebase = false;
int result = -1; int result = -1;
fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);


@@ -606,6 +607,7 @@ int JackClient::ReleaseTimebase()
int result = -1; int result = -1;
fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result); fChannel->ReleaseTimebase(GetClientControl()->fRefNum, &result);
if (result == 0) { if (result == 0) {
GetClientControl()->fTransportTimebase = false;
fTimebase = NULL; fTimebase = NULL;
fTimebaseArg = NULL; fTimebaseArg = NULL;
} }
@@ -615,10 +617,9 @@ int JackClient::ReleaseTimebase()
/* Call the server if the client is active, otherwise keeps the arguments */ /* Call the server if the client is active, otherwise keeps the arguments */
int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg) int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
{ {
if (IsActive())
GetClientControl()->fTransportState = (sync_callback == NULL) ? JackTransportStopped : JackTransportSynching;
fSync = sync_callback;
GetClientControl()->fTransportSync = (fSync != NULL);
fSyncArg = arg; fSyncArg = arg;
fSync = sync_callback;
return 0; return 0;
} }


@@ -628,38 +629,13 @@ int JackClient::SetSyncTimeout(jack_time_t timeout)
return 0; return 0;
} }


/* Call the server if the client is active, otherwise keeps the arguments */
/*
int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
{
if (IsActive()) {
int result = -1;
fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
jack_log("SetTimebaseCallback result = %ld", result);
if (result == 0) {
fTimebase = timebase_callback;
fTimebaseArg = arg;
} else {
fTimebase = NULL;
fTimebaseArg = NULL;
}
jack_log("SetTimebaseCallback OK result = %ld", result);
return result;
} else {
fTimebase = timebase_callback;
fTimebaseArg = arg;
fConditionnal = conditional;
return 0;
}
}
*/

int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg) int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
{ {
int result = -1; int result = -1;
fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result); fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
jack_log("SetTimebaseCallback result = %ld", result); jack_log("SetTimebaseCallback result = %ld", result);
if (result == 0) { if (result == 0) {
GetClientControl()->fTransportTimebase = true;
fTimebase = timebase_callback; fTimebase = timebase_callback;
fTimebaseArg = arg; fTimebaseArg = arg;
} else { } else {
@@ -731,68 +707,45 @@ void JackClient::TransportStop()
} }


// Never called concurently with the server // Never called concurently with the server
// TODO check concurency with SetSyncCallback

// TODO check concurrency with SetSyncCallback
void JackClient::CallSyncCallback() void JackClient::CallSyncCallback()
{ {
JackTransportEngine& transport = GetEngineControl()->fTransport;
jack_position_t* cur_pos = transport.ReadCurrentState();
jack_transport_state_t transport_state = transport.GetState();
switch (transport_state) {
case JackTransportStarting: // Starting...
if (fSync == NULL) {
if (GetClientControl()->fTransportSync) {
JackTransportEngine& transport = GetEngineControl()->fTransport;
jack_position_t* cur_pos = transport.ReadCurrentState();
jack_transport_state_t transport_state = transport.GetState();
if (fSync != NULL) {
if (fSync(transport_state, cur_pos, fSyncArg)) {
GetClientControl()->fTransportState = JackTransportRolling; GetClientControl()->fTransportState = JackTransportRolling;
} else if (GetClientControl()->fTransportState == JackTransportStarting) {
if (fSync(transport_state, cur_pos, fSyncArg))
GetClientControl()->fTransportState = JackTransportRolling;
GetClientControl()->fTransportSync = false;
} }
break;

case JackTransportRolling:
if (fSync != NULL && GetClientControl()->fTransportState == JackTransportStarting) { // Client still not ready
if (fSync(transport_state, cur_pos, fSyncArg))
GetClientControl()->fTransportState = JackTransportRolling;
}
break;

case JackTransportSynching:
// New pos when transport engine is stopped...
if (fSync != NULL) {
fSync(JackTransportStopped, cur_pos, fSyncArg);
GetClientControl()->fTransportState = JackTransportStopped;
}
break;

default:
break;
} else {
GetClientControl()->fTransportState = JackTransportRolling;
GetClientControl()->fTransportSync = false;
}
} }
} }


void JackClient::CallTimebaseCallback() void JackClient::CallTimebaseCallback()
{ {
JackTransportEngine& transport = GetEngineControl()->fTransport; JackTransportEngine& transport = GetEngineControl()->fTransport;
if (fTimebase != NULL && GetClientControl()->fRefNum == transport.GetTimebaseMaster()) {
if (GetClientControl()->fRefNum == transport.GetTimebaseMaster()) { // Client *is* timebase...
jack_transport_state_t transport_state = transport.GetState(); jack_transport_state_t transport_state = transport.GetState();
jack_position_t* cur_pos = transport.WriteNextStateStart(1); jack_position_t* cur_pos = transport.WriteNextStateStart(1);

switch (transport_state) {

case JackTransportRolling:
fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
break;

case JackTransportSynching:
fTimebase(JackTransportStopped, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
break;

default:
break;
if (transport_state == JackTransportRolling) {
assert(fTimebase);
fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, false, fTimebaseArg);
} else if (GetClientControl()->fTransportTimebase) {
assert(fTimebase);
fTimebase(transport_state, GetEngineControl()->fBufferSize, cur_pos, true, fTimebaseArg);
GetClientControl()->fTransportTimebase = true; // Callback is called only once with "new_pos" = true
} }
transport.WriteNextStateStop(1); transport.WriteNextStateStop(1);
} }
} }


+ 4
- 0
common/JackClientControl.h View File

@@ -39,6 +39,8 @@ struct JackClientControl : public JackShmMem
char fName[JACK_CLIENT_NAME_SIZE + 1]; char fName[JACK_CLIENT_NAME_SIZE + 1];
bool fCallback[kMaxNotification]; bool fCallback[kMaxNotification];
volatile jack_transport_state_t fTransportState; volatile jack_transport_state_t fTransportState;
volatile bool fTransportSync; /* Will be true when slow-sync cb has to be called */
volatile bool fTransportTimebase; /* Will be true when timebase cb is called with new_pos on */
int fRefNum; int fRefNum;
bool fActive; bool fActive;


@@ -71,6 +73,8 @@ struct JackClientControl : public JackShmMem
fCallback[kStopFreewheelCallback] = true; fCallback[kStopFreewheelCallback] = true;
fRefNum = refnum; fRefNum = refnum;
fTransportState = JackTransportStopped; fTransportState = JackTransportStopped;
fTransportSync = false;
fTransportTimebase = false;
fActive = false; fActive = false;
} }




+ 2
- 2
common/JackEngine.cpp View File

@@ -374,7 +374,7 @@ int JackEngine::ClientCheck(const char* name, char* name_res, int protocol, int
*status = 0; *status = 0;
strcpy(name_res, name); strcpy(name_res, name);


jack_log("Check protocol client %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
jack_log("Check protocol client %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);


if (protocol != JACK_PROTOCOL_VERSION) { if (protocol != JACK_PROTOCOL_VERSION) {
*status |= (JackFailure | JackVersionError); *status |= (JackFailure | JackVersionError);
@@ -561,7 +561,7 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai
// Remove the client from the table // Remove the client from the table
ReleaseRefnum(refnum); ReleaseRefnum(refnum);


// Notiy unregister
// Notify unregister
jack_int_t ports[PORT_NUM_FOR_CLIENT]; jack_int_t ports[PORT_NUM_FOR_CLIENT];
int i; int i;




+ 43
- 49
common/JackTransportEngine.cpp View File

@@ -44,11 +44,12 @@ JackTransportEngine::JackTransportEngine(): JackAtomicArrayState<jack_position_t
// compute the number of cycle for timeout // compute the number of cycle for timeout
void JackTransportEngine::SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size) void JackTransportEngine::SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size)
{ {
long buf_usecs = (long)((buffer_size * (jack_time_t) 1000000) / frame_rate);
long buf_usecs = (long)((buffer_size * (jack_time_t)1000000) / frame_rate);
fSyncTimeLeft = fSyncTimeout / buf_usecs; fSyncTimeLeft = fSyncTimeout / buf_usecs;
jack_log("SyncTimeout fSyncTimeout = %ld fSyncTimeLeft = %ld", (long)fSyncTimeout, (long)fSyncTimeLeft); jack_log("SyncTimeout fSyncTimeout = %ld fSyncTimeLeft = %ld", (long)fSyncTimeout, (long)fSyncTimeLeft);
} }


// Server
int JackTransportEngine::ResetTimebase(int refnum) int JackTransportEngine::ResetTimebase(int refnum)
{ {
if (fTimeBaseMaster == refnum) { if (fTimeBaseMaster == refnum) {
@@ -62,6 +63,7 @@ int JackTransportEngine::ResetTimebase(int refnum)
} }
} }


// Server
int JackTransportEngine::SetTimebase(int refnum, bool conditionnal) int JackTransportEngine::SetTimebase(int refnum, bool conditionnal)
{ {
if (conditionnal && fTimeBaseMaster > 0) { if (conditionnal && fTimeBaseMaster > 0) {
@@ -79,44 +81,50 @@ int JackTransportEngine::SetTimebase(int refnum, bool conditionnal)
} }
} }


bool JackTransportEngine::CheckOneSynching(JackClientInterface** table)
// RT
bool JackTransportEngine::CheckAllRolling(JackClientInterface** table)
{ {
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i]; JackClientInterface* client = table[i];
if (client && client->GetClientControl()->fTransportState == JackTransportSynching) {
jack_log("CheckOneSynching");
return true;
if (client && client->GetClientControl()->fTransportState != JackTransportRolling) {
jack_log("CheckAllRolling ref = %ld is not rolling", i);
return false;
} }
} }
return false;
jack_log("CheckAllRolling");
return true;
} }


bool JackTransportEngine::CheckAllRolling(JackClientInterface** table)
// RT
void JackTransportEngine::MakeAllStartingLocating(JackClientInterface** table)
{ {
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i]; JackClientInterface* client = table[i];
if (client && client->GetClientControl()->fTransportState != JackTransportRolling) {
jack_log("CheckAllRolling refnum = %ld is not rolling", i);
return false;
if (client) {
// Inactive clients don't have their process function called at all, so they appear as already "rolling" for the transport....
client->GetClientControl()->fTransportState = (client->GetClientControl()->fActive) ? JackTransportStarting : JackTransportRolling;
client->GetClientControl()->fTransportSync = true;
client->GetClientControl()->fTransportTimebase = true;
jack_log("MakeAllStartingLocating ref = %ld", i);
} }
} }
jack_log("CheckAllRolling");
return true;
} }


void JackTransportEngine::MakeAllStarting(JackClientInterface** table)
// RT
void JackTransportEngine::MakeAllStopping(JackClientInterface** table)
{ {
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i]; JackClientInterface* client = table[i];
if (client) { if (client) {
// Unactive clients don't have their process function called at all, they appear as already "rolling" for the transport....
client->GetClientControl()->fTransportState = (client->GetClientControl()->fActive) ? JackTransportStarting : JackTransportRolling;
jack_log("MakeAllStarting refnum = %ld", i);
client->GetClientControl()->fTransportSync = false;
client->GetClientControl()->fTransportTimebase = false;
client->GetClientControl()->fTransportState = JackTransportStopped;
jack_log("MakeAllStopping ref = %ld", i);
} }
} }
jack_log("MakeAllStarting");
} }


// RT
void JackTransportEngine::CycleBegin(jack_nframes_t frame_rate, jack_time_t time) // really needed?? (would be done in CycleEnd...) void JackTransportEngine::CycleBegin(jack_nframes_t frame_rate, jack_time_t time) // really needed?? (would be done in CycleEnd...)
{ {
jack_position_t* pending = WriteNextStateStart(1); // Update "pending" state jack_position_t* pending = WriteNextStateStart(1); // Update "pending" state
@@ -125,6 +133,7 @@ void JackTransportEngine::CycleBegin(jack_nframes_t frame_rate, jack_time_t time
WriteNextStateStop(1); WriteNextStateStop(1);
} }


// RT
void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t frame_rate, jack_nframes_t buffer_size) void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t frame_rate, jack_nframes_t buffer_size)
{ {
TrySwitchState(1); // Switch from "pending" to "current", it always works since there is always a pending state TrySwitchState(1); // Switch from "pending" to "current", it always works since there is always a pending state
@@ -141,59 +150,42 @@ void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t f
/* state transition switch */ /* state transition switch */
switch (fTransportState) { switch (fTransportState) {


case JackTransportSynching:
if (cmd == TransportCommandStart) {
fTransportState = JackTransportStarting;
MakeAllStarting(table);
SyncTimeout(frame_rate, buffer_size);
jack_log("transport locate ==> starting....");
} else if (fPendingPos) {
fTransportState = JackTransportSynching;
jack_log("transport locate ==> locate....");
} else {
fTransportState = JackTransportStopped;
jack_log("transport locate ==> stopped....");
}
break;

case JackTransportStopped: case JackTransportStopped:
// Set a JackTransportStarting for the current cycle, if all clients are ready (now slow_sync) ==> JackTransportRolling next state
// Set a JackTransportStarting for the current cycle, if all clients are ready (no slow_sync) ==> JackTransportRolling next state
if (cmd == TransportCommandStart) { if (cmd == TransportCommandStart) {
jack_log("transport stopped ==> starting");
fTransportState = JackTransportStarting; fTransportState = JackTransportStarting;
MakeAllStarting(table);
MakeAllStartingLocating(table);
SyncTimeout(frame_rate, buffer_size); SyncTimeout(frame_rate, buffer_size);
jack_log("transport stopped ==> starting....");
} else if (fPendingPos || CheckOneSynching(table)) {
fTransportState = JackTransportSynching;
jack_log("transport stopped ==> locate....");
}
}
break; break;


case JackTransportStarting: case JackTransportStarting:
jack_log("transport starting fSyncTimeLeft %ld", fSyncTimeLeft);

if (cmd == TransportCommandStop) { if (cmd == TransportCommandStop) {
fTransportState = JackTransportStopped;
jack_log("transport starting ==> stopped"); jack_log("transport starting ==> stopped");
fTransportState = JackTransportStopped;
MakeAllStopping(table);
} else if (fPendingPos) { } else if (fPendingPos) {
jack_log("transport starting ==> starting");
fTransportState = JackTransportStarting; fTransportState = JackTransportStarting;
MakeAllStarting(table);
MakeAllStartingLocating(table);
SyncTimeout(frame_rate, buffer_size); SyncTimeout(frame_rate, buffer_size);
} else if (--fSyncTimeLeft == 0 || CheckAllRolling(table)) {
} else if (--fSyncTimeLeft == 0 || CheckAllRolling(table)) { // Slow clients may still catch up
jack_log("transport starting ==> rolling fSyncTimeLeft = %ld", fSyncTimeLeft);
fTransportState = JackTransportRolling; fTransportState = JackTransportRolling;
jack_log("transport starting ==> rolling.... fSyncTimeLeft %ld", fSyncTimeLeft);
} }
break; break;


case JackTransportRolling: case JackTransportRolling:
if (cmd == TransportCommandStop) { if (cmd == TransportCommandStop) {
fTransportState = JackTransportStopped;
jack_log("transport rolling ==> stopped"); jack_log("transport rolling ==> stopped");
} else if (fPendingPos || CheckOneSynching(table)) {
fTransportState = JackTransportStopped;
MakeAllStopping(table);
} else if (fPendingPos) {
jack_log("transport rolling ==> starting");
fTransportState = JackTransportStarting; fTransportState = JackTransportStarting;
MakeAllStarting(table);
MakeAllStartingLocating(table);
SyncTimeout(frame_rate, buffer_size); SyncTimeout(frame_rate, buffer_size);
jack_log("transport rolling ==> starting....");
} }
break; break;


@@ -218,6 +210,7 @@ void JackTransportEngine::CycleEnd(JackClientInterface** table, jack_nframes_t f
} }
} }


// Client
void JackTransportEngine::ReadCurrentPos(jack_position_t* pos) void JackTransportEngine::ReadCurrentPos(jack_position_t* pos)
{ {
UInt16 next_index = GetCurrentIndex(); UInt16 next_index = GetCurrentIndex();
@@ -229,6 +222,7 @@ void JackTransportEngine::ReadCurrentPos(jack_position_t* pos)
} while (cur_index != next_index); // Until a coherent state has been read } while (cur_index != next_index); // Until a coherent state has been read
} }


// RT, client
void JackTransportEngine::TransportCopyPosition(jack_position_t* from, jack_position_t* to) void JackTransportEngine::TransportCopyPosition(jack_position_t* from, jack_position_t* to)
{ {
int tries = 0; int tries = 0;


+ 41
- 2
common/JackTransportEngine.h View File

@@ -49,6 +49,43 @@ We have:
The current position can be read by clients. The current position can be read by clients.


We use a JackAtomicArrayState pattern that allows to manage several "next" states independantly. We use a JackAtomicArrayState pattern that allows to manage several "next" states independantly.
In jack1 implementation, transport code (jack_transport_cycle_end) was not called if the graph could not be locked (see jack_run_one_cycle).
Here transport cycle (CycleBegin, CycleEnd) has to run in the RT thread concurrently with code executed from the "command" thread.
Each client maintains a state in it's shared memory area defined by:
- it's current transport state
- a boolean that is "true" when slow-sync cb has to be called
- a boolean that is "true" when timebase cb is called with new_pos on
Several operations set the "slow-sync cb" flag to true:
- setting a new cb (client)
- activate (client)
- transport start (server)
- new pos (server)
Slow-sync cb calls stops when:
- the cb return true (client)
- desactivate (client)
- transport stop (server)
Several operations set the "timebase cb" flag to true:
- setting a new cb (client)
- activate (client)
- transport start (server) ??
- new pos (server)
Timebase cb "new_pos" argument calls stops when:
- after one cb call with "new_pos" argument true (client)
- desactivate (client)
- release (client)
- transport stop (server)
*/ */


class JackTransportEngine : public JackAtomicArrayState<jack_position_t> class JackTransportEngine : public JackAtomicArrayState<jack_position_t>
@@ -65,9 +102,11 @@ class JackTransportEngine : public JackAtomicArrayState<jack_position_t>
bool fPendingPos; bool fPendingPos;
SInt32 fWriteCounter; SInt32 fWriteCounter;


bool CheckOneSynching(JackClientInterface** table);
bool CheckAllRolling(JackClientInterface** table); bool CheckAllRolling(JackClientInterface** table);
void MakeAllStarting(JackClientInterface** table);
void MakeAllStartingLocating(JackClientInterface** table);
void MakeAllStopping(JackClientInterface** table);
void SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size); void SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size);


public: public:


+ 14
- 14
common/jack/jack.h View File

@@ -923,20 +923,20 @@ extern "C"
*/ */
void jack_set_error_function (void (*func)(const char *)); void jack_set_error_function (void (*func)(const char *));


/**
* Display JACK info message.
*
* Set via jack_set_info_function(), otherwise a JACK-provided
* default will print @a msg (plus a newline) to stdout.
*
* @param msg info message text (no newline at end).
*/
extern void (*jack_info_callback)(const char *msg);
/**
* Set the @ref jack_info_callback for info message display.
*/
void jack_set_info_function (void (*func)(const char *));
/**
* Display JACK info message.
*
* Set via jack_set_info_function(), otherwise a JACK-provided
* default will print @a msg (plus a newline) to stdout.
*
* @param msg info message text (no newline at end).
*/
extern void (*jack_info_callback)(const char *msg);
/**
* Set the @ref jack_info_callback for info message display.
*/
void jack_set_info_function (void (*func)(const char *));


#ifdef __cplusplus #ifdef __cplusplus
} }


+ 0
- 1
common/jack/transport.h View File

@@ -37,7 +37,6 @@ typedef enum {
JackTransportRolling = 1, /**< Transport playing */ JackTransportRolling = 1, /**< Transport playing */
JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */
JackTransportStarting = 3, /**< Waiting for sync ready */ JackTransportStarting = 3, /**< Waiting for sync ready */
JackTransportSynching = 4 /**< internal use*/


} jack_transport_state_t; } jack_transport_state_t;




+ 53
- 22
common/transport_types.h View File

@@ -39,7 +39,7 @@ extern "C"
JackTransportRolling = 1, /**< Transport playing */ JackTransportRolling = 1, /**< Transport playing */
JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */
JackTransportStarting = 3, /**< Waiting for sync ready */ JackTransportStarting = 3, /**< Waiting for sync ready */
JackTransportSynching = 4 /**< temporary*/
//JackTransportSynching = 4 /**< temporary*/


} jack_transport_state_t; } jack_transport_state_t;


@@ -51,53 +51,84 @@ extern "C"
typedef enum { typedef enum {


JackPositionBBT = 0x10, /**< Bar, Beat, Tick */ JackPositionBBT = 0x10, /**< Bar, Beat, Tick */
JackPositionTimecode = 0x20 /**< External timecode */

JackPositionTimecode = 0x20, /**< External timecode */
JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */
JackAudioVideoRatio = 0x80, /**< audio frames per video frame */
JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */
} jack_position_bits_t; } jack_position_bits_t;


/** all valid position bits */ /** all valid position bits */
#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode) #define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode)
#define EXTENDED_TIME_INFO #define EXTENDED_TIME_INFO


/**
* Struct for transport position information.
*/
typedef struct { typedef struct {
/* these four cannot be set from clients: the server sets them */ /* these four cannot be set from clients: the server sets them */
jack_unique_t unique_1; /**< unique ID */ jack_unique_t unique_1; /**< unique ID */
jack_time_t usecs; /**< monotonic, free-rolling */
jack_time_t usecs; /**< monotonic, free-rolling */
jack_nframes_t frame_rate; /**< current frame rate (per second) */ jack_nframes_t frame_rate; /**< current frame rate (per second) */
jack_nframes_t frame; /**< frame number, always present */ jack_nframes_t frame; /**< frame number, always present */


jack_position_bits_t valid; /**< which other fields are valid */ jack_position_bits_t valid; /**< which other fields are valid */


/* JackPositionBBT fields: */ /* JackPositionBBT fields: */
int32_t bar; /**< current bar */
int32_t beat; /**< current beat-within-bar */
int32_t tick; /**< current tick-within-beat */
double bar_start_tick;
int32_t bar; /**< current bar */
int32_t beat; /**< current beat-within-bar */
int32_t tick; /**< current tick-within-beat */
double bar_start_tick;


float beats_per_bar; /**< time signature "numerator" */
float beat_type; /**< time signature "denominator" */
double ticks_per_beat;
double beats_per_minute;
float beats_per_bar; /**< time signature "numerator" */
float beat_type; /**< time signature "denominator" */
double ticks_per_beat;
double beats_per_minute;


/* JackPositionTimecode fields: (EXPERIMENTAL: could change) */ /* JackPositionTimecode fields: (EXPERIMENTAL: could change) */
double frame_time; /**< current time in seconds */
double next_time; /**< next sequential frame_time
(unless repositioned) */
double frame_time; /**< current time in seconds */
double next_time; /**< next sequential frame_time
(unless repositioned) */
/* JackBBTFrameOffset fields: */
jack_nframes_t bbt_offset; /**< frame offset for the BBT fields
(the given bar, beat, and tick
values actually refer to a time
frame_offset frames before the
start of the cycle), should
be assumed to be 0 if
JackBBTFrameOffset is not
set. If JackBBTFrameOffset is
set and this value is zero, the BBT
time refers to the first frame of this
cycle. If the value is positive,
the BBT time refers to a frame that
many frames before the start of the
cycle. */

/* JACK video positional data (experimental) */

float audio_frames_per_video_frame; /**< number of audio frames
per video frame. Should be assumed
zero if JackAudioVideoRatio is not
set. If JackAudioVideoRatio is set
and the value is zero, no video
data exists within the JACK graph */

jack_nframes_t video_offset; /**< audio frame at which the first video
frame in this cycle occurs. Should
be assumed to be 0 if JackVideoFrameOffset
is not set. If JackVideoFrameOffset is
set, but the value is zero, there is
no video frame within this cycle. */


/* For binary compatibility, new fields should be allocated from /* For binary compatibility, new fields should be allocated from
* this padding area with new valid bits controlling access, so * this padding area with new valid bits controlling access, so
* the existing structure size and offsets are preserved. */ * the existing structure size and offsets are preserved. */
int32_t padding[10];
int32_t padding[7];


/* When (unique_1 == unique_2) the contents are consistent. */ /* When (unique_1 == unique_2) the contents are consistent. */
jack_unique_t unique_2; /**< unique ID */ jack_unique_t unique_2; /**< unique ID */


}
jack_position_t;
} jack_position_t;


/** /**
* Prototype for the @a sync_callback defined by slow-sync clients. * Prototype for the @a sync_callback defined by slow-sync clients.


Loading…
Cancel
Save