Jack2
1.9.8
|
00001 /* 00002 Copyright (C) 2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 00018 */ 00019 00020 #include "JackAudioAdapter.h" 00021 #include "JackError.h" 00022 #include "JackCompilerDeps.h" 00023 #include "JackTools.h" 00024 #include "JackTime.h" 00025 #include "jslist.h" 00026 #include <stdio.h> 00027 #include <stdlib.h> 00028 #include <assert.h> 00029 00030 using namespace std; 00031 00032 namespace Jack 00033 { 00034 00035 int JackAudioAdapter::Process(jack_nframes_t frames, void* arg) 00036 { 00037 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); 00038 jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()]; 00039 jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; 00040 00041 // Always clear output 00042 for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { 00043 inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); 00044 memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); 00045 } 00046 00047 for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { 00048 outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); 00049 } 00050 00051 adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); 00052 return 0; 00053 } 00054 00055 int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg) 00056 { 00057 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); 00058 adapter->Reset(); 00059 adapter->fAudioAdapter->SetHostBufferSize(buffer_size); 00060 return 0; 00061 } 00062 00063 int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg) 00064 { 00065 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); 00066 adapter->Reset(); 00067 adapter->fAudioAdapter->SetHostSampleRate(sample_rate); 00068 return 0; 00069 } 00070 00071 void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg) 00072 { 00073 JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); 00074 00075 if (mode == JackCaptureLatency) { 00076 for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { 00077 jack_latency_range_t range; 00078 range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i); 00079 jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range); 00080 } 00081 00082 } else { 00083 for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { 00084 jack_latency_range_t range; 00085 range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i); 00086 jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range); 00087 } 00088 } 00089 } 00090 00091 JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params) 00092 :fClient(client), fAudioAdapter(audio_io) 00093 { 00094 const JSList* node; 00095 const jack_driver_param_t* param; 00096 fAutoConnect = false; 00097 00098 for (node = params; node; node = jack_slist_next(node)) { 00099 param = (const jack_driver_param_t*)node->data; 00100 switch (param->character) { 00101 case 'c': 00102 fAutoConnect = true; 00103 break; 00104 } 00105 } 00106 } 00107 00108 JackAudioAdapter::~JackAudioAdapter() 00109 { 00110 // When called, Close has already been used for the client, thus ports are already unregistered. 00111 delete fAudioAdapter; 00112 } 00113 00114 void JackAudioAdapter::FreePorts() 00115 { 00116 for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { 00117 if (fCapturePortList[i]) { 00118 jack_port_unregister(fClient, fCapturePortList[i]); 00119 } 00120 } 00121 for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { 00122 if (fPlaybackPortList[i]) { 00123 jack_port_unregister(fClient, fPlaybackPortList[i]); 00124 } 00125 } 00126 00127 delete[] fCapturePortList; 00128 delete[] fPlaybackPortList; 00129 } 00130 00131 void JackAudioAdapter::ConnectPorts() 00132 { 00133 const char** ports; 00134 00135 ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); 00136 if (ports != NULL) { 00137 for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) { 00138 jack_connect(fClient, jack_port_name(fCapturePortList[i]), ports[i]); 00139 } 00140 jack_free(ports); 00141 } 00142 00143 ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); 00144 if (ports != NULL) { 00145 for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) { 00146 jack_connect(fClient, ports[i], jack_port_name(fPlaybackPortList[i])); 00147 } 00148 jack_free(ports); 00149 } 00150 } 00151 00152 void JackAudioAdapter::Reset() 00153 { 00154 fAudioAdapter->Reset(); 00155 } 00156 00157 int JackAudioAdapter::Open() 00158 { 00159 char name[32]; 00160 jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs()); 00161 fAudioAdapter->Create(); 00162 00163 //jack ports 00164 fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()]; 00165 fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()]; 00166 00167 for (int i = 0; i < fAudioAdapter->GetInputs(); i++) { 00168 snprintf(name, sizeof(name), "capture_%d", i + 1); 00169 if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) { 00170 goto fail; 00171 } 00172 } 00173 00174 for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) { 00175 snprintf(name, sizeof(name), "playback_%d", i + 1); 00176 if ((fPlaybackPortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, 0)) == NULL) { 00177 goto fail; 00178 } 00179 } 00180 00181 //callbacks and activation 00182 if (jack_set_process_callback(fClient, Process, this) < 0) { 00183 goto fail; 00184 } 00185 if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) { 00186 goto fail; 00187 } 00188 if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) { 00189 goto fail; 00190 } 00191 if (jack_set_latency_callback(fClient, Latency, this) < 0) { 00192 goto fail; 00193 } 00194 if (jack_activate(fClient) < 0) { 00195 goto fail; 00196 } 00197 00198 if (fAutoConnect) { 00199 ConnectPorts(); 00200 } 00201 00202 // Ring buffers are now allocated... 00203 return fAudioAdapter->Open(); 00204 return 0; 00205 00206 fail: 00207 FreePorts(); 00208 fAudioAdapter->Destroy(); 00209 return -1; 00210 } 00211 00212 int JackAudioAdapter::Close() 00213 { 00214 fAudioAdapter->Close(); 00215 fAudioAdapter->Destroy(); 00216 return 0; 00217 } 00218 00219 } //namespace