Subversion Repositories svn.mios32

Rev

Rev 1542 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
932 tk 1
/* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
2
// $Id: Midio128Tool.cpp 1724 2013-03-28 20:23:40Z tk $
3
/*
4
 * MIDIO128 Tool Window
5
 *
6
 * ==========================================================================
7
 *
8
 *  Copyright (C) 2010 Thorsten Klose (tk@midibox.org)
9
 *  Licensed for personal non-commercial use only.
10
 *  All other rights reserved.
11
 *
12
 * ==========================================================================
13
 */
14
 
15
#include "Midio128Tool.h"
16
#include "MiosStudio.h"
17
 
18
 
19
Midio128ToolConfigGlobals::Midio128ToolConfigGlobals()
20
{
21
    addAndMakeVisible(mergerLabel = new Label(String::empty, T("MIDI Merger:")));
22
    mergerLabel->setJustificationType(Justification::right);
23
    addAndMakeVisible(mergerComboBox = new ComboBox(String::empty));
24
    mergerComboBox->setWantsKeyboardFocus(true);
25
    mergerComboBox->addItem(T("Disabled"), 1);
26
    mergerComboBox->addItem(T("Enabled (received MIDI events forwarded to MIDI Out)"), 2);
1134 tk 27
    mergerComboBox->addItem(T("MIDIbox Link Endpoint (last core in the MIDIbox chain)"), 3);
28
    mergerComboBox->addItem(T("MIDIbox Link Forwarding Point (core in a MIDIbox chain)"), 4);
932 tk 29
    mergerComboBox->setSelectedId(1, true);
30
 
31
    addAndMakeVisible(debounceLabel = new Label(String::empty, T("DIN Debouncing (mS):")));
32
    debounceLabel->setJustificationType(Justification::right);
33
    addAndMakeVisible(debounceSlider = new Slider(String::empty));
34
    debounceSlider->setWantsKeyboardFocus(true);
35
    debounceSlider->setSliderStyle(Slider::LinearHorizontal);
36
    debounceSlider->setTextBoxStyle(Slider::TextBoxLeft, false, 80, 20);
37
    debounceSlider->setRange(0, 255, 1);
38
    debounceSlider->setValue(20);
39
 
40
    addAndMakeVisible(altPrgChangesLabel = new Label(String::empty, T("Program Change Mode:")));
41
    altPrgChangesLabel->setJustificationType(Justification::right);
42
    addAndMakeVisible(altPrgChangesComboBox = new ComboBox(String::empty));
43
    altPrgChangesComboBox->setWantsKeyboardFocus(true);
44
    altPrgChangesComboBox->addItem(T("DOUT pin will toggle between 0 and 1 whenever PC event is received"), 1);
45
    altPrgChangesComboBox->addItem(T("Exclusive: assigned DOUT pin will be activated, all others deactivated (channel-wise)"), 2);
46
    altPrgChangesComboBox->setSelectedId(1, true);
47
 
48
    addAndMakeVisible(forwardInToOutLabel = new Label(String::empty, T("DIN->DOUT Forwarding Mode:")));
49
    forwardInToOutLabel->setJustificationType(Justification::right);
50
    addAndMakeVisible(forwardInToOutComboBox = new ComboBox(String::empty));
51
    forwardInToOutComboBox->setWantsKeyboardFocus(true);
52
    forwardInToOutComboBox->addItem(T("Disabled"), 1);
53
    forwardInToOutComboBox->addItem(T("DIN pin changes will be forwarded to DOUT pins with same number"), 2);
54
    forwardInToOutComboBox->setSelectedId(2);
55
 
56
    addAndMakeVisible(inverseInputsLabel = new Label(String::empty, T("DIN Input Polarity:")));
57
    inverseInputsLabel->setJustificationType(Justification::right);
58
    addAndMakeVisible(inverseInputsComboBox = new ComboBox(String::empty));
59
    inverseInputsComboBox->setWantsKeyboardFocus(true);
934 tk 60
    inverseInputsComboBox->addItem(T("Inverted (0V = Active/Pressed, 5V = Open/Depressed"), 1);
61
    inverseInputsComboBox->addItem(T("Normal (0V = Open/Depressed, 5V = Active/Pressed"), 2);
62
    inverseInputsComboBox->setSelectedId(2);
932 tk 63
 
64
    addAndMakeVisible(inverseOutputsLabel = new Label(String::empty, T("DOUT Output Polarity:")));
65
    inverseOutputsLabel->setJustificationType(Justification::right);
66
    addAndMakeVisible(inverseOutputsComboBox = new ComboBox(String::empty));
67
    inverseOutputsComboBox->setWantsKeyboardFocus(true);
934 tk 68
    inverseOutputsComboBox->addItem(T("Normal (5V = Active/On, 0V = Not Active/Off"), 1);
932 tk 69
    inverseOutputsComboBox->addItem(T("Inverted (0V = Not Active/Off, 5V = Active/On"), 2);
70
    inverseOutputsComboBox->setSelectedId(1);
71
 
72
    addAndMakeVisible(allNotesOffChannelLabel = new Label(String::empty, T("MIDI Channel for \"All Notes Off\":")));
73
    allNotesOffChannelLabel->setJustificationType(Justification::right);
74
    addAndMakeVisible(allNotesOffChannelComboBox = new ComboBox(String::empty));
75
    allNotesOffChannelComboBox->setWantsKeyboardFocus(true);
76
    for(int i=1; i<=17; ++i) {
77
        if( i == 1 )
78
            allNotesOffChannelComboBox->addItem(T("none (ignored)"), i);
79
        else
80
            allNotesOffChannelComboBox->addItem(String(i-1), i);
81
    }
82
    allNotesOffChannelComboBox->setSelectedId(1);
83
 
84
    addAndMakeVisible(touchsensorSensitivityLabel = new Label(String::empty, T("Touch Sensor Sensitivity:")));
85
    touchsensorSensitivityLabel->setJustificationType(Justification::right);
86
    addAndMakeVisible(touchsensorSensitivitySlider = new Slider(String::empty));
87
    touchsensorSensitivitySlider->setWantsKeyboardFocus(true);
88
    touchsensorSensitivitySlider->setSliderStyle(Slider::LinearHorizontal);
89
    touchsensorSensitivitySlider->setTextBoxStyle(Slider::TextBoxLeft, false, 80, 20);
90
    touchsensorSensitivitySlider->setRange(0, 32, 1);
91
    touchsensorSensitivitySlider->setValue(3);
92
}
93
 
