Jack2
1.9.8
|
00001 /* 00002 Copyright (C) 2009 Grame 00003 Copyright (C) 2011 Devin Anderson 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 00019 */ 00020 00021 #include <cmath> 00022 00023 #include "JackEngineControl.h" 00024 #include "JackWinMMEDriver.h" 00025 00026 using Jack::JackWinMMEDriver; 00027 00028 JackWinMMEDriver::JackWinMMEDriver(const char *name, const char *alias, 00029 JackLockedEngine *engine, 00030 JackSynchro *table): 00031 JackMidiDriver(name, alias, engine, table) 00032 { 00033 input_ports = 0; 00034 output_ports = 0; 00035 period = 0; 00036 } 00037 00038 JackWinMMEDriver::~JackWinMMEDriver() 00039 {} 00040 00041 int 00042 JackWinMMEDriver::Attach() 00043 { 00044 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00045 jack_port_id_t index; 00046 jack_nframes_t latency = buffer_size; 00047 jack_latency_range_t latency_range; 00048 const char *name; 00049 JackPort *port; 00050 latency_range.max = latency + 00051 ((jack_nframes_t) std::ceil((period / 1000.0) * 00052 fEngineControl->fSampleRate)); 00053 latency_range.min = latency; 00054 00055 jack_info("JackWinMMEDriver::Attach - fCaptureChannels %d", fCaptureChannels); 00056 jack_info("JackWinMMEDriver::Attach - fPlaybackChannels %d", fPlaybackChannels); 00057 00058 // Inputs 00059 for (int i = 0; i < fCaptureChannels; i++) { 00060 JackWinMMEInputPort *input_port = input_ports[i]; 00061 name = input_port->GetName(); 00062 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00063 JACK_DEFAULT_MIDI_TYPE, 00064 CaptureDriverFlags, buffer_size, &index) < 0) { 00065 jack_error("JackWinMMEDriver::Attach - cannot register input port " 00066 "with name '%s'.", name); 00067 // X: Do we need to deallocate ports? 00068 return -1; 00069 } 00070 port = fGraphManager->GetPort(index); 00071 port->SetAlias(input_port->GetAlias()); 00072 port->SetLatencyRange(JackCaptureLatency, &latency_range); 00073 fCapturePortList[i] = index; 00074 } 00075 00076 if (! fEngineControl->fSyncMode) { 00077 latency += buffer_size; 00078 latency_range.max = latency; 00079 latency_range.min = latency; 00080 } 00081 00082 // Outputs 00083 for (int i = 0; i < fPlaybackChannels; i++) { 00084 JackWinMMEOutputPort *output_port = output_ports[i]; 00085 name = output_port->GetName(); 00086 if (fEngine->PortRegister(fClientControl.fRefNum, name, 00087 JACK_DEFAULT_MIDI_TYPE, 00088 PlaybackDriverFlags, buffer_size, &index) < 0) { 00089 jack_error("JackWinMMEDriver::Attach - cannot register output " 00090 "port with name '%s'.", name); 00091 // X: Do we need to deallocate ports? 00092 return -1; 00093 } 00094 port = fGraphManager->GetPort(index); 00095 port->SetAlias(output_port->GetAlias()); 00096 port->SetLatencyRange(JackPlaybackLatency, &latency_range); 00097 fPlaybackPortList[i] = index; 00098 } 00099 00100 return 0; 00101 } 00102 00103 int 00104 JackWinMMEDriver::Close() 00105 { 00106 // Generic MIDI driver close 00107 int result = JackMidiDriver::Close(); 00108 00109 if (input_ports) { 00110 for (int i = 0; i < fCaptureChannels; i++) { 00111 delete input_ports[i]; 00112 } 00113 delete[] input_ports; 00114 input_ports = 0; 00115 } 00116 if (output_ports) { 00117 for (int i = 0; i < fPlaybackChannels; i++) { 00118 delete output_ports[i]; 00119 } 00120 delete[] output_ports; 00121 output_ports = 0; 00122 } 00123 if (period) { 00124 if (timeEndPeriod(period) != TIMERR_NOERROR) { 00125 jack_error("JackWinMMEDriver::Close - failed to unset timer " 00126 "resolution."); 00127 result = -1; 00128 } 00129 } 00130 return result; 00131 } 00132 00133 int 00134 JackWinMMEDriver::Open(bool capturing, bool playing, int in_channels, 00135 int out_channels, bool monitor, 00136 const char* capture_driver_name, 00137 const char* playback_driver_name, 00138 jack_nframes_t capture_latency, 00139 jack_nframes_t playback_latency) 00140 { 00141 const char *client_name = fClientControl.fName; 00142 int input_count = 0; 00143 int output_count = 0; 00144 int num_potential_inputs = midiInGetNumDevs(); 00145 int num_potential_outputs = midiOutGetNumDevs(); 00146 00147 jack_info("JackWinMMEDriver::Open - num_potential_inputs %d", num_potential_inputs); 00148 jack_info("JackWinMMEDriver::Open - num_potential_outputs %d", num_potential_outputs); 00149 00150 period = 0; 00151 TIMECAPS caps; 00152 if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) { 00153 jack_error("JackWinMMEDriver::Open - could not get timer device " 00154 "capabilities. Continuing anyway ..."); 00155 } else { 00156 period = caps.wPeriodMin; 00157 if (timeBeginPeriod(period) != TIMERR_NOERROR) { 00158 jack_error("JackWinMMEDriver::Open - could not set minimum timer " 00159 "resolution. Continuing anyway ..."); 00160 period = 0; 00161 } else { 00162 00163 jack_info("JackWinMMEDriver::Open - multimedia timer resolution " 00164 "set to %d milliseconds.", period); 00165 00166 } 00167 } 00168 00169 if (num_potential_inputs) { 00170 try { 00171 input_ports = new JackWinMMEInputPort *[num_potential_inputs]; 00172 } catch (std::exception e) { 00173 jack_error("JackWinMMEDriver::Open - while creating input port " 00174 "array: %s", e.what()); 00175 goto unset_timer_resolution; 00176 } 00177 for (int i = 0; i < num_potential_inputs; i++) { 00178 try { 00179 input_ports[input_count] = 00180 new JackWinMMEInputPort(fAliasName, client_name, 00181 capture_driver_name, i); 00182 } catch (std::exception e) { 00183 jack_error("JackWinMMEDriver::Open - while creating input " 00184 "port: %s", e.what()); 00185 continue; 00186 } 00187 input_count++; 00188 } 00189 } 00190 if (num_potential_outputs) { 00191 try { 00192 output_ports = new JackWinMMEOutputPort *[num_potential_outputs]; 00193 } catch (std::exception e) { 00194 jack_error("JackWinMMEDriver::Open - while creating output port " 00195 "array: %s", e.what()); 00196 goto destroy_input_ports; 00197 } 00198 for (int i = 0; i < num_potential_outputs; i++) { 00199 try { 00200 output_ports[output_count] = 00201 new JackWinMMEOutputPort(fAliasName, client_name, 00202 playback_driver_name, i); 00203 } catch (std::exception e) { 00204 jack_error("JackWinMMEDriver::Open - while creating output " 00205 "port: %s", e.what()); 00206 continue; 00207 } 00208 output_count++; 00209 } 00210 } 00211 00212 jack_info("JackWinMMEDriver::Open - input_count %d", input_count); 00213 jack_info("JackWinMMEDriver::Open - output_count %d", output_count); 00214 00215 if (! (input_count || output_count)) { 00216 jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs " 00217 "allocated."); 00218 } else if (! JackMidiDriver::Open(capturing, playing, input_count, 00219 output_count, monitor, 00220 capture_driver_name, 00221 playback_driver_name, capture_latency, 00222 playback_latency)) { 00223 return 0; 00224 } 00225 00226 if (output_ports) { 00227 for (int i = 0; i < output_count; i++) { 00228 delete output_ports[i]; 00229 } 00230 delete[] output_ports; 00231 output_ports = 0; 00232 } 00233 destroy_input_ports: 00234 if (input_ports) { 00235 for (int i = 0; i < input_count; i++) { 00236 delete input_ports[i]; 00237 } 00238 delete[] input_ports; 00239 input_ports = 0; 00240 } 00241 unset_timer_resolution: 00242 if (period) { 00243 if (timeEndPeriod(period) != TIMERR_NOERROR) { 00244 jack_error("JackWinMMEDriver::Open - failed to unset timer " 00245 "resolution."); 00246 } 00247 } 00248 return -1; 00249 } 00250 00251 int 00252 JackWinMMEDriver::Read() 00253 { 00254 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00255 for (int i = 0; i < fCaptureChannels; i++) { 00256 input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size); 00257 } 00258 00259 return 0; 00260 } 00261 00262 int 00263 JackWinMMEDriver::Write() 00264 { 00265 jack_nframes_t buffer_size = fEngineControl->fBufferSize; 00266 for (int i = 0; i < fPlaybackChannels; i++) { 00267 output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size); 00268 } 00269 00270 return 0; 00271 } 00272 00273 int 00274 JackWinMMEDriver::Start() 00275 { 00276 jack_info("JackWinMMEDriver::Start - Starting driver."); 00277 00278 JackMidiDriver::Start(); 00279 00280 int input_count = 0; 00281 int output_count = 0; 00282 00283 jack_info("JackWinMMEDriver::Start - Enabling input ports."); 00284 00285 for (; input_count < fCaptureChannels; input_count++) { 00286 if (input_ports[input_count]->Start() < 0) { 00287 jack_error("JackWinMMEDriver::Start - Failed to enable input " 00288 "port."); 00289 goto stop_input_ports; 00290 } 00291 } 00292 00293 jack_info("JackWinMMEDriver::Start - Enabling output ports."); 00294 00295 for (; output_count < fPlaybackChannels; output_count++) { 00296 if (output_ports[output_count]->Start() < 0) { 00297 jack_error("JackWinMMEDriver::Start - Failed to enable output " 00298 "port."); 00299 goto stop_output_ports; 00300 } 00301 } 00302 00303 jack_info("JackWinMMEDriver::Start - Driver started."); 00304 00305 return 0; 00306 00307 stop_output_ports: 00308 for (int i = 0; i < output_count; i++) { 00309 if (output_ports[i]->Stop() < 0) { 00310 jack_error("JackWinMMEDriver::Start - Failed to disable output " 00311 "port."); 00312 } 00313 } 00314 stop_input_ports: 00315 for (int i = 0; i < input_count; i++) { 00316 if (input_ports[i]->Stop() < 0) { 00317 jack_error("JackWinMMEDriver::Start - Failed to disable input " 00318 "port."); 00319 } 00320 } 00321 00322 return -1; 00323 } 00324 00325 int 00326 JackWinMMEDriver::Stop() 00327 { 00328 int result = 0; 00329 00330 JackMidiDriver::Stop(); 00331 00332 jack_info("JackWinMMEDriver::Stop - disabling input ports."); 00333 00334 for (int i = 0; i < fCaptureChannels; i++) { 00335 if (input_ports[i]->Stop() < 0) { 00336 jack_error("JackWinMMEDriver::Stop - Failed to disable input " 00337 "port."); 00338 result = -1; 00339 } 00340 } 00341 00342 jack_info("JackWinMMEDriver::Stop - disabling output ports."); 00343 00344 for (int i = 0; i < fPlaybackChannels; i++) { 00345 if (output_ports[i]->Stop() < 0) { 00346 jack_error("JackWinMMEDriver::Stop - Failed to disable output " 00347 "port."); 00348 result = -1; 00349 } 00350 } 00351 00352 return result; 00353 } 00354 00355 #ifdef __cplusplus 00356 extern "C" 00357 { 00358 #endif 00359 00360 // singleton kind of driver 00361 static Jack::JackDriverClientInterface* driver = NULL; 00362 00363 SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() 00364 { 00365 jack_driver_desc_t * desc; 00366 00367 return jack_driver_descriptor_construct("winmme", JackDriverSlave, "WinMME API based MIDI backend", NULL); 00368 } 00369 00370 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) 00371 { 00372 /* 00373 unsigned int capture_ports = 2; 00374 unsigned int playback_ports = 2; 00375 unsigned long wait_time = 0; 00376 const JSList * node; 00377 const jack_driver_param_t * param; 00378 bool monitor = false; 00379 00380 for (node = params; node; node = jack_slist_next (node)) { 00381 param = (const jack_driver_param_t *) node->data; 00382 00383 switch (param->character) { 00384 00385 case 'C': 00386 capture_ports = param->value.ui; 00387 break; 00388 00389 case 'P': 00390 playback_ports = param->value.ui; 00391 break; 00392 00393 case 'r': 00394 sample_rate = param->value.ui; 00395 break; 00396 00397 case 'p': 00398 period_size = param->value.ui; 00399 break; 00400 00401 case 'w': 00402 wait_time = param->value.ui; 00403 break; 00404 00405 case 'm': 00406 monitor = param->value.i; 00407 break; 00408 } 00409 } 00410 */ 00411 00412 // singleton kind of driver 00413 if (!driver) { 00414 driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table); 00415 if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) { 00416 return driver; 00417 } else { 00418 delete driver; 00419 return NULL; 00420 } 00421 } else { 00422 jack_info("JackWinMMEDriver already allocated, cannot be loaded twice"); 00423 return NULL; 00424 } 00425 00426 } 00427 00428 #ifdef __cplusplus 00429 } 00430 #endif 00431 00432 00433 /* 00434 jack_connect system:midi_capture_1 system_midi:playback_1 00435 jack_connect system:midi_capture_1 system_midi:playback_2 00436 00437 jack_connect system:midi_capture_1 system_midi:playback_1 00438 00439 jack_connect system:midi_capture_1 system_midi:playback_1 00440 00441 jack_connect system:midi_capture_1 system_midi:playback_1 00442 00443 jack_connect system_midi:capture_1 system:midi_playback_1 00444 jack_connect system_midi:capture_2 system:midi_playback_1 00445 00446 jack_connect system_midi:capture_1 system_midi:playback_1 00447 00448 */ 00449