202 lines
5.4 KiB
C++
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
|