94
 
95
Midio128ToolConfigGlobals::~Midio128ToolConfigGlobals()
96
{
97
}
98
 
99
//==============================================================================
100
void Midio128ToolConfigGlobals::resized()
101
{
102
    int labelX = 10;
103
    int labelY0 = 10;
104
    int labelYOffset = 28;
105
    int labelWidth = 250;
106
    int labelHeight = 24;
107
 
108
    int controlX = labelX + labelWidth + 20;
109
    int controlY0 = labelY0;
110
    int controlYOffset = labelYOffset;
111
    int controlWidth = getWidth()-labelWidth-40-2*labelX;
112
    int controlHeight = labelHeight;
113
 
114
    mergerLabel->setBounds(labelX, labelY0 + 0*labelYOffset, labelWidth, labelHeight);
115
    mergerComboBox->setBounds(controlX, controlY0 + 0*controlYOffset, controlWidth, controlHeight);
116
 
117
    debounceLabel->setBounds(labelX, labelY0 + 1*labelYOffset, labelWidth, labelHeight);
118
    debounceSlider->setBounds(controlX, controlY0 + 1*controlYOffset, controlWidth, controlHeight);
119
 
120
    altPrgChangesLabel->setBounds(labelX, labelY0 + 2*labelYOffset, labelWidth, labelHeight);
121
    altPrgChangesComboBox->setBounds(controlX, controlY0 + 2*controlYOffset, controlWidth, controlHeight);
122
 
123
    forwardInToOutLabel->setBounds(labelX, labelY0 + 3*labelYOffset, labelWidth, labelHeight);
124
    forwardInToOutComboBox->setBounds(controlX, controlY0 + 3*controlYOffset, controlWidth, controlHeight);
125
 
126
    inverseInputsLabel->setBounds(labelX, labelY0 + 4*labelYOffset, labelWidth, labelHeight);
127
    inverseInputsComboBox->setBounds(controlX, controlY0 + 4*controlYOffset, controlWidth, controlHeight);
128
 
129
    inverseOutputsLabel->setBounds(labelX, labelY0 + 5*labelYOffset, labelWidth, labelHeight);
130
    inverseOutputsComboBox->setBounds(controlX, controlY0 + 5*controlYOffset, controlWidth, controlHeight);
131
 
132
    allNotesOffChannelLabel->setBounds(labelX, labelY0 + 6*labelYOffset, labelWidth, labelHeight);
133
    allNotesOffChannelComboBox->setBounds(controlX, controlY0 + 6*controlYOffset, controlWidth, controlHeight);
134
 
135
    touchsensorSensitivityLabel->setBounds(labelX, labelY0 + 7*labelYOffset, labelWidth, labelHeight);
136
    touchsensorSensitivitySlider->setBounds(controlX, controlY0 + 7*controlYOffset, controlWidth, controlHeight);
137
}
138
 
139
 
934 tk 140
//==============================================================================
141
void Midio128ToolConfigGlobals::getDump(Array<uint8> &syxDump)
142
{
143
    int merger = mergerComboBox->getSelectedId()-1;
144
    int debounce = debounceSlider->getValue();
145
    int altPrgChanges = altPrgChangesComboBox->getSelectedId()-1;
146
    int forwardInToOut = forwardInToOutComboBox->getSelectedId()-1;
147
    int inverseInputs = inverseInputsComboBox->getSelectedId()-1;
148
    int inverseOutputs = inverseOutputsComboBox->getSelectedId()-1;
149
    int touchsensorSensitivity = touchsensorSensitivitySlider->getValue();
150
    int allNotesOffChannel = allNotesOffChannelComboBox->getSelectedId()-1;
932 tk 151
 
934 tk 152
    syxDump.set(0x400, merger);
153
    syxDump.set(0x402, debounce & 0x0f);
154
    syxDump.set(0x403, (debounce>>4) & 0x0f);
155
    syxDump.set(0x404, altPrgChanges);
156
    syxDump.set(0x406, forwardInToOut);
157
    syxDump.set(0x408, inverseInputs);
158
    syxDump.set(0x40a, inverseOutputs);
159
    syxDump.set(0x40c, touchsensorSensitivity & 0x0f);
160
    syxDump.set(0x40d, (touchsensorSensitivity>>4) & 0x0f);
161
    syxDump.set(0x40e, 0x00); // reserved for global channel
162
    syxDump.set(0x410, allNotesOffChannel);
163
}
164
 
165
void Midio128ToolConfigGlobals::setDump(const Array<uint8> &syxDump)
166
{
167
    int merger = syxDump[0x400];
168
    int debounce = (syxDump[0x402] & 0x0f) | ((syxDump[0x403] << 4) & 0xf0);
169
    int altPrgChanges = syxDump[0x404];
170
    int forwardInToOut = syxDump[0x406];
171
    int inverseInputs = syxDump[0x408];
172
    int inverseOutputs = syxDump[0x40a];
173
    int touchsensorSensitivity = (syxDump[0x40c] & 0x0f) | ((syxDump[0x40d] << 4) & 0xf0);
174
    int allNotesOffChannel = syxDump[0x410];
175
 
176
    mergerComboBox->setSelectedId(merger+1);
177
    debounceSlider->setValue(debounce);
178
    altPrgChangesComboBox->setSelectedId(altPrgChanges+1);
179
    forwardInToOutComboBox->setSelectedId(forwardInToOut+1);
180
    inverseInputsComboBox->setSelectedId(inverseInputs+1);
181
    inverseOutputsComboBox->setSelectedId(inverseOutputs+1);
182
    allNotesOffChannelComboBox->setSelectedId(allNotesOffChannel+1);
183
    touchsensorSensitivitySlider->setValue(touchsensorSensitivity);
184
}
185
 
186
 
932 tk 187
//==============================================================================
188
//==============================================================================
189
//==============================================================================
190
Midio128ToolConfigDout::Midio128ToolConfigDout()
191
    : font(14.0f)
192
    , numRows(128)
