git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4150 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.7
@@ -39,6 +39,7 @@ Valerio Pilo | |||||
* Revert r4119 (RT notification in the server). JackAudioDriver::ProcessSync now skip backend write in case of graph process failure. | * Revert r4119 (RT notification in the server). JackAudioDriver::ProcessSync now skip backend write in case of graph process failure. | ||||
* Fix incorrect error codes in alsa/usx2y.c and alsa/JackAlsaDriver.cpp. | * Fix incorrect error codes in alsa/usx2y.c and alsa/JackAlsaDriver.cpp. | ||||
* Synchronize public headers with JACK1. Update OSX project. | * Synchronize public headers with JACK1. Update OSX project. | ||||
* New latency API implementation (in progress). | |||||
2011-02-09 Stephane Letz <letz@grame.fr> | 2011-02-09 Stephane Letz <letz@grame.fr> | ||||
@@ -115,6 +115,9 @@ extern "C" | |||||
void *); | void *); | ||||
EXPORT int jack_set_xrun_callback (jack_client_t *, | EXPORT int jack_set_xrun_callback (jack_client_t *, | ||||
JackXRunCallback xrun_callback, void *arg); | JackXRunCallback xrun_callback, void *arg); | ||||
EXPORT int jack_set_latency_callback (jack_client_t *client, | |||||
JackLatencyCallback callback, void *arg); | |||||
EXPORT int jack_activate (jack_client_t *client); | EXPORT int jack_activate (jack_client_t *client); | ||||
EXPORT int jack_deactivate (jack_client_t *client); | EXPORT int jack_deactivate (jack_client_t *client); | ||||
EXPORT jack_port_t * jack_port_register (jack_client_t *client, | EXPORT jack_port_t * jack_port_register (jack_client_t *client, | ||||
@@ -138,12 +141,19 @@ extern "C" | |||||
const jack_port_t *port); | const jack_port_t *port); | ||||
EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst); | EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst); | ||||
EXPORT int jack_port_untie (jack_port_t *port); | EXPORT int jack_port_untie (jack_port_t *port); | ||||
// Old latency API | |||||
EXPORT jack_nframes_t jack_port_get_latency (jack_port_t *port); | EXPORT jack_nframes_t jack_port_get_latency (jack_port_t *port); | ||||
EXPORT jack_nframes_t jack_port_get_total_latency (jack_client_t *, | EXPORT jack_nframes_t jack_port_get_total_latency (jack_client_t *, | ||||
jack_port_t *port); | jack_port_t *port); | ||||
EXPORT void jack_port_set_latency (jack_port_t *, jack_nframes_t); | EXPORT void jack_port_set_latency (jack_port_t *, jack_nframes_t); | ||||
EXPORT int jack_recompute_total_latency (jack_client_t*, jack_port_t* port); | EXPORT int jack_recompute_total_latency (jack_client_t*, jack_port_t* port); | ||||
// New latency API | |||||
EXPORT void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); | |||||
EXPORT void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range); | |||||
EXPORT int jack_recompute_total_latencies (jack_client_t*); | EXPORT int jack_recompute_total_latencies (jack_client_t*); | ||||
EXPORT int jack_port_set_name (jack_port_t *port, const char *port_name); | EXPORT int jack_port_set_name (jack_port_t *port, const char *port_name); | ||||
EXPORT int jack_port_set_alias (jack_port_t *port, const char *alias); | EXPORT int jack_port_set_alias (jack_port_t *port, const char *alias); | ||||
EXPORT int jack_port_unset_alias (jack_port_t *port, const char *alias); | EXPORT int jack_port_unset_alias (jack_port_t *port, const char *alias); | ||||
@@ -526,6 +536,40 @@ EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames) | |||||
} | } | ||||
} | } | ||||
EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) | |||||
{ | |||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_port_get_latency_range"); | |||||
#endif | |||||
uintptr_t port_aux = (uintptr_t)port; | |||||
jack_port_id_t myport = (jack_port_id_t)port_aux; | |||||
if (!CheckPort(myport)) { | |||||
jack_error("jack_port_get_latency_range called with an incorrect port %ld", myport); | |||||
} else { | |||||
WaitGraphChange(); | |||||
JackGraphManager* manager = GetGraphManager(); | |||||
if (manager) | |||||
manager->GetPort(myport)->GetLatencyRange(mode, range); | |||||
} | |||||
} | |||||
EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) | |||||
{ | |||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_port_set_latency_range"); | |||||
#endif | |||||
uintptr_t port_aux = (uintptr_t)port; | |||||
jack_port_id_t myport = (jack_port_id_t)port_aux; | |||||
if (!CheckPort(myport)) { | |||||
jack_error("jack_port_set_latency_range called with an incorrect port %ld", myport); | |||||
} else { | |||||
WaitGraphChange(); | |||||
JackGraphManager* manager = GetGraphManager(); | |||||
if (manager) | |||||
manager->GetPort(myport)->SetLatencyRange(mode, range); | |||||
} | |||||
} | |||||
EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* port) | EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* port) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
@@ -988,6 +1032,20 @@ EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xr | |||||
} | } | ||||
} | } | ||||
EXPORT int jack_set_latency_callback(jack_client_t *ext_client, JackLatencyCallback latency_callback, void *arg) | |||||
{ | |||||
#ifdef __CLIENTDEBUG__ | |||||
JackGlobals::CheckContext("jack_set_latency_callback"); | |||||
#endif | |||||
JackClient* client = (JackClient*)ext_client; | |||||
if (client == NULL) { | |||||
jack_error("jack_set_latency_callback called with a NULL client"); | |||||
return -1; | |||||
} else { | |||||
return client->SetLatencyCallback(latency_callback, arg); | |||||
} | |||||
} | |||||
EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg) | EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg) | ||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
@@ -335,4 +335,37 @@ jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index) | |||||
return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize); | return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize); | ||||
} | } | ||||
int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) | |||||
{ | |||||
switch (notify) { | |||||
case kLatencyCallback: | |||||
HandleLatencyCallback(value1); | |||||
break; | |||||
default: | |||||
JackDriver::ClientNotify(refnum, name, notify, sync, message, value1, value2); | |||||
break; | |||||
} | |||||
return 0; | |||||
} | |||||
void JackAudioDriver::HandleLatencyCallback(int status) | |||||
{ | |||||
jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency; | |||||
for (int i = 0; i < fCaptureChannels; i++) { | |||||
if (mode == JackPlaybackLatency) { | |||||
fGraphManager->RecalculateLatency(fCapturePortList[i], mode); | |||||
} | |||||
} | |||||
for (int i = 0; i < fPlaybackChannels; i++) { | |||||
if (mode == JackCaptureLatency) { | |||||
fGraphManager->RecalculateLatency(fPlaybackPortList[i], mode); | |||||
} | |||||
} | |||||
} | |||||
} // end of namespace | } // end of namespace |
@@ -57,6 +57,8 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
jack_default_audio_sample_t* GetOutputBuffer(int port_index); | jack_default_audio_sample_t* GetOutputBuffer(int port_index); | ||||
jack_default_audio_sample_t* GetMonitorBuffer(int port_index); | jack_default_audio_sample_t* GetMonitorBuffer(int port_index); | ||||
void HandleLatencyCallback(int status); | |||||
public: | public: | ||||
JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | ||||
@@ -95,6 +97,8 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | virtual int SetSampleRate(jack_nframes_t sample_rate); | ||||
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | |||||
}; | }; | ||||
} // end of namespace | } // end of namespace | ||||
@@ -60,6 +60,9 @@ JackClient::JackClient(JackSynchro* table):fThread(this) | |||||
fTimebase = NULL; | fTimebase = NULL; | ||||
fSync = NULL; | fSync = NULL; | ||||
fThreadFun = NULL; | fThreadFun = NULL; | ||||
fSession = NULL; | |||||
fLatency = NULL; | |||||
fProcessArg = NULL; | fProcessArg = NULL; | ||||
fGraphOrderArg = NULL; | fGraphOrderArg = NULL; | ||||
fXrunArg = NULL; | fXrunArg = NULL; | ||||
@@ -75,6 +78,8 @@ JackClient::JackClient(JackSynchro* table):fThread(this) | |||||
fSyncArg = NULL; | fSyncArg = NULL; | ||||
fTimebaseArg = NULL; | fTimebaseArg = NULL; | ||||
fThreadFunArg = NULL; | fThreadFunArg = NULL; | ||||
fSessionArg = NULL; | |||||
fLatencyArg = NULL; | |||||
} | } | ||||
JackClient::~JackClient() | JackClient::~JackClient() | ||||
@@ -289,12 +294,113 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, | |||||
res = (fImmediateSessionReply) ? 1 : 2; | res = (fImmediateSessionReply) ? 1 : 2; | ||||
} | } | ||||
break; | break; | ||||
case kLatencyCallback: | |||||
res = HandleLatencyCallback(value1); | |||||
break; | |||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
int JackClient::HandleLatencyCallback(int status) | |||||
{ | |||||
jack_latency_callback_mode_t mode = (status == 0) ? JackCaptureLatency : JackPlaybackLatency; | |||||
jack_latency_range_t latency = { UINT32_MAX, 0 }; | |||||
/* first setup all latency values of the ports. | |||||
* this is based on the connections of the ports. | |||||
*/ | |||||
list<jack_port_id_t>::iterator it; | |||||
for (it = fPortList.begin(); it != fPortList.end(); it++) { | |||||
JackPort* port = GetGraphManager()->GetPort(*it); | |||||
if ((port->GetFlags() & JackPortIsOutput) && (mode == JackPlaybackLatency)) { | |||||
GetGraphManager()->RecalculateLatency(*it, mode); | |||||
} | |||||
if ((port->GetFlags() & JackPortIsInput) && (mode == JackCaptureLatency)) { | |||||
GetGraphManager()->RecalculateLatency(*it, mode); | |||||
} | |||||
} | |||||
if (!fLatency) { | |||||
/* | |||||
* default action is to assume all ports depend on each other. | |||||
* then always take the maximum latency. | |||||
*/ | |||||
if (mode == JackPlaybackLatency) { | |||||
/* iterate over all OutputPorts, to find maximum playback latency | |||||
*/ | |||||
for (it = fPortList.begin(); it != fPortList.end(); it++) { | |||||
JackPort* port = GetGraphManager()->GetPort(*it); | |||||
if (port->GetFlags() & JackPortIsOutput) { | |||||
jack_latency_range_t other_latency; | |||||
port->GetLatencyRange(mode, &other_latency); | |||||
if (other_latency.max > latency.max) | |||||
latency.max = other_latency.max; | |||||
if (other_latency.min < latency.min) | |||||
latency.min = other_latency.min; | |||||
} | |||||
} | |||||
if (latency.min == UINT32_MAX) | |||||
latency.min = 0; | |||||
/* now set the found latency on all input ports | |||||
*/ | |||||
for (it = fPortList.begin(); it != fPortList.end(); it++) { | |||||
JackPort* port = GetGraphManager()->GetPort(*it); | |||||
if (port->GetFlags() & JackPortIsInput) { | |||||
port->SetLatencyRange(mode, &latency); | |||||
} | |||||
} | |||||
} | |||||
if (mode == JackCaptureLatency) { | |||||
/* iterate over all InputPorts, to find maximum playback latency | |||||
*/ | |||||
for (it = fPortList.begin(); it != fPortList.end(); it++) { | |||||
JackPort* port = GetGraphManager()->GetPort(*it); | |||||
if (port->GetFlags() & JackPortIsInput) { | |||||
jack_latency_range_t other_latency; | |||||
port->GetLatencyRange(mode, &other_latency); | |||||
if (other_latency.max > latency.max) | |||||
latency.max = other_latency.max; | |||||
if (other_latency.min < latency.min) | |||||
latency.min = other_latency.min; | |||||
} | |||||
} | |||||
if (latency.min == UINT32_MAX) | |||||
latency.min = 0; | |||||
/* now set the found latency on all output ports | |||||
*/ | |||||
for (it = fPortList.begin(); it != fPortList.end(); it++) { | |||||
JackPort* port = GetGraphManager()->GetPort(*it); | |||||
if (port->GetFlags() & JackPortIsOutput) { | |||||
port->SetLatencyRange(mode, &latency); | |||||
} | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
/* we have a latency callback setup by the client, | |||||
* lets use it... | |||||
*/ | |||||
fLatency(mode, fLatencyArg); | |||||
return 0; | |||||
} | |||||
/*! | /*! | ||||
\brief We need to start thread before activating in the server, otherwise the FW driver | \brief We need to start thread before activating in the server, otherwise the FW driver | ||||
connected to the client may not be activated. | connected to the client may not be activated. | ||||
@@ -1011,6 +1117,19 @@ int JackClient::SetSessionCallback(JackSessionCallback callback, void *arg) | |||||
} | } | ||||
} | } | ||||
int JackClient::SetLatencyCallback(JackLatencyCallback callback, void *arg) | |||||
{ | |||||
if (IsActive()) { | |||||
jack_error("You cannot set callbacks on an active client"); | |||||
return -1; | |||||
} else { | |||||
GetClientControl()->fCallback[kLatencyCallback] = (callback != NULL); | |||||
fLatencyArg = arg; | |||||
fLatency = callback; | |||||
return 0; | |||||
} | |||||
} | |||||
//------------------ | //------------------ | ||||
// Internal clients | // Internal clients | ||||
//------------------ | //------------------ | ||||
@@ -67,6 +67,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
JackSyncCallback fSync; | JackSyncCallback fSync; | ||||
JackThreadCallback fThreadFun; | JackThreadCallback fThreadFun; | ||||
JackSessionCallback fSession; | JackSessionCallback fSession; | ||||
JackLatencyCallback fLatency; | |||||
void* fProcessArg; | void* fProcessArg; | ||||
void* fGraphOrderArg; | void* fGraphOrderArg; | ||||
@@ -85,6 +86,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
void* fSyncArg; | void* fSyncArg; | ||||
void* fThreadFunArg; | void* fThreadFunArg; | ||||
void* fSessionArg; | void* fSessionArg; | ||||
void* fLatencyArg; | |||||
char fServerName[64]; | char fServerName[64]; | ||||
JackThread fThread; /*! Thread to execute the Process function */ | JackThread fThread; /*! Thread to execute the Process function */ | ||||
@@ -116,6 +118,8 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
inline void CallTimebaseCallbackAux(); | inline void CallTimebaseCallbackAux(); | ||||
inline int ActivateAux(); | inline int ActivateAux(); | ||||
int HandleLatencyCallback(int status); | |||||
public: | public: | ||||
JackClient(); | JackClient(); | ||||
@@ -178,6 +182,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
virtual int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | virtual int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | ||||
virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | virtual int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | ||||
virtual int SetSessionCallback(JackSessionCallback callback, void *arg); | virtual int SetSessionCallback(JackSessionCallback callback, void *arg); | ||||
virtual int SetLatencyCallback(JackLatencyCallback callback, void *arg); | |||||
// Internal clients | // Internal clients | ||||
virtual char* GetInternalClientName(int ref); | virtual char* GetInternalClientName(int ref); | ||||
@@ -167,7 +167,7 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||||
int JackDriver::Close() | int JackDriver::Close() | ||||
{ | { | ||||
if (fClientControl.fRefNum >= 0) { | |||||
if (fClientControl.fRefNum >= 0) { | |||||
jack_log("JackDriver::Close"); | jack_log("JackDriver::Close"); | ||||
fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync | fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync | ||||
fClientControl.fActive = false; | fClientControl.fActive = false; | ||||
@@ -207,7 +207,7 @@ int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, | |||||
jack_log("JackDriver::kStopFreewheel"); | jack_log("JackDriver::kStopFreewheel"); | ||||
SetupDriverSync(fClientControl.fRefNum, false); | SetupDriverSync(fClientControl.fRefNum, false); | ||||
break; | break; | ||||
} | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -223,13 +223,13 @@ void JackDriver::CycleIncTime() | |||||
} | } | ||||
void JackDriver::CycleTakeBeginTime() | void JackDriver::CycleTakeBeginTime() | ||||
{ | |||||
{ | |||||
fBeginDateUst = GetMicroSeconds(); // Take callback date here | fBeginDateUst = GetMicroSeconds(); // Take callback date here | ||||
fEngineControl->CycleIncTime(fBeginDateUst); | fEngineControl->CycleIncTime(fBeginDateUst); | ||||
} | } | ||||
void JackDriver::CycleTakeEndTime() | void JackDriver::CycleTakeEndTime() | ||||
{ | |||||
{ | |||||
fEndDateUst = GetMicroSeconds(); // Take end date here | fEndDateUst = GetMicroSeconds(); // Take end date here | ||||
} | } | ||||
@@ -254,7 +254,7 @@ void JackDriver::NotifySampleRate(jack_nframes_t sample_rate) | |||||
fEngine->NotifySampleRate(sample_rate); | fEngine->NotifySampleRate(sample_rate); | ||||
fEngineControl->InitFrameTime(); | fEngineControl->InitFrameTime(); | ||||
} | } | ||||
void JackDriver::NotifyFailure(int code, const char* reason) | void JackDriver::NotifyFailure(int code, const char* reason) | ||||
{ | { | ||||
fEngine->NotifyFailure(code, reason); | fEngine->NotifyFailure(code, reason); | ||||
@@ -245,7 +245,7 @@ int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // C | |||||
// Client | // Client | ||||
jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count) | jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count) | ||||
{ | { | ||||
const jack_int_t* connections = manager->GetConnections(port_index); | |||||
const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index); | |||||
jack_nframes_t max_latency = 0; | jack_nframes_t max_latency = 0; | ||||
jack_port_id_t dst_index; | jack_port_id_t dst_index; | ||||
@@ -296,6 +296,46 @@ int JackGraphManager::ComputeTotalLatencies() | |||||
return 0; | return 0; | ||||
} | } | ||||
void JackGraphManager::RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode) | |||||
{ | |||||
const jack_int_t* connections = ReadCurrentState()->GetConnections(port_index); | |||||
JackPort* port = GetPort(port_index); | |||||
jack_latency_range_t latency = { UINT32_MAX, 0 }; | |||||
jack_port_id_t dst_index; | |||||
for (int i = 0; (i < CONNECTION_NUM_FOR_PORT) && ((dst_index = connections[i]) != EMPTY); i++) { | |||||
AssertPort(dst_index); | |||||
JackPort* dst_port = GetPort(dst_index); | |||||
jack_latency_range_t other_latency; | |||||
dst_port->GetLatencyRange(mode, &other_latency); | |||||
if (other_latency.max > latency.max) | |||||
latency.max = other_latency.max; | |||||
if (other_latency.min < latency.min) | |||||
latency.min = other_latency.min; | |||||
} | |||||
if (latency.min == UINT32_MAX) | |||||
latency.min = 0; | |||||
port->SetLatencyRange(mode, &latency); | |||||
} | |||||
void JackGraphManager::RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode) | |||||
{ | |||||
UInt16 cur_index; | |||||
UInt16 next_index; | |||||
do { | |||||
cur_index = GetCurrentIndex(); | |||||
RecalculateLatencyAux(port_index, mode); | |||||
next_index = GetCurrentIndex(); | |||||
} while (cur_index != next_index); // Until a coherent state has been read | |||||
jack_log("JackGraphManager::RecalculateLatency port_index = %ld", port_index); | |||||
} | |||||
// Server | // Server | ||||
void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size) | void JackGraphManager::SetBufferSize(jack_nframes_t buffer_size) | ||||
{ | { | ||||
@@ -53,6 +53,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||||
float* GetBuffer(jack_port_id_t port_index); | float* GetBuffer(jack_port_id_t port_index); | ||||
void* GetBufferAux(JackConnectionManager* manager, jack_port_id_t port_index, jack_nframes_t frames); | void* GetBufferAux(JackConnectionManager* manager, jack_port_id_t port_index, jack_nframes_t frames); | ||||
jack_nframes_t ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count); | jack_nframes_t ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count); | ||||
void RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode); | |||||
public: | public: | ||||
@@ -72,8 +73,11 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||||
JackPort* GetPort(jack_port_id_t index); | JackPort* GetPort(jack_port_id_t index); | ||||
jack_port_id_t GetPort(const char* name); | jack_port_id_t GetPort(const char* name); | ||||
int ComputeTotalLatency(jack_port_id_t port_index); | int ComputeTotalLatency(jack_port_id_t port_index); | ||||
int ComputeTotalLatencies(); | int ComputeTotalLatencies(); | ||||
void RecalculateLatency(jack_port_id_t port_index, jack_latency_callback_mode_t mode); | |||||
int RequestMonitor(jack_port_id_t port_index, bool onoff); | int RequestMonitor(jack_port_id_t port_index, bool onoff); | ||||
// Connections management | // Connections management | ||||
@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -46,6 +46,7 @@ enum NotificationType { | |||||
kShutDownCallback = 15, | kShutDownCallback = 15, | ||||
kQUIT = 16, | kQUIT = 16, | ||||
kSessionCallback = 17, | kSessionCallback = 17, | ||||
kLatencyCallback = 18, | |||||
kMaxNotification | kMaxNotification | ||||
}; | }; | ||||
@@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -44,6 +44,8 @@ bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type | |||||
fInUse = true; | fInUse = true; | ||||
fLatency = 0; | fLatency = 0; | ||||
fTotalLatency = 0; | fTotalLatency = 0; | ||||
fPlaybackLatency.min = fPlaybackLatency.max = 0; | |||||
fCaptureLatency.min = fCaptureLatency.max = 0; | |||||
fTied = NO_PORT; | fTied = NO_PORT; | ||||
// DB: At this point we do not know current buffer size in frames, | // DB: At this point we do not know current buffer size in frames, | ||||
// but every time buffer will be returned to any user, | // but every time buffer will be returned to any user, | ||||
@@ -86,6 +88,48 @@ jack_nframes_t JackPort::GetTotalLatency() const | |||||
void JackPort::SetLatency(jack_nframes_t nframes) | void JackPort::SetLatency(jack_nframes_t nframes) | ||||
{ | { | ||||
fLatency = nframes; | fLatency = nframes; | ||||
/* setup the new latency values here, | |||||
* so we dont need to change the backend codes. | |||||
*/ | |||||
if (fFlags & JackPortIsOutput) { | |||||
fCaptureLatency.min = nframes; | |||||
fCaptureLatency.max = nframes; | |||||
} | |||||
if (fFlags & JackPortIsInput) { | |||||
fPlaybackLatency.min = nframes; | |||||
fPlaybackLatency.max = nframes; | |||||
} | |||||
} | |||||
void JackPort::SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) | |||||
{ | |||||
if (mode == JackCaptureLatency) { | |||||
fCaptureLatency = *range; | |||||
/* hack to set port->shared->latency up for | |||||
* backend ports | |||||
*/ | |||||
if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical)) | |||||
fLatency = (range->min + range->max) / 2; | |||||
} else { | |||||
fPlaybackLatency = *range; | |||||
/* hack to set port->shared->latency up for | |||||
* backend ports | |||||
*/ | |||||
if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical)) | |||||
fLatency = (range->min + range->max) / 2; | |||||
} | |||||
} | |||||
void JackPort::GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const | |||||
{ | |||||
if (mode == JackCaptureLatency) { | |||||
*range = fCaptureLatency; | |||||
} else { | |||||
*range = fPlaybackLatency; | |||||
} | |||||
} | } | ||||
int JackPort::Tie(jack_port_id_t port_index) | int JackPort::Tie(jack_port_id_t port_index) | ||||
@@ -103,10 +147,10 @@ int JackPort::UnTie() | |||||
int JackPort::RequestMonitor(bool onoff) | int JackPort::RequestMonitor(bool onoff) | ||||
{ | { | ||||
/** | /** | ||||
jackd.h | |||||
jackd.h | |||||
* If @ref JackPortCanMonitor is set for this @a port, turn input | * If @ref JackPortCanMonitor is set for this @a port, turn input | ||||
* monitoring on or off. Otherwise, do nothing. | * monitoring on or off. Otherwise, do nothing. | ||||
if (!(fFlags & JackPortCanMonitor)) | if (!(fFlags & JackPortCanMonitor)) | ||||
return -1; | return -1; | ||||
*/ | */ | ||||
@@ -123,10 +167,10 @@ int JackPort::RequestMonitor(bool onoff) | |||||
int JackPort::EnsureMonitor(bool onoff) | int JackPort::EnsureMonitor(bool onoff) | ||||
{ | { | ||||
/** | /** | ||||
jackd.h | |||||
jackd.h | |||||
* If @ref JackPortCanMonitor is set for this @a port, turn input | * If @ref JackPortCanMonitor is set for this @a port, turn input | ||||
* monitoring on or off. Otherwise, do nothing. | * monitoring on or off. Otherwise, do nothing. | ||||
if (!(fFlags & JackPortCanMonitor)) | if (!(fFlags & JackPortCanMonitor)) | ||||
return -1; | return -1; | ||||
*/ | */ | ||||
@@ -51,6 +51,8 @@ class SERVER_EXPORT JackPort | |||||
jack_nframes_t fLatency; | jack_nframes_t fLatency; | ||||
jack_nframes_t fTotalLatency; | jack_nframes_t fTotalLatency; | ||||
jack_latency_range_t fPlaybackLatency; | |||||
jack_latency_range_t fCaptureLatency; | |||||
uint8_t fMonitorRequests; | uint8_t fMonitorRequests; | ||||
bool fInUse; | bool fInUse; | ||||
@@ -88,9 +90,13 @@ class SERVER_EXPORT JackPort | |||||
int UnTie(); | int UnTie(); | ||||
jack_nframes_t GetLatency() const; | jack_nframes_t GetLatency() const; | ||||
jack_nframes_t GetTotalLatency() const; | |||||
void SetLatency(jack_nframes_t latency); | void SetLatency(jack_nframes_t latency); | ||||
void SetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range); | |||||
void GetLatencyRange(jack_latency_callback_mode_t mode, jack_latency_range_t* range) const; | |||||
jack_nframes_t GetTotalLatency() const; | |||||
int RequestMonitor(bool onoff); | int RequestMonitor(bool onoff); | ||||
int EnsureMonitor(bool onoff); | int EnsureMonitor(bool onoff); | ||||
bool MonitoringInput() | bool MonitoringInput() | ||||