Subversion Repositories svn.mios32

Rev

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

Rev Author Line No. Line
877 tk 1
/* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
2
// $Id: MiosStudio.cpp 2180 2015-06-14 19:21:59Z tk $
3
/*
4
 * MIDI Monitor Component
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 "MiosStudio.h"
1761 tk 16
#include "../version.h"
877 tk 17
 
1762 tk 18
#ifdef _WIN32
19
#include <windows.h>
20
#include <stdio.h>
21
#include <fcntl.h>
22
#include <io.h>
23
#include <iostream>
24
#include <fstream>
25
#endif
26
 
877 tk 27
//==============================================================================
28
MiosStudio::MiosStudio()
1759 tk 29
    : batchMode(false)
2180 tk 30
    , duggleMode(false)
1759 tk 31
    , uploadWindow(0)
908 tk 32
    , midiInMonitor(0)
33
    , midiOutMonitor(0)
34
    , miosTerminal(0)
35
    , midiKeyboard(0)
917 tk 36
    , initialMidiScanCounter(1) // start step-wise MIDI port scan
1759 tk 37
    , batchWaitCounter(0)
1762 tk 38
    , initialGuiX(-1) // centered
39
    , initialGuiY(-1) // centered
877 tk 40
{
1762 tk 41
    bool hideMonitors = false;
42
    bool hideUpload = false;
43
    bool hideTerminal = false;
44
    bool hideKeyboard = false;
45
    int  guiWidth = 800;
46
    int  guiHeight = 650;
1764 tk 47
    int  firstDeviceId = -1;
1762 tk 48
 
1759 tk 49
    // parse the command line
50
    {
51
        int numErrors = 0;
52
        bool quitIfBatch = false;
53
        StringArray commandLineArray = JUCEApplication::getCommandLineParameterArray();
1764 tk 54
 
55
        // first search for --batch option
1759 tk 56
        for(int i=0; i<commandLineArray.size(); ++i) {
1764 tk 57
            if( commandLineArray[i].compare("--batch") == 0 ) {
58
                batchMode = true;
59
                redirectIOToConsole();
60
            }
61
        }
62
 
63
        // now for the remaining options
64
        for(int i=0; i<commandLineArray.size(); ++i) {
1759 tk 65
            if( commandLineArray[i].compare("--help") == 0 ) {
66
                commandLineInfoMessages += "Command Line Parameters:\n";
67
                commandLineInfoMessages += "--help                  this page\n";
68
                commandLineInfoMessages += "--version               shows version number\n";
69
                commandLineInfoMessages += "--batch                 don't open GUI\n";
70
                commandLineInfoMessages += "--in=<port>             optional search string for MIDI IN port\n";
71
                commandLineInfoMessages += "--out=<port>            optional search string for MIDI OUT port\n";
72
                commandLineInfoMessages += "--device_id=<id>        sets the device id, should be done before upload if necessary\n";
73
                commandLineInfoMessages += "--query                 queries the selected core\n";
74
                commandLineInfoMessages += "--upload_hex=<file>     upload specified .hex file to core. Multiple --upload_hex allowed!\n";
75
                commandLineInfoMessages += "--upload_file=<file>    upload specified file to SD Card. Multiple --upload_file allowed!\n";
76
                commandLineInfoMessages += "--send_syx=<file>       send specified .syx file to core. Multiple --send_syx allowed!\n";
77
                commandLineInfoMessages += "--terminal=<command>    send a MIOS terminal command. Multiple --terminal allowed!\n";
78
                commandLineInfoMessages += "--wait=<seconds>        Waits for the given seconds.\n";
1764 tk 79
                commandLineInfoMessages += "--gui_x=<x>             specifies the initial window X position\n";
80
                commandLineInfoMessages += "--gui_y=<y>             specifies the initial window Y position\n";
81
                commandLineInfoMessages += "--gui_width=<width>     specifies the initial window width\n";
82
                commandLineInfoMessages += "--gui_height=<height>   specifies the initial window height\n";
83
                commandLineInfoMessages += "--gui_title=<name>      changes the name of the application in the title bar\n";
84
                commandLineInfoMessages += "--gui_hide_monitors     disables the MIDI IN/OUT monitor when the GUI is started\n";
85
                commandLineInfoMessages += "--gui_hide_upload       disables the upload panel when the GUI is started\n";
86
                commandLineInfoMessages += "--gui_hide_terminal     disables the terminal panel when the GUI is started\n";
87
                commandLineInfoMessages += "--gui_hide_keyboard     disables the virtual keyboard panel when the GUI is started\n";
1759 tk 88
                commandLineInfoMessages += "\n";
89
                commandLineInfoMessages += "Usage Examples:\n";
90
                commandLineInfoMessages += "  MIOS_Studio --in=MIOS32 --out=MIOS32\n";
91
                commandLineInfoMessages += "    starts MIOS Studio with MIDI IN/OUT port matching with 'MIOS32'\n";
92
                commandLineInfoMessages += "\n";
93
                commandLineInfoMessages += "  MIOS_Studio --upload_hex=project.hex\n";
94
                commandLineInfoMessages += "    starts MIOS Studio and uploads the project.hex file immediately\n";
95
                commandLineInfoMessages += "\n";
96
                commandLineInfoMessages += "  MIOS_Studio --batch --upload_hex=project.hex\n";
97
                commandLineInfoMessages += "    starts MIOS Studio without GUI and uploads the project.hex file\n";
98
                commandLineInfoMessages += "\n";
1762 tk 99
                commandLineInfoMessages += "  MIOS_Studio --batch --upload_file=default.ngc --upload_file=default.ngl\n";
1759 tk 100
                commandLineInfoMessages += "    starts MIOS Studio without GUI and uploads two files to SD Card (MIOS32 only)\n";
101
                commandLineInfoMessages += "\n";
102
                commandLineInfoMessages += "  MIOS_Studio --batch --terminal=\"help\" --wait=1\n";
103
                commandLineInfoMessages += "    starts MIOS Studio, executes the \"help\" command in MIOS Terminal and waits 1 second for response\n";
104
                commandLineInfoMessages += "\n";
105
                commandLineInfoMessages += "NOTE: most parameters can be combined to a sequence of operations.\n";
106
                commandLineInfoMessages += "      E.g. upload a .hex file, upload files to SD Card, execute a terminal command and wait some seconds before exit.\n";
107
                quitIfBatch = true;
108
            } else if( commandLineArray[i].compare("--version") == 0 ) {
109
                commandLineInfoMessages += String("MIOS Studio ") + String(MIOS_STUDIO_VERSION) + String("\n");
110
            } else if( commandLineArray[i].compare("--batch") == 0 ) {
1764 tk 111
                // already handled above
1759 tk 112
            } else if( commandLineArray[i].startsWith("--in=") ) {
113
                inPortFromCommandLine = commandLineArray[i].substring(5);
1766 tk 114
                inPortFromCommandLine.trimCharactersAtStart(" \t\"'");
115
                inPortFromCommandLine.trimCharactersAtEnd(" \t\"'");
1759 tk 116
                std::cout << "Preselected MIDI IN Port: " << inPortFromCommandLine << std::endl;
117
            } else if( commandLineArray[i].startsWith("--out=") ) {
118
                outPortFromCommandLine = commandLineArray[i].substring(6);
1766 tk 119
                outPortFromCommandLine.trimCharactersAtStart(" \t\"'");
120
                outPortFromCommandLine.trimCharactersAtEnd(" \t\"'");
1759 tk 121
                std::cout << "Preselected MIDI OUT Port: " << outPortFromCommandLine << std::endl;
122
            } else if( commandLineArray[i].startsWith("--device_id") ) {
123
                String id = commandLineArray[i].substring(12);
1766 tk 124
                id.trimCharactersAtStart(" \t\"'");
125
                id.trimCharactersAtEnd(" \t\"'");
1764 tk 126
                int idValue = id.getIntValue();
127
                if( idValue < 0 || idValue > 127 ) {
128
                    commandLineErrorMessages += String("ERROR: device ID should be within 0..127!\n");
129
                    ++numErrors;
130
                } else {
131
                    if( firstDeviceId < 0 ) {
132
                        firstDeviceId = idValue;
133
                    } else {
134
                        batchJobs.add(String("device_id ") + id);
135
                    }
136
                }
1759 tk 137
            } else if( commandLineArray[i].startsWith("--query") ) {
138
                batchJobs.add(String("query"));
2180 tk 139
            } else if( commandLineArray[i].startsWith("--duggle") ) {
140
                duggleMode = true;
1759 tk 141
            } else if( commandLineArray[i].startsWith("--upload_hex") ) {
142
                String file = commandLineArray[i].substring(13);
1766 tk 143
                file.trimCharactersAtStart(" \t\"'");
144
                file.trimCharactersAtEnd(" \t\"'");
1759 tk 145
                batchJobs.add(String("upload_hex ") + file);
146
            } else if( commandLineArray[i].startsWith("--upload_file") ) {
147
                String file = commandLineArray[i].substring(14);
1766 tk 148
                file.trimCharactersAtStart(" \t\"'");
149
                file.trimCharactersAtEnd(" \t\"'");
1759 tk 150
                batchJobs.add(String("upload_file ") + file);
151
            } else if( commandLineArray[i].startsWith("--send_syx") ) {
152
                String file = commandLineArray[i].substring(11);
1766 tk 153
                file.trimCharactersAtStart(" \t\"'");
154
                file.trimCharactersAtEnd(" \t\"'");
1759 tk 155
                batchJobs.add(String("send_syx ") + file);
156
            } else if( commandLineArray[i].startsWith("--terminal") ) {
157
                String command = commandLineArray[i].substring(11);
1766 tk 158
                command.trimCharactersAtStart(" \t\"'");
159
                command.trimCharactersAtEnd(" \t\"'");
1759 tk 160
                batchJobs.add(String("terminal ") + command);
161
            } else if( commandLineArray[i].startsWith("--wait") ) {
162
                String command = commandLineArray[i].substring(7);
1766 tk 163
                command.trimCharactersAtStart(" \t\"'");
164
                command.trimCharactersAtEnd(" \t\"'");
1759 tk 165
                batchJobs.add(String("wait ") + command);
1762 tk 166
            } else if( commandLineArray[i].startsWith("--gui_x") ) {
167
                int value = commandLineArray[i].substring(8).getIntValue();
168
                if( value >= 0 )
169
                    initialGuiX = value;
170
            } else if( commandLineArray[i].startsWith("--gui_y") ) {
171
                int value = commandLineArray[i].substring(8).getIntValue();
172
                if( value >= 0 )
173
                    initialGuiY = value;
174
            } else if( commandLineArray[i].startsWith("--gui_width") ) {
175
                int value = commandLineArray[i].substring(12).getIntValue();
176
                if( value > 0 )
177
                    guiWidth = value;
178
            } else if( commandLineArray[i].startsWith("--gui_height") ) {
179
                int value = commandLineArray[i].substring(13).getIntValue();
180
                if( value > 0 )
181
                    guiHeight = value;
182
            } else if( commandLineArray[i].startsWith("--gui_title") ) {
183
                initialGuiTitle = commandLineArray[i].substring(12);
1766 tk 184
                initialGuiTitle.trimCharactersAtStart(" \t\"'");
185
                initialGuiTitle.trimCharactersAtEnd(" \t\"'");
1762 tk 186
            } else if( commandLineArray[i].startsWith("--gui_hide_monitors") ) {
187
                hideMonitors = true;
188
            } else if( commandLineArray[i].startsWith("--gui_hide_upload") ) {
189
                hideUpload = true;
190
            } else if( commandLineArray[i].startsWith("--gui_hide_terminal") ) {
191
                hideTerminal = true;
192
            } else if( commandLineArray[i].startsWith("--gui_hide_keyboard") ) {
193
                hideKeyboard = true;
1760 tk 194
            } else if( commandLineArray[i].startsWith("-psn") ) {
195
                // ignore for MacOS
2180 tk 196
            } else if( commandLineArray[i].startsWith("-NSDocumentRevisionsDebugMode") ) {
197
                // ignore for MacOS
198
            } else if( commandLineArray[i].startsWith("YES") ) {
199
                // ignore for MacOS
1759 tk 200
            } else {
201
                commandLineErrorMessages += String("ERROR: unknown command line parameter: ") + commandLineArray[i] + String("\n");
1762 tk 202
                commandLineErrorMessages += String("Enter '--help' to get a list of all available options!\n");
1759 tk 203
                ++numErrors;
204
            }
205
        }
206
 
207
        std::cout << commandLineInfoMessages;
208
 
209
        if( numErrors ) {
210
            quitIfBatch = true;
211
 
212
            if( runningInBatchMode() ) {
213
                std::cerr << commandLineErrorMessages;
214
            } else {
215
                // AlertWindow will be shown from timerCallback() once MIOS Studio is running
216
            }
217
        }
218
 
219
        if( runningInBatchMode() && quitIfBatch ) {
1762 tk 220
#ifdef _WIN32
221
            std::cout << "Press <enter> to quit console." << std::endl;
222
            while (GetAsyncKeyState(VK_RETURN) & 0x8000) {}
223
            while (!(GetAsyncKeyState(VK_RETURN) & 0x8000)) {}
224
#endif
1759 tk 225
            JUCEApplication::getInstance()->setApplicationReturnValue(1); // error
226
            JUCEApplication::quit();
227
        }
228
 
1764 tk 229
        if( runningInBatchMode() ) {
1759 tk 230
            batchJobs.add("quit");
231
        }
232
    }
233
 
234
    // instantiate components
908 tk 235
    uploadHandler = new UploadHandler(this);
1502 tk 236
    sysexPatchDb = new SysexPatchDb();
908 tk 237
 
878 tk 238
    addAndMakeVisible(uploadWindow = new UploadWindow(this));
239
    addAndMakeVisible(midiInMonitor = new MidiMonitor(this, true));
240
    addAndMakeVisible(midiOutMonitor = new MidiMonitor(this, false));
241
    addAndMakeVisible(miosTerminal = new MiosTerminal(this));
242
    addAndMakeVisible(midiKeyboard = new MidiKeyboard(this));
877 tk 243
 
1189 tk 244
    // tools are created and made visible via tools button in Upload Window
245
    sysexToolWindow = 0;
246
    oscToolWindow = 0;
247
    midio128ToolWindow = 0;
248
    mbCvToolWindow = 0;
249
    mbhpMfToolWindow = 0;
1502 tk 250
    sysexLibrarianWindow = 0;
1542 tk 251
    miosFileBrowserWindow = 0;
927 tk 252
 
1626 tk 253
    addAndMakeVisible(horizontalDividerBar1 = new StretchableLayoutResizerBar(&horizontalLayout, 1, false));
254
    addAndMakeVisible(horizontalDividerBar2 = new StretchableLayoutResizerBar(&horizontalLayout, 3, false));
255
    addAndMakeVisible(horizontalDividerBar3 = new StretchableLayoutResizerBar(&horizontalLayout, 5, false));
256
    addAndMakeVisible(verticalDividerBarMonitors = new StretchableLayoutResizerBar(&verticalLayoutMonitors, 1, true));
257
    addAndMakeVisible(resizer = new ResizableCornerComponent(this, &resizeLimits));
258
    resizeLimits.setSizeLimits(200, 100, 2048, 2048);
259
 
937 tk 260
    commandManager = new ApplicationCommandManager();
261
    commandManager->registerAllCommandsForTarget(this);
262
    commandManager->registerAllCommandsForTarget(JUCEApplication::getInstance());
263
    addKeyListener(commandManager->getKeyMappings());
264
    setApplicationCommandManagerToWatch(commandManager);
265
 
1762 tk 266
    if( hideMonitors ) {
267
        midiInMonitor->setVisible(false);
268
        verticalDividerBarMonitors->setVisible(false);
269
        midiOutMonitor->setVisible(false);
270
    }
271
    if( hideUpload ) {
272
        horizontalDividerBar1->setVisible(false);
273
        uploadWindow->setVisible(false);
274
    }
275
    if( hideTerminal ) {
276
        horizontalDividerBar2->setVisible(false);
277
        miosTerminal->setVisible(false);
278
    }
279
    if( hideKeyboard ) {
280
        horizontalDividerBar3->setVisible(false);
281
        midiKeyboard->setVisible(false);
282
    }
283
 
1626 tk 284
    updateLayout();
877 tk 285
 
1764 tk 286
    if( firstDeviceId >= 0 ) {
287
        std::cout << "Setting Device ID=" << firstDeviceId << std::endl;
288
        uploadWindow->setDeviceId(firstDeviceId);
289
    }
290
 
878 tk 291
    Timer::startTimer(1);
292
 
1762 tk 293
    setSize(guiWidth, guiHeight);
877 tk 294
}
295
 
296
MiosStudio::~MiosStudio()
297
{
1759 tk 298
    if( uploadHandler )
299
        deleteAndZero(uploadHandler);
1189 tk 300
    if( sysexToolWindow )
301
        deleteAndZero(sysexToolWindow);
302
    if( oscToolWindow )
303
        deleteAndZero(oscToolWindow);
304
    if( midio128ToolWindow )
305
        deleteAndZero(midio128ToolWindow);
306
    if( mbCvToolWindow )
307
        deleteAndZero(mbCvToolWindow);
308
    if( mbhpMfToolWindow )
309
        deleteAndZero(mbhpMfToolWindow);
1502 tk 310
    if( sysexLibrarianWindow )
311
        deleteAndZero(sysexLibrarianWindow);
1542 tk 312
    if( miosFileBrowserWindow )
313
        deleteAndZero(miosFileBrowserWindow);
923 tk 314
 
315
    // try: avoid crash under Windows by disabling all MIDI INs/OUTs
937 tk 316
    closeMidiPorts();
877 tk 317
}
318
 
319
//==============================================================================
1762 tk 320
#ifdef _WIN32
321
// see http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=9868
322
 
323
// Code taken from here: http://dslweb.nwnexus.com/~ast/dload/guicon.htm
324
// Modified to support attaching to an owner console.
325
void MiosStudio::redirectIOToConsole()
326
{
327
    int hConHandle;
328
    long lStdHandle;
329
    FILE *fp;
330
    if (1) // TK: crashes the application: AttachConsole(ATTACH_PARENT_PROCESS) == 0)
331
    {
332
      // We couldn't obtain a parent console.  Probably application was launched 
333
      // from inside Explorer (E.G. the run prompt, or a shortcut).
334
      // We'll spawn a new console window instead then!
335
      CONSOLE_SCREEN_BUFFER_INFO coninfo;
336
      AllocConsole();
337
      GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
338
      coninfo.dwSize.Y = 500;
339
      SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
340
    }
341
    // redirect unbuffered STDOUT to the console
342
    lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
343
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
344
    fp = _fdopen( hConHandle, "w" );
345
    *stdout = *fp;
346
    setvbuf( stdout, NULL, _IONBF, 0 );
347
    // redirect unbuffered STDIN to the console
348
    lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
349
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
350
    fp = _fdopen( hConHandle, "r" );
351
    *stdin = *fp;
352
    setvbuf( stdin, NULL, _IONBF, 0 );
353
    // redirect unbuffered STDERR to the console
354
    lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
355
    hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
356
    fp = _fdopen( hConHandle, "w" );
357
    *stderr = *fp;
358
    setvbuf( stderr, NULL, _IONBF, 0 );
359
    // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
360
    // point to console as well
361
    std::ios::sync_with_stdio();
362
}
363
 
364
#else
365
 
366
// Empty function avoid ifdefs elsewhere.
367
void MiosStudio::redirectIOToConsole() {}
368
 
369
#endif
370
 
371
 
372
//==============================================================================
877 tk 373
void MiosStudio::paint (Graphics& g)
374
{
928 tk 375
    g.fillAll(Colour(0xffc1d0ff));
877 tk 376
}
377
 
378
void MiosStudio::resized()
379
{
1626 tk 380
    horizontalLayout.layOutComponents(layoutHComps.getRawDataPointer(), layoutHComps.size(),
877 tk 381
                                       4, 4,
382
                                       getWidth() - 8, getHeight() - 8,
383
                                       true,  // lay out above each other
384
                                       true); // resize the components' heights as well as widths
385
 
1626 tk 386
    if( layoutVComps.size() ) {
387
        verticalLayoutMonitors.layOutComponents(layoutVComps.getRawDataPointer(), layoutVComps.size(),
388
                                                4,
389
                                                4 + horizontalLayout.getItemCurrentPosition(0),
390
                                                getWidth() - 8,
391
                                                horizontalLayout.getItemCurrentAbsoluteSize(0),
392
                                                false, // lay out side-by-side
393
                                                true); // resize the components' heights as well as widths
394
    }
877 tk 395
 
927 tk 396
    resizer->setBounds(getWidth()-16, getHeight()-16, 16, 16);
877 tk 397
}
878 tk 398
 
399
 
400
//==============================================================================
1759 tk 401
bool MiosStudio::runningInBatchMode(void)
402
{
403
    return batchMode;
404
}
405
 
406
//==============================================================================
878 tk 407
void MiosStudio::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message)
408
{
1724 tk 409
    uint8 *data = (uint8 *)message.getRawData();
939 tk 410
    uint32 size = message.getRawDataSize();
411
 
878 tk 412
    // TK: the Juce specific "MidiBuffer" sporatically throws an assertion when overloaded
413
    // therefore I'm using a std::queue instead
414
 
891 tk 415
 
939 tk 416
    // ugly fix for reduced buffer size under windows...
417
    if( size > 2 && data[0] == 0xf0 && data[size-1] != 0xf7 ) {
418
        // first message without F7 at the end
419
        sysexReceiveBuffer.clear();
420
        for(int pos=0; pos<size; ++pos)
421
            sysexReceiveBuffer.add(data[pos]);
422
        return; // hopefully we will receive F7 with the next call
423
 
424
    } else if( sysexReceiveBuffer.size() && !(data[0] & 0x80) && data[size-1] != 0xf7 ) {
425
        // continued message without F7 at the end
426
        for(int pos=0; pos<size; ++pos)
427
            sysexReceiveBuffer.add(data[pos]);
428
        return; // hopefully we will receive F7 with the next call
429
 
430
    } else if( sysexReceiveBuffer.size() && data[size-1] == 0xf7 ) {
431
        // finally we received F7
940 tk 432
        for(int pos=0; pos<size; ++pos)
433
            sysexReceiveBuffer.add(data[pos]);
434
 
939 tk 435
        // propagate combined message
436
        uint8 *bufferedData = &sysexReceiveBuffer.getReference(0);        
437
        MidiMessage combinedMessage(bufferedData, sysexReceiveBuffer.size());
438
        sysexReceiveBuffer.clear();
439
 
440
        const ScopedLock sl(midiInQueueLock); // lock will be released at end of function
441
        midiInQueue.push(combinedMessage);
442
 
443
        // propagate to upload handler
444
        uploadHandler->handleIncomingMidiMessage(source, combinedMessage);
445
 
446
    } else {
447
        sysexReceiveBuffer.clear();
448
 
449
        const ScopedLock sl(midiInQueueLock); // lock will be released at end of function
450
        midiInQueue.push(message);
451
 
452
        // propagate to upload handler
453
        uploadHandler->handleIncomingMidiMessage(source, message);
454
    }
878 tk 455
}
456
 
457
 
458
//==============================================================================
928 tk 459
void MiosStudio::sendMidiMessage(MidiMessage &message)
891 tk 460
{
461
    MidiOutput *out = audioDeviceManager.getDefaultMidiOutput();
928 tk 462
 
463
    // if timestamp isn't set, to this now to ensure a plausible MIDI Out monitor output
464
    if( message.getTimeStamp() == 0 )
465
        message.setTimeStamp((double)Time::getMillisecondCounter() / 1000.0);
466
 
891 tk 467
    if( out )
468
        out->sendMessageNow(message);
469
 
928 tk 470
    const ScopedLock sl(midiOutQueueLock); // lock will be released at end of function
891 tk 471
    midiOutQueue.push(message);
472
}
473
 
474
 
475
//==============================================================================
937 tk 476
void MiosStudio::closeMidiPorts(void)
477
{
478
    const StringArray allMidiIns(MidiInput::getDevices());
479
    for (int i = allMidiIns.size(); --i >= 0;)
480
        audioDeviceManager.setMidiInputEnabled(allMidiIns[i], false);
481
 
482
    audioDeviceManager.setDefaultMidiOutput(String::empty);
483
}
484
 
485
 
486
//==============================================================================
878 tk 487
void MiosStudio::timerCallback()
488
{
917 tk 489
    // step-wise MIDI port scan after startup
490
    if( initialMidiScanCounter ) {
491
        switch( initialMidiScanCounter ) {
492
        case 1:
1759 tk 493
            Timer::stopTimer();
494
 
495
            midiInMonitor->scanMidiDevices(inPortFromCommandLine);
917 tk 496
            ++initialMidiScanCounter;
1759 tk 497
 
498
            Timer::startTimer(1);
917 tk 499
            break;
878 tk 500
 
917 tk 501
        case 2:
1759 tk 502
            Timer::stopTimer();
503
 
504
            midiOutMonitor->scanMidiDevices(outPortFromCommandLine);
917 tk 505
            ++initialMidiScanCounter;
1759 tk 506
 
507
            Timer::startTimer(1);
917 tk 508
            break;
878 tk 509
 
917 tk 510
        case 3:
1759 tk 511
            Timer::stopTimer();
512
 
1762 tk 513
            if( !runningInBatchMode() ) {
514
                // and check for infos
515
                if( commandLineInfoMessages.length() ) {
516
                    AlertWindow::showMessageBox(AlertWindow::InfoIcon,
517
                                                T("Info"),
518
                                                commandLineInfoMessages,
519
                                                String::empty);
520
                    commandLineInfoMessages = String::empty;
521
                }
1759 tk 522
 
1762 tk 523
                // now also check for command line errors
524
                if( commandLineErrorMessages.length() ) {
525
                    AlertWindow::showMessageBox(AlertWindow::WarningIcon,
526
                                                T("Command Line Error"),
527
                                                commandLineErrorMessages,
528
                                                String::empty);
529
                    commandLineErrorMessages = String::empty;
530
                }
1759 tk 531
            }
532
 
533
            // try to query selected core
917 tk 534
            audioDeviceManager.addMidiInputCallback(String::empty, this);
1759 tk 535
 
917 tk 536
            if( getMidiOutput() != String::empty )
537
                uploadWindow->queryCore();
878 tk 538
 
917 tk 539
            initialMidiScanCounter = 0; // stop scan
1759 tk 540
 
541
            Timer::startTimer(1);
917 tk 542
            break;
543
        }
544
    } else {
1050 tk 545
        // important: only broadcast 1..5 messages per timer tick to avoid GUI hangups when
917 tk 546
        // a large bulk of data is received
878 tk 547
 
1050 tk 548
        for(int checkLoop=0; checkLoop<5; ++checkLoop) {
549
            if( !midiInQueue.empty() ) {
550
                const ScopedLock sl(midiInQueueLock); // lock will be released at end of this scope
928 tk 551
 
1050 tk 552
                MidiMessage &message = midiInQueue.front();
917 tk 553
 
1724 tk 554
                uint8 *data = (uint8 *)message.getRawData();
1050 tk 555
                if( data[0] >= 0x80 && data[0] < 0xf8 )
556
                    runningStatus = data[0];
917 tk 557
 
1050 tk 558
                // propagate incoming event to MIDI components
559
                midiInMonitor->handleIncomingMidiMessage(message, runningStatus);
917 tk 560
 
1050 tk 561
                // filter runtime events for following components to improve performance
562
                if( data[0] < 0xf8 ) {
1189 tk 563
                    if( sysexToolWindow )
564
                        sysexToolWindow->handleIncomingMidiMessage(message, runningStatus);
565
                    if( midio128ToolWindow )
566
                        midio128ToolWindow->handleIncomingMidiMessage(message, runningStatus);
567
                    if( mbCvToolWindow )
568
                        mbCvToolWindow->handleIncomingMidiMessage(message, runningStatus);
569
                    if( mbhpMfToolWindow )
570
                        mbhpMfToolWindow->handleIncomingMidiMessage(message, runningStatus);
1502 tk 571
                    if( sysexLibrarianWindow )
572
                        sysexLibrarianWindow->handleIncomingMidiMessage(message, runningStatus);
1759 tk 573
                    if( miosFileBrowserWindow ) {
1542 tk 574
                        miosFileBrowserWindow->handleIncomingMidiMessage(message, runningStatus);
1759 tk 575
                    }
1050 tk 576
                    miosTerminal->handleIncomingMidiMessage(message, runningStatus);
577
                    midiKeyboard->handleIncomingMidiMessage(message, runningStatus);
578
                }
579
 
580
                midiInQueue.pop();
917 tk 581
            }
582
 
1050 tk 583
            if( !midiOutQueue.empty() ) {
584
                const ScopedLock sl(midiOutQueueLock); // lock will be released at end of this scope
878 tk 585
 
1050 tk 586
                MidiMessage &message = midiOutQueue.front();
928 tk 587
 
1050 tk 588
                midiOutMonitor->handleIncomingMidiMessage(message, message.getRawData()[0]);
878 tk 589
 
1050 tk 590
                midiOutQueue.pop();
591
            }
917 tk 592
        }
1759 tk 593
 
594
        if( batchJobs.size() ) {
595
            if( batchWaitCounter ) {
596
                --batchWaitCounter;
597
            } else if( uploadWindow->uploadInProgress() ||
598
                       (sysexToolWindow && sysexToolWindow->sendSyxInProgress()) ||
599
                       (miosFileBrowserWindow && miosFileBrowserWindow->uploadFileInProgress()) ) {
600
                // wait...
601
            } else {
602
                String job(batchJobs[0]);
603
                batchJobs.remove(0);
604
 
605
                if( job.startsWithIgnoreCase("device_id ") ) {
606
                    int id = job.substring(10).getIntValue();
607
                    if( id < 0 || id > 127 ) {
608
                        std::cerr << "ERROR: device ID should be within 0..127!" << std::endl;
609
                    } else {
610
                        std::cout << "Setting Device ID=" << id << std::endl;
611
                        uploadWindow->setDeviceId(id);
612
                    }
613
                } else if( job.startsWithIgnoreCase("query") ) {
614
                    std::cout << "Query Core..." << std::endl;
615
                    uploadWindow->queryFromExternal();
616
                } else if( job.startsWithIgnoreCase("upload_hex ") ) {
617
                    String filename = job.substring(11);
618
 
619
                    std::cout << "Uploading " << filename << "..." << std::endl;
620
                    uploadWindow->uploadFileFromExternal(filename);
621
                } else if( job.startsWithIgnoreCase("upload_file ") ) {
622
                    String filename = job.substring(12);
623
 
624
                    std::cout << "Uploading " << filename << "..." << std::endl;
625
                    if( !miosFileBrowserWindow ) {
626
                        miosFileBrowserWindow = new MiosFileBrowserWindow(this);
627
                        if( !runningInBatchMode() ) {
628
                            miosFileBrowserWindow->setVisible(true);
629
                        }
630
                    }
631
                    miosFileBrowserWindow->uploadFileFromExternal(filename);
632
                } else if( job.startsWithIgnoreCase("send_syx ") ) {
633
                    String filename = job.substring(9);
634
 
635
                    std::cout << "Sending SysEx " << filename << "..." << std::endl;
636
                    if( !sysexToolWindow ) {
637
                        sysexToolWindow = new SysexToolWindow(this);
638
                        if( !runningInBatchMode() ) {
639
                            sysexToolWindow->setVisible(true);
640
                        }
641
                    }
642
                    sysexToolWindow->sendSyxFile(filename);
643
                } else if( job.startsWithIgnoreCase("terminal ") ) {
644
                    String command = job.substring(9);
645
 
646
                    std::cout << "MIOS Terminal command: " << command << std::endl;
647
                    miosTerminal->execCommand(command);
648
                } else if( job.startsWithIgnoreCase("wait ") ) {
649
                    int counter = job.substring(5).getIntValue();
650
                    if( counter < 0 ) {
651
                        counter = 0;
652
                    }
653
                    std::cout << "Waiting for " << counter << " second" << ((counter == 1) ? "" : "s") << "..." << std::endl;
654
                    batchWaitCounter = counter*1000;
655
                } else if( job.startsWithIgnoreCase("quit") ) {
656
                    if( runningInBatchMode() ) {
1762 tk 657
#ifdef _WIN32
658
                        std::cout << "Press <enter> to quit console." << std::endl;
659
                        while (GetAsyncKeyState(VK_RETURN) & 0x8000) {}
660
                        while (!(GetAsyncKeyState(VK_RETURN) & 0x8000)) {}
661
#endif
1759 tk 662
                        JUCEApplication::getInstance()->setApplicationReturnValue(0); // no error
663
                        JUCEApplication::quit();
664
                    } else {
665
                        AlertWindow::showMessageBox(AlertWindow::InfoIcon,
666
                                                    T("Info"),
667
                                                    T("All batch jobs executed."),
668
                                                    String::empty);
669
                    }
670
                } else {
671
                    std::cerr << "ERROR: unknown batch job: '" << job << "'!" << std::endl;
672
                }
673
            }
674
        }
894 tk 675
    }
878 tk 676
}
677
 
678
 
679
//==============================================================================
680
void MiosStudio::setMidiInput(const String &port)
681
{
682
    const StringArray allMidiIns(MidiInput::getDevices());
683
    for (int i = allMidiIns.size(); --i >= 0;) {
684
        bool enabled = allMidiIns[i] == port;
685
        audioDeviceManager.setMidiInputEnabled(allMidiIns[i], enabled);
686
    }
687
 
688
    // propagate port change
928 tk 689
    if( uploadWindow && initialMidiScanCounter == 0 && port != String::empty )
908 tk 690
        uploadWindow->midiPortChanged();
691
 
1595 tk 692
    // store setting if MIDI input selected
693
    if( port != String::empty ) {
1724 tk 694
        PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
1595 tk 695
        if( propertiesFile )
696
            propertiesFile->setValue(T("midiIn"), port);
697
    }
878 tk 698
}
699
 
908 tk 700
String MiosStudio::getMidiInput(void)
701
{
917 tk 702
    // restore setting
1724 tk 703
    PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
917 tk 704
    return propertiesFile ? propertiesFile->getValue(T("midiIn"), String::empty) : String::empty;
908 tk 705
}
706
 
878 tk 707
void MiosStudio::setMidiOutput(const String &port)
708
{
709
    audioDeviceManager.setDefaultMidiOutput(port);
710
 
711
    // propagate port change
928 tk 712
    if( uploadWindow && initialMidiScanCounter == 0 && port != String::empty )
908 tk 713
        uploadWindow->midiPortChanged();
714
 
1595 tk 715
    // store setting if MIDI output selected
716
    if( port != String::empty ) {
1724 tk 717
        PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
1595 tk 718
        if( propertiesFile )
719
            propertiesFile->setValue(T("midiOut"), port);
720
    }
878 tk 721
}
722
 
908 tk 723
String MiosStudio::getMidiOutput(void)
724
{
917 tk 725
    // restore setting
1724 tk 726
    PropertiesFile *propertiesFile = MiosStudioProperties::getInstance()->getCommonSettings(true);
917 tk 727
    return propertiesFile ? propertiesFile->getValue(T("midiOut"), String::empty) : String::empty;
908 tk 728
}
937 tk 729
 
730
 
731
 
732
 
733
//==============================================================================
1724 tk 734
StringArray MiosStudio::getMenuBarNames()
937 tk 735
{
1724 tk 736
    const char* const names[] = { "Application", "Tools", "Help", 0 };
937 tk 737
 
1724 tk 738
    return StringArray ((const char**) names);
937 tk 739
}
740
 
1724 tk 741
PopupMenu MiosStudio::getMenuForIndex(int topLevelMenuIndex, const String& menuName)
937 tk 742
{
743
    PopupMenu menu;
744
 
745
    if( topLevelMenuIndex == 0 ) {
746
        // "Application" menu
1626 tk 747
        menu.addCommandItem(commandManager, enableMonitors);
748
        menu.addCommandItem(commandManager, enableUpload);
749
        menu.addCommandItem(commandManager, enableTerminal);
750
        menu.addCommandItem(commandManager, enableKeyboard);
751
        menu.addSeparator();
937 tk 752
        menu.addCommandItem(commandManager, rescanDevices);
753
        menu.addSeparator();
754
        menu.addCommandItem(commandManager, StandardApplicationCommandIDs::quit);
755
    } else if( topLevelMenuIndex == 1 ) {
756
        // "Tools" menu
757
        menu.addCommandItem(commandManager, showSysexTool);
1502 tk 758
        menu.addCommandItem(commandManager, showSysexLibrarian);
1003 tk 759
        menu.addCommandItem(commandManager, showOscTool);
937 tk 760
        menu.addCommandItem(commandManager, showMidio128Tool);
761
        menu.addCommandItem(commandManager, showMbCvTool);
1131 tk 762
        menu.addCommandItem(commandManager, showMbhpMfTool);
1542 tk 763
        menu.addCommandItem(commandManager, showMiosFileBrowser);
937 tk 764
    } else if( topLevelMenuIndex == 2 ) {
765
        // "Help" menu
766
        menu.addCommandItem(commandManager, showMiosStudioPage);
767
        menu.addCommandItem(commandManager, showTroubleshootingPage);
768
    }
769
 
770
    return menu;
771
}
772
 
773
void MiosStudio::menuItemSelected(int menuItemID, int topLevelMenuIndex)
774
{
775
}
776
 
777
 
778
//==============================================================================
779
// The following methods implement the ApplicationCommandTarget interface, allowing
780
// this window to publish a set of actions it can perform, and which can be mapped
781
// onto menus, keypresses, etc.
782
 
783
ApplicationCommandTarget* MiosStudio::getNextCommandTarget()
784
{
785
    // this will return the next parent component that is an ApplicationCommandTarget (in this
786
    // case, there probably isn't one, but it's best to use this method in your own apps).
787
    return findFirstTargetParentComponent();
788
}
789
 
790
void MiosStudio::getAllCommands(Array <CommandID>& commands)
791
{
792
    // this returns the set of all commands that this target can perform..
793
    const CommandID ids[] = { showSysexTool,
1003 tk 794
                              showOscTool,
937 tk 795
                              showMidio128Tool,
796
                              showMbCvTool,
1131 tk 797
                              showMbhpMfTool,
1502 tk 798
                              showSysexLibrarian,
1542 tk 799
                              showMiosFileBrowser,
1626 tk 800
                              enableMonitors,
801
                              enableUpload,
802
                              enableTerminal,
803
                              enableKeyboard,
937 tk 804
                              rescanDevices,
805
                              showMiosStudioPage,
806
                              showTroubleshootingPage
807
    };
808
 
809
    commands.addArray (ids, numElementsInArray (ids));
810
}
811
 
812
// This method is used when something needs to find out the details about one of the commands
813
// that this object can perform..
814
void MiosStudio::getCommandInfo(const CommandID commandID, ApplicationCommandInfo& result)
815
{
816
    const String applicationCategory (T("Application"));
817
    const String toolsCategory(T("Tools"));
818
    const String helpCategory (T("Help"));
819
 
820
    switch( commandID ) {
1626 tk 821
    case enableMonitors:
822
        result.setInfo(T("Show MIDI Monitors"), T("Enables/disables the MIDI IN/OUT Monitors"), applicationCategory, 0);
823
        result.setTicked(verticalDividerBarMonitors->isVisible());
1724 tk 824
        result.addDefaultKeypress('M', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1626 tk 825
        break;
826
 
827
    case enableUpload:
828
        result.setInfo(T("Show Upload Window"), T("Enables/disables the Upload Window"), applicationCategory, 0);
829
        result.setTicked(uploadWindow->isVisible());
1724 tk 830
        result.addDefaultKeypress('U', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1626 tk 831
        break;
832
 
833
    case enableTerminal:
834
        result.setInfo(T("Show MIOS Terminal"), T("Enables/disables the MIOS Terminal"), applicationCategory, 0);
835
        result.setTicked(miosTerminal->isVisible());
1724 tk 836
        result.addDefaultKeypress('T', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1626 tk 837
        break;
838
 
839
    case enableKeyboard:
840
        result.setInfo(T("Show Virtual Keyboard"), T("Enables/disables the virtual Keyboard"), applicationCategory, 0);
841
        result.setTicked(midiKeyboard->isVisible());
1724 tk 842
        result.addDefaultKeypress('K', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1626 tk 843
        break;
844
 
937 tk 845
    case rescanDevices:
846
        result.setInfo(T("Rescan MIDI Devices"), T("Updates the MIDI In/Out port lists"), applicationCategory, 0);
1724 tk 847
        result.addDefaultKeypress('R', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 848
        break;
849
 
850
    case showSysexTool:
851
        result.setInfo(T("SysEx Tool"), T("Allows to send and receive SysEx dumps"), toolsCategory, 0);
1189 tk 852
        result.setTicked(sysexToolWindow && sysexToolWindow->isVisible());
1724 tk 853
        result.addDefaultKeypress('1', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 854
        break;
855
 
1542 tk 856
    case showSysexLibrarian:
857
        result.setInfo(T("SysEx Librarian"), T("Allows to manage SysEx files"), toolsCategory, 0);
858
        result.setTicked(sysexLibrarianWindow && sysexLibrarianWindow->isVisible());
1724 tk 859
        result.addDefaultKeypress('2', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1542 tk 860
        break;
861
 
1003 tk 862
    case showOscTool:
863
        result.setInfo(T("OSC Tool"), T("Allows to send and receive OSC messages"), toolsCategory, 0);
1189 tk 864
        result.setTicked(oscToolWindow && oscToolWindow->isVisible());
1724 tk 865
        result.addDefaultKeypress('3', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1003 tk 866
        break;
867
 
937 tk 868
    case showMidio128Tool:
1463 tk 869
        result.setInfo(T("MIDIO128 V2 Tool"), T("Allows to configure a MIDIO128 V2"), toolsCategory, 0);
1189 tk 870
        result.setTicked(midio128ToolWindow && midio128ToolWindow->isVisible());
1724 tk 871
        result.addDefaultKeypress('4', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 872
        break;
873
 
874
    case showMbCvTool:
1463 tk 875
        result.setInfo(T("MIDIbox CV V1 Tool"), T("Allows to configure a MIDIbox CV V1"), toolsCategory, 0);
1189 tk 876
        result.setTicked(mbCvToolWindow && mbCvToolWindow->isVisible());
1724 tk 877
        result.addDefaultKeypress('5', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 878
        break;
879
 
1131 tk 880
    case showMbhpMfTool:
1463 tk 881
        result.setInfo(T("MBHP_MF_NG Tool"), T("Allows to configure the MBHP_MF_NG firmware"), toolsCategory, 0);
1189 tk 882
        result.setTicked(mbhpMfToolWindow && mbhpMfToolWindow->isVisible());
1724 tk 883
        result.addDefaultKeypress('6', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1131 tk 884
        break;
885
 
1542 tk 886
    case showMiosFileBrowser:
887
        result.setInfo(T("MIOS32 File Browser"), T("Allows to send and receive files to/from MIOS32 applications"), toolsCategory, 0);
888
        result.setTicked(miosFileBrowserWindow && miosFileBrowserWindow->isVisible());
1724 tk 889
        result.addDefaultKeypress('7', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
1502 tk 890
        break;
891
 
937 tk 892
    case showMiosStudioPage:
893
        result.setInfo(T("MIOS Studio Page (Web)"), T("Opens the MIOS Studio page on uCApps.de"), helpCategory, 0);
1724 tk 894
        result.addDefaultKeypress ('H', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 895
        break;
896
 
897
    case showTroubleshootingPage:
898
        result.setInfo(T("MIDI Troubleshooting Page (Web)"), T("Opens the MIDI Troubleshooting page on uCApps.de"), helpCategory, 0);
1724 tk 899
        result.addDefaultKeypress ('I', ModifierKeys::commandModifier|ModifierKeys::shiftModifier);
937 tk 900
        break;
901
    }
902
}
903
 
904
// this is the ApplicationCommandTarget method that is used to actually perform one of our commands..
905
bool MiosStudio::perform(const InvocationInfo& info)
906
{
907
    switch( info.commandID ) {
1626 tk 908
    case enableMonitors:
909
        if( verticalDividerBarMonitors->isVisible() ) {
910
            midiInMonitor->setVisible(false);
911
            verticalDividerBarMonitors->setVisible(false);
912
            midiOutMonitor->setVisible(false);
913
        } else {
914
            midiInMonitor->setVisible(true);
915
            verticalDividerBarMonitors->setVisible(true);
916
            midiOutMonitor->setVisible(true);
917
        }
918
        updateLayout();
919
        break;
920
 
921
    case enableUpload:        
922
        if( horizontalDividerBar1->isVisible() ) {
923
            horizontalDividerBar1->setVisible(false);
924
            uploadWindow->setVisible(false);
925
        } else {
926
            horizontalDividerBar1->setVisible(true);
927
            uploadWindow->setVisible(true);
928
        }
929
        updateLayout();
930
        break;
931
 
932
    case enableTerminal:
933
        if( horizontalDividerBar2->isVisible() ) {
934
            horizontalDividerBar2->setVisible(false);
935
            miosTerminal->setVisible(false);
936
        } else {
937
            horizontalDividerBar2->setVisible(true);
938
            miosTerminal->setVisible(true);
939
        }
940
        updateLayout();
941
        break;
942
 
943
    case enableKeyboard:
944
        if( horizontalDividerBar3->isVisible() ) {
945
            horizontalDividerBar3->setVisible(false);
946
            midiKeyboard->setVisible(false);
947
        } else {
948
            horizontalDividerBar3->setVisible(true);
949
            midiKeyboard->setVisible(true);
950
        }
951
        updateLayout();
952
        break;
953
 
937 tk 954
    case rescanDevices:
1555 tk 955
        // TK: doesn't always work, therefore some warnings ;-)
2180 tk 956
        if( !duggleMode && AlertWindow::showOkCancelBox(AlertWindow::WarningIcon,
1555 tk 957
                                         T("Rescan MIDI Devices"),
958
                                         T("Please note that the rescan function\nmostly doesn't work properly!\nIt's better to restart MIOS Studio!\n"),
959
                                         T("I've no idea what this means"),
960
                                         T("Understood")) ) {
961
            if( AlertWindow::showOkCancelBox(AlertWindow::WarningIcon,
962
                                             T("Rescan MIDI Devices"),
963
                                             T("This means that it's better to quit MIOS Studio now, and open it again!\n"),
964
                                             T("I've still no idea what this means"),
965
                                             T("Understood")) ) {
966
                AlertWindow::showOkCancelBox(AlertWindow::WarningIcon,
967
                                             T("Rescan MIDI Devices"),
968
                                             T("Switched to Newbie Mode:\n"),
969
                                             T("Quit"),
970
                                             T("Quit"));
971
                // ;-)
972
                JUCEApplication::quit();
973
            }
974
        }
975
 
937 tk 976
        closeMidiPorts();
977
        initialMidiScanCounter = 1;
978
        break;
979
 
980
    case showSysexTool:
1189 tk 981
        if( !sysexToolWindow )
982
            sysexToolWindow = new SysexToolWindow(this);
937 tk 983
        sysexToolWindow->setVisible(true);
984
        sysexToolWindow->toFront(true);
985
        break;
986
 
1003 tk 987
    case showOscTool:
1189 tk 988
        if( !oscToolWindow )
989
            oscToolWindow = new OscToolWindow(this);
1003 tk 990
        oscToolWindow->setVisible(true);
991
        oscToolWindow->toFront(true);
992
        break;
993
 
937 tk 994
    case showMidio128Tool:
1189 tk 995
        if( !midio128ToolWindow )
996
            midio128ToolWindow = new Midio128ToolWindow(this);
937 tk 997
        midio128ToolWindow->setVisible(true);
998
        midio128ToolWindow->toFront(true);
999
        break;
1000
 
1001
    case showMbCvTool:
1189 tk 1002
        if( !mbCvToolWindow )
1003
            mbCvToolWindow = new MbCvToolWindow(this);
937 tk 1004
        mbCvToolWindow->setVisible(true);
1005
        mbCvToolWindow->toFront(true);
1006
        break;
1007
 
1131 tk 1008
    case showMbhpMfTool:
1189 tk 1009
        if( !mbhpMfToolWindow )
1010
            mbhpMfToolWindow = new MbhpMfToolWindow(this);
1131 tk 1011
        mbhpMfToolWindow->setVisible(true);
1012
        mbhpMfToolWindow->toFront(true);
1013
        break;
1014
 
1502 tk 1015
    case showSysexLibrarian:
1016
        if( !sysexLibrarianWindow )
1017
            sysexLibrarianWindow = new SysexLibrarianWindow(this);
1018
        sysexLibrarianWindow->setVisible(true);
1019
        sysexLibrarianWindow->toFront(true);
1020
        break;
1021
 
1542 tk 1022
    case showMiosFileBrowser:
1023
        if( !miosFileBrowserWindow )
1024
            miosFileBrowserWindow = new MiosFileBrowserWindow(this);
1025
        miosFileBrowserWindow->setVisible(true);
1026
        miosFileBrowserWindow->toFront(true);
1027
        break;
1028
 
937 tk 1029
    case showMiosStudioPage: {
1030
        URL webpage(T("http://www.uCApps.de/mios_studio.html"));
1031
        webpage.launchInDefaultBrowser();
1032
    }  break;
1033
 
1034
    case showTroubleshootingPage: {
1035
        URL webpage(T("http://www.uCApps.de/howto_debug_midi.html"));
1036
        webpage.launchInDefaultBrowser();
1037
    } break;
1038
    default:
1039
        return false;
1040
    }
1041
 
1042
    return true;
1043
};
1626 tk 1044
 
1045
 
1046
void MiosStudio::updateLayout(void)
1047
{
1048
    ////////////////////////////////////////////////////////////////////////////////////////////////
1049
    layoutHComps.clear();
1050
    horizontalLayout.clearAllItems();
1051
 
1052
    int itemIx = 0;
1053
    if( verticalDividerBarMonitors->isVisible() ) {
1054
        horizontalLayout.setItemLayout(itemIx++,    50,   -1, -1); // MIDI In/Out Monitors
1055
        layoutHComps.add(0);
1056
    }
1057
 
1058
    if( uploadWindow->isVisible() ) {
1059
        if( itemIx ) {
1060
            horizontalLayout.setItemLayout(itemIx++,    8,      8,     8); // Resizer
1061
            layoutHComps.add(horizontalDividerBar1);
1062
        }
1063
 
1064
        horizontalLayout.setItemLayout(itemIx++,   186,    186,  186); // Upload Window
1065
        layoutHComps.add(uploadWindow);
1066
    }
1067
 
1068
    if( miosTerminal->isVisible() ) {
1069
        if( itemIx ) {
1070
            horizontalLayout.setItemLayout(itemIx++,    8,      8,     8); // Resizer
1071
            layoutHComps.add(horizontalDividerBar2);
1072
        }
1073
 
1074
        horizontalLayout.setItemLayout(itemIx++,   50,   -1, -1); // MIOS Terminal
1075
        layoutHComps.add(miosTerminal);
1076
 
1077
    }
1078
 
1079
    if( midiKeyboard->isVisible() ) {
1080
        if( itemIx ) {
1081
            horizontalLayout.setItemLayout(itemIx++,    8,      8,     8); // Resizer
1082
            layoutHComps.add(horizontalDividerBar3);
1083
        }
1084
 
1085
        horizontalLayout.setItemLayout(itemIx++,   124,    124,  124); // MIDI Keyboard
1086
        layoutHComps.add(midiKeyboard);
1087
    }
1088
 
1089
    // dummy to ensure that MIDI keyboard or upload window is displayed with right size if all other components invisible
1090
    horizontalLayout.setItemLayout(itemIx++,   0, 0, 0);
1091
    layoutHComps.add(0);
1092
 
1093
    ////////////////////////////////////////////////////////////////////////////////////////////////
1094
    layoutVComps.clear();
1095
    verticalLayoutMonitors.clearAllItems();
1096
    if( verticalDividerBarMonitors->isVisible() ) {
1097
        //                                   num  min   max   prefered  
1098
        verticalLayoutMonitors.setItemLayout(0, -0.2, -0.8, -0.5); // MIDI In Monitor
1099
        layoutVComps.add(midiInMonitor);
1100
 
1101
        verticalLayoutMonitors.setItemLayout(1,    8,    8,    8); // resizer
1102
        layoutVComps.add(verticalDividerBarMonitors);
1103
 
1104
        verticalLayoutMonitors.setItemLayout(2, -0.2, -0.8, -0.5); // MIDI Out Monitor
1105
        layoutVComps.add(midiOutMonitor);
1106
    }
1107
 
1108
 
1109
    ////////////////////////////////////////////////////////////////////////////////////////////////
1110
    resized();
1111
}
1112