193
{
194
    for(int dout=0; dout<numRows; ++dout) {
934 tk 195
        doutChannel.add(1); // Default MIDI Channel
932 tk 196
 
197
        if( dout < 64 ) {
934 tk 198
            doutEvent.add(3); // Note On
199
            doutParameter.add(0x30 + dout); // Note Number
932 tk 200
        } else {
934 tk 201
            doutEvent.add(5); // CC
202
            doutParameter.add(0x10 + dout - 64); // CC Number
932 tk 203
        }
204
    }
205
 
206
    addAndMakeVisible(table = new TableListBox(T("DOUT Button Table"), this));
207
    table->setColour(ListBox::outlineColourId, Colours::grey);
208
    table->setOutlineThickness(1);
209
 
1187 tk 210
    table->getHeader().addColumn(T("DOUT"), 1, 50);
211
    table->getHeader().addColumn(T("SR/Pin"), 2, 50);
212
    table->getHeader().addColumn(T("Channel"), 3, 75);
213
    table->getHeader().addColumn(T("Event"), 4, 125);
214
    table->getHeader().addColumn(T("Parameter"), 5, 75);
932 tk 215
 
216
    setSize(800, 200);
217
}
218
 
219
Midio128ToolConfigDout::~Midio128ToolConfigDout()
220
{
221
}
222
 
223
//==============================================================================
224
int Midio128ToolConfigDout::getNumRows()
225
{
226
    return numRows;
227
}
228
 
229
void Midio128ToolConfigDout::paintRowBackground(Graphics &g, int rowNumber, int width, int height, bool rowIsSelected)
230
{
231
    if( rowIsSelected )
232
        g.fillAll(Colours::lightblue);
233
}
234
 
235
void Midio128ToolConfigDout::paintCell(Graphics &g, int rowNumber, int columnId, int width, int height, bool rowIsSelected)
236
{
237
    g.setColour(Colours::black);
238
    g.setFont(font);
239
 
240
    switch( columnId ) {
241
    case 1: {
242
        const String text(rowNumber);
243
        g.drawText(text, 2, 0, width - 4, height, Justification::centred, true);
244
    } break;
245
 
246
    case 2: {
933 tk 247
        const String text = String(rowNumber/8 + 1) + T("/D") + String(7 - (rowNumber%8));
932 tk 248
        g.drawText(text, 2, 0, width - 4, height, Justification::centred, true);
249
    } break;
250
    }
251
 
252
    g.setColour(Colours::black.withAlpha (0.2f));
253
    g.fillRect(width - 1, 0, 1, height);
254
}
255
 
256
 
257
Component* Midio128ToolConfigDout::refreshComponentForCell(int rowNumber, int columnId, bool isRowSelected, Component* existingComponentToUpdate)
258
{
259
    switch( columnId ) {
260
    case 3: {
261
        ConfigTableSlider *slider = (ConfigTableSlider *)existingComponentToUpdate;
262
 
263
        if( slider == 0 ) {
264
            slider = new ConfigTableSlider(*this);
265
            slider->setRange(1, 16);
266
        }
267
 
268
        slider->setRowAndColumn(rowNumber, columnId);
269
        return slider;
270
    } break;
271
 
272
    case 4: {
273
        ConfigTableComboBox *comboBox = (ConfigTableComboBox *)existingComponentToUpdate;
274
 
275
        if( comboBox == 0 ) {
276
            comboBox = new ConfigTableComboBox(*this);
934 tk 277
            comboBox->addItem(T("Disabled"), 1);
278
            comboBox->addItem(T("Note Off"), 2);
279
            comboBox->addItem(T("Note On"), 3);
280
            comboBox->addItem(T("Poly Aftertouch"), 4);
935 tk 281
            comboBox->addItem(T("Controller (CC)"), 5);
934 tk 282
            comboBox->addItem(T("Program Change"), 6);
283
            comboBox->addItem(T("Channel Aftertouch"), 7);
284
            comboBox->addItem(T("Pitch Bender"), 8);
285
            comboBox->addItem(T("Meta Event"), 9);
932 tk 286
        }
287
 
288
        comboBox->setRowAndColumn(rowNumber, columnId);
289
        return comboBox;
290
    } break;
291
 
292
    case 5: {
293
        ConfigTableSlider *slider = (ConfigTableSlider *)existingComponentToUpdate;
294
 
295
        if( slider == 0 ) {
296
            slider = new ConfigTableSlider(*this);
297
            slider->setRange(0, 127);
298
        }
299
 
300
        slider->setRowAndColumn(rowNumber, columnId);
301
        return slider;
302
    } break;
303
    }
304
 
305
    return 0;
306
}
307
 
308
 
309
//==============================================================================
310
void Midio128ToolConfigDout::resized()
311
{
312
    // position our table with a gap around its edge
1724 tk 313
    table->setBoundsInset(BorderSize<int>(8));
932 tk 314
}
315
 
316
 
317
//==============================================================================
318
int Midio128ToolConfigDout::getTableValue(const int rowNumber, const int columnId)
319
{
320
    switch( columnId ) {
321
    case 3: return doutChannel[rowNumber];
322
    case 4: return doutEvent[rowNumber];
323
    case 5: return doutParameter[rowNumber];
324
    }
325
    return 0;
326
}
327
 
328
void Midio128ToolConfigDout::setTableValue(const int rowNumber, const int columnId, const int newValue)
329
{
330
    switch( columnId ) {
934 tk 331
    case 3: doutChannel.set(rowNumber, newValue); break;
332
    case 4: doutEvent.set(rowNumber, newValue); break;
333
    case 5: doutParameter.set(rowNumber, newValue); break;
932 tk 334
    }
335
}
336
 
337
 
934 tk 338
//==============================================================================
339
void Midio128ToolConfigDout::getDump(Array<uint8> &syxDump)
340
{
341
    for(int dout=0; dout<numRows; ++dout) {
342
        int channel = (doutChannel[dout] - 1) & 0x0f;
343
        int event = (doutEvent[dout] - 2);
344
        int parameter = doutParameter[dout] & 0x7f;
932 tk 345
 
934 tk 346
        if( event < 0 ) {
347
            syxDump.set(0x000 + 2*dout + 0, 0x7f);
348
            syxDump.set(0x000 + 2*dout + 1, 0x7f);
349
        } else {
350
            syxDump.set(0x000 + 2*dout + 0, (event << 4) | channel);
351
            syxDump.set(0x000 + 2*dout + 1, parameter);
352
        }
353
    }
354
}
355
 
