jack2/common/JackTransportEngine.h

202 lines
5.4 KiB
C++

/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2004-2008 Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __JackTransportEngine__
#define __JackTransportEngine__
#include "JackAtomicArrayState.h"
#include "JackCompilerDeps.h"
#include "types.h"
namespace Jack
{
typedef enum {
TransportCommandNone = 0,
TransportCommandStart = 1,
TransportCommandStop = 2,
} transport_command_t;
/*!
\brief The client transport structure.
We have:
- a "current" position
- a "pending" position prepared by the server at each cycle
- a "request" position wanted by a client
At the beginning of a cycle the server needs to select a new current position. When a request and a pending position are available,
the request takes precedence on the pending one. The server atomically switches to the new position.
The current position can be read by clients.
We use a JackAtomicArrayState pattern that allows to manage several "next" states independently.
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)
- deactivate (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)
- deactivate (client)
- release (client)
- transport stop (server)
*/
class JackClientInterface;
PRE_PACKED_STRUCTURE
class SERVER_EXPORT JackTransportEngine : public JackAtomicArrayState<jack_position_t>
{
private:
jack_transport_state_t fTransportState;
volatile transport_command_t fTransportCmd;
transport_command_t fPreviousCmd; /* previous transport_cmd */
jack_time_t fSyncTimeout;
int fSyncTimeLeft;
int fTimeBaseMaster;
bool fPendingPos;
bool fNetworkSync;
bool fConditionnal;
alignas(SInt32) SInt32 fWriteCounter;
bool CheckAllRolling(JackClientInterface** table);
void MakeAllStartingLocating(JackClientInterface** table);
void MakeAllStopping(JackClientInterface** table);
void MakeAllLocating(JackClientInterface** table);
void SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size);
public:
JackTransportEngine();
~JackTransportEngine()
{}
void SetCommand(transport_command_t state)
{
fTransportCmd = state;
}
jack_transport_state_t GetState() const
{
return fTransportState;
}
void SetState(jack_transport_state_t state)
{
fTransportState = state;
}
/*
\brief
*/
int ResetTimebase(int refnum);
/*
\brief
*/
int SetTimebaseMaster(int refnum, bool conditionnal);
void GetTimebaseMaster(int& refnum, bool& conditionnal)
{
refnum = fTimeBaseMaster;
conditionnal = fConditionnal;
}
/*
\brief
*/
void CycleBegin(jack_nframes_t frame_rate, jack_time_t time);
/*
\brief
*/
void CycleEnd(JackClientInterface** table, jack_nframes_t frame_rate, jack_nframes_t buffer_size);
/*
\brief
*/
void SetSyncTimeout(jack_time_t timeout)
{
fSyncTimeout = timeout;
}
void ReadCurrentPos(jack_position_t* pos);
jack_unique_t GenerateUniqueID()
{
return (jack_unique_t)INC_ATOMIC(&fWriteCounter);
}
void RequestNewPos(jack_position_t* pos);
jack_transport_state_t Query(jack_position_t* pos);
jack_nframes_t GetCurrentFrame();
static void CopyPosition(jack_position_t* from, jack_position_t* to);
bool GetNetworkSync() const
{
return fNetworkSync;
}
void SetNetworkSync(bool sync)
{
fNetworkSync = sync;
}
} POST_PACKED_STRUCTURE;
} // end of namespace
#endif