24#if defined(H2CORE_HAVE_JACK) || _DOXYGEN_
32#include <jack/metadata.h>
51#ifdef H2CORE_HAVE_LASH
57#define J_DEBUGLOG(x) if ( __logger->should_log( Logger::Debug ) ) { \
58 __logger->log( Logger::Debug, _class_name(), __FUNCTION__, \
59 QString( "%1" ).arg( x ), "\033[37m" ); }
70 __INFOLOG( QString(
"New JACK sample rate: [%1]/sec")
71 .arg( QString::number(
static_cast<int>(nframes) ) ) );
79 __INFOLOG( QString(
"new JACK buffer size: [%1]")
80 .arg( QString::number(
static_cast<int>(nframes) ) ) );
101 ___INFOLOG( QString(
"New XRun. [%1] in total" )
105#ifdef HAVE_INTEGRATION_TESTS
109 JackAudioDriver::m_nIntegrationLastRelocationFrame = -1;
118#ifdef HAVE_INTEGRATION_TESTS
119long JackAudioDriver::m_nIntegrationLastRelocationFrame = -1;
134#ifdef HAVE_INTEGRATION_TESTS
135 , m_bIntegrationRelocationLoop( false )
136 , m_bIntegrationCheckRelocationLoop( false )
178#ifdef H2CORE_HAVE_LASH
186 bConnectDefaults =
false;
192 if ( bConnectDefaults ) {
216 WARNINGLOG(
"Could not connect to the saved output ports. Connect to the first pair of input ports instead." );
224 const char ** portnames = jack_get_ports(
m_pClient,
nullptr,
nullptr, JackPortIsInput );
225 if ( !portnames || !portnames[0] || !portnames[1] ) {
226 ERRORLOG(
"Couldn't locate two Jack input ports" );
231 portnames[0] ) != 0 ||
233 portnames[1] ) != 0 ) {
234 ERRORLOG(
"Couldn't connect to first pair of Jack input ports" );
254 if ( pOldClient !=
nullptr ) {
255 int nReturnCode = jack_client_close( pOldClient );
256 if ( nReturnCode != 0 ) {
257 ERRORLOG(
"Error in jack_client_close" );
267 int nReturnCode = jack_deactivate(
m_pClient );
268 if ( nReturnCode != 0 ) {
269 ERRORLOG(
"Error in jack_deactivate" );
294 if ( pBuffer !=
nullptr ) {
295 memset( pBuffer, 0, nFrames *
sizeof(
float ) );
298 if ( pBuffer !=
nullptr ) {
299 memset( pBuffer, 0, nFrames *
sizeof(
float ) );
310 if ( ! ( pos.valid & JackPositionBBT ) ) {
316 if ( pos.beat_type < 1 ||
319 pos.beat > pos.beats_per_bar ||
320 pos.beats_per_bar < 1 ||
321 pos.beats_per_minute <
MIN_BPM ||
322 pos.beats_per_minute >
MAX_BPM ||
324 pos.tick >= pos.ticks_per_beat ||
325 pos.ticks_per_beat < 1 ||
326 std::isnan( pos.bar_start_tick ) ||
327 std::isnan( pos.beats_per_bar ) ||
328 std::isnan( pos.beat_type ) ||
329 std::isnan( pos.ticks_per_beat ) ||
330 std::isnan( pos.beats_per_minute ) ) {
332 J_DEBUGLOG( QString(
"Invalid BBT content. beat_type: %1, bar: %2, beat: %3, tick: %4, beats_per_bar: %5, beats_per_minute: %6, ticks_per_beat: %7, bar_start_tick: %8, beat_type: %9" )
333 .arg( pos.beat_type ).arg( pos.bar ).arg( pos.beat )
334 .arg( pos.tick ).arg( pos.beats_per_bar )
335 .arg( pos.beats_per_minute ).arg( pos.ticks_per_beat )
336 .arg( pos.bar_start_tick ).arg( pos.beat_type ) );
338 ERRORLOG(
"Invalid timebase information. Hydrogen falls back to frame-based relocation. In case you encounter this error frequently, you might considering to disabling JACK timebase support in the Preferences in order to avoid glitches." );
351 long nSongSizeInTicks = 0;
352 auto pSong = pHydrogen->getSong();
353 if ( pSong !=
nullptr ) {
354 nResolution = pSong->getResolution();
355 loopMode = pSong->getLoopMode();
356 nSongSizeInTicks = pSong->lengthInTicks();
363 auto pAudioEngine = pHydrogen->getAudioEngine();
365 const double fTicksPerBeat =
366 static_cast<double>( nResolution / pos.beat_type * 4 );
368 bool bEndOfSongReached =
false;
379 nBarTicks = pos.bar_start_tick * ( fTicksPerBeat / pos.ticks_per_beat );
384 nBarTicks >= nSongSizeInTicks ) {
385 bEndOfSongReached =
true;
390 if ( bEndOfSongReached ) {
397 fNewTick =
static_cast<double>(nBarTicks) +
398 ( pos.beat - 1 ) * fTicksPerBeat +
399 pos.tick * ( fTicksPerBeat / pos.ticks_per_beat );
403 J_DEBUGLOG( QString(
"Calculated tick [%1] from pos.bar: %2, nBarTicks: %3, pos.beat: %4, fTicksPerBeat: %5, pos.tick: %6, pos.ticks_per_beat: %7, bEndOfSongReached: %8" )
404 .arg( fNewTick ).arg( pos.bar ).arg( nBarTicks )
405 .arg( pos.beat ).arg( fTicksPerBeat )
406 .arg( pos.tick ).arg( pos.ticks_per_beat )
407 .arg( bEndOfSongReached ) );
414 jack_position_t* pJackPosition ) {
417 if ( pSong !=
nullptr ) {
418 nResolution = pSong->getResolution();
427 int nPatternLength = 0;
429 for ( std::vector<Pattern*>::const_iterator ppPattern = pPatternList->cbegin();
430 ppPattern < pPatternList ->cend(); ppPattern++ ) {
431 if ( (*ppPattern)->get_length() > nPatternLength ) {
432 nPatternLength = (*ppPattern)->get_length();
433 pPattern = *ppPattern;
436 for (
const auto& ppVirtualPattern : *(*ppPattern)->get_flattened_virtual_patterns() ) {
437 if ( ppVirtualPattern->get_length() > nPatternLength ) {
438 nPatternLength = ppVirtualPattern->get_length();
439 pPattern = ppVirtualPattern;
444 float fNumerator, fDenumerator;
445 if ( pPattern !=
nullptr ) {
453 const float fTicksPerBeat =
454 static_cast<float>(nResolution) * 4 / fDenumerator;
456 pJackPosition->frame_rate =
458 pJackPosition->ticks_per_beat = fTicksPerBeat;
459 pJackPosition->valid = JackPositionBBT;
461 pJackPosition->beats_per_bar = fNumerator;
463 pJackPosition->beat_type = fDenumerator;
464 pJackPosition->beats_per_minute =
static_cast<double>(transportPos.
getBpm());
471 pJackPosition->bar = 1;
472 pJackPosition->beat = 1;
473 pJackPosition->tick = 0;
474 pJackPosition->bar_start_tick = 0;
478 pJackPosition->bar = transportPos.
getColumn() + 1;
484 pJackPosition->beat =
static_cast<int>(std::floor(
486 static_cast<float>(pJackPosition->ticks_per_beat)));
488 pJackPosition->beat++;
491 pJackPosition->tick = std::fmod(
493 pJackPosition->ticks_per_beat );
500 ERRORLOG(
"This function should not have been called with JACK timebase disabled in the Preferences" );
504 ERRORLOG( QString(
"Relocation using BBT information can only be used in the presence of another JACK Timebase controller" ) );
509 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
512 if ( pSong ==
nullptr ) {
523 if ( fNewTick == -1 ) {
526 pAudioEngine->stop();
527 pAudioEngine->stopPlayback();
531 J_DEBUGLOG(
"Exceeding length of song. Locating back to start." );
538 pAudioEngine->locate( 0,
false );
547 J_DEBUGLOG( QString(
"Locate to tick [%1]" ).arg( fNewTick ) );
550 pAudioEngine->locate( fNewTick,
false );
569 auto pAudioEngine = pHydrogen->getAudioEngine();
573#ifdef HAVE_INTEGRATION_TESTS
589 case JackTransportStopped:
593 case JackTransportRolling:
597 case JackTransportStarting:
604 ERRORLOG(
"Unknown jack transport state" );
607 if ( pHydrogen->getSong() ==
nullptr ) {
622 J_DEBUGLOG( QString(
"JACK state: %1, TimebaseFrameOffset: %2, pos: %3" )
626 J_DEBUGLOG( QString(
"Timebase state: %1, tracking: %2" )
652 J_DEBUGLOG( QString(
"Updating Timebase [0] [%1] -> [%2]" )
670 J_DEBUGLOG( QString(
"Updating Timebase [1] [%1] -> [%2]" )
697 J_DEBUGLOG( QString(
"Updating Timebase [2] [%1] -> [%2]" )
715 const bool bRelocation =
716 ( pAudioEngine->getTransportPosition()->getFrame() -
717 pAudioEngine->getTransportPosition()->getFrameOffsetTempo() -
724 J_DEBUGLOG( QString(
"[relocation detected] frames: %1, offset: %2, Jack frames: %3, m_nTimebaseFrameOffset: %4, timebase mode: %5" )
725 .arg( pAudioEngine->getTransportPosition()->getFrame() )
726 .arg( pAudioEngine->getTransportPosition()->getFrameOffsetTempo() )
732 J_DEBUGLOG( QString(
"[BBT info available] update transport" ) );
747#ifdef HAVE_INTEGRATION_TESTS
754 if ( m_bIntegrationCheckRelocationLoop && bRelocation &&
756 if ( JackAudioDriver::m_nIntegrationLastRelocationFrame !=
758 JackAudioDriver::m_nIntegrationLastRelocationFrame =
761 ERRORLOG( QString(
"Relocation Loop! [%1] is detected as relocation a second time." )
763 m_bIntegrationRelocationLoop =
true;
769 J_DEBUGLOG( QString(
"[relocation done] m_nTimebaseFrameOffset: %1, new pos: %2" )
771 .arg( pAudioEngine->getTransportPosition()->toQString() ) );
805 jack_default_audio_sample_t* out =
nullptr;
819 jack_default_audio_sample_t* out =
nullptr;
837#define CLIENT_FAILURE(msg) { \
838 ERRORLOG("Could not connect to JACK server (" msg ")"); \
839 if ( m_pClient != nullptr ) { \
840 ERRORLOG("...but JACK returned a non-null pointer?"); \
841 m_pClient = nullptr; \
843 if (nTries) ERRORLOG("...trying again."); \
847#define CLIENT_SUCCESS(msg) { \
857 QString sClientName =
"Hydrogen";
859#ifdef H2CORE_HAVE_OSC
860 QString sNsmClientId = pPreferences->getNsmClientId();
862 if( !sNsmClientId.isEmpty() ){
863 sClientName = sNsmClientId;
868 jack_status_t status;
871 while ( nTries > 0 ) {
899 m_pClient = jack_client_open( sClientName.toLocal8Bit(),
911 case JackInvalidOption:
914 case JackNameNotUnique:
916 sClientName = jack_get_client_name(
m_pClient);
917 CLIENT_SUCCESS(QString(
"Jack assigned the client name '%1'").arg(sClientName));
922 case JackServerStarted:
925 case JackServerFailed:
928 case JackServerError:
931 case JackNoSuchClient:
934 case JackLoadFailure:
937 case JackInitFailure:
943 case JackVersionError:
948 ERRORLOG(
"Unknown status with JACK server.");
951 " assuming we're OK");
971 if ( jack_set_process_callback(
973 ERRORLOG(
"Unable to set process callback" );
979 if ( jack_set_sample_rate_callback(
981 ERRORLOG(
"Unable to set sample rate callback" );
987 if ( jack_set_buffer_size_callback(
989 ERRORLOG(
"Unable to set buffersize callback" );
994 ERRORLOG(
"Unable to set XRun callback" );
1018 JackPortIsOutput, 0 );
1020 JACK_METADATA_PRETTY_NAME,
"Main Output L",
1021 "text/plain" ) != 0 ) {
1022 INFOLOG(
"Unable to set pretty name of left main output" );
1025 JackPortIsOutput, 0 );
1027 JACK_METADATA_PRETTY_NAME,
"Main Output R",
1028 "text/plain" ) != 0 ) {
1029 INFOLOG(
"Unable to set pretty name of right main output" );
1037#ifdef H2CORE_HAVE_LASH
1038 if ( pPreferences->useLash() ){
1041 const auto sClientNameLocal8Bit = sClientName.toLocal8Bit();
1049 pPreferences->m_bJackTimebaseEnabled ){
1058 std::shared_ptr<Song> pSong = pHydrogen->
getSong();
1059 if ( pSong !=
nullptr ) {
1072 auto pInstrumentList = pSong->getInstrumentList();
1073 std::shared_ptr<Instrument> pInstrument;
1074 int nInstruments =
static_cast<int>(pInstrumentList->size());
1076 WARNINGLOG( QString(
"Creating / renaming %1 ports" ).arg( nInstruments ) );
1078 int nTrackCount = 0;
1088 std::shared_ptr<InstrumentComponent> pInstrumentComponent;
1089 for (
int n = 0; n <= nInstruments - 1; n++ ) {
1090 pInstrument = pInstrumentList->get( n );
1091 for (
auto& pInstrumentComponent : *pInstrument->get_components() ) {
1092 setTrackOutput( nTrackCount, pInstrument, pInstrumentComponent, pSong);
1093 m_trackMap[pInstrument->get_id()][pInstrumentComponent->get_drumkit_componentID()] =
1099 jack_port_t *pPortL, *pPortR;
1104 if ( jack_port_unregister(
m_pClient, pPortL ) != 0 ) {
1105 ERRORLOG( QString(
"Unable to unregister left port [%1]" ).arg( n ) );
1108 if ( jack_port_unregister(
m_pClient, pPortR ) != 0 ) {
1109 ERRORLOG( QString(
"Unable to unregister right port [%1]" ).arg( n ) );
1116void JackAudioDriver::setTrackOutput(
int n, std::shared_ptr<Instrument> pInstrument, std::shared_ptr<InstrumentComponent> pInstrumentComponent, std::shared_ptr<Song> pSong )
1118 QString sComponentName;
1125 sComponentName = QString(
"Track_%1_" ).arg( m + 1 );
1127 jack_port_register(
m_pClient, ( sComponentName +
"L" ).toLocal8Bit(),
1128 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
1131 jack_port_register(
m_pClient, ( sComponentName +
"R" ).toLocal8Bit(),
1132 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
1142 auto pDrumkitComponent = pSong->getComponent( pInstrumentComponent->get_drumkit_componentID() );
1143 sComponentName = QString(
"Track_%1_%2_%3_" ).arg( n + 1 )
1144 .arg( pInstrument->get_name() ).arg( pDrumkitComponent->get_name() );
1146#ifdef HAVE_JACK_PORT_RENAME
1151 ( sComponentName +
"L" ).toLocal8Bit() ) != 0 ) {
1152 ERRORLOG( QString(
"Unable to rename left port of track [%1] to [%2]" )
1153 .arg( n ).arg( sComponentName +
"L" ) );
1156 ( sComponentName +
"R" ).toLocal8Bit() ) != 0 ) {
1157 ERRORLOG( QString(
"Unable to rename right port of track [%1] to [%2]" )
1158 .arg( n ).arg( sComponentName +
"R" ) );
1162 ( sComponentName +
"L" ).toLocal8Bit() ) != 0 ) {
1163 ERRORLOG( QString(
"Unable to set name of left port of track [%1] to [%2]" )
1164 .arg( n ).arg( sComponentName +
"R" ) );
1167 ( sComponentName +
"R" ).toLocal8Bit() ) != 0 ) {
1168 ERRORLOG( QString(
"Unable to set name of right port of track [%1] to [%2]" )
1169 .arg( n ).arg( sComponentName +
"R" ) );
1182 ERRORLOG(
"No client registered" );
1194 ERRORLOG(
"No client registered" );
1210 J_DEBUGLOG( QString(
"Relocate to position: %1" )
1214 if ( jack_transport_reposition(
m_pClient,
1216 ERRORLOG( QString(
"Position rejected [%1]" )
1221 long long nNewFrame = nFrame;
1227 nNewFrame = std::max(
static_cast<long long>(0),
1231 J_DEBUGLOG( QString(
"Relocate to nFrame: %1, nNewFrame: %2, m_nTimebaseFrameOffset: %3, timebase state: %4" )
1232 .arg( nFrame ).arg( nNewFrame )
1240 if ( jack_transport_locate(
m_pClient, nNewFrame ) != 0 ) {
1241 ERRORLOG( QString(
"Invalid relocation request to frame [%1]" )
1242 .arg( nNewFrame ) );
1246 ERRORLOG(
"No client registered" );
1258 ERRORLOG(
"This function should not have been called with JACK Timebase disabled in the Preferences" );
1264 int nReturnValue = jack_set_timebase_callback(
m_pClient, 0,
1266 if ( nReturnValue != 0 ){
1268 WARNINGLOG( QString(
"Hydrogen was not able to register itself as Timebase controller: [%1]" )
1269 .arg( nReturnValue ) );
1275 J_DEBUGLOG( QString(
"Updating Timebase [2] [%1] -> [%2]" )
1287 WARNINGLOG(
"Timebase control should currently not be requested by Hydrogen" );
1295 ERRORLOG( QString(
"Not fully initialized yet" ) );
1300 ERRORLOG(
"This function should not have been called with JACK timebase disabled in the Preferences" );
1304 if ( jack_release_timebase(
m_pClient ) ) {
1305 ERRORLOG(
"Unable to release Timebase control" );
1320 J_DEBUGLOG( QString(
"Updating Timebase [%1] -> [%2]" )
1331 jack_nframes_t nFrames,
1332 jack_position_t* pJackPosition,
1337 if ( pDriver ==
nullptr ){
1342 std::shared_ptr<TransportPosition> pPos =
nullptr;
1350 pAudioEngine->unlock();
1354 const long long nInitialFrame = pJackPosition->frame;
1356 const auto posFromFrame = [&](
long long nFrame,
1357 jack_position_t* pJackPosition ) {
1358 if ( nFrame == pAudioEngine->getTransportPosition()->getFrame() ) {
1361 pPos = pAudioEngine->getTransportPosition();
1364 pPos = std::make_shared<TransportPosition>(
"JackTimebaseCallback" );
1367 pAudioEngine->updateTransportPosition( fTick, nFrame, pPos );
1379 posFromFrame( nInitialFrame, pJackPosition );
1381 if ( nInitialFrame != pJackPosition->frame ) {
1382 ERRORLOG( QString(
"Provided frame glitched! Tring again using new one..." ) );
1383 const long long nSecondFrame = pJackPosition->frame;
1384 posFromFrame( nSecondFrame, pJackPosition );
1394 J_DEBUGLOG( QString(
"Updating Timebase [%1] -> [%2]" )
1407 J_DEBUGLOG( QString(
"Interal transport pos: %1" )
1408 .arg( pPos->toQString() ) );
1413 pAudioEngine->unlock();
1426 return std::nan(
"no tempo, no masters");
1440 J_DEBUGLOG( QString(
"m_JackTransportState: %1,\n m_JackTransportPos: %2,\nm_timebaseState: %3, current pattern column: %4" )
1444 .arg( pHydrogen->getAudioEngine()->getTransportPosition()->
1449 return QString(
"frame: %1, frame_rate: %2, valid: %3, bar: %4, beat: %5, tick: %6, bar_start_tick: %7, beats_per_bar: %8, beat_type: %9, ticks_per_beat: %10, beats_per_minute: %11, frame_time: %12, next_time: %13" )
1450 .arg( pos.frame ).arg( pos.frame_rate )
1451 .arg( pos.valid, 8, 16, QLatin1Char(
'0' ) )
1452 .arg( pos.bar ).arg( pos.beat ).arg( pos.tick )
1453 .arg( pos.bar_start_tick ).arg( pos.beats_per_bar )
1454 .arg( pos.beat_type ).arg( pos.ticks_per_beat )
1455 .arg( pos.beats_per_minute ).arg( pos.frame_time )
1456 .arg( pos.next_time );
1466 return "Controller";
1473 case JackTransportStopped:
1475 case JackTransportRolling:
1477 case JackTransportStarting:
1479 case JackTransportLooping:
1485 return QString(
"Unknown JackTransportState [%1]" )
1486 .arg(
static_cast<int>(t) );
#define RIGHT_HERE
Macro intended to be used for the logging of the locking of the H2Core::AudioEngine.
#define CLIENT_FAILURE(msg)
#define CLIENT_SUCCESS(msg)
@ Playing
Transport is rolling.
@ Ready
Ready to process audio.
@ Testing
State used during the unit tests of the AudioEngine.
void lock(const char *file, unsigned int line, const char *function)
Mutex locking of the AudioEngine.
virtual unsigned getSampleRate()=0
static EventQueue * get_instance()
Returns a pointer to the current EventQueue singleton stored in __instance.
void push_event(const EventType type, const int nValue)
Queues the next event into the EventQueue.
std::shared_ptr< Song > getSong() const
Get the current song.
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
AudioEngine * getAudioEngine() const
@ JACK_CANNOT_ACTIVATE_CLIENT
@ JACK_ERROR_IN_PORT_REGISTER
Unable to register output ports for the JACK client using jack_port_register() (jack/jack....
@ JACK_CANNOT_CLOSE_CLIENT
The client of Hydrogen can not be disconnected from the JACK server using jack_client_close() (jack/j...
@ JACK_CANNOT_CONNECT_OUTPUT_PORT
Unable to connect either the JackAudioDriver::output_port_1 and the JackAudioDriver::output_port_name...
AudioOutput * getAudioOutput() const
Used to display audio driver info.
void raiseError(unsigned nErrorCode)
JACK (Jack Audio Connection Kit) server driver.
virtual void disconnect() override
Disconnects the JACK client of the Hydrogen from the JACK server.
int m_nTrackPortCount
Total number of output ports currently in use.
static QString JackTransportStateToQString(const jack_transport_state_t &pPos)
long long m_nTimebaseFrameOffset
Stores an intended deviation of our transport position from the one hold by the JACK server.
jack_port_t * m_pTrackOutputPortsL[MAX_INSTRUMENTS]
Vector of all left audio output ports currently used by the local JACK client.
jack_position_t m_nextJackTransportPos
Use for relocation if Hydrogen is Timebase controller (and needs to provide valid BBT information in ...
void initTimebaseControl()
Acquires control of JACK Timebase.
TimebaseTracking
Used internally to keep track of the current Timebase state.
@ Valid
Current timebase state is on par with JACK server.
@ OnHold
We are uncertain of the current timebase state and wait a processing cycle to determine what to do ne...
static void transportToBBT(const TransportPosition &transportPos, jack_position_t *pPos)
virtual float * getOut_L() override
Get content in the left stereo output port.
Timebase m_timebaseState
Whether Hydrogen is receiving relocation and tempo changes as part of BBT information,...
static QString JackTransportPosToQString(const jack_position_t &pPos)
virtual int init(unsigned bufferSize) override
Initializes the JACK audio driver.
JackAudioDriver(JackProcessCallback m_processCallback)
Constructor of the JACK server driver.
bool m_bConnectDefaults
Specifies whether the default left and right (master) audio JACK ports will be automatically connecte...
static unsigned long jackServerSampleRate
Sample rate of the JACK audio server.
static JackAudioDriver * pJackDriverInstance
Instance of the JackAudioDriver.
QString m_sOutputPortName2
Destination of the right source port m_pOutputPort2, for which a connection will be established in co...
QString m_sOutputPortName1
Destination of the left source port m_pOutputPort1, for which a connection will be established in con...
float * getTrackOut_R(unsigned nTrack)
Get content of right output port of a specific track.
float getTimebaseControllerBpm() const
static int jackDriverSampleRate(jack_nframes_t nframes, void *param)
Callback function for the JACK audio server to set the sample rate jackServerSampleRate.
void clearPerTrackAudioBuffers(uint32_t nFrames)
Resets the buffers contained in m_pTrackOutputPortsL and m_pTrackOutputPortsR.
const jack_position_t & getJackPosition() const
jack_port_t * m_pOutputPort2
Right source port.
int m_trackMap[MAX_INSTRUMENTS][MAX_COMPONENTS]
Matrix containing the track number of each component of all instruments.
void startTransport()
Tells the JACK server to start transport.
virtual float * getOut_R() override
Get content in the right stereo output port.
static int jackServerXRuns
Number of XRuns since the driver started.
virtual unsigned getBufferSize() override
static QString TimebaseTrackingToQString(const TimebaseTracking &t)
void releaseTimebaseControl()
Release Hydrogen from the JACK Timebase control.
void setTrackOutput(int n, std::shared_ptr< Instrument > instr, std::shared_ptr< InstrumentComponent > pCompo, std::shared_ptr< Song > pSong)
Renames the n 'th port of JACK client and creates it if it's not already present.
static double bbtToTick(const jack_position_t &pos)
Timebase
Whether Hydrogen or another program is in Timebase control.
@ Listener
An external program is Timebase controller and Hydrogen will disregard all tempo markers on the Timel...
@ None
Only normal clients registered.
@ Controller
Hydrogen itself is Timebase controller and provides its current tempo to other Timebase listeners.
jack_client_t * m_pClient
Object holding the external client session with the JACK server.
void deactivate()
Deactivates the JACK client of Hydrogen and disconnects all ports belonging to it.
static Timebase TimebaseFromInt(int nState)
float m_fLastTimebaseBpm
Stores the last tempo sent by an external Timebase controller.
int m_lastTransportBits
Remembers the BBT capability bit received in a JACK process cycle.
virtual int connect() override
Connects to output ports via the JACK server.
Timebase getTimebaseState() const
static QString TimebaseToQString(const Timebase &t)
jack_position_t m_JackTransportPos
Current transport position obtained using jack_transport_query() (jack/transport.h).
jack_port_t * m_pOutputPort1
Left source port.
static int jackDriverBufferSize(jack_nframes_t nframes, void *arg)
Callback function for the JACK audio server to set the buffer size jackServerBufferSize.
static jack_nframes_t jackServerBufferSize
Buffer size of the JACK audio server.
void stopTransport()
Tells the JACK server to stop transport.
void updateTransportPosition()
The function queries the transport position and additional information from the JACK server,...
static bool isBBTValid(const jack_position_t &pos)
static void jackDriverShutdown(void *arg)
Callback function for the JACK audio server to shutting down the JACK driver.
TimebaseTracking m_timebaseTracking
Whether the current timebase state is stable or about to change.
static int jackXRunCallback(void *arg)
Report an XRun event to the GUI.
void makeTrackOutputs(std::shared_ptr< Song > pSong)
Creates per component output ports for each instrument.
virtual unsigned getSampleRate() override
static void JackTimebaseCallback(jack_transport_state_t state, jack_nframes_t nFrames, jack_position_t *pJackPosition, int new_pos, void *arg)
Callback function for the JACK server to supply additional timebase information.
JackProcessCallback m_processCallback
Main process callback.
~JackAudioDriver()
Destructor of the JACK server driver.
void printState() const
Show debugging information.
float * getTrackOut_L(unsigned nTrack)
Get content of left output port of a specific track.
jack_transport_state_t m_JackTransportState
Current transport state returned by jack_transport_query() (jack/transport.h).
void relocateUsingBBT()
Uses the bar-beat-tick information to relocate the transport position.
jack_port_t * m_pTrackOutputPortsR[MAX_INSTRUMENTS]
Vector of all right audio output ports currently used by the local JACK client.
void locateTransport(long long nFrame)
Re-positions the transport position to nFrame.
virtual int getXRuns() const override
Get the number of XRuns that occurred since the audio driver has started.
Pattern class is a Note container.
int get_denominator() const
get the note multimap
Manager for User Preferences File (singleton)
int m_bJackTimebaseMode
Specifies if Hydrogen support the of JACK Timebase protocol.
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
bool m_bJackTimebaseEnabled
External applications with a faulty JACK Timebase implementation can mess up the transport within Hyd...
@ USE_JACK_TRANSPORT
Specifies whether or not to use JACK transport capabilities.
@ NO_JACK_TIMEBASE_CONTROL
Specifies that Hydrogen should not be in control of JACK Timebase information.
@ USE_JACK_TIMEBASE_CONTROL
Specifies that Hydrogen should attempt to acquire JACK Timebase control.
static constexpr int nDefaultResolution
@ Finishing
Transport is still in loop mode (frames and ticks larger than song size are allowed) but playback end...
Object holding most of the information about the transport state of the AudioEngine.
long long getFrame() const
long getPatternTickPosition() const
const PatternList * getPlayingPatterns() const
static double computeTickFromFrame(long long nFrame, int nSampleRate=0)
Calculates tick equivalent of nFrame.
long getPatternStartTick() const
static LashClient * get_instance()
void setJackClientName(const std::string &jackClientName)
Set the name of the JACK client by modifying jackClientName.
void sendJackClientName()
#define MAX_INSTRUMENTS
Maximum number of instruments allowed in Hydrogen.
#define MAX_NOTES
Maximum number of notes.
#define MAX_COMPONENTS
Maximum number of components each Instrument is allowed to have.
@ EVENT_RELOCATION
Triggered in case there is a relocation of the transport position while trasnsport is not rolling.
@ EVENT_JACK_TIMEBASE_STATE_CHANGED
Toggles the button indicating the usage JACK Timebase control and informs the GUI about a state chang...