356
void Midio128ToolConfigDout::setDump(const Array<uint8> &syxDump)
357
{
358
    for(int dout=0; dout<numRows; ++dout) {
359
        int channel = syxDump[0x000 + 2*dout + 0] & 0x0f;
360
        int event = (syxDump[0x000 + 2*dout + 0] >> 4) & 0x7;
361
        int parameter = syxDump[0x000 + 2*dout + 1] & 0x7f;
362
 
363
        if( channel == 0xf && event == 0x7 && parameter == 0x7f ) {
364
            doutChannel.set(dout, 1);
365
            doutEvent.set(dout, 1);
366
            doutParameter.set(dout, 0);
367
        } else {
368
            doutChannel.set(dout, channel + 1);
369
            doutEvent.set(dout, event ? (event+2) : 1);
370
            doutParameter.set(dout, parameter);
371
        }
372
    }
373
    table->updateContent();
374
}
375
 
376
 
377
 
932 tk 378
//==============================================================================
379
//==============================================================================
380
//==============================================================================
381
Midio128ToolConfigDin::Midio128ToolConfigDin()
382
    : font(14.0f)
383
    , numRows(128)
384
{
385
    for(int din=0; din<numRows; ++din) {
934 tk 386
        dinChannel.add(1); // Default MIDI Channel
387
        dinMode.add(1); // OnOff
932 tk 388
 
389
        if( din < 64 ) {
934 tk 390
            dinOnEvent.add(3); // Note On
391
            dinOnParameter1.add(0x30 + din); // Note Number
392
            dinOnParameter2.add(0x7f); // Max Velocity
393
            dinOffEvent.add(3); // Note On
394
            dinOffParameter1.add(0x30 + din); // Note Number
395
            dinOffParameter2.add(0x00); // 0 Velocity (-> Note Off)
932 tk 396
        } else {
934 tk 397
            dinOnEvent.add(5); // CC
398
            dinOnParameter1.add(0x10 + din - 64); // CC Number
399
            dinOnParameter2.add(0x7f); // Max value
400
            dinOffEvent.add(5); // CC
401
            dinOffParameter1.add(0x10 + din - 64); // CC Number
402
            dinOffParameter2.add(0x00); // 0
932 tk 403
        }
404
    }
405
 
406
    addAndMakeVisible(table = new TableListBox(T("DIN Button Table"), this));
407
    table->setColour(ListBox::outlineColourId, Colours::grey);
408
    table->setOutlineThickness(1);
409
 
1187 tk 410
    table->getHeader().addColumn(T("DIN"), 1, 50);
411
    table->getHeader().addColumn(T("SR/Pin"), 2, 50);
412
    table->getHeader().addColumn(T("Channel"), 3, 75);
413
    table->getHeader().addColumn(T("On Event"), 4, 125);
414
    table->getHeader().addColumn(T("On Par.1"), 5, 75);
415
    table->getHeader().addColumn(T("On Par.2"), 6, 75);
416
    table->getHeader().addColumn(T("Off Event"), 7, 125);
417
    table->getHeader().addColumn(T("Off Par.1"), 8, 75);
418
    table->getHeader().addColumn(T("Off Par.2"), 9, 75);
419
    table->getHeader().addColumn(T("Mode"), 10, 75);
932 tk 420
 
421
    setSize(800, 200);
422
}
423
 
424
Midio128ToolConfigDin::~Midio128ToolConfigDin()
425
{
426
}
427
 
428
//==============================================================================
429
int Midio128ToolConfigDin::getNumRows()
430
{
431
    return numRows;
432
}
433
 
434
void Midio128ToolConfigDin::paintRowBackground(Graphics &g, int rowNumber, int width, int height, bool rowIsSelected)
435
{
436
    if( rowIsSelected )
437
        g.fillAll(Colours::lightblue);
438
}
439
 
440
void Midio128ToolConfigDin::paintCell(Graphics &g, int rowNumber, int columnId, int width, int height, bool rowIsSelected)
441
{
442
    g.setColour(Colours::black);
443
    g.setFont(font);
444
 
445
    switch( columnId ) {
446
    case 1: {
447
        const String text(rowNumber);
448
        g.drawText(text, 2, 0, width - 4, height, Justification::centred, true);
449
    } break;
450
 
451
    case 2: {
933 tk 452
        const String text = String(rowNumber/8 + 1) + T("/D") + String(rowNumber%8);
932 tk 453
        g.drawText(text, 2, 0, width - 4, height, Justification::centred, true);
454
    } break;
455
    }
456
 
457
    g.setColour(Colours::black.withAlpha (0.2f));
458
    g.fillRect(width - 1, 0, 1, height);
459
}
460
 
461
 
462
Component* Midio128ToolConfigDin::refreshComponentForCell(int rowNumber, int columnId, bool isRowSelected, Component* existingComponentToUpdate)
463
{
464
    switch( columnId ) {
465
    case 3: {
466
        ConfigTableSlider *slider = (ConfigTableSlider *)existingComponentToUpdate;
467
 
468
        if( slider == 0 ) {
469
            slider = new ConfigTableSlider(*this);
470
            slider->setRange(1, 16);
471
        }
472
 
473
        slider->setRowAndColumn(rowNumber, columnId);
474
        return slider;
475
    } break;
476
 
477
    case 4:
478
    case 7: {
479
        ConfigTableComboBox *comboBox = (ConfigTableComboBox *)existingComponentToUpdate;
480
 
481
        if( comboBox == 0 ) {
482
            comboBox = new ConfigTableComboBox(*this);
934 tk 483
            comboBox->addItem(T("Disabled"), 1);
484
            comboBox->addItem(T("Note Off"), 2);
485
            comboBox->addItem(T("Note On"), 3);
486
            comboBox->addItem(T("Poly Aftertouch"), 4);
935 tk 487
            comboBox->addItem(T("Controller (CC)"), 5);
934 tk 488
            comboBox->addItem(T("Program Change"), 6);
489
            comboBox->addItem(T("Channel Aftertouch"), 7);
490
            comboBox->addItem(T("Pitch Bender"), 8);
491
            comboBox->addItem(T("Meta Event"), 9);
932 tk 492
        }
493
 
494
        comboBox->setRowAndColumn(rowNumber, columnId);
495
        return comboBox;
496
    } break;
497
 
498
    case 5:
499
    case 6:
500
    case 8:
501
    case 9: {
502
        ConfigTableSlider *slider = (ConfigTableSlider *)existingComponentToUpdate;
503
 
504
        if( slider == 0 ) {
505
            slider = new ConfigTableSlider(*this);
506
            slider->setRange(0, 127);
507
        }
508
 
509
        slider->setRowAndColumn(rowNumber, columnId);
510
        return slider;
511
    } break;
512
 
513
    case 10: {
514
        ConfigTableComboBox *comboBox = (ConfigTableComboBox *)existingComponentToUpdate;
515
 
516
        if( comboBox == 0 ) {
517
            comboBox = new ConfigTableComboBox(*this);
518
            comboBox->addItem(T("On/Off"), 1);
519
            comboBox->addItem(T("On Only"), 2);
520
            comboBox->addItem(T("Toggle"), 3);
521
        }
522
 
523
        comboBox->setRowAndColumn(rowNumber, columnId);
524
        return comboBox;
525
    } break;
526
    }
527
 
528
    return 0;
529
}
530
 
