23 #include "JackEngineControl.h" 24 #include "JackWinMMEDriver.h" 25 #include "driver_interface.h" 29 JackWinMMEDriver::JackWinMMEDriver(
const char *name,
const char *alias,
30 JackLockedEngine *engine,
32 JackMidiDriver(name, alias, engine, table)
39 JackWinMMEDriver::~JackWinMMEDriver()
43 JackWinMMEDriver::Attach()
45 jack_nframes_t buffer_size = fEngineControl->fBufferSize;
47 jack_nframes_t latency = buffer_size;
51 latency_range.
max = latency +
52 ((jack_nframes_t) std::ceil((period / 1000.0) *
53 fEngineControl->fSampleRate));
54 latency_range.
min = latency;
56 jack_log(
"JackWinMMEDriver::Attach - fCaptureChannels %d", fCaptureChannels);
57 jack_log(
"JackWinMMEDriver::Attach - fPlaybackChannels %d", fPlaybackChannels);
60 for (
int i = 0; i < fCaptureChannels; i++) {
61 JackWinMMEInputPort *input_port = input_ports[i];
62 name = input_port->GetName();
63 if (fEngine->PortRegister(fClientControl.fRefNum, name,
64 JACK_DEFAULT_MIDI_TYPE,
65 CaptureDriverFlags, buffer_size, &index) < 0) {
66 jack_error(
"JackWinMMEDriver::Attach - cannot register input port " 67 "with name '%s'.", name);
71 port = fGraphManager->GetPort(index);
72 port->SetAlias(input_port->GetAlias());
73 port->SetLatencyRange(JackCaptureLatency, &latency_range);
74 fCapturePortList[i] = index;
77 if (! fEngineControl->fSyncMode) {
78 latency += buffer_size;
79 latency_range.
max = latency;
80 latency_range.
min = latency;
84 for (
int i = 0; i < fPlaybackChannels; i++) {
85 JackWinMMEOutputPort *output_port = output_ports[i];
86 name = output_port->GetName();
87 if (fEngine->PortRegister(fClientControl.fRefNum, name,
88 JACK_DEFAULT_MIDI_TYPE,
89 PlaybackDriverFlags, buffer_size, &index) < 0) {
90 jack_error(
"JackWinMMEDriver::Attach - cannot register output " 91 "port with name '%s'.", name);
95 port = fGraphManager->GetPort(index);
96 port->SetAlias(output_port->GetAlias());
97 port->SetLatencyRange(JackPlaybackLatency, &latency_range);
98 fPlaybackPortList[i] = index;
105 JackWinMMEDriver::Close()
108 int result = JackMidiDriver::Close();
111 for (
int i = 0; i < fCaptureChannels; i++) {
112 delete input_ports[i];
114 delete[] input_ports;
118 for (
int i = 0; i < fPlaybackChannels; i++) {
119 delete output_ports[i];
121 delete[] output_ports;
125 if (timeEndPeriod(period) != TIMERR_NOERROR) {
126 jack_error(
"JackWinMMEDriver::Close - failed to unset timer " 135 JackWinMMEDriver::Open(
bool capturing,
bool playing,
int in_channels,
136 int out_channels,
bool monitor,
137 const char* capture_driver_name,
138 const char* playback_driver_name,
139 jack_nframes_t capture_latency,
140 jack_nframes_t playback_latency)
142 const char *client_name = fClientControl.fName;
144 int output_count = 0;
145 int num_potential_inputs = midiInGetNumDevs();
146 int num_potential_outputs = midiOutGetNumDevs();
148 jack_log(
"JackWinMMEDriver::Open - num_potential_inputs %d", num_potential_inputs);
149 jack_log(
"JackWinMMEDriver::Open - num_potential_outputs %d", num_potential_outputs);
153 if (timeGetDevCaps(&caps,
sizeof(TIMECAPS)) != TIMERR_NOERROR) {
154 jack_error(
"JackWinMMEDriver::Open - could not get timer device " 155 "capabilities. Continuing anyway ...");
157 period = caps.wPeriodMin;
158 if (timeBeginPeriod(period) != TIMERR_NOERROR) {
159 jack_error(
"JackWinMMEDriver::Open - could not set minimum timer " 160 "resolution. Continuing anyway ...");
163 jack_log(
"JackWinMMEDriver::Open - multimedia timer resolution " 164 "set to %d milliseconds.", period);
168 if (num_potential_inputs) {
170 input_ports =
new JackWinMMEInputPort *[num_potential_inputs];
171 }
catch (std::exception& e) {
172 jack_error(
"JackWinMMEDriver::Open - while creating input port " 173 "array: %s", e.what());
174 goto unset_timer_resolution;
176 for (
int i = 0; i < num_potential_inputs; i++) {
178 input_ports[input_count] =
179 new JackWinMMEInputPort(fAliasName, client_name,
180 capture_driver_name, i);
181 }
catch (std::exception& e) {
182 jack_error(
"JackWinMMEDriver::Open - while creating input " 183 "port: %s", e.what());
189 if (num_potential_outputs) {
191 output_ports =
new JackWinMMEOutputPort *[num_potential_outputs];
192 }
catch (std::exception& e) {
193 jack_error(
"JackWinMMEDriver::Open - while creating output port " 194 "array: %s", e.what());
195 goto destroy_input_ports;
197 for (
int i = 0; i < num_potential_outputs; i++) {
199 output_ports[output_count] =
200 new JackWinMMEOutputPort(fAliasName, client_name,
201 playback_driver_name, i);
202 }
catch (std::exception& e) {
203 jack_error(
"JackWinMMEDriver::Open - while creating output " 204 "port: %s", e.what());
211 jack_log(
"JackWinMMEDriver::Open - input_count %d", input_count);
212 jack_log(
"JackWinMMEDriver::Open - output_count %d", output_count);
214 if (! (input_count || output_count)) {
215 jack_error(
"JackWinMMEDriver::Open - no WinMME inputs or outputs " 217 }
else if (! JackMidiDriver::Open(capturing, playing, input_count,
218 output_count, monitor,
220 playback_driver_name, capture_latency,
226 for (
int i = 0; i < output_count; i++) {
227 delete output_ports[i];
229 delete[] output_ports;
234 for (
int i = 0; i < input_count; i++) {
235 delete input_ports[i];
237 delete[] input_ports;
240 unset_timer_resolution:
242 if (timeEndPeriod(period) != TIMERR_NOERROR) {
243 jack_error(
"JackWinMMEDriver::Open - failed to unset timer " 251 JackWinMMEDriver::Read()
253 jack_nframes_t buffer_size = fEngineControl->fBufferSize;
254 for (
int i = 0; i < fCaptureChannels; i++) {
255 input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
262 JackWinMMEDriver::Write()
264 jack_nframes_t buffer_size = fEngineControl->fBufferSize;
265 for (
int i = 0; i < fPlaybackChannels; i++) {
266 output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
273 JackWinMMEDriver::Start()
275 jack_log(
"JackWinMMEDriver::Start - Starting driver.");
277 JackMidiDriver::Start();
280 int output_count = 0;
282 jack_log(
"JackWinMMEDriver::Start - Enabling input ports.");
284 for (; input_count < fCaptureChannels; input_count++) {
285 if (input_ports[input_count]->Start() < 0) {
286 jack_error(
"JackWinMMEDriver::Start - Failed to enable input " 288 goto stop_input_ports;
292 jack_log(
"JackWinMMEDriver::Start - Enabling output ports.");
294 for (; output_count < fPlaybackChannels; output_count++) {
295 if (output_ports[output_count]->Start() < 0) {
296 jack_error(
"JackWinMMEDriver::Start - Failed to enable output " 298 goto stop_output_ports;
302 jack_log(
"JackWinMMEDriver::Start - Driver started.");
306 for (
int i = 0; i < output_count; i++) {
307 if (output_ports[i]->Stop() < 0) {
308 jack_error(
"JackWinMMEDriver::Start - Failed to disable output " 313 for (
int i = 0; i < input_count; i++) {
314 if (input_ports[i]->Stop() < 0) {
315 jack_error(
"JackWinMMEDriver::Start - Failed to disable input " 324 JackWinMMEDriver::Stop()
328 JackMidiDriver::Stop();
330 jack_log(
"JackWinMMEDriver::Stop - disabling input ports.");
332 for (
int i = 0; i < fCaptureChannels; i++) {
333 if (input_ports[i]->Stop() < 0) {
334 jack_error(
"JackWinMMEDriver::Stop - Failed to disable input " 340 jack_log(
"JackWinMMEDriver::Stop - disabling output ports.");
342 for (
int i = 0; i < fPlaybackChannels; i++) {
343 if (output_ports[i]->Stop() < 0) {
344 jack_error(
"JackWinMMEDriver::Stop - Failed to disable output " 363 return jack_driver_descriptor_construct(
"winmme", JackDriverSlave,
"WinMME API based MIDI backend", NULL);
411 if (driver->Open(1, 1, 0, 0,
false,
"in",
"out", 0, 0) == 0) {
418 jack_info(
"JackWinMMEDriver already allocated, cannot be loaded twice");
Locked Engine, access to methods is serialized using a mutex.
Inter process synchronization using POSIX semaphore.
SERVER_EXPORT void jack_error(const char *fmt,...)
SERVER_EXPORT void jack_info(const char *fmt,...)
The base interface for drivers clients.
SERVER_EXPORT void jack_log(const char *fmt,...)