JackWinMMEDriver.cpp 12.3 KB
Newer Older
1
2
/*
Copyright (C) 2009 Grame
3
Copyright (C) 2011 Devin Anderson
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "JackEngineControl.h"
22
#include "JackWinMMEDriver.h"
23

24
using Jack::JackWinMMEDriver;
25

26
27
28
29
JackWinMMEDriver::JackWinMMEDriver(const char *name, const char *alias,
                                   JackLockedEngine *engine,
                                   JackSynchro *table):
    JackMidiDriver(name, alias, engine, table)
30
{
31
32
33
34
    fCaptureChannels = 0;
    fPlaybackChannels = 0;
    input_ports = 0;
    output_ports = 0;
35
36
}

37
JackWinMMEDriver::~JackWinMMEDriver()
sletz's avatar
sletz committed
38
{}
39

40
41
int
JackWinMMEDriver::Attach()
42
{
43
44
45
46
47
48
49
50
51
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    jack_port_id_t index;
    jack_nframes_t latency = buffer_size;
    jack_latency_range_t latency_range;
    const char *name;
    JackPort *port;
    latency_range.max = latency;
    latency_range.min = latency;

52
53
54
    jack_info("JackWinMMEDriver::Attach - fCaptureChannels  %d", fCaptureChannels);
    jack_info("JackWinMMEDriver::Attach - fPlaybackChannels  %d", fPlaybackChannels);

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    // Inputs
    for (int i = 0; i < fCaptureChannels; i++) {
        JackWinMMEInputPort *input_port = input_ports[i];
        name = input_port->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            CaptureDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackWinMMEDriver::Attach - cannot register input port "
                       "with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
        }
        port = fGraphManager->GetPort(index);
        port->SetAlias(input_port->GetAlias());
        port->SetLatencyRange(JackCaptureLatency, &latency_range);
        fCapturePortList[i] = index;
    }
73

74
75
76
77
78
    if (! fEngineControl->fSyncMode) {
        latency += buffer_size;
        latency_range.max = latency;
        latency_range.min = latency;
    }
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    // Outputs
    for (int i = 0; i < fPlaybackChannels; i++) {
        JackWinMMEOutputPort *output_port = output_ports[i];
        name = output_port->GetName();
        index = fGraphManager->AllocatePort(fClientControl.fRefNum, name,
                                            JACK_DEFAULT_MIDI_TYPE,
                                            PlaybackDriverFlags, buffer_size);
        if (index == NO_PORT) {
            jack_error("JackWinMMEDriver::Attach - cannot register output "
                       "port with name '%s'.", name);
            // X: Do we need to deallocate ports?
            return -1;
        }
        port = fGraphManager->GetPort(index);
        port->SetAlias(output_port->GetAlias());
        port->SetLatencyRange(JackPlaybackLatency, &latency_range);
        fPlaybackPortList[i] = index;
    }
98

99
100
    return 0;
}
101

102
103
104
int
JackWinMMEDriver::Close()
{
sletz's avatar
sletz committed
105
    // Generic MIDI driver close
106
    int result = JackMidiDriver::Close();
sletz's avatar
sletz committed
107

108
109
110
    if (input_ports) {
        for (int i = 0; i < fCaptureChannels; i++) {
            delete input_ports[i];
111
        }
112
113
        delete[] input_ports;
        input_ports = 0;
114
    }
115
116
117
    if (output_ports) {
        for (int i = 0; i < fPlaybackChannels; i++) {
            delete output_ports[i];
118
        }
119
120
        delete[] output_ports;
        output_ports = 0;
121
    }
122
    return result;
123
124
}

125
126
127
128
129
130
131
int
JackWinMMEDriver::Open(bool capturing, bool playing, int in_channels,
                       int out_channels, bool monitor,
                       const char* capture_driver_name,
                       const char* playback_driver_name,
                       jack_nframes_t capture_latency,
                       jack_nframes_t playback_latency)
132
{
133
134
    const char *client_name = fClientControl.fName;
    int input_count = 0;
135
    int output_count = 0;
136
137
    int num_potential_inputs = midiInGetNumDevs();
    int num_potential_outputs = midiOutGetNumDevs();
138
139
140
141

    jack_info("JackWinMMEDriver::Open - num_potential_inputs  %d", num_potential_inputs);
    jack_info("JackWinMMEDriver::Open - num_potential_outputs  %d", num_potential_outputs);

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
    if (num_potential_inputs) {
        try {
            input_ports = new JackWinMMEInputPort *[num_potential_inputs];
        } catch (std::exception e) {
            jack_error("JackWinMMEDriver::Open - while creating input port "
                       "array: %s", e.what());
            return -1;
        }
        for (int i = 0; i < num_potential_inputs; i++) {
            try {
                input_ports[input_count] =
                    new JackWinMMEInputPort(fAliasName, client_name,
                                            capture_driver_name, i);
            } catch (std::exception e) {
                jack_error("JackWinMMEDriver::Open - while creating input "
                           "port: %s", e.what());
                continue;
            }
            input_count++;
        }
162
    }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    if (num_potential_outputs) {
        try {
            output_ports = new JackWinMMEOutputPort *[num_potential_outputs];
        } catch (std::exception e) {
            jack_error("JackWinMMEDriver::Open - while creating output port "
                       "array: %s", e.what());
            goto destroy_input_ports;
        }
        for (int i = 0; i < num_potential_outputs; i++) {
            try {
                output_ports[output_count] =
                    new JackWinMMEOutputPort(fAliasName, client_name,
                                             playback_driver_name, i);
            } catch (std::exception e) {
                jack_error("JackWinMMEDriver::Open - while creating output "
                           "port: %s", e.what());
                continue;
            }
            output_count++;
        }
183
    }
184
185
186
187

    jack_info("JackWinMMEDriver::Open - input_count  %d", input_count);
    jack_info("JackWinMMEDriver::Open - output_count  %d", output_count);

188
189
190
191
192
193
194
195
196
    if (! (input_count || output_count)) {
        jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs "
                   "allocated.");
    } else if (! JackMidiDriver::Open(capturing, playing, input_count,
                                      output_count, monitor,
                                      capture_driver_name,
                                      playback_driver_name, capture_latency,
                                      playback_latency)) {
        return 0;
197
    }
198
199
200
201
202

 destroy_input_ports:
    if (input_ports) {
        for (int i = 0; i < input_count; i++) {
            delete input_ports[i];
203
        }
204
205
        delete[] input_ports;
        input_ports = 0;
206
    }
207
    return -1;
208
209
}

210
211
int
JackWinMMEDriver::Read()
212
{
213
214
215
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    for (int i = 0; i < fCaptureChannels; i++) {
        input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
216
    }
217
218
219
220
221
222
223
224
225
226
227

    return 0;
}

int
JackWinMMEDriver::Write()
{
    jack_nframes_t buffer_size = fEngineControl->fBufferSize;
    for (int i = 0; i < fPlaybackChannels; i++) {
        output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
    }
sletz's avatar
sletz committed
228

229
    return 0;
230
231
}

232
233
int
JackWinMMEDriver::Start()
234
{
235
236
237
238
239
240
    jack_info("JackWinMMEDriver::Start - Starting driver.");

    JackMidiDriver::Start();

    int input_count = 0;
    int output_count = 0;
241

242
    jack_info("JackWinMMEDriver::Start - Enabling input ports.");
243

244
245
246
247
248
    for (; input_count < fCaptureChannels; input_count++) {
        if (input_ports[input_count]->Start() < 0) {
            jack_error("JackWinMMEDriver::Start - Failed to enable input "
                       "port.");
            goto stop_input_ports;
249
250
251
        }
    }

252
253
254
255
256
257
258
    jack_info("JackWinMMEDriver::Start - Enabling output ports.");

    for (; output_count < fPlaybackChannels; output_count++) {
        if (output_ports[output_count]->Start() < 0) {
            jack_error("JackWinMMEDriver::Start - Failed to enable output "
                       "port.");
            goto stop_output_ports;
259
260
261
        }
    }

262
    jack_info("JackWinMMEDriver::Start - Driver started.");
263

264
265
266
267
268
269
270
    return 0;

 stop_output_ports:
    for (int i = 0; i < output_count; i++) {
        if (output_ports[i]->Stop() < 0) {
            jack_error("JackWinMMEDriver::Start - Failed to disable output "
                       "port.");
271
272
        }
    }
273
274
275
276
277
 stop_input_ports:
    for (int i = 0; i < input_count; i++) {
        if (input_ports[i]->Stop() < 0) {
            jack_error("JackWinMMEDriver::Start - Failed to disable input "
                       "port.");
278
279
280
        }
    }

281
    return -1;
282
283
}

284
285
int
JackWinMMEDriver::Stop()
286
{
287
    int result = 0;
288

289
    jack_info("JackWinMMEDriver::Stop - disabling input ports.");
290

291
292
293
294
295
296
297
    for (int i = 0; i < fCaptureChannels; i++) {
        if (input_ports[i]->Stop() < 0) {
            jack_error("JackWinMMEDriver::Stop - Failed to disable input "
                       "port.");
            result = -1;
        }
    }
298

299
    jack_info("JackWinMMEDriver::Stop - disabling output ports.");
300

301
302
303
304
305
    for (int i = 0; i < fPlaybackChannels; i++) {
        if (output_ports[i]->Stop() < 0) {
            jack_error("JackWinMMEDriver::Stop - Failed to disable output "
                       "port.");
            result = -1;
306
307
        }
    }
308
309

    return result;
310
311
312
313
314
315
316
317
318
319
}

#ifdef __cplusplus
extern "C"
{
#endif

    SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
    {
        jack_driver_desc_t * desc;
320
        //unsigned int i;
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403

        desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
        strcpy(desc->name, "winmme");                             // size MUST be less then JACK_DRIVER_NAME_MAX + 1
        strcpy(desc->desc, "WinMME API based MIDI backend");      // size MUST be less then JACK_DRIVER_PARAM_DESC + 1

        desc->nparams = 0;
        desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));

        return desc;
    }

    SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
    {
        /*
        unsigned int capture_ports = 2;
        unsigned int playback_ports = 2;
        unsigned long wait_time = 0;
        const JSList * node;
        const jack_driver_param_t * param;
        bool monitor = false;

        for (node = params; node; node = jack_slist_next (node)) {
            param = (const jack_driver_param_t *) node->data;

            switch (param->character) {

                case 'C':
                    capture_ports = param->value.ui;
                    break;

                case 'P':
                    playback_ports = param->value.ui;
                    break;

                case 'r':
                    sample_rate = param->value.ui;
                    break;

                case 'p':
                    period_size = param->value.ui;
                    break;

                case 'w':
                    wait_time = param->value.ui;
                    break;

                case 'm':
                    monitor = param->value.i;
                    break;
            }
        }
        */

        Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
        if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
            return driver;
        } else {
            delete driver;
            return NULL;
        }
    }

#ifdef __cplusplus
}
#endif


/*
jack_connect system:midi_capture_1 system_midi:playback_1
jack_connect system:midi_capture_1 system_midi:playback_2

jack_connect system:midi_capture_1 system_midi:playback_1

jack_connect system:midi_capture_1 system_midi:playback_1

jack_connect system:midi_capture_1 system_midi:playback_1

jack_connect system_midi:capture_1 system:midi_playback_1
jack_connect system_midi:capture_2 system:midi_playback_1

jack_connect system_midi:capture_1  system_midi:playback_1

*/