531
 
532
//==============================================================================
533
void Midio128ToolConfigDin::resized()
534
{
535
    // position our table with a gap around its edge
1724 tk 536
    table->setBoundsInset(BorderSize<int>(8));
932 tk 537
}
538
 
539
 
540
//==============================================================================
541
int Midio128ToolConfigDin::getTableValue(const int rowNumber, const int columnId)
542
{
543
    switch( columnId ) {
544
    case 3: return dinChannel[rowNumber];
545
    case 4: return dinOnEvent[rowNumber];
546
    case 5: return dinOnParameter1[rowNumber];
547
    case 6: return dinOnParameter2[rowNumber];
548
    case 7: return dinOffEvent[rowNumber];
549
    case 8: return dinOffParameter1[rowNumber];
550
    case 9: return dinOffParameter2[rowNumber];
551
    case 10: return dinMode[rowNumber];
552
    }
553
    return 0;
554
}
555
 
556
void Midio128ToolConfigDin::setTableValue(const int rowNumber, const int columnId, const int newValue)
557
{
558
    switch( columnId ) {
934 tk 559
    case 3: dinChannel.set(rowNumber, newValue); break;
560
    case 4: dinOnEvent.set(rowNumber, newValue); break;
561
    case 5: dinOnParameter1.set(rowNumber, newValue); break;
562
    case 6: dinOnParameter2.set(rowNumber, newValue); break;
563
    case 7: dinOffEvent.set(rowNumber, newValue); break;
564
    case 8: dinOffParameter1.set(rowNumber, newValue); break;
565
    case 9: dinOffParameter2.set(rowNumber, newValue); break;
566
    case 10: dinMode.set(rowNumber, newValue); break;
932 tk 567
    }
568
}
569
 
570
 
571
//==============================================================================
934 tk 572
void Midio128ToolConfigDin::getDump(Array<uint8> &syxDump)
573
{
574
    for(int din=0; din<numRows; ++din) {
575
        int onChannel = (dinChannel[din] - 1) & 0x0f;
576
        int onEvent = (dinOnEvent[din] - 2);
577
        int onParameter1 = dinOnParameter1[din] & 0x7f;
578
        int onParameter2 = dinOnParameter2[din] & 0x7f;
579
        int offChannel = (dinChannel[din] - 1) & 0x0f;
580
        int offEvent = (dinOffEvent[din] - 2);
581
        int offParameter1 = dinOffParameter1[din] & 0x7f;
582
        int offParameter2 = dinOffParameter2[din] & 0x7f;
583
        int mode = (dinMode[din]-1) & 0x07;
584
 
585
        if( onEvent < 0 ) {
586
            syxDump.set(0x100 + 6*din + 0, 0x7f);
587
            syxDump.set(0x100 + 6*din + 1, 0x7f);
588
            syxDump.set(0x100 + 6*din + 2, 0x7f);
589
        } else {
590
            syxDump.set(0x100 + 6*din + 0, (onEvent << 4) | onChannel);
591
            syxDump.set(0x100 + 6*din + 1, onParameter1);
592
            syxDump.set(0x100 + 6*din + 2, onParameter2);
593
        }
594
 
595
        if( offEvent < 0 ) {
596
            syxDump.set(0x100 + 6*din + 3, 0x7f);
597
            syxDump.set(0x100 + 6*din + 4, 0x7f);
598
            syxDump.set(0x100 + 6*din + 5, 0x7f);
599
        } else {
600
            syxDump.set(0x100 + 6*din + 3, (offEvent << 4) | offChannel);
601
            syxDump.set(0x100 + 6*din + 4, offParameter1);
602
            syxDump.set(0x100 + 6*din + 5, offParameter2);
603
        }
604
 
605
        int modeAddr = 0x420 + (din/2);
606
        if( din & 1 )
607
            syxDump.set(modeAddr, (syxDump[modeAddr] & 0x0f) | (mode << 4));
608
        else
609
            syxDump.set(modeAddr, (syxDump[modeAddr] & 0xf0) | mode);
610
    }
611
}
612
 
613
void Midio128ToolConfigDin::setDump(const Array<uint8> &syxDump)
614
{
615
    for(int din=0; din<numRows; ++din) {
616
        int onChannel = syxDump[0x100 + 6*din + 0] & 0x0f;
617
        int onEvent = (syxDump[0x100 + 6*din + 0] >> 4) & 0x7;
618
        int onParameter1 = syxDump[0x100 + 6*din + 1] & 0x7f;
619
        int onParameter2 = syxDump[0x100 + 6*din + 2] & 0x7f;
620
        int offChannel = syxDump[0x100 + 6*din + 3] & 0x0f;
621
        int offEvent = (syxDump[0x100 + 6*din + 3] >> 4) & 0x7;
622
        int offParameter1 = syxDump[0x100 + 6*din + 4] & 0x7f;
623
        int offParameter2 = syxDump[0x100 + 6*din + 5] & 0x7f;
624
        int mode = syxDump[0x420 + (din/2)];
625
        mode = ((din & 1) ? (mode >> 4) : mode) & 0x07;
626
 
627
        if( onChannel == 0xf && onEvent == 0x7 && onParameter1 == 0x7f && onParameter2 == 0x7f ) {
628
            onChannel = -1;
629
            dinOnEvent.set(din, 1);
630
            dinOnParameter1.set(din, 0);
631
            dinOnParameter2.set(din, 0);
632
        } else {
633
            dinOnEvent.set(din, onEvent ? (onEvent+2) : 1);
634
            dinOnParameter1.set(din, onParameter1);
635
            dinOnParameter2.set(din, onParameter2);
636
        }
637
 
638
        if( offChannel == 0xf && offEvent == 0x7 && offParameter1 == 0x7f && offParameter2 == 0x7f ) {
639
            offChannel = -1;
640
            dinOffEvent.set(din, 1);
641
            dinOffParameter1.set(din, 0);
642
            dinOffParameter2.set(din, 0);
643
        } else {
644
            dinOffEvent.set(din, offEvent ? (offEvent+2) : 1);
645
            dinOffParameter1.set(din, offParameter1);
646
            dinOffParameter2.set(din, offParameter2);
647
        }
648
 
649
        // we only allow to configure a single channel for both events
650
        if( onChannel >= 0 )
651
            dinChannel.set(din, onChannel+1);
652
        else if( offChannel >= 0 )
653
            dinChannel.set(din, offChannel+1);
654
        else
655
            dinChannel.set(din, 1);
656
 
657
        // DIN mode
658
        dinMode.set(din, mode+1);
659
    }
660
    table->updateContent();
661
}
662
 
