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() | ||||