00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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
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
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
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
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
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
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
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448