hydrogen 1.1.1
JackAudioDriver Class Reference

JACK (Jack Audio Connection Kit) server driver. More...

#include <JackAudioDriver.h>

Inheritance diagram for JackAudioDriver:
AudioOutput Object

Public Types

enum class  Timebase { Master = 1 , Slave = 0 , None = -1 }
 Whether Hydrogen or another program is Jack timebase master. More...
 

Public Member Functions

 JackAudioDriver (JackProcessCallback m_processCallback)
 Constructor of the JACK server driver. More...
 
 ~JackAudioDriver ()
 Destructor of the JACK server driver. More...
 
int connect ()
 Connects to output ports via the JACK server. More...
 
void disconnect ()
 Disconnects the JACK client of the Hydrogen from the JACK server. More...
 
void deactivate ()
 Deactivates the JACK client of Hydrogen and disconnects all ports belonging to it. More...
 
unsigned getBufferSize ()
 
unsigned getSampleRate ()
 
void clearPerTrackAudioBuffers (uint32_t nFrames)
 Resets the buffers contained in m_pTrackOutputPortsL and m_pTrackOutputPortsR. More...
 
void makeTrackOutputs (Song *pSong)
 Creates per component output ports for each instrument. More...
 
void setConnectDefaults (bool flag)
 
bool getConnectDefaults ()
 
float * getOut_L ()
 Get content in the left stereo output port. More...
 
float * getOut_R ()
 Get content in the right stereo output port. More...
 
float * getTrackOut_L (unsigned nTrack)
 Get content of left output port of a specific track. More...
 
float * getTrackOut_R (unsigned nTrack)
 Get content of right output port of a specific track. More...
 
float * getTrackOut_L (Instrument *instr, InstrumentComponent *pCompo)
 Convenience function looking up the track number of a component of an instrument using in m_trackMap using their IDs Instrument::__id and InstrumentComponent::__related_drumkit_componentID. More...
 
float * getTrackOut_R (Instrument *instr, InstrumentComponent *pCompo)
 Convenience function looking up the track number of a component of an instrument using in m_trackMap using their IDs Instrument::__id and InstrumentComponent::__related_drumkit_componentID. More...
 
int init (unsigned bufferSize)
 Initializes the JACK audio driver. More...
 
virtual void play ()
 Starts the JACK transport. More...
 
virtual void stop ()
 Stops the JACK transport. More...
 
virtual void locate (unsigned long nFrame)
 Re-positions the transport position to nFrame. More...
 
virtual void updateTransportInfo ()
 
virtual void setBpm (float fBPM)
 Set the tempo stored TransportInfo::m_fBPM of the local instance of the TransportInfo AudioOutput::m_transport. More...
 
void calculateFrameOffset (long long oldFrame)
 Calculates the difference between the true transport position and the internal one. More...
 
void initTimebaseMaster ()
 Registers Hydrogen as JACK timebase master. More...
 
void releaseTimebaseMaster ()
 Calls jack_release_timebase() (jack/transport.h) to release Hydrogen from the JACK timebase master responsibilities. More...
 
Timebase getTimebaseState () const
 
- Public Member Functions inherited from AudioOutput
 AudioOutput (const char *class_name)
 
virtual ~AudioOutput ()
 
virtual int init (unsigned nBufferSize)=0
 
virtual int connect ()=0
 
virtual void disconnect ()=0
 
virtual unsigned getBufferSize ()=0
 
virtual unsigned getSampleRate ()=0
 
virtual int getLatency ()
 Approximate audio latency (in frames) A reasonable approximation is the buffer time on most audio systems. More...
 
virtual float * getOut_L ()=0
 
virtual float * getOut_R ()=0
 
virtual void updateTransportInfo ()=0
 
virtual void play ()=0
 
virtual void stop ()=0
 
virtual void locate (unsigned long nFrame)=0
 
virtual void setBpm (float fBPM)=0
 
- Public Member Functions inherited from Object
 ~Object ()
 destructor More...
 
 Object (const Object &obj)
 copy constructor More...
 
 Object (const char *class_name)
 constructor More...
 
const char * class_name () const
 return the class name More...
 
virtual QString toQString (const QString &sPrefix, bool bShort=true) const
 Formatted string version for debugging purposes. More...
 
void Print (bool bShort=true) const
 Prints content of toQString() via DEBUGLOG. More...
 

Static Public Member Functions

static int jackDriverSampleRate (jack_nframes_t nframes, void *param)
 Callback function for the JACK audio server to set the sample rate jackServerSampleRate and prints a message to the __INFOLOG, which has to be included via a Logger instance in the provided param. More...
 
static int jackDriverBufferSize (jack_nframes_t nframes, void *arg)
 Callback function for the JACK audio server to set the buffer size jackServerBufferSize. More...
 
- Static Public Member Functions inherited from AudioOutput
static QStringList getDevices ()
 
