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
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
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
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
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
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
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
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
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
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
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449