Subversion Repositories svn.mios32

Rev

Rev 1190 | Rev 1465 | Go to most recent revision | 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: MidiMonitor.cpp 1463 2012-04-10 19:35:42Z 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 "MidiMonitor.h"
878 tk 16
#include "MiosStudio.h"
877 tk 17
 
18
 
19
//==============================================================================
878 tk 20
MidiMonitor::MidiMonitor(MiosStudio *_miosStudio, const bool _inPort)
21
    : miosStudio(_miosStudio)
877 tk 22
    , inPort(_inPort)
878 tk 23
    , filterMidiClock(1)
24
    , filterActiveSense(1)
25
    , filterMiosTerminalMessage(1)
886 tk 26
    , cutLongMessages(1)
877 tk 27
{
28
    addAndMakeVisible(midiPortSelector = new ComboBox(String::empty));
29
    midiPortSelector->addListener(this);
30
    midiPortSelector->clear();
917 tk 31
    midiPortSelector->addItem (TRANS("<< device scan running >>"), -1);
32
    midiPortSelector->setSelectedId(-1, true);
33
    midiPortSelector->setEnabled(false);
34
    midiPortLabel = new Label("", inPort ? T("MIDI IN: ") : T("MIDI OUT: "));
35
    midiPortLabel->attachToComponent(midiPortSelector, true);
36
 
37
    addAndMakeVisible(monitorLogBox = new LogBox(T("Midi Monitor")));
920 tk 38
    monitorLogBox->addEntry(Colours::red, T("Connecting to MIDI driver - be patient!"));
917 tk 39
 
40
    setSize(400, 200);
41
}
42
 
43
MidiMonitor::~MidiMonitor()
44
{
45
}
46
 
47
//==============================================================================
48
// Should be called after startup once window is visible
49
void MidiMonitor::scanMidiDevices()
50
{
51
    monitorLogBox->clear();
52
 
53
    midiPortSelector->setEnabled(false);
54
    midiPortSelector->clear();
877 tk 55
    midiPortSelector->addItem (TRANS("<< none >>"), -1);
56
    midiPortSelector->addSeparator();
57
 
917 tk 58
    // restore settings
59
    String selectedPort;
60
    StringArray midiPorts;
61
    if( inPort ) {
920 tk 62
        monitorLogBox->addEntry(Colours::red, T("Scanning for MIDI Inputs..."));
917 tk 63
        selectedPort = miosStudio->getMidiInput();
64
        midiPorts = MidiInput::getDevices();
65
    } else {
920 tk 66
        monitorLogBox->addEntry(Colours::red, T("Scanning for MIDI Outputs..."));
917 tk 67
        selectedPort = miosStudio->getMidiOutput();
68
        midiPorts = MidiOutput::getDevices();
69
    }
70
 
877 tk 71
    int current = -1;
908 tk 72
    for(int i=0; i<midiPorts.size(); ++i) {
73
        midiPortSelector->addItem(midiPorts[i], i+1);
917 tk 74
        bool enabled = midiPorts[i] == selectedPort;
877 tk 75
 
76
        if( enabled )
77
            current = i + 1;
917 tk 78
 
920 tk 79
        monitorLogBox->addEntry(Colours::blue, "[" + String(i+1) + "] " + midiPorts[i] + (enabled ? " (*)" : ""));
917 tk 80
 
81
        if( inPort )
82
            miosStudio->audioDeviceManager.setMidiInputEnabled(midiPorts[i], enabled);
83
        else if( enabled )
84
            miosStudio->audioDeviceManager.setDefaultMidiOutput(midiPorts[i]);
877 tk 85
    }
86
    midiPortSelector->setSelectedId(current, true);
917 tk 87
    midiPortSelector->setEnabled(true);
877 tk 88
 
917 tk 89
    if( current == -1 )
90
        if( inPort )
91
            miosStudio->setMidiInput(String::empty);
92
        else
93
            miosStudio->setMidiOutput(String::empty);
877 tk 94
 
920 tk 95
    monitorLogBox->addEntry(Colours::grey, T("MIDI Monitor ready."));
877 tk 96
}
97
 
98
//==============================================================================
99
void MidiMonitor::paint (Graphics& g)
100
{
101
    g.fillAll(Colours::white);
102
}
103
 
104
void MidiMonitor::resized()
105
{
1033 tk 106
    midiPortLabel->setBounds(4, 4, 60, 22);
107
    midiPortSelector->setBounds(4+60, 4, getWidth()-8-60, 22);
894 tk 108
    monitorLogBox->setBounds(4, 4+22+4, getWidth()-8, getHeight()-(4+22+4+4));
877 tk 109
}
110
 
111
 
112
//==============================================================================
113
void MidiMonitor::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
114
{
115
    if( comboBoxThatHasChanged == midiPortSelector ) {
917 tk 116
        String portName = midiPortSelector->getText();
117
        if( portName == T("<< none >>") )
118
            portName = String::empty;
119
 
878 tk 120
        if( inPort )
917 tk 121
            miosStudio->setMidiInput(portName);
878 tk 122
        else
917 tk 123
            miosStudio->setMidiOutput(portName);
877 tk 124
    }
125
}
126
 