- Static Public Member Functions inherited from Object
static void set_count (bool flag)
 enable/disable class instances counting More...
 
static bool count_active ()
 return true if class instances counting is enabled More...
 
static unsigned objects_count ()
 return the number of objects More...
 
static void write_objects_map_to (std::ostream &out)
 output the full objects map to a given ostream More...
 
static void write_objects_map_to_cerr ()
 output objects map to stderr More...
 
static int bootstrap (Logger *logger, bool count=false)
 must be called before any Object instantiation ! More...
 
static Loggerlogger ()
 return the logger instance More...
 

Data Fields

jack_client_t * m_pClient
 Object holding the external client session with the JACK server. More...
 
int m_currentPos
 Stores the latest transport position (for both rolling and stopped transport). More...
 
- Data Fields inherited from AudioOutput
TransportInfo m_transport
 Local instance of the TransportInfo. More...
 

Static Public Attributes

static unsigned long jackServerSampleRate = 0
 Sample rate of the JACK audio server. More...
 
static jack_nframes_t jackServerBufferSize = 0
 Buffer size of the JACK audio server. More...
 
static JackAudioDriverpJackDriverInstance = nullptr
 Instance of the JackAudioDriver. More...
 
static int nWaits = 0
 Required in JackTimebaseCallback() to keep the sync between the timebase master and all other JACK clients. More...
 
- Static Public Attributes inherited from Object
static QString sPrintIndention = " "
 String used to format the debugging string output of some core classes. More...
 

Protected Member Functions

void jack_session_callback_impl (jack_session_event_t *event)
 

Static Protected Member Functions

static void JackTimebaseCallback (jack_transport_state_t state, jack_nframes_t nFrames, jack_position_t *pJackPosition, int new_pos, void *arg)
 Callback function registered to the JACK server in initTimebaseMaster() if Hydrogen is set as JACK timebase master. More...
 
static void jackDriverShutdown (void *arg)
 Callback function for the JACK audio server to shutting down the JACK driver. More...
 
static void jack_session_callback (jack_session_event_t *event, void *arg)
 Function to call by the JACK server when a session event is to be delivered. More...
 
static void printJackTransportPos (const jack_position_t *pPos)
 

Private Member Functions

void printState () const
 Show debugging information. More...
 
bool compareAdjacentBBT () const
 Compares the BBT information stored in m_JackTransportPos and m_previousJackTransportPos with respect to the tempo and the transport position in bars, beats, and ticks. More...
 
void relocateUsingBBT ()
 Uses the bar-beat-tick information to relocate the transport position. More...
 
void setTrackOutput (int n, Instrument *instr, InstrumentComponent *pCompo, Song *pSong)
 Renames the n 'th port of JACK client and creates it if it's not already present. More...
 

Private Attributes

long long m_frameOffset
 Constant offset between the internal transport position in TransportInfo::m_nFrames and the external one. More...
 
JackProcessCallback m_processCallback
 Function the JACK server will call whenever there is work to do. More...
 
jack_port_t * m_pOutputPort1
 Left source port for which a connection to m_sOutputPortName1 will be established in connect() via the JACK server. More...
 
jack_port_t * m_pOutputPort2
 Right source port for which a connection to m_sOutputPortName2 will be established in connect() via the JACK server. More...
 
QString m_sOutputPortName1
 Destination of the left source port m_pOutputPort1, for which a connection will be established in connect(). More...
 
QString m_sOutputPortName2
 Destination of the right source port m_pOutputPort2, for which a connection will be established in connect(). More...
 
int m_trackMap [MAX_INSTRUMENTS][MAX_COMPONENTS]
 Matrix containing the track number of each component of of all instruments. More...
 
int m_nTrackPortCount
 Total number of output ports currently in use. More...
 
jack_port_t * m_pTrackOutputPortsL [MAX_INSTRUMENTS]
 Vector of all left audio output ports currently used by the local JACK client. More...
 
jack_port_t * m_pTrackOutputPortsR [MAX_INSTRUMENTS]
 Vector of all right audio output ports currently used by the local JACK client. More...
 
jack_transport_state_t m_JackTransportState
 Current transport state returned by jack_transport_query() (jack/transport.h). More...
 
jack_position_t m_JackTransportPos
 Current transport position obtained using jack_transport_query() (jack/transport.h). More...
 
jack_position_t m_previousJackTransportPos
 Used for detecting changes in the BBT transport information with external timebase master application, which do not propagate these changes on time. More...
 
bool m_bConnectDefaults
 Specifies whether the default left and right (master) audio JACK ports will be automatically connected to the system's sink when registering the JACK client in connect(). More...
 
int m_nTimebaseTracking
 Whether Hydrogen or another program is Jack timebase master. More...
 
Timebase m_timebaseState
 More user-friendly version of m_nTimebaseTracking. More...
 

Additional Inherited Members

- Static Protected Attributes inherited from Object
static Logger__logger = nullptr
 logger instance pointer More...
 

