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