932 tk 663
//==============================================================================
664
//==============================================================================
934 tk 665
//==============================================================================
932 tk 666
Midio128ToolConfig::Midio128ToolConfig(MiosStudio *_miosStudio)
667
    : miosStudio(_miosStudio)
668
    , TabbedComponent(TabbedButtonBar::TabsAtTop)
669
{
934 tk 670
    addTab(T("DINs"),   Colour(0xfff0f0d0), configDin = new Midio128ToolConfigDin(), true);
671
    addTab(T("DOUTs"),  Colour(0xfff0f0c0), configDout = new Midio128ToolConfigDout(), true);
935 tk 672
    addTab(T("Global"), Colour(0xfff0f0e0), configGlobals = new Midio128ToolConfigGlobals(), true);
932 tk 673
    setSize(800, 200);
674
}
675
 
676
Midio128ToolConfig::~Midio128ToolConfig()
677
{
678
}
679
 
680
//==============================================================================
934 tk 681
void Midio128ToolConfig::getDump(Array<uint8> &syxDump)
932 tk 682
{
934 tk 683
    for(int addr=0x000; addr<0x460; ++addr)
684
        syxDump.set(addr, 0x00);
685
    for(int addr=0x460; addr<0x600; ++addr)
686
        syxDump.set(addr, 0x7f);
687
 
688
    configGlobals->getDump(syxDump);
689
    configDin->getDump(syxDump);
690
    configDout->getDump(syxDump);
932 tk 691
}
692
 
934 tk 693
void Midio128ToolConfig::setDump(const Array<uint8> &syxDump)
694
{
695
    configGlobals->setDump(syxDump);
696
    configDin->setDump(syxDump);
697
    configDout->setDump(syxDump);
698
}
932 tk 699
 
934 tk 700
 
701
 
932 tk 702
//==============================================================================
934 tk 703
//==============================================================================
704
//==============================================================================
705
Midio128ToolControl::Midio128ToolControl(MiosStudio *_miosStudio, Midio128ToolConfig *_midio128ToolConfig)
706
    : miosStudio(_miosStudio)
707
    , midio128ToolConfig(_midio128ToolConfig)
708
    , progress(0)
709
    , receiveDump(false)
710
    , dumpReceived(false)
711
    , checksumError(false)
932 tk 712
{
1131 tk 713
    addAndMakeVisible(loadButton = new TextButton(T("Load")));
1502 tk 714
    loadButton->addListener(this);
934 tk 715
 
1131 tk 716
    addAndMakeVisible(saveButton = new TextButton(T("Save")));
1502 tk 717
    saveButton->addListener(this);
934 tk 718
 
719
    addAndMakeVisible(deviceIdLabel = new Label(T("Device ID"), T("Device ID:")));
720
    deviceIdLabel->setJustificationType(Justification::right);
721
 
722
    addAndMakeVisible(deviceIdSlider = new Slider(T("Device ID")));
723
    deviceIdSlider->setRange(0, 7, 1);
724
    deviceIdSlider->setSliderStyle(Slider::IncDecButtons);
1131 tk 725
    deviceIdSlider->setTextBoxStyle(Slider::TextBoxLeft, false, 30, 20);
934 tk 726
    deviceIdSlider->setDoubleClickReturnValue(true, 0);
727
 
1131 tk 728
    addAndMakeVisible(receiveButton = new TextButton(T("Receive")));
1502 tk 729
    receiveButton->addListener(this);
934 tk 730
 
1131 tk 731
    addAndMakeVisible(sendButton = new TextButton(T("Send")));
1502 tk 732
    sendButton->addListener(this);
934 tk 733
 
734
    addAndMakeVisible(progressBar = new ProgressBar(progress));
735
 
736
    // restore settings
1724 tk 737
    PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
934 tk 738
    if( propertiesFile ) {
739
        deviceIdSlider->setValue(propertiesFile->getIntValue(T("midio128DeviceId"), 0) & 7);
740
        String syxFileName(propertiesFile->getValue(T("midio128SyxFile"), String::empty));
741
        if( syxFileName != String::empty )
742
            syxFile = File(syxFileName);
743
    }
744
 
745
    setSize(800, 200);
932 tk 746
}
747
 
934 tk 748
Midio128ToolControl::~Midio128ToolControl()
749
{
750
}
932 tk 751
 
934 tk 752
//==============================================================================
753
void Midio128ToolControl::paint (Graphics& g)
754
{
755
    g.fillAll(Colours::white);
756
}
932 tk 757
 
934 tk 758
void Midio128ToolControl::resized()
759
{
760
    int buttonX0 = 10;
761
    int buttonXOffset = 80;
762
    int buttonY = 8;
763
    int buttonWidth = 72;
764
    int buttonHeight = 24;
765
 
766
    loadButton->setBounds(buttonX0 + 0*buttonXOffset, buttonY, buttonWidth, buttonHeight);
767
    saveButton->setBounds(buttonX0 + 1*buttonXOffset, buttonY, buttonWidth, buttonHeight);
768
 
769
    deviceIdLabel->setBounds(buttonX0 + 20+2*buttonXOffset, buttonY, buttonWidth, buttonHeight);
770
    deviceIdSlider->setBounds(buttonX0 + 20+3*buttonXOffset, buttonY, buttonWidth, buttonHeight);
771
 
772
    receiveButton->setBounds(buttonX0 + 40+4*buttonXOffset, buttonY, buttonWidth, buttonHeight);
773
    sendButton->setBounds(buttonX0 + 40+5*buttonXOffset, buttonY, buttonWidth, buttonHeight);
774
 
775
    int progressBarX = sendButton->getX() + buttonWidth + 20;
776
    progressBar->setBounds(progressBarX, buttonY, getWidth()-progressBarX-buttonX0, buttonHeight);
777
}
778
 