Detailed Description

JACK (Jack Audio Connection Kit) server driver.

Transport Control:

Each JACK client can start and stop the transport or relocate the current transport position. The request will take place in cycles. During the first the status of the transport changes to JackTransportStarting to inform all clients a change is about to happen. During the second the status is again JackTransportRolling and the transport position is updated according to the request. The current timebase master (see below), if present, needs another cycle to update the additional transport information.

Such a relocation request is also triggered when clicking on the timeline or the player control buttons of Hydrogen. Internally, audioEngine_stop() is called during the cycle in which the JACK transport status is JackTransportStarting and started again by audioEngine_start() when in JackTransportRolling in the next cycle. Note that if there are slow synchronizing client in JACK's connection graph, it can take multiple cycles until the JACK transport is rolling again.

Also note that Hydrogen overwrites its local TransportInfo stored in AudioOutput::m_transport only with the transport position of the JACK server if a relocation did happened or another timebase master did change the speed. During normal transport the current position TransportInfo::m_nFrames will be always the same as the one of JACK during a cycle and incremented by the buffer size in audioEngine_process() at the very end of the cycle. The same happens for the transport information of the JACK server but in parallel.

Timebase Master:

The timebase master is responsible to update additional information in the transport information of the JACK server apart from the transport position in frames (see TransportInfo::m_nFrames if you aren't familiar with frames), like the current beat, bar, tick, tick size, speed etc. Every client can be registered as timebase master by supplying a callback (for Hydrogen this would be JackTimebaseCallback()) but there can be at most one timebase master at a time. Having none at all is perfectly fine too. Apart from this additional responsibility, the registered client has no other rights compared to others.

After the status of the JACK transport has changed from JackTransportStarting to JackTransportRolling, the timebase master needs an additional cycle to update its information.

Having an external timebase master present will change the general behavior of Hydrogen. All local tempo settings on the Timeline will be disregarded and the tempo broadcasted by the JACK server will be used instead.

This object will only be accessible if H2CORE_HAVE_JACK was defined during the configuration and the user enables the support of the JACK server.

Member Enumeration Documentation

◆ Timebase

enum class Timebase
strong

Whether Hydrogen or another program is Jack timebase master.

Enumerator
Master 

Hydrogen itself is timebase master.

Slave 

An external program is timebase master and Hydrogen will disregard all tempo marker on the Timeline and, instead, only use the BPM provided by JACK.

None 

Only normal clients registered.

Constructor & Destructor Documentation

◆ JackAudioDriver()

JackAudioDriver ( JackProcessCallback  m_processCallback)

Constructor of the JACK server driver.

Parameters
m_processCallbackPrototype for the client supplied function that is called by the engine anytime there is work to be done. It gets two input arguments nframes of type jack_nframes_t, which specifies the number of frames to process, and a void pointer called arg, which points to a client supplied structure. Two preconditions do act on the nframes argument: nframes == getBufferSize() and nframes == pow(2,x) It returns zero on success and non-zero on error.

◆ ~JackAudioDriver()

Destructor of the JACK server driver.

Calling disconnect().

Member Function Documentation

◆ calculateFrameOffset()

void calculateFrameOffset ( long long  oldFrame)

Calculates the difference between the true transport position and the internal one.

The internal transport position used in most parts of Hydrogen is given in ticks. But since the size of a tick is tempo-dependent, passing a tempo marker in the Timeline will cause the corresponding internal transport position in frames to diverge from the external one by a constant offset. This function will calculate and store it in m_frameOffset.

Parameters
oldFrameProvides the previous transport position in frames prior to the change in tick size. This is required if transport is not rolling during the relocation into a region of different speed since there is no up-to-date JACK query providing these information.

◆ clearPerTrackAudioBuffers()

void clearPerTrackAudioBuffers ( uint32_t  nFrames)

Resets the buffers contained in m_pTrackOutputPortsL and m_pTrackOutputPortsR.

Parameters
nFramesSize of the buffers used in the audio process callback function.

◆ compareAdjacentBBT()

bool compareAdjacentBBT ( ) const
private

Compares the BBT information stored in m_JackTransportPos and m_previousJackTransportPos with respect to the tempo and the transport position in bars, beats, and ticks.

Returns
true If m_JackTransportPos is expected to follow m_previousJackTransportPos.

◆ connect()

int connect ( )
virtual

Connects to output ports via the JACK server.

Starts by telling the JACK server that Hydrogen is ready to process audio using the jack_activate function (from the jack/jack.h header) and overwriting the memory allocated by m_pTrackOutputPortsL and m_pTrackOutputPortsR with zeros. If the m_bConnectDefaults variable is true or LashClient is used and Hydrogen is not within a new Lash project, the function attempts to connect the m_pOutputPort1 port with m_sOutputPortName1 and the m_pOutputPort2 port with m_sOutputPortName2. To establish the connection, jack_connect() (jack/jack.h) will be used. In case this was not successful, the function will look up all ports containing the JackPortIsInput (jack/types.h) flag using jack_get_ports() (jack/jack.h) and attempts to connect to the first two it found.

Returns
  • 0 : if either the connection of the output ports did work, two ports having the JackPortIsInput flag where found and the m_pOutputPort1 and m_pOutputPort2 ports where successfully connected to them, or the user enabled Lash during compilation and an established project was used.
  • 1 : The activation of the JACK client using jack_activate() (jack/jack.h) did fail.
  • 2 : The connections to m_sOutputPortName1 and m_sOutputPortName2 could not be established and the there were either no JACK ports holding the JackPortIsInput flag found or no connection to them could be established.

Implements AudioOutput.

◆ deactivate()

void deactivate ( )

Deactivates the JACK client of Hydrogen and disconnects all ports belonging to it.

It calls the jack_deactivate() (jack/jack.h) function on the current client m_pClient and overwrites the memory allocated by m_pTrackOutputPortsL and m_pTrackOutputPortsR with zeros.

◆ disconnect()

void disconnect ( )
virtual

Disconnects the JACK client of the Hydrogen from the JACK server.

Firstly, it calls deactivate(). Then, it closes the connection between the JACK server and the local client using jack_client_close (jack/jack.h), and sets the m_pClient pointer to nullptr.

Implements AudioOutput.

◆ getBufferSize()

unsigned getBufferSize ( )
virtual
Returns
Global variable jackServerBufferSize.

Implements AudioOutput.

◆ getConnectDefaults()

bool getConnectDefaults ( )
inline

◆ getOut_L()

float * getOut_L ( )
virtual

Get content in the left stereo output port.

It calls jack_port_get_buffer() (jack/jack.h) with both the port name m_pOutputPort1 and buffer size jackServerBufferSize.

Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

Implements AudioOutput.

◆ getOut_R()

float * getOut_R ( )
virtual

Get content in the right stereo output port.

It calls jack_port_get_buffer() (jack/jack.h) with both the port name m_pOutputPort2 and buffer size jackServerBufferSize.

Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

Implements AudioOutput.

◆ getSampleRate()

unsigned getSampleRate ( )
virtual
Returns
Global variable jackServerSampleRate.

Implements AudioOutput.

◆ getTimebaseState()

JackAudioDriver::Timebase getTimebaseState ( ) const

◆ getTrackOut_L() [1/2]

float * getTrackOut_L ( Instrument instr,
InstrumentComponent pCompo 
)

Convenience function looking up the track number of a component of an instrument using in m_trackMap using their IDs Instrument::__id and InstrumentComponent::__related_drumkit_componentID.

Using the track number it then calls getTrackOut_L( unsigned ) and returns its result.

Parameters
instrPointer to an Instrument
pCompoPointer to one of the instrument's components.
Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

◆ getTrackOut_L() [2/2]

float * getTrackOut_L ( unsigned  nTrack)

Get content of left output port of a specific track.

It calls jack_port_get_buffer() (jack/jack.h) with the port in the nTrack element of m_pTrackOutputPortsL and buffer size jackServerBufferSize.

Parameters
nTrackTrack number. Must not be bigger than m_nTrackPortCount.
Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

◆ getTrackOut_R() [1/2]

float * getTrackOut_R ( Instrument instr,
InstrumentComponent pCompo 
)

Convenience function looking up the track number of a component of an instrument using in m_trackMap using their IDs Instrument::__id and InstrumentComponent::__related_drumkit_componentID.

Using the track number it then calls getTrackOut_R( unsigned ) and returns its result.

Parameters
instrPointer to an Instrument
pCompoPointer to one of the instrument's components.
Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

◆ getTrackOut_R() [2/2]

float * getTrackOut_R ( unsigned  nTrack)

Get content of right output port of a specific track.

It calls jack_port_get_buffer() (jack/jack.h) with the port in the nTrack element of m_pTrackOutputPortsR and buffer size jackServerBufferSize.

Parameters
nTrackTrack number. Must not be bigger than m_nTrackPortCount.
Returns
Pointer to buffer content of type jack_default_audio_sample_t* (jack/types.h)

◆ init()

int init ( unsigned  bufferSize)
virtual

Initializes the JACK audio driver.

Firstly, it determines the destination ports m_sOutputPortName1 and m_sOutputPortName2 the output ports of Hydrogen will be connected to in connect() from Preferences::m_sJackPortName1 and Preferences::m_sJackPortName2. The name of the JACK client is either set to "Hydrogen" or, if H2CORE_HAVE_OSC was defined during compilation and OSC support is enabled, to Preferences::m_sNsmClientId via Preferences::getNsmClientId().

Next, the function attempts to open an external client session with the JACK server using jack_client_open() (jack/jack.h) and saves it to the pointer m_pClient. In case this didn't work properly, it will start two more attempts. Sometime JACK doesn't stop and start fast enough. If the compiler flag H2CORE_HAVE_JACKSESSION was set and the user enabled the usage of JACK session, the client will be opened using the corresponding option and the sessionID Token Preferences::jackSessionUUID, obtained via Preferences::getJackSessionUUID(), will be provided so the sessionmanager can identify the client again.

If the client was opened properly, the function will get its sample rate using jack_get_sample_rate() and buffer size using jack_get_buffer_size() (both jack/jack.h) and stores them in jackServerSampleRate, Preferences::m_nSampleRate, jackServerBufferSize, and Preferences::m_nBufferSize. In addition, it also registers JackAudioDriver::m_processCallback, jackDriverSampleRate, jackDriverBufferSize, and jackDriverShutdown using jack_set_process_callback(), jack_set_sample_rate_callback(), jack_set_buffer_size_callback(), and jack_on_shutdown() (all in jack/jack.h).

Next, two output ports called "out_L" and "out_R" are registered for the client m_pClient using jack_port_register().

If everything worked properly, LASH is used (Preferences::useLash()) by the user, and the LashClient is LashClient::isConnected() the name of the client will be stored in LashClient::jackClientName using LashClient::setJackClientName. If JACK session was enabled, the jack_session_callback() will be registered using jack_set_session_callback() (jack/session.h).

Finally, the function will check whether Hydrogen should be the JACK timebase master or not via Preferences::m_bJackMasterMode and calls initTimebaseMaster() if its indeed the case.

Parameters
bufferSizeUnused and only present to assure compatibility with the JACK API.
Returns
  • 0 : on success.
  • -1 : if the pointer m_pClient obtained via jack_client_open() (jack/jack.h) is 0.
  • 4 : unable to register the "out_L" and/or "out_R" output ports for the JACK client using jack_port_register() (jack/jack.h).

Implements AudioOutput.

◆ initTimebaseMaster()

void initTimebaseMaster ( )

Registers Hydrogen as JACK timebase master.

If for some reason registering Hydrogen as timebase master does not work, the function sets Preferences::m_bJackMasterMode to Preferences::NO_JACK_TIME_MASTER.

If the function is called with Preferences::m_bJackMasterMode set to Preferences::NO_JACK_TIME_MASTER, releaseTimebaseMaster() will be called instead.

◆ jack_session_callback()

static void jack_session_callback ( jack_session_event_t *  event,
void *  arg 
)
staticprotected

Function to call by the JACK server when a session event is to be delivered.

It is registered to the JACK client in init() using jack_set_session_callback() (jack/session.h) if H2CORE_HAVE_JACKSESSION was defined during compilation.

Internally it hands the event to jack_session_callback_impl().

Parameters
eventJack session event (see jack/session.h)
argPointer to an instance of the JackAudioDriver.

◆ jack_session_callback_impl()

void jack_session_callback_impl ( jack_session_event_t *  event)
protected

◆ jackDriverBufferSize()

int jackDriverBufferSize ( jack_nframes_t  nframes,
void *  arg 
)
static

Callback function for the JACK audio server to set the buffer size jackServerBufferSize.

It gets registered as a callback function of the JACK server in JackAudioDriver::init() using jack_set_buffer_size_callback().

Parameters
nframesNew buffer size. The object has to be of type jack_nframes_t, which is defined in the jack/types.h header.
argNot used within the function but kept for compatibility reasons since the JackBufferSizeCallback (jack/types.h) requires a second input argument arg of type void, which is a pointer supplied by the jack_set_buffer_size_callback() function.
Returns
0 on success

◆ jackDriverSampleRate()

int jackDriverSampleRate ( jack_nframes_t  nframes,
void *  param 
)
static

Callback function for the JACK audio server to set the sample rate jackServerSampleRate and prints a message to the __INFOLOG, which has to be included via a Logger instance in the provided param.

It gets registered as a callback function of the JACK server in JackAudioDriver::init() using jack_set_sample_rate_callback().

Parameters
nframesNew sample rate. The object has to be of type jack_nframes_t, which is defined in the jack/types.h header.
paramObject containing a Logger member to display the change in the sample rate in its INFOLOG.
Returns
0 on success

◆ jackDriverShutdown()

void jackDriverShutdown ( void *  arg)
staticprotected

Callback function for the JACK audio server to shutting down the JACK driver.

The JackAudioDriver::m_pClient pointer stored in the current instance of the JACK audio driver pJackDriverInstance is set to the nullptr and a Hydrogen::JACK_SERVER_SHUTDOWN error is raised using Hydrogen::raiseError().

It gets registered as a callback function of the JACK server in JackAudioDriver::init() using jack_on_shutdown().

Parameters
argNot used within the function but kept for compatibility reasons since jack_shutdown() (jack/jack.h) the argument arg of type void.

◆ JackTimebaseCallback()

void JackTimebaseCallback ( jack_transport_state_t  state,
jack_nframes_t  nFrames,
jack_position_t *  pJackPosition,
int  new_pos,
void *  arg 
)
staticprotected

Callback function registered to the JACK server in initTimebaseMaster() if Hydrogen is set as JACK timebase master.

It will update the current position not just in frames till the beginning of the song, but also in terms of beat, bar, and tick values.

The function it will be called after the audioEngine_process() function and only if the m_JackTransportState is JackTransportRolling.

Parameters
stateCurrent transport state. Not used within the function but to ensure compatibility.
nFramesBuffer size. Not used within the function but to ensure compatibility.
pJackPositionCurrent transport position.
new_posUpdated transport position in frames. Not used within the function but to ensure compatibility.
argPointer to a JackAudioDriver instance.

◆ locate()

void locate ( unsigned long  nFrame)
virtual

Re-positions the transport position to nFrame.

If the Preferences::USE_JACK_TRANSPORT mode is chosen in Preferences::m_bJackTransportMode, the jack_transport_locate() (jack/transport.h) function will be used to request the new transport position. If not, nFrame will be assigned to TransportInfo::m_nFrames of the local instance of the TransportInfo AudioOutput::m_transport.

The new position takes effect in two process cycles during which JACK's state will be in JackTransportStarting and the transport won't be rolling.

Parameters
nFrameRequested new transport position.

Implements AudioOutput.

◆ makeTrackOutputs()

void makeTrackOutputs ( Song pSong)

Creates per component output ports for each instrument.

Firstly, it resets m_trackMap with zeros. Then, it loops through all the instruments and their components, creates a new output or resets an existing one for each of them using setTrackOutput(), and stores the corresponding track number in m_trackMap. Finally, all ports in m_pTrackOutputPortsL and m_pTrackOutputPortsR, which haven't been used in the previous step, are unregistered using jack_port_unregister() (jack/jack.h) and overwritten with 0. m_nTrackPortCount will be set to biggest track number encountered during the creation/reassignment step.

The function will only perform its tasks if the Preferences::m_bJackTrackOuts is set to true.

◆ play()

void play ( )
virtual

Starts the JACK transport.

If the JACK transport was activated in the GUI by clicking either the "J.TRANS" or "J.MASTER" button, the jack_transport_start() (jack/transport.h) function will be called to start the JACK transport. Else, the internal TransportInfo::m_status will be set to TransportInfo::ROLLING instead.

Implements AudioOutput.

◆ printJackTransportPos()

void printJackTransportPos ( const jack_position_t *  pPos)
staticprotected

◆ printState()

void printState ( ) const
private

Show debugging information.

◆ releaseTimebaseMaster()

void releaseTimebaseMaster ( )

Calls jack_release_timebase() (jack/transport.h) to release Hydrogen from the JACK timebase master responsibilities.

This causes the JackTimebaseCallback() callback function to not be called by the JACK server anymore.

◆ relocateUsingBBT()

void relocateUsingBBT ( )
private

Uses the bar-beat-tick information to relocate the transport position.

This type of operation is triggered whenever the transport position gets relocated or the tempo is changed using Jack in the presence of an external timebase master. In addition, the function also updates the current tick size to prevent the audioEngine_checkBPMUpdate() function from doing so.

◆ setBpm()

void setBpm ( float  fBPM)
virtual

Set the tempo stored TransportInfo::m_fBPM of the local instance of the TransportInfo AudioOutput::m_transport.

Only sets the tempo to fBPM if its value is at least

  1. Sometime (especially during the first cycle after locating with transport stopped) the JACK server sends some artifacts (6.95334e-310) which should not be assigned.
Parameters
fBPMnew tempo.

Implements AudioOutput.

◆ setConnectDefaults()

void setConnectDefaults ( bool  flag)
inline
Parameters
flagSets m_bConnectDefaults

◆ setTrackOutput()

void setTrackOutput ( int  n,
Instrument instr,
InstrumentComponent pCompo,
Song pSong 
)
private

Renames the n 'th port of JACK client and creates it if it's not already present.

If the track number n is bigger than the number of ports currently in usage m_nTrackPortCount, n + 1 - m_nTrackPortCount new stereo ports will be created using jack_port_register() (jack/jack.h) and m_nTrackPortCount updated to n + 1.

Afterwards, the n 'th port is renamed to a concatenation of "Track_", DrumkitComponent::__name, "_", n + 1, "_", Instrument::__name, and "_L", or "_R" using either jack_port_rename() (if HAVE_JACK_PORT_RENAME is defined) or jack_port_set_name() (both jack/jack.h). The former renaming function triggers a PortRename notifications to clients that have registered a port rename handler.

Parameters
nTrack number for which a port should be renamed (and created).
instrPointer to the corresponding Instrument.
pCompoPointer to the corresponding InstrumentComponent.
pSongPointer to the corresponding Song.

◆ stop()

void stop ( )
virtual

Stops the JACK transport.

If the JACK transport was activated in the GUI by clicking either the "J.TRANS" or "J.MASTER" button, the jack_transport_stop() (jack/transport.h) function will be called to stop the JACK transport. Else, the internal TransportInfo::m_status will be set to TransportInfo::STOPPED instead.

Implements AudioOutput.

◆ updateTransportInfo()

void updateTransportInfo ( )
virtual
Updating the local instance of the TransportInfo
AudioOutput::m_transport.

The function queries the transport position and additional
information from the JACK server, writes them to
#m_JackTransportPos and in #m_JackTransportState, and updates
the information stored in AudioOutput::m_transport in case of a
mismatch.

If #m_JackTransportState is either _JackTransportStopped_ or

JackTransportStarting, transport will be (temporarily) stopped - TransportInfo::m_status will be set to TransportInfo::STOPPED. If it's JackTransportRolling, transport will be started - TransportInfo::m_status will be set to TransportInfo::ROLLING.

The function will check whether a relocation took place by the JACK server and whether the current tempo did change with respect to the last transport cycle and updates the transport information accordingly.

If Preferences::USE_JACK_TRANSPORT was not selected in Preferences::m_bJackTransportMode, the function will return without performing any action.

Implements AudioOutput.

Field Documentation

◆ jackServerBufferSize

jack_nframes_t jackServerBufferSize = 0
static

Buffer size of the JACK audio server.

It is set by the callback function jackDriverBufferSize() registered in the JACK server and accessed via JackAudioDriver::getBufferSize(). Its initialization is handled by JackAudioDriver::init(), which sets it to the buffer size of the Hydrogen's external JACK client via jack_get_buffer_size() (jack/jack.h).

◆ jackServerSampleRate

unsigned long jackServerSampleRate = 0
static

Sample rate of the JACK audio server.

It is set by the callback function jackDriverSampleRate() registered in the JACK server and accessed via JackAudioDriver::getSampleRate(). Its initialization is handled by JackAudioDriver::init(), which sets it to the sample rate of the Hydrogen's external JACK client via jack_get_sample_rate() (jack/jack.h).

◆ m_bConnectDefaults

bool m_bConnectDefaults
private

Specifies whether the default left and right (master) audio JACK ports will be automatically connected to the system's sink when registering the JACK client in connect().

After the JackAudioDriver has been created by createDriver(), the variable will be, again, set to Preferences::m_bJackConnectDefaults.

◆ m_currentPos

int m_currentPos

Stores the latest transport position (for both rolling and stopped transport).

In case the user is clicking on a different location SongEditorPositionRuler::mousePressEvent() will trigger both a relocation and a (possible) change in speed. The change in speed causes the audioEngine_checkBPMChange() function to update the ticksize in case playhead got moved into a region of different tempo and triggers the calculateFrameOffset() function. But the latter can only work properly if transport is rolling since it has to know the frame position prior to the change in tick size and there is no up-to-date JACK query providing this information.

◆ m_frameOffset

long long m_frameOffset
private

Constant offset between the internal transport position in TransportInfo::m_nFrames and the external one.

Imagine the following setting: During the playback you decide to change the speed of the song. This would cause a lot of position information within Hydrogen, which are given in ticks, to be off since the tick size depends on the speed and just got changed too. Instead, TransportInfo::m_nFrames will scaled to reflect the changes and everything will be still in place with the user to not note a single thing. Unfortunately, now the transport position in frames of the audio engine and of the JACK server are off by a constant offset. To nevertheless be able to identify relocation in updateTransportInfo(), this constant offset is stored in this variable and used in updateTransportInfo() to determine whether a relocation did happen.

Positive values correspond to a position ahead of the current transport information. The variable is initialized with 0 in JackAudioDriver() and updated in calculateFrameOffset().

◆ m_JackTransportPos

jack_position_t m_JackTransportPos
private

Current transport position obtained using jack_transport_query() (jack/transport.h).

It corresponds to the first frame of the current cycle. If it is NULL, jack_transport_query() won't return any position information.

The valid member of m_JackTransportPos will show which fields contain valid data. Thus, if it is set to JackPositionBBT, bar, beat, and tick information are provided by the current timebase master in addition to the transport information in frames. It is of class jack_position_bits_t (jack/types.h) and is an enumerator with five different options:

  • JackPositionBBT = 0x10 : Bar, Beat, Tick
  • 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

The frame member contains the current transport position.

It is set in updateTransportInfo(). Please see the documentation of JackTimebaseCallback() for more information about its different members.

◆ m_JackTransportState

jack_transport_state_t m_JackTransportState
private

Current transport state returned by jack_transport_query() (jack/transport.h).


It is valid for the entire cycle and can have five different values:

  • JackTransportStopped = 0 : Transport is halted
  • JackTransportRolling = 1 : Transport is playing
  • JackTransportLooping = 2 : For OLD_TRANSPORT, now ignored
  • JackTransportStarting = 3 : Waiting for sync ready
  • JackTransportNetStarting = 4 : Waiting for sync ready on the network

The actual number of states depends on your JACK version. The listing above was done for version 1.9.12.

◆ m_nTimebaseTracking

int m_nTimebaseTracking
private

Whether Hydrogen or another program is Jack timebase master.

While Hydrogen can unregister as timebase master on its own, it can not be observed directly whether another application has taken over as timebase master. When the JACK server is releasing Hydrogen in the later case, it won't advertise this fact but simply won't call the JackTimebaseCallback() anymore. But since this will be called in every cycle after updateTransportInfo(), we can use this variable to determine if Hydrogen is still timebase master.

As Hydrogen registered as timebase master using initTimebaseMaster() it will be initialized with 1, decremented in updateTransportInfo(), and reset to 1 in JackTimebaseCallback(). Whenever it is zero in updateTransportInfo(), m_nTimebaseTracking will be updated accordingly.

◆ m_nTrackPortCount

int m_nTrackPortCount
private

Total number of output ports currently in use.

It gets updated by makeTrackOutputs().

◆ m_pClient

jack_client_t* m_pClient

Object holding the external client session with the JACK server.

◆ m_pOutputPort1

jack_port_t* m_pOutputPort1
private

Left source port for which a connection to m_sOutputPortName1 will be established in connect() via the JACK server.

◆ m_pOutputPort2

jack_port_t* m_pOutputPort2
private

Right source port for which a connection to m_sOutputPortName2 will be established in connect() via the JACK server.

◆ m_previousJackTransportPos

jack_position_t m_previousJackTransportPos
private

Used for detecting changes in the BBT transport information with external timebase master application, which do not propagate these changes on time.

◆ m_processCallback

JackProcessCallback m_processCallback
private

Function the JACK server will call whenever there is work to do.

The audioEngine_process() function will be used and registered using jack_set_process_callback() (jack/jack.h) in init().

The code must be suitable for real-time execution. That means that it cannot call functions that might block for a long time. This includes malloc(), free(), printf(), pthread_mutex_lock(), sleep(), wait(), poll(), select(), pthread_join(), pthread_cond_wait(), etc, etc.

◆ m_pTrackOutputPortsL

jack_port_t* m_pTrackOutputPortsL[MAX_INSTRUMENTS]
private

Vector of all left audio output ports currently used by the local JACK client.

They will be initialized with all zeros in both JackAudioDriver(), deactivate(), and connect(). Individual components will be created, renamed, or reassigned in setTrackOutput(), deleted in makeTrackOutputs(), and accessed via getTrackOut_L(). It is set to a length of MAX_INSTRUMENTS.

◆ m_pTrackOutputPortsR

jack_port_t* m_pTrackOutputPortsR[MAX_INSTRUMENTS]
private

Vector of all right audio output ports currently used by the local JACK client.

They will be initialized with all zeros in both JackAudioDriver(), deactivate(), and connect(). Individual components will be created, renamed, or reassigned in setTrackOutput(), deleted in makeTrackOutputs(), and accessed via getTrackOut_R(). It is set to a length of MAX_INSTRUMENTS.

◆ m_sOutputPortName1

QString m_sOutputPortName1
private

Destination of the left source port m_pOutputPort1, for which a connection will be established in connect().

It is set to Preferences::m_sJackPortName1 during the call of init().

◆ m_sOutputPortName2

QString m_sOutputPortName2
private

Destination of the right source port m_pOutputPort2, for which a connection will be established in connect().

It is set to Preferences::m_sJackPortName2 during the call of init().

◆ m_timebaseState

Timebase m_timebaseState
private

More user-friendly version of m_nTimebaseTracking.

◆ m_trackMap

int m_trackMap[MAX_INSTRUMENTS][MAX_COMPONENTS]
private

Matrix containing the track number of each component of of all instruments.

Its rows represent the instruments and its columns their components. m_trackMap[2][1]=6 thus therefore mean the output of the second component of the third instrument is assigned the seventh output port. Since its total size is defined by MAX_INSTRUMENTS and MAX_COMPONENTS, most of its entries will be zero.

It gets updated by makeTrackOutputs().

◆ nWaits

int nWaits = 0
static

Required in JackTimebaseCallback() to keep the sync between the timebase master and all other JACK clients.

Whenever a relocation takes place in Hydrogen as timebase master, the speed of the timeline at the destination frame must not be sent in the timebase callback. Instead, Hydrogen must wait two full cycles of the audioEngine before broadcasting the new tempo again. This is because the Hydrogen (as timebase master) requires two full cycles to set the tempo itself and there is a rather intricate dependence on values calculate in various other functions.

◆ pJackDriverInstance

JackAudioDriver * pJackDriverInstance = nullptr
static

Instance of the JackAudioDriver.