1463 tk 127
 
877 tk 128
//==============================================================================
1463 tk 129
char* MidiMonitor::getNoteString(uint8 note, char* strBuffer)
130
{
131
    const char note_tab[12][3] = { "c-", "c#", "d-", "d#", "e-", "f-", "f#", "g-", "g#", "a-", "a#", "b-" };
132
 
133
    // print "---" if note number is 0
134
    if( note == 0 ) {
135
        strBuffer[0] = '-';
136
        strBuffer[1] = '-';
137
        strBuffer[2] = '-';
138
    } else {
139
        // determine octave, note contains semitone number thereafter
140
        uint8 octave = note / 12;
141
        note %= 12;
142
 
143
        // semitone (capital letter if octave >= 2)
144
        strBuffer[0] = octave >= 2 ? (note_tab[note][0] + 'A'-'a') : note_tab[note][0];
145
        strBuffer[1] = note_tab[note][1];
146
 
147
        // octave
148
        switch( octave ) {
149
            case 0:  strBuffer[2] = '2'; break; // -2
150
            case 1:  strBuffer[2] = '1'; break; // -1
151
            default: strBuffer[2] = '0' + (octave-2); // 0..7
152
        }
153
    }
154
    strBuffer[3] = 0;
155
 
156
    return strBuffer;
157
}
158
 
159
//==============================================================================
878 tk 160
void MidiMonitor::handleIncomingMidiMessage(const MidiMessage& message, uint8 runningStatus)
877 tk 161
{
886 tk 162
    uint32 size = message.getRawDataSize();
878 tk 163
    uint8 *data = message.getRawData();
877 tk 164
 
878 tk 165
    bool isMidiClock = data[0] == 0xf8;
166
    bool isActiveSense = data[0] == 0xfe;
886 tk 167
    bool isMiosTerminalMessage = SysexHelper::isValidMios32DebugMessage(data, size, -1);
878 tk 168
 
169
    if( !(isMidiClock && filterMidiClock) &&
170
        !(isActiveSense && filterActiveSense) &&
171
        !(isMiosTerminalMessage && filterMiosTerminalMessage) ) {
172
 
912 tk 173
        double timeStamp = message.getTimeStamp() ? message.getTimeStamp() : ((double)Time::getMillisecondCounter() / 1000.0);
878 tk 174
        String timeStampStr = (timeStamp > 0)
175
            ? String::formatted(T("%8.3f"), timeStamp)
176
            : T("now");
177
 
908 tk 178
        String hexStr = String::toHexString(data, size);
179
 
1463 tk 180
        String descStr;
181
        char strBuffer[4];
182
        switch( data[0] & 0xf0 ) {
183
            case 0x80:
184
                descStr = String::formatted(T("   Chn#%2d  Note Off %s  Vel:%d"),
185
                                            (data[0] & 0x0f) + 1,
186
                                            getNoteString(data[1], strBuffer),
187
                                            data[2]);
188
                break;
189
 
190
            case 0x90:
191
                if( data[2] == 0 ) {
192
                    descStr = String::formatted(T("   Chn#%2d  Note Off %s (optimized)"),
193
                                                (data[0] & 0x0f) + 1,
194
                                                getNoteString(data[1], strBuffer),
195
                                                data[2]);
196
                } else {
197
                    descStr = String::formatted(T("   Chn#%2d  Note On  %s  Vel:%d"),
198
                                                (data[0] & 0x0f) + 1,
199
                                                getNoteString(data[1], strBuffer),
200
                                                data[2]);
201
                }
202
                break;
203
 
204
            case 0xa0:
205
                descStr = String::formatted(T("   Chn#%2d  Aftertouch %s %d"),
206
                                            (data[0] & 0x0f) + 1,
207
                                            getNoteString(data[1], strBuffer),
208
                                            data[2]);
209
                break;
210
 
211
            case 0xb0:
212
                descStr = String::formatted(T("   Chn#%2d  CC#%3d = %d"),
213
                                            (data[0] & 0x0f) + 1,
214
                                            data[1],
215
                                            data[2]);
216
                break;
217
 
218
            case 0xc0:
219
                descStr = String::formatted(T("   Chn#%2d  Program Change %d"),
220
                                            (data[0] & 0x0f) + 1,
221
                                            data[1]);
222
                break;
223
 
224
            case 0xd0:
225
                descStr = String::formatted(T("   Chn#%2d  Aftertouch %s"),
226
                                            (data[0] & 0x0f) + 1,
227
                                            getNoteString(data[1], strBuffer));
228
                break;
229
 
230
            case 0xe0:
231
                descStr = String::formatted(T("   Chn#%2d  Pitchbend %d"),
232
                                            (data[0] & 0x0f) + 1,
233
                                            (int)((data[1] & 0x7f) | ((data[2] & 0x7f) << 7)) - 8192);
234
                break;
235
 
236
            default:
237
                descStr = String::formatted(T("")); // nothing to add here
238
        }
239
 
240
        monitorLogBox->addEntry(Colours::black, "[" + timeStampStr + "] " + hexStr + descStr);
878 tk 241
    }
877 tk 242
}