932 tk 779
//==============================================================================
934 tk 780
void Midio128ToolControl::buttonClicked(Button* buttonThatWasClicked)
781
{
782
    if( buttonThatWasClicked == loadButton ) {
783
        FileChooser fc(T("Choose a .syx file that you want to open..."),
784
                       syxFile,
785
                       T("*.syx"));
786
 
787
        if( fc.browseForFileToOpen() ) {
788
            syxFile = fc.getResult();
789
            if( loadSyx(syxFile) ) {
1724 tk 790
                PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
934 tk 791
                if( propertiesFile )
792
                    propertiesFile->setValue(T("midio128SyxFile"), syxFile.getFullPathName());
793
            }
794
        }
795
    } else if( buttonThatWasClicked == saveButton ) {
796
        FileChooser fc(T("Choose a .syx file that you want to save..."),
797
                       syxFile,
798
                       T("*.syx"));
799
        if( fc.browseForFileToSave(true) ) {
800
            syxFile = fc.getResult();
801
            if( saveSyx(syxFile) ) {
1724 tk 802
                PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
934 tk 803
                if( propertiesFile )
804
                    propertiesFile->setValue(T("midio128SyxFile"), syxFile.getFullPathName());
805
            }
806
        }
807
    } else if( buttonThatWasClicked == sendButton || buttonThatWasClicked == receiveButton ) {
808
        loadButton->setEnabled(false);
809
        saveButton->setEnabled(false);
810
        sendButton->setEnabled(false);
811
        receiveButton->setEnabled(false);
812
        syxBlock = 0;
813
        progress = 0;
1502 tk 814
        checksumError = false;
934 tk 815
        if( buttonThatWasClicked == receiveButton ) {
816
            receiveDump = true;
817
            currentSyxDump.clear();
818
        } else {
819
            receiveDump = false;
820
            midio128ToolConfig->getDump(currentSyxDump);
821
        }
822
        startTimer(1);
823
    }
824
}
825
 
826
 
932 tk 827
//==============================================================================
934 tk 828
void Midio128ToolControl::sliderValueChanged(Slider* slider)
829
{
830
    if( slider == deviceIdSlider ) {
831
        // store setting
1724 tk 832
        PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
934 tk 833
        if( propertiesFile )
834
            propertiesFile->setValue(T("midio128DeviceId"), (int)slider->getValue());
835
    }
836
}
837
 
838
 
932 tk 839
//==============================================================================
934 tk 840
void Midio128ToolControl::timerCallback()
841
{
842
    stopTimer(); // will be restarted if required
843
 
844
    bool transferFinished = false;
845
 
846
    if( receiveDump ) {
847
        if( syxBlock > 0 ) {
848
            if( !dumpReceived ) {
849
                transferFinished = true;
850
                AlertWindow::showMessageBox(AlertWindow::WarningIcon,
851
                                            T("No response from core."),
852
                                            T("Check:\n- MIDI In/Out connections\n- Device ID\n- that MIDIO128 firmware has been uploaded"),
853
                                            String::empty);
935 tk 854
            } else if( checksumError ) {
934 tk 855
                transferFinished = true;
856
                AlertWindow::showMessageBox(AlertWindow::WarningIcon,
857
                                            T("Detected checksum error!"),
858
                                            T("Check:\n- MIDI In/Out connections\n- your MIDI interface"),
859
                                            String::empty);
860
            }
861
        }
862
 
863
        if( !transferFinished ) {
864
            if( syxBlock >= 6 ) {
865
                transferFinished = true;
866
 
867
                if( currentSyxDump.size() != 6*256 ) {
868
                    AlertWindow::showMessageBox(AlertWindow::WarningIcon,
869
                                                T("Unexpected MIDI handling error!"),
870
                                                T("Please inform TK how this happened."),
871
                                                T("will do"));
872
                } else {
873
                    midio128ToolConfig->setDump(currentSyxDump);
874
                }
875
            } else {
876
                dumpReceived = false;
877
                checksumError = false;
878
                Array<uint8> data = SysexHelper::createMidio128ReadBlock((uint8)deviceIdSlider->getValue(),
879
                                                                         syxBlock);
880
                MidiMessage message = SysexHelper::createMidiMessage(data);
881
                miosStudio->sendMidiMessage(message);
882
 
883
                progress = (double)++syxBlock / 6.0;
884
                startTimer(1000);
885
            }
886
        }
887
    } else {
888
        if( syxBlock >= 6 ) {
889
            transferFinished = true;
890
        } else {
891
            Array<uint8> data = SysexHelper::createMidio128WriteBlock((uint8)deviceIdSlider->getValue(),
892
                                                                      syxBlock,
893
                                                                      &currentSyxDump.getReference(syxBlock*256));
894
            MidiMessage message = SysexHelper::createMidiMessage(data);
895
            miosStudio->sendMidiMessage(message);
896
 
897
            progress = (double)++syxBlock / 6.0;
898
            startTimer(1000);
899
        }
900
    }
901
 
902
    if( transferFinished ) {
903
        progress = 0;
904
        loadButton->setEnabled(true);
905
        saveButton->setEnabled(true);
906
        sendButton->setEnabled(true);
907
        receiveButton->setEnabled(true);
908
    }
909
}
910
 
911
//==============================================================================
912
void Midio128ToolControl::handleIncomingMidiMessage(const MidiMessage& message, uint8 runningStatus)
913
{
1724 tk 914
    uint8 *data = (uint8 *)message.getRawData();
934 tk 915
    uint32 size = message.getRawDataSize();
916
 
917
    if( receiveDump ) {
918
        int receivedBlock = syxBlock-1;
919
        if( SysexHelper::isValidMidio128WriteBlock(data, size, (int)deviceIdSlider->getValue()) &&
920
            data[6] == receivedBlock ) {
921
            dumpReceived = true;
922
 
923
            if( size != 265 ) {
924
                checksumError = true;
925
            } else {
926
                uint8 checksum = 0x00;
927
                int pos;
928
                for(pos=6; pos<6+1+256; ++pos)
929
                    checksum += data[pos];
930
                if( data[pos] != (-(int)checksum & 0x7f) )
931
                    checksumError = true;
932
                else {
933
                    for(pos=7; pos<6+1+256; ++pos)
934
                        currentSyxDump.add(data[pos]);
935
                }
936
            }
937
 
938
            // trigger timer immediately
939
            stopTimer();
940
            startTimer(1);
941
        }
942
    } else if( isTimerRunning() ) {
943
        if( SysexHelper::isValidMidio128Acknowledge(data, size, (int)deviceIdSlider->getValue()) ) {
944
            // trigger timer immediately
945
            stopTimer();
946
            startTimer(1);
947
        }
948
    }
949
}
950
 
