2 Copyright (C) 2009 Grame
3 Copyright (C) 2011 Devin Anderson
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "JackEngineControl.h"
24 #include "JackWinMMEDriver.h"
25 #include "driver_interface.h"
27 using Jack::JackWinMMEDriver
;
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
;
48 jack_latency_range_t latency_range
;
51 latency_range
.max
= latency
+
52 ((jack_nframes_t
) std::ceil((period
/ 1000.0) *
53 fEngineControl
->fSampleRate
));
54 latency_range
.min
= latency
;
56 jack_info("JackWinMMEDriver::Attach - fCaptureChannels %d", fCaptureChannels
);
57 jack_info("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
);
68 // X: Do we need to deallocate ports?
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
);
92 // X: Do we need to deallocate ports?
95 port
= fGraphManager
->GetPort(index
);
96 port
->SetAlias(output_port
->GetAlias());
97 port
->SetLatencyRange(JackPlaybackLatency
, &latency_range
);
98 fPlaybackPortList
[i
] = index
;
105 JackWinMMEDriver::Close()
107 // Generic MIDI driver 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_info("JackWinMMEDriver::Open - num_potential_inputs %d", num_potential_inputs
);
149 jack_info("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 ...");
164 jack_info("JackWinMMEDriver::Open - multimedia timer resolution "
165 "set to %d milliseconds.", period
);
170 if (num_potential_inputs
) {
172 input_ports
= new JackWinMMEInputPort
*[num_potential_inputs
];
173 } catch (std::exception e
) {
174 jack_error("JackWinMMEDriver::Open - while creating input port "
175 "array: %s", e
.what());
176 goto unset_timer_resolution
;
178 for (int i
= 0; i
< num_potential_inputs
; i
++) {
180 input_ports
[input_count
] =
181 new JackWinMMEInputPort(fAliasName
, client_name
,
182 capture_driver_name
, i
);
183 } catch (std::exception e
) {
184 jack_error("JackWinMMEDriver::Open - while creating input "
185 "port: %s", e
.what());
191 if (num_potential_outputs
) {
193 output_ports
= new JackWinMMEOutputPort
*[num_potential_outputs
];
194 } catch (std::exception e
) {
195 jack_error("JackWinMMEDriver::Open - while creating output port "
196 "array: %s", e
.what());
197 goto destroy_input_ports
;
199 for (int i
= 0; i
< num_potential_outputs
; i
++) {
201 output_ports
[output_count
] =
202 new JackWinMMEOutputPort(fAliasName
, client_name
,
203 playback_driver_name
, i
);
204 } catch (std::exception e
) {
205 jack_error("JackWinMMEDriver::Open - while creating output "
206 "port: %s", e
.what());
213 jack_info("JackWinMMEDriver::Open - input_count %d", input_count
);
214 jack_info("JackWinMMEDriver::Open - output_count %d", output_count
);
216 if (! (input_count
|| output_count
)) {
217 jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs "
219 } else if (! JackMidiDriver::Open(capturing
, playing
, input_count
,
220 output_count
, monitor
,
222 playback_driver_name
, capture_latency
,
228 for (int i
= 0; i
< output_count
; i
++) {
229 delete output_ports
[i
];
231 delete[] output_ports
;
236 for (int i
= 0; i
< input_count
; i
++) {
237 delete input_ports
[i
];
239 delete[] input_ports
;
242 unset_timer_resolution
:
244 if (timeEndPeriod(period
) != TIMERR_NOERROR
) {
245 jack_error("JackWinMMEDriver::Open - failed to unset timer "
253 JackWinMMEDriver::Read()
255 jack_nframes_t buffer_size
= fEngineControl
->fBufferSize
;
256 for (int i
= 0; i
< fCaptureChannels
; i
++) {
257 input_ports
[i
]->ProcessJack(GetInputBuffer(i
), buffer_size
);
264 JackWinMMEDriver::Write()
266 jack_nframes_t buffer_size
= fEngineControl
->fBufferSize
;
267 for (int i
= 0; i
< fPlaybackChannels
; i
++) {
268 output_ports
[i
]->ProcessJack(GetOutputBuffer(i
), buffer_size
);
275 JackWinMMEDriver::Start()
277 jack_info("JackWinMMEDriver::Start - Starting driver.");
279 JackMidiDriver::Start();
282 int output_count
= 0;
284 jack_info("JackWinMMEDriver::Start - Enabling input ports.");
286 for (; input_count
< fCaptureChannels
; input_count
++) {
287 if (input_ports
[input_count
]->Start() < 0) {
288 jack_error("JackWinMMEDriver::Start - Failed to enable input "
290 goto stop_input_ports
;
294 jack_info("JackWinMMEDriver::Start - Enabling output ports.");
296 for (; output_count
< fPlaybackChannels
; output_count
++) {
297 if (output_ports
[output_count
]->Start() < 0) {
298 jack_error("JackWinMMEDriver::Start - Failed to enable output "
300 goto stop_output_ports
;
304 jack_info("JackWinMMEDriver::Start - Driver started.");
309 for (int i
= 0; i
< output_count
; i
++) {
310 if (output_ports
[i
]->Stop() < 0) {
311 jack_error("JackWinMMEDriver::Start - Failed to disable output "
316 for (int i
= 0; i
< input_count
; i
++) {
317 if (input_ports
[i
]->Stop() < 0) {
318 jack_error("JackWinMMEDriver::Start - Failed to disable input "
327 JackWinMMEDriver::Stop()
331 JackMidiDriver::Stop();
333 jack_info("JackWinMMEDriver::Stop - disabling input ports.");
335 for (int i
= 0; i
< fCaptureChannels
; i
++) {
336 if (input_ports
[i
]->Stop() < 0) {
337 jack_error("JackWinMMEDriver::Stop - Failed to disable input "
343 jack_info("JackWinMMEDriver::Stop - disabling output ports.");
345 for (int i
= 0; i
< fPlaybackChannels
; i
++) {
346 if (output_ports
[i
]->Stop() < 0) {
347 jack_error("JackWinMMEDriver::Stop - Failed to disable output "
361 // singleton kind of driver
362 static Jack::JackDriverClientInterface
* driver
= NULL
;
364 SERVER_EXPORT jack_driver_desc_t
* driver_get_descriptor()
366 return jack_driver_descriptor_construct("winmme", JackDriverSlave
, "WinMME API based MIDI backend", NULL
);
369 SERVER_EXPORT
Jack::JackDriverClientInterface
* driver_initialize(Jack::JackLockedEngine
* engine
, Jack::JackSynchro
* table
, const JSList
* params
)
372 unsigned int capture_ports = 2;
373 unsigned int playback_ports = 2;
374 unsigned long wait_time = 0;
376 const jack_driver_param_t * param;
377 bool monitor = false;
379 for (node = params; node; node = jack_slist_next (node)) {
380 param = (const jack_driver_param_t *) node->data;
382 switch (param->character) {
385 capture_ports = param->value.ui;
389 playback_ports = param->value.ui;
393 sample_rate = param->value.ui;
397 period_size = param->value.ui;
401 wait_time = param->value.ui;
405 monitor = param->value.i;
411 // singleton kind of driver
413 driver
= new Jack::JackWinMMEDriver("system_midi", "winmme", engine
, table
);
414 if (driver
->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
421 jack_info("JackWinMMEDriver already allocated, cannot be loaded twice");
433 jack_connect system:midi_capture_1 system_midi:playback_1
434 jack_connect system:midi_capture_1 system_midi:playback_2
436 jack_connect system:midi_capture_1 system_midi:playback_1
438 jack_connect system:midi_capture_1 system_midi:playback_1
440 jack_connect system:midi_capture_1 system_midi:playback_1
442 jack_connect system_midi:capture_1 system:midi_playback_1
443 jack_connect system_midi:capture_2 system:midi_playback_1
445 jack_connect system_midi:capture_1 system_midi:playback_1