~ubuntu-branches/ubuntu/vivid/aeolus/vivid

« back to all changes in this revision

Viewing changes to source/imidi-osx.cc

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2010-04-19 19:12:51 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100419191251-hgarjfcdfl7c0ryl
Tags: 0.8.4-3
debian/patches/01-makefile.patch: Drop -march=native flag, it isn't valid
for Debian packages as the results are unpredictable, thanks to
Bastian Blank for reporting this (Closes: #578278).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2008 Hans Fugal <hans@fugal.net>
 
3
    
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
*/
 
18
 
 
19
/* OS X CoreMIDI version of Imidi. Might be cleaner to do some kind of
 
20
 * inheritance, but for now this will do. Makefile.osx doesn't build imidi.cc
 
21
 * but rather this file, and vice versa for the normal Linux Makefile.
 
22
 */
 
23
 
 
24
 
 
25
#include "imidi.h"
 
26
 
 
27
 
 
28
Imidi::Imidi (Lfq_u32 *qnote, Lfq_u8 *qmidi, uint16_t *midimap, const char *appname) : 
 
29
    A_thread ("Imidi"),
 
30
    _qnote (qnote),
 
31
    _qmidi (qmidi),
 
32
    _midimap (midimap),
 
33
    _appname (appname)
 
34
{
 
35
}
 
36
 
 
37
 
 
38
Imidi::~Imidi (void)
 
39
{
 
40
}
 
41
 
 
42
 
 
43
void Imidi::terminate (void)
 
44
{
 
45
    put_event (EV_EXIT, 1);
 
46
}
 
47
 
 
48
 
 
49
void Imidi::thr_main (void)
 
50
{
 
51
    open_midi ();
 
52
    get_event (1 << EV_EXIT);
 
53
    close_midi ();
 
54
    send_event (EV_EXIT, 1);
 
55
}
 
56
 
 
57
 
 
58
static void coremidi_proc_static (const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
 
59
{
 
60
    Imidi *imidi = (Imidi*)refCon;
 
61
    imidi->coremidi_proc (pktlist, 0, connRefCon);
 
62
}
 
63
 
 
64
 
 
65
void Imidi::open_midi (void)
 
66
{
 
67
    // If in the future dest is needed in close_midi (or elsewhere) this could
 
68
    // be made an instance variable.
 
69
    MIDIEndpointRef dest;
 
70
 
 
71
    _handle = NULL;
 
72
    CFStringRef name = CFStringCreateWithCString(0, _appname, kCFStringEncodingUTF8);
 
73
    MIDIClientCreate(name, NULL, NULL, &_handle);
 
74
    MIDIDestinationCreate(_handle, name, coremidi_proc_static, this, &dest);
 
75
 
 
76
#if 0
 
77
    // is this stuff needed? I'm guessing no, but we'll see when I plugin the
 
78
    // USB keyboard
 
79
    MIDIPortRef inPort = NULL;
 
80
    MIDIInputPortCreate(_handle, CFSTR("In"), coremidi_proc_static, this, &inPort);
 
81
 
 
82
    // open connections from all sources (TODO is this what we want?)
 
83
    int n = MIDIGetNumberOfSources();
 
84
    for (int i=0; i<n; i++)
 
85
    {
 
86
        MIDIEndpointRef src = MIDIGetSource(i);
 
87
        MIDIPortConnectSource(inPort, src, (void*)src);
 
88
    }
 
89
#endif
 
90
 
 
91
    // FA
 
92
    // _client and _ippport are printed in the main window's title as [_client:_ipport]
 
93
    // They are the info required to connect to a source using the ALSA sequencer.
 
94
    // Anything equivalent for OSX ?
 
95
 
 
96
    // hcf 
 
97
    // _appname is the name of the destination, and that's what users are
 
98
    // likely to use when connecting MIDI sources to it.
 
99
 
 
100
    M_midi_info *M = new M_midi_info ();
 
101
    M->_client = 0; 
 
102
    M->_ipport = 0;
 
103
    memcpy (M->_chbits, _midimap, 16);
 
104
    send_event (TO_MODEL, M);
 
105
}
 
106
 
 
107
 
 
108
void Imidi::close_midi (void)
 
109
{
 
110
    // nothing to do here - everything is closed automagically (if I
 
111
    // understand the docs correctly)
 
112
}
 
113
 
 
114
 
 
115
void Imidi::coremidi_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
 
116
{
 
117
    int c, d, f, m, n, p, t, v, s;
 
118
    MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
 
119
 
 
120
    for (unsigned int j=0; j < pktlist->numPackets; j++)
 
121
    {
 
122
        for (int i=0; i < packet->length; i++) 
 
123
        {
 
124
            // FA 
 
125
            // Maybe this should be factored out so it can be
 
126
            // shared with the ALSA version. But not urgent.
 
127
 
 
128
            // hcf
 
129
            // Yeah, and the JACK MIDI version too.
 
130
 
 
131
            Byte *E = &packet->data[i];
 
132
            s = E[0];
 
133
            t = s & 0xF0;
 
134
            c = s & 0x0F;
 
135
 
 
136
            if (!(s & 0x80))
 
137
                continue; // skip data bytes
 
138
 
 
139
            m = _midimap [c] & 127;        // Keyboard and hold bits
 
140
            d = (_midimap [c] >>  8) & 7;  // Division number if (f & 2)
 
141
            f = (_midimap [c] >> 12) & 7;  // Control enabled if (f & 4)
 
142
 
 
143
            switch (t)
 
144
            { 
 
145
            case 0x80:
 
146
            case 0x90:
 
147
                // Note on or off.
 
148
                n = E[1];
 
149
                v = E[2];
 
150
                if ((t == 0x90) && v)
 
151
                {
 
152
                    // Note on.
 
153
                    if (n < 36)
 
154
                    {
 
155
                        if ((f & 4) && (n >= 24) && (n < 34))
 
156
                        {
 
157
                            // Preset selection, sent to model thread
 
158
                            // if on control-enabled channel.
 
159
                            if (_qmidi->write_avail () >= 3)
 
160
                            {
 
161
                                _qmidi->write (0, 0x90);
 
162
                                _qmidi->write (1, n);
 
163
                                _qmidi->write (2, v);
 
164
                                _qmidi->write_commit (3);
 
165
                            }
 
166
                        }
 
167
                    }
 
168
                    else if (n <= 96)
 
169
                    {
 
170
                        if (m)
 
171
                        {
 
172
                            if (_qnote->write_avail () > 0)
 
173
                            {
 
174
                                _qnote->write (0, (1 << 24) | ((n - 36) << 8) | m);
 
175
                                _qnote->write_commit (1);
 
176
                            } 
 
177
                        }
 
178
                    }
 
179
                }
 
180
                else
 
181
                {
 
182
                    // Note off.
 
183
                    if (n < 36)
 
184
                    {
 
185
                    }
 
186
                    else if (n <= 96)
 
187
                    {
 
188
                        if (m)
 
189
                        {
 
190
                            if (_qnote->write_avail () > 0)
 
191
                            {
 
192
                                _qnote->write (0, ((n - 36) << 8) | m);
 
193
                                _qnote->write_commit (1);
 
194
                            } 
 
195
                        }
 
196
                    }
 
197
                }
 
198
                break;
 
199
 
 
200
            case 0xB0:
 
201
                p = E[1];
 
202
                v = E[2];
 
203
                switch (p)
 
204
                {
 
205
                case MIDICTL_HOLD:
 
206
                    // Hold pedal.
 
207
                    if (m & HOLD_MASK)
 
208
                    {
 
209
                        v = (v > 63) ? 9 : 8;
 
210
                        if (_qnote->write_avail () > 0)
 
211
                        {
 
212
                            _qnote->write (0, (v << 24) | (m << 16));
 
213
                            _qnote->write_commit (1);
 
214
                        } 
 
215
                    }
 
216
                    break;
 
217
 
 
218
                case MIDICTL_ASOFF:
 
219
                    // All sound off, accepted on control channels only.
 
220
                    // Clears all keyboards, including held notes.
 
221
                    if (f & 4)
 
222
                    {
 
223
                        if (_qnote->write_avail () > 0)
 
224
                        {
 
225
                            _qnote->write (0, (2 << 24) | ( ALL_MASK << 16) | ALL_MASK);
 
226
                            _qnote->write_commit (1);
 
227
                        } 
 
228
                    }
 
229
                    break;
 
230
 
 
231
                case MIDICTL_ANOFF:
 
232
                    // All notes off, accepted on channels controlling
 
233
                    // a keyboard. Does not clear held notes. 
 
234
                    if (m)
 
235
                    {
 
236
                        if (_qnote->write_avail () > 0)
 
237
                        {
 
238
                            _qnote->write (0, (2 << 24) | (m << 16) | m);
 
239
                            _qnote->write_commit (1);
 
240
                        } 
 
241
                    }
 
242
                    break;
 
243
 
 
244
                case MIDICTL_BANK:      
 
245
                case MIDICTL_IFELM:     
 
246
                    // Program bank selection or stop control, sent
 
247
                    // to model thread if on control-enabled channel.
 
248
                    if (f & 4)
 
249
                    {
 
250
                        if (_qmidi->write_avail () >= 3)
 
251
                        {
 
252
                            _qmidi->write (0, 0xB0 | c);
 
253
                            _qmidi->write (1, p);
 
254
                            _qmidi->write (2, v);
 
255
                            _qmidi->write_commit (3);
 
256
                        }
 
257
                    }
 
258
                case MIDICTL_SWELL:
 
259
                case MIDICTL_TFREQ:
 
260
                case MIDICTL_TMODD:
 
261
                    // Per-division performance controls, sent to model
 
262
                    // thread if on a channel that controls a division.
 
263
                    if (f & 2)
 
264
                    {
 
265
                        if (_qmidi->write_avail () >= 3)
 
266
                        {
 
267
                            _qmidi->write (0, 0xB0 | c);
 
268
                            _qmidi->write (1, p);
 
269
                            _qmidi->write (2, v);
 
270
                            _qmidi->write_commit (3);
 
271
                        }
 
272
                    }
 
273
                    break;
 
274
                }
 
275
                break;
 
276
 
 
277
            case 0xC0:
 
278
                // Program change sent to model thread
 
279
                // if on control-enabled channel.
 
280
                n = E[1];
 
281
                if (f & 4)
 
282
                {
 
283
                    if (_qmidi->write_avail () >= 3)
 
284
                    {
 
285
                        _qmidi->write (0, 0xC0);
 
286
                        _qmidi->write (1, n);
 
287
                        _qmidi->write (2, 0);
 
288
                        _qmidi->write_commit (3);
 
289
                    }
 
290
                }
 
291
                break;
 
292
            }
 
293
        }
 
294
 
 
295
        packet = MIDIPacketNext(packet);
 
296
    }
 
297
}