| @@ -44,12 +44,17 @@ JackAudioDriver::~JackAudioDriver() | |||||
| int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
| { | { | ||||
| // Update engine and graph manager state | |||||
| fEngineControl->fBufferSize = buffer_size; | fEngineControl->fBufferSize = buffer_size; | ||||
| fGraphManager->SetBufferSize(buffer_size); | fGraphManager->SetBufferSize(buffer_size); | ||||
| fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
| if (!fEngineControl->fTimeOut) | if (!fEngineControl->fTimeOut) | ||||
| fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
| return 0; | |||||
| UpdateLatencies(); | |||||
| // Redirect on slaves drivers... | |||||
| return JackDriver::SetBufferSize(buffer_size); | |||||
| } | } | ||||
| int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate) | int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate) | ||||
| @@ -58,7 +63,8 @@ int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate) | |||||
| fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec | ||||
| if (!fEngineControl->fTimeOut) | if (!fEngineControl->fTimeOut) | ||||
| fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs); | ||||
| return 0; | |||||
| return JackDriver::SetSampleRate(sample_rate); | |||||
| } | } | ||||
| int JackAudioDriver::Open(jack_nframes_t buffer_size, | int JackAudioDriver::Open(jack_nframes_t buffer_size, | ||||
| @@ -95,13 +101,33 @@ int JackAudioDriver::Open(bool capturing, | |||||
| return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | ||||
| } | } | ||||
| void JackAudioDriver::UpdateLatencies() | |||||
| { | |||||
| jack_latency_range_t range; | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| range.max = range.min = fEngineControl->fBufferSize; | |||||
| fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| if (! fEngineControl->fSyncMode) { | |||||
| range.max = range.min = fEngineControl->fBufferSize * 2; | |||||
| } | |||||
| fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| if (fWithMonitorPorts) { | |||||
| range.min = range.max = fEngineControl->fBufferSize; | |||||
| fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| } | |||||
| } | |||||
| int JackAudioDriver::Attach() | int JackAudioDriver::Attach() | ||||
| { | { | ||||
| JackPort* port; | JackPort* port; | ||||
| jack_port_id_t port_index; | jack_port_id_t port_index; | ||||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| jack_latency_range_t range; | |||||
| int i; | int i; | ||||
| jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | ||||
| @@ -115,8 +141,6 @@ int JackAudioDriver::Attach() | |||||
| } | } | ||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| range.min = range.max = fEngineControl->fBufferSize + fCaptureLatency; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fCapturePortList[i] = port_index; | fCapturePortList[i] = port_index; | ||||
| jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index); | jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index); | ||||
| } | } | ||||
| @@ -130,9 +154,6 @@ int JackAudioDriver::Attach() | |||||
| } | } | ||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| // Add more latency if "async" mode is used... | |||||
| range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency; | |||||
| port->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| fPlaybackPortList[i] = port_index; | fPlaybackPortList[i] = port_index; | ||||
| jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); | ||||
| @@ -144,14 +165,12 @@ int JackAudioDriver::Attach() | |||||
| jack_error("Cannot register monitor port for %s", name); | jack_error("Cannot register monitor port for %s", name); | ||||
| return -1; | return -1; | ||||
| } else { | } else { | ||||
| port = fGraphManager->GetPort(port_index); | |||||
| range.min = range.max = fEngineControl->fBufferSize; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fMonitorPortList[i] = port_index; | |||||
| fMonitorPortList[i] = port_index; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| UpdateLatencies(); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -62,6 +62,7 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
| jack_default_audio_sample_t* GetMonitorBuffer(int port_index); | jack_default_audio_sample_t* GetMonitorBuffer(int port_index); | ||||
| void HandleLatencyCallback(int status); | void HandleLatencyCallback(int status); | ||||
| void UpdateLatencies(); | |||||
| public: | public: | ||||
| @@ -418,12 +418,28 @@ bool JackDriver::IsFixedBufferSize() | |||||
| int JackDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
| { | { | ||||
| return 0; | |||||
| int res = 0; | |||||
| list<JackDriverInterface*>::const_iterator it; | |||||
| for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | |||||
| JackDriverInterface* slave = *it; | |||||
| if (slave->SetBufferSize(buffer_size) < 0) | |||||
| res = -1; | |||||
| } | |||||
| return res; | |||||
| } | } | ||||
| int JackDriver::SetSampleRate(jack_nframes_t sample_rate) | int JackDriver::SetSampleRate(jack_nframes_t sample_rate) | ||||
| { | { | ||||
| return 0; | |||||
| int res = 0; | |||||
| list<JackDriverInterface*>::const_iterator it; | |||||
| for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | |||||
| JackDriverInterface* slave = *it; | |||||
| if (slave->SetSampleRate(sample_rate) < 0) | |||||
| res = -1; | |||||
| } | |||||
| return res; | |||||
| } | } | ||||
| bool JackDriver::Initialize() | bool JackDriver::Initialize() | ||||
| @@ -78,6 +78,7 @@ int JackDummyDriver::Process() | |||||
| int JackDummyDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackDummyDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
| { | { | ||||
| // Generic change, never fails | |||||
| JackAudioDriver::SetBufferSize(buffer_size); | JackAudioDriver::SetBufferSize(buffer_size); | ||||
| fWaitTime = (unsigned long)((((float)buffer_size) / ((float)fEngineControl->fSampleRate)) * 1000000.0f); | fWaitTime = (unsigned long)((((float)buffer_size) / ((float)fEngineControl->fSampleRate)) * 1000000.0f); | ||||
| return 0; | return 0; | ||||
| @@ -145,6 +145,7 @@ int JackMidiDriver::Write() | |||||
| int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
| { | { | ||||
| // Update latencies | |||||
| jack_latency_range_t latency_range; | jack_latency_range_t latency_range; | ||||
| latency_range.max = buffer_size; | latency_range.max = buffer_size; | ||||
| latency_range.min = buffer_size; | latency_range.min = buffer_size; | ||||
| @@ -392,7 +392,7 @@ namespace Jack | |||||
| { | { | ||||
| JackNetMaster* obj = static_cast<JackNetMaster*>(arg); | JackNetMaster* obj = static_cast<JackNetMaster*>(arg); | ||||
| if (nframes != obj->fParams.fPeriodSize) { | if (nframes != obj->fParams.fPeriodSize) { | ||||
| jack_error("Cannot handle bufer size change, so JackNetMaster proxy will be removed..."); | |||||
| jack_error("Cannot handle buffer size change, so JackNetMaster proxy will be removed..."); | |||||
| obj->Exit(); | obj->Exit(); | ||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -223,13 +223,11 @@ int JackServer::SetBufferSize(jack_nframes_t buffer_size) | |||||
| } | } | ||||
| if (fAudioDriver->SetBufferSize(buffer_size) == 0) { | if (fAudioDriver->SetBufferSize(buffer_size) == 0) { | ||||
| fFreewheelDriver->SetBufferSize(buffer_size); | |||||
| fEngine->NotifyBufferSize(buffer_size); | fEngine->NotifyBufferSize(buffer_size); | ||||
| return fAudioDriver->Start(); | return fAudioDriver->Start(); | ||||
| } else { // Failure: try to restore current value | } else { // Failure: try to restore current value | ||||
| jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size); | jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size); | ||||
| fAudioDriver->SetBufferSize(current_buffer_size); | fAudioDriver->SetBufferSize(current_buffer_size); | ||||
| fFreewheelDriver->SetBufferSize(current_buffer_size); | |||||
| fAudioDriver->Start(); | fAudioDriver->Start(); | ||||
| // SetBufferSize actually failed, so return an error... | // SetBufferSize actually failed, so return an error... | ||||
| return -1; | return -1; | ||||
| @@ -55,8 +55,11 @@ int JackAlsaDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
| ((alsa_driver_t *)fDriver)->frame_rate); | ((alsa_driver_t *)fDriver)->frame_rate); | ||||
| if (res == 0) { // update fEngineControl and fGraphManager | if (res == 0) { // update fEngineControl and fGraphManager | ||||
| JackAudioDriver::SetBufferSize(buffer_size); // never fails | |||||
| JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||||
| // ALSA specific | |||||
| UpdateLatencies(); | |||||
| } else { | } else { | ||||
| // Restore old values | |||||
| alsa_driver_reset_parameters((alsa_driver_t *)fDriver, fEngineControl->fBufferSize, | alsa_driver_reset_parameters((alsa_driver_t *)fDriver, fEngineControl->fBufferSize, | ||||
| ((alsa_driver_t *)fDriver)->user_nperiods, | ((alsa_driver_t *)fDriver)->user_nperiods, | ||||
| ((alsa_driver_t *)fDriver)->frame_rate); | ((alsa_driver_t *)fDriver)->frame_rate); | ||||
| @@ -65,6 +68,28 @@ int JackAlsaDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
| return res; | return res; | ||||
| } | } | ||||
| void JackAlsaDriver::UpdateLatencies() | |||||
| { | |||||
| jack_latency_range_t range; | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| range.min = range.max = alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency; | |||||
| fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| // Add one buffer more latency if "async" mode is used... | |||||
| range.min = range.max = (alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + | |||||
| ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency; | |||||
| fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| // Monitor port | |||||
| if (fWithMonitorPorts) { | |||||
| range.min = range.max = alsa_driver->frames_per_cycle; | |||||
| fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| } | |||||
| } | |||||
| int JackAlsaDriver::Attach() | int JackAlsaDriver::Attach() | ||||
| { | { | ||||
| JackPort* port; | JackPort* port; | ||||
| @@ -72,7 +97,6 @@ int JackAlsaDriver::Attach() | |||||
| unsigned long port_flags = (unsigned long)CaptureDriverFlags; | unsigned long port_flags = (unsigned long)CaptureDriverFlags; | ||||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| jack_latency_range_t range; | |||||
| assert(fCaptureChannels < DRIVER_PORT_NUM); | assert(fCaptureChannels < DRIVER_PORT_NUM); | ||||
| assert(fPlaybackChannels < DRIVER_PORT_NUM); | assert(fPlaybackChannels < DRIVER_PORT_NUM); | ||||
| @@ -97,8 +121,6 @@ int JackAlsaDriver::Attach() | |||||
| } | } | ||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| range.min = range.max = alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fCapturePortList[i] = port_index; | fCapturePortList[i] = port_index; | ||||
| jack_log("JackAlsaDriver::Attach fCapturePortList[i] %ld ", port_index); | jack_log("JackAlsaDriver::Attach fCapturePortList[i] %ld ", port_index); | ||||
| } | } | ||||
| @@ -114,11 +136,6 @@ int JackAlsaDriver::Attach() | |||||
| } | } | ||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| // Add one buffer more latency if "async" mode is used... | |||||
| range.min = range.max = (alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) + | |||||
| ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency; | |||||
| port->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| fPlaybackPortList[i] = port_index; | fPlaybackPortList[i] = port_index; | ||||
| jack_log("JackAlsaDriver::Attach fPlaybackPortList[i] %ld ", port_index); | jack_log("JackAlsaDriver::Attach fPlaybackPortList[i] %ld ", port_index); | ||||
| @@ -129,14 +146,13 @@ int JackAlsaDriver::Attach() | |||||
| if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
| jack_error ("ALSA: cannot register monitor port for %s", name); | jack_error ("ALSA: cannot register monitor port for %s", name); | ||||
| } else { | } else { | ||||
| port = fGraphManager->GetPort(port_index); | |||||
| range.min = range.max = alsa_driver->frames_per_cycle; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fMonitorPortList[i] = port_index; | fMonitorPortList[i] = port_index; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| UpdateLatencies(); | |||||
| if (alsa_driver->midi) { | if (alsa_driver->midi) { | ||||
| int err = (alsa_driver->midi->attach)(alsa_driver->midi); | int err = (alsa_driver->midi->attach)(alsa_driver->midi); | ||||
| if (err) | if (err) | ||||
| @@ -42,6 +42,8 @@ class JackAlsaDriver : public JackAudioDriver | |||||
| int fReservedCaptureDevice; | int fReservedCaptureDevice; | ||||
| int fReservedPlaybackDevice; | int fReservedPlaybackDevice; | ||||
| void UpdateLatencies(); | |||||
| public: | public: | ||||
| JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
| @@ -1563,6 +1563,53 @@ int JackCoreAudioDriver::Close() | |||||
| return res; | return res; | ||||
| } | } | ||||
| void JackCoreAudioDriver::UpdateLatencies() | |||||
| { | |||||
| UInt32 size; | |||||
| OSStatus err; | |||||
| jack_latency_range_t range; | |||||
| range.max = fEngineControl->fBufferSize; | |||||
| range.min = fEngineControl->fBufferSize; | |||||
| for (int i = 0; i < fCaptureChannels; i++) { | |||||
| size = sizeof(UInt32); | |||||
| UInt32 value1 = 0; | |||||
| UInt32 value2 = 0; | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
| range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; | |||||
| fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| for (int i = 0; i < fPlaybackChannels; i++) { | |||||
| size = sizeof(UInt32); | |||||
| UInt32 value1 = 0; | |||||
| UInt32 value2 = 0; | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
| // Add more latency if "async" mode is used... | |||||
| range.min = range.max | |||||
| = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency; | |||||
| fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| // Monitor port | |||||
| if (fWithMonitorPorts) { | |||||
| range.min = range.max = fEngineControl->fBufferSize; | |||||
| fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range); | |||||
| } | |||||
| } | |||||
| } | |||||
| int JackCoreAudioDriver::Attach() | int JackCoreAudioDriver::Attach() | ||||
| { | { | ||||
| OSStatus err; | OSStatus err; | ||||
| @@ -1573,7 +1620,6 @@ int JackCoreAudioDriver::Attach() | |||||
| char channel_name[64]; | char channel_name[64]; | ||||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | ||||
| jack_latency_range_t range; | |||||
| jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | ||||
| @@ -1598,20 +1644,8 @@ int JackCoreAudioDriver::Attach() | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| size = sizeof(UInt32); | |||||
| UInt32 value1 = 0; | |||||
| UInt32 value2 = 0; | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fCapturePortList[i] = port_index; | fCapturePortList[i] = port_index; | ||||
| } | } | ||||
| @@ -1636,21 +1670,8 @@ int JackCoreAudioDriver::Attach() | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| size = sizeof(UInt32); | |||||
| UInt32 value1 = 0; | |||||
| UInt32 value2 = 0; | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
| err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | |||||
| if (err != noErr) | |||||
| jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
| port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
| port->SetAlias(alias); | port->SetAlias(alias); | ||||
| // Add more latency if "async" mode is used... | |||||
| range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency; | |||||
| port->SetLatencyRange(JackPlaybackLatency, &range); | |||||
| fPlaybackPortList[i] = port_index; | fPlaybackPortList[i] = port_index; | ||||
| // Monitor ports | // Monitor ports | ||||
| @@ -1661,14 +1682,13 @@ int JackCoreAudioDriver::Attach() | |||||
| jack_error("Cannot register monitor port for %s", name); | jack_error("Cannot register monitor port for %s", name); | ||||
| return -1; | return -1; | ||||
| } else { | } else { | ||||
| port = fGraphManager->GetPort(port_index); | |||||
| range.min = range.max = fEngineControl->fBufferSize; | |||||
| port->SetLatencyRange(JackCaptureLatency, &range); | |||||
| fMonitorPortList[i] = port_index; | fMonitorPortList[i] = port_index; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| UpdateLatencies(); | |||||
| // Input buffers do no change : prepare them only once | // Input buffers do no change : prepare them only once | ||||
| for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
| fJackInputData->mBuffers[i].mData = GetInputBuffer(i); | fJackInputData->mBuffers[i].mData = GetInputBuffer(i); | ||||
| @@ -1716,17 +1736,19 @@ int JackCoreAudioDriver::Stop() | |||||
| int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
| { | { | ||||
| OSStatus err; | |||||
| UInt32 outSize = sizeof(UInt32); | UInt32 outSize = sizeof(UInt32); | ||||
| err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size); | |||||
| OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size); | |||||
| if (err != noErr) { | if (err != noErr) { | ||||
| jack_error("Cannot set buffer size %ld", buffer_size); | jack_error("Cannot set buffer size %ld", buffer_size); | ||||
| printError(err); | printError(err); | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| JackAudioDriver::SetBufferSize(buffer_size); // never fails | |||||
| JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||||
| // CoreAudio specific | |||||
| UpdateLatencies(); | |||||
| // Input buffers do no change : prepare them only once | // Input buffers do no change : prepare them only once | ||||
| for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
| @@ -40,7 +40,7 @@ typedef UInt8 CAAudioHardwareDeviceSectionID; | |||||
| #define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00) | #define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00) | ||||
| #define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00) | #define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00) | ||||
| #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) | #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF) | ||||
| #define WAIT_COUNTER 60 | #define WAIT_COUNTER 60 | ||||
| /*! | /*! | ||||
| @@ -74,13 +74,13 @@ class JackCoreAudioDriver : public JackAudioDriver | |||||
| float fIOUsage; | float fIOUsage; | ||||
| float fComputationGrain; | float fComputationGrain; | ||||
| bool fClockDriftCompensate; | bool fClockDriftCompensate; | ||||
| /* | |||||
| /* | |||||
| #ifdef MAC_OS_X_VERSION_10_5 | #ifdef MAC_OS_X_VERSION_10_5 | ||||
| AudioDeviceIOProcID fMesureCallbackID; | AudioDeviceIOProcID fMesureCallbackID; | ||||
| #endif | #endif | ||||
| */ | */ | ||||
| static OSStatus Render(void *inRefCon, | static OSStatus Render(void *inRefCon, | ||||
| AudioUnitRenderActionFlags *ioActionFlags, | AudioUnitRenderActionFlags *ioActionFlags, | ||||
| const AudioTimeStamp *inTimeStamp, | const AudioTimeStamp *inTimeStamp, | ||||
| @@ -106,13 +106,13 @@ class JackCoreAudioDriver : public JackAudioDriver | |||||
| OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | OSStatus GetDefaultOutputDevice(AudioDeviceID* id); | ||||
| OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); | ||||
| OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput); | OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput); | ||||
| // Setup | // Setup | ||||
| OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | ||||
| OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice); | ||||
| OSStatus DestroyAggregateDevice(); | OSStatus DestroyAggregateDevice(); | ||||
| bool IsAggregateDevice(AudioDeviceID device); | bool IsAggregateDevice(AudioDeviceID device); | ||||
| int SetupDevices(const char* capture_driver_uid, | int SetupDevices(const char* capture_driver_uid, | ||||
| const char* playback_driver_uid, | const char* playback_driver_uid, | ||||
| char* capture_driver_name, | char* capture_driver_name, | ||||
| @@ -146,10 +146,12 @@ class JackCoreAudioDriver : public JackAudioDriver | |||||
| int AddListeners(); | int AddListeners(); | ||||
| void RemoveListeners(); | void RemoveListeners(); | ||||
| bool TakeHogAux(AudioDeviceID deviceID, bool isInput); | bool TakeHogAux(AudioDeviceID deviceID, bool isInput); | ||||
| bool TakeHog(); | bool TakeHog(); | ||||
| void UpdateLatencies(); | |||||
| public: | public: | ||||
| JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | ||||
| @@ -86,13 +86,11 @@ namespace Jack | |||||
| return -1; | return -1; | ||||
| //get devices | //get devices | ||||
| if (capturing) | |||||
| { | |||||
| if (capturing) { | |||||
| if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) | if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| if (playing) | |||||
| { | |||||
| if (playing) { | |||||
| if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) | if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| @@ -100,25 +98,21 @@ namespace Jack | |||||
| jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice); | jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice); | ||||
| //default channels number required | //default channels number required | ||||
| if (inchannels == 0) | |||||
| { | |||||
| if (inchannels == 0) { | |||||
| jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max); | jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max); | ||||
| inchannels = in_max; | inchannels = in_max; | ||||
| } | } | ||||
| if (outchannels == 0) | |||||
| { | |||||
| if (outchannels == 0) { | |||||
| jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max); | jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max); | ||||
| outchannels = out_max; | outchannels = out_max; | ||||
| } | } | ||||
| //too many channels required, take max available | //too many channels required, take max available | ||||
| if (inchannels > in_max) | |||||
| { | |||||
| if (inchannels > in_max) { | |||||
| jack_error("This device has only %d available input channels.", in_max); | jack_error("This device has only %d available input channels.", in_max); | ||||
| inchannels = in_max; | inchannels = in_max; | ||||
| } | } | ||||
| if (outchannels > out_max) | |||||
| { | |||||
| if (outchannels > out_max) { | |||||
| jack_error("This device has only %d available output channels.", out_max); | jack_error("This device has only %d available output channels.", out_max); | ||||
| outchannels = out_max; | outchannels = out_max; | ||||
| } | } | ||||
| @@ -148,8 +142,7 @@ namespace Jack | |||||
| paNoFlag, // Clipping is on... | paNoFlag, // Clipping is on... | ||||
| Render, | Render, | ||||
| this); | this); | ||||
| if (err != paNoError) | |||||
| { | |||||
| if (err != paNoError) { | |||||
| jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); | jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); | ||||
| goto error; | goto error; | ||||
| } | } | ||||
| @@ -218,13 +211,12 @@ error: | |||||
| PaStreamParameters inputParameters; | PaStreamParameters inputParameters; | ||||
| PaStreamParameters outputParameters; | PaStreamParameters outputParameters; | ||||
| if ((err = Pa_CloseStream(fStream)) != paNoError) | |||||
| { | |||||
| if ((err = Pa_CloseStream(fStream)) != paNoError) { | |||||
| jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err)); | jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err)); | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| //change parametering | |||||
| // Update parameters | |||||
| inputParameters.device = fInputDevice; | inputParameters.device = fInputDevice; | ||||
| inputParameters.channelCount = fCaptureChannels; | inputParameters.channelCount = fCaptureChannels; | ||||
| inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output | ||||
| @@ -250,15 +242,14 @@ error: | |||||
| Render, | Render, | ||||
| this); | this); | ||||
| if (err != paNoError) | |||||
| { | |||||
| if (err != paNoError) { | |||||
| jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); | jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err)); | ||||
| return -1; | return -1; | ||||
| } | |||||
| else | |||||
| { | |||||
| // Only done when success | |||||
| return JackAudioDriver::SetBufferSize(buffer_size); // never fails | |||||
| } else { | |||||
| JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||||
| // PortAudio specific | |||||
| UpdateLatencies(); | |||||
| return 0; | |||||
| } | } | ||||
| } | } | ||||
| @@ -48,6 +48,8 @@ class JackPortAudioDriver : public JackAudioDriver | |||||
| PaStreamCallbackFlags statusFlags, | PaStreamCallbackFlags statusFlags, | ||||
| void* userData); | void* userData); | ||||
| void UpdateLatencies(); | |||||
| public: | public: | ||||
| JackPortAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, PortAudioDevices* pa_devices) | JackPortAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, PortAudioDevices* pa_devices) | ||||