951
 
952
//==============================================================================
953
bool Midio128ToolControl::loadSyx(File &syxFile)
954
{
955
    FileInputStream *inFileStream = syxFile.createInputStream();
956
 
1542 tk 957
    if( !inFileStream ) {
934 tk 958
        AlertWindow::showMessageBox(AlertWindow::WarningIcon,
959
                                    T("The file ") + syxFile.getFileName(),
960
                                    T("doesn't exist!"),
961
                                    String::empty);
962
        return false;
963
    } else if( inFileStream->isExhausted() || !inFileStream->getTotalLength() ) {
964
        AlertWindow::showMessageBox(AlertWindow::WarningIcon,
965
                                    T("The file ") + syxFile.getFileName(),
966
                                    T("is empty!"),
967
                                    String::empty);
968
        return false;
969
    }
970
 
971
    int64 size = inFileStream->getTotalLength();
972
    uint8 *buffer = (uint8 *)juce_malloc(size);
973
    int64 readNumBytes = inFileStream->read(buffer, size);
974
    int numValidBlocks = 0;
975
    Array<uint8> syxDump;
976
    String errorMessage;
977
 
978
    if( readNumBytes != size ) {
979
        errorMessage = String(T("cannot be read completely!"));
980
    } else {
981
        for(int pos=0; pos<size; ++pos) {
982
            if( SysexHelper::isValidMidio128WriteBlock(buffer+pos, size - pos, -1) ) {
983
                pos += 6;
984
 
985
                if( pos < size ) {
986
                    int block = buffer[pos++];
987
                    if( block < 6 ) {
988
                        int blockPos = 0;
989
                        uint8 checksum = block;
990
                        while( pos < size && buffer[pos] != 0xf7 && blockPos < 256 ) {
991
                            uint8 b = buffer[pos++];
992
                            syxDump.set(block*256 + blockPos, b);
993
                            checksum += b;
994
                            ++blockPos;
995
                        }
996
 
997
                        if( blockPos != 256 ) {
998
                            errorMessage = String::formatted(T("contains invalid data: block %d not complete (only %d bytes)"), block, blockPos);
999
                        } else {
1000
                            checksum = (-(int)checksum) & 0x7f;
1001
                            if( buffer[pos] != checksum ) {
1002
                                errorMessage = String::formatted(T("contains invalid checksum in block %d (expected %02X but read %02X)!"), block, checksum, buffer[pos]);
1003
                            } else {
1004
                                ++pos;
1005
                                ++numValidBlocks;
1006
                            }
1007
                        }
1008
                    } else {
1009
                        errorMessage = String::formatted(T("contains invalid block: %d"), block);
1010
                    }
1011
                }
1012
            }
1013
        }
1014
    }
1015
 
1016
    juce_free(buffer);
1017
 
1018
    if( errorMessage == String::empty ) {
1019
        if( !numValidBlocks )
1020
            errorMessage = String(T("doesn't contain valid MIDIO128 data!"));
1021
        else if( numValidBlocks < 6 )
1022
            errorMessage = String::formatted(T("is not complete (expect 6 blocks, only found %d blocks"), numValidBlocks);
1023
    }
1024
 
1025
    if( errorMessage != String::empty ) {
1026
        AlertWindow::showMessageBox(AlertWindow::WarningIcon,
1027
                                    T("The file ") + syxFile.getFileName(),
1028
                                    errorMessage,
1029
                                    String::empty);
1030
        return false;
1031
    }
1032
 
1033
    midio128ToolConfig->setDump(syxDump);
1034
 
1035
    return true;
1036
}
1037
 
1038
bool Midio128ToolControl::saveSyx(File &syxFile)
1039
{
1040
    syxFile.deleteFile();
1041
    FileOutputStream *outFileStream = syxFile.createOutputStream();
1042
 
1043
    if( !outFileStream || outFileStream->failedToOpen() ) {
1044
        AlertWindow::showMessageBox(AlertWindow::WarningIcon,
1045
                                    String::empty,
1046
                                    T("File cannot be created!"),
1047
                                    String::empty);
1048
        return false;
1049
    }
1050
 
1051
    Array<uint8> syxDump;
1052
    midio128ToolConfig->getDump(syxDump);
1053
 
1054
    for(int block=0; block<6; ++block) {
1055
        Array<uint8> data = SysexHelper::createMidio128WriteBlock((uint8)deviceIdSlider->getValue(),
1056
                                                                  block,
1057
                                                                  &syxDump.getReference(block*256));
1058
        outFileStream->write(&data.getReference(0), data.size());
1059
    }
1060
 
1061
    delete outFileStream;
1062
 
1063
    return true;
1064
}
1065
 
1066
 
1067
//==============================================================================
1068
//==============================================================================
1069
//==============================================================================
932 tk 1070
Midio128Tool::Midio128Tool(MiosStudio *_miosStudio)
1071
    : miosStudio(_miosStudio)
1072
{
1073
    addAndMakeVisible(midio128ToolConfig = new Midio128ToolConfig(miosStudio));
934 tk 1074
    addAndMakeVisible(midio128ToolControl = new Midio128ToolControl(miosStudio, midio128ToolConfig));
932 tk 1075
 
1076
    resizeLimits.setSizeLimits(100, 300, 2048, 2048);
1077
    addAndMakeVisible(resizer = new ResizableCornerComponent(this, &resizeLimits));
1078
 
1079
    setSize(860, 500);
1080
}
1081
 
1082
Midio128Tool::~Midio128Tool()
1083
{
1084
}
1085
 
1086
//==============================================================================
1087
void Midio128Tool::paint (Graphics& g)
1088
{
934 tk 1089
    //g.fillAll(Colour(0xffc1d0ff));
1090
    g.fillAll(Colours::white);
932 tk 1091
}
1092
 
1093
void Midio128Tool::resized()
1094
{
1095
    midio128ToolControl->setBounds(0, 0, getWidth(), 40);
1096
    midio128ToolConfig->setBounds(0, 40, getWidth(), getHeight()-40);
1097
    resizer->setBounds(getWidth()-16, getHeight()-16, 16, 16);
1098
}