1 |
schoenebeck |
201 |
/*************************************************************************** |
2 |
|
|
* * |
3 |
|
|
* LinuxSampler - modular, streaming capable sampler * |
4 |
|
|
* * |
5 |
|
|
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
|
|
* Copyright (C) 2004 Grame * |
7 |
schoenebeck |
2559 |
* Copyright (C) 2014 Christian Schoenebeck * |
8 |
schoenebeck |
201 |
* * |
9 |
|
|
* This program is free software; you can redistribute it and/or modify * |
10 |
|
|
* it under the terms of the GNU General Public License as published by * |
11 |
|
|
* the Free Software Foundation; either version 2 of the License, or * |
12 |
|
|
* (at your option) any later version. * |
13 |
|
|
* * |
14 |
|
|
* This program is distributed in the hope that it will be useful, * |
15 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
16 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
17 |
|
|
* GNU General Public License for more details. * |
18 |
|
|
* * |
19 |
|
|
* You should have received a copy of the GNU General Public License * |
20 |
|
|
* along with this program; if not, write to the Free Software * |
21 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, * |
22 |
|
|
* MA 02111-1307 USA * |
23 |
|
|
***************************************************************************/ |
24 |
|
|
|
25 |
|
|
#include "MidiInputDeviceMidiShare.h" |
26 |
|
|
|
27 |
|
|
namespace LinuxSampler { |
28 |
|
|
|
29 |
|
|
#define MSHSlotName "LinuxSampler" |
30 |
|
|
#define MSHDriverName "LinuxSampler" |
31 |
|
|
|
32 |
|
|
#define MidiShareDrvRef 127 |
33 |
|
|
|
34 |
|
|
/** |
35 |
|
|
* Create MidiShare input device for LinuxSampler. |
36 |
|
|
* |
37 |
|
|
* @param AutoConnectPortID - (optional) Alsa client and port ID of a |
38 |
|
|
* MIDI source we should auto connect to |
39 |
|
|
* (e.g. "64:0") |
40 |
|
|
* @throws MidiInputException if initialization failed |
41 |
|
|
*/ |
42 |
|
|
MidiInputDeviceMidiShare::MidiInputDeviceMidiShare(char* AutoConnectPortID) : MidiInputDevice(MidiInputDevice::type_midishare) |
43 |
|
|
{ |
44 |
|
|
if (!MidiShare()) |
45 |
|
|
throw MidiInputException("MidiShare not installed"); |
46 |
|
|
|
47 |
|
|
#if defined(MIDISHARE_DRIVER) |
48 |
|
|
OpenDriver(); |
49 |
|
|
#else |
50 |
|
|
OpenAppl(); |
51 |
|
|
#endif |
52 |
|
|
|
53 |
|
|
hMidiFilter = MidiNewFilter(); |
54 |
|
|
|
55 |
|
|
if (hMidiFilter == 0) { |
56 |
|
|
MidiClose(hRefnum); |
57 |
|
|
throw MidiInputException("MidiShare filter can not be allocated"); |
58 |
|
|
} |
59 |
|
|
|
60 |
|
|
for (int i = 0 ; i < 256; i++) { |
61 |
|
|
MidiAcceptPort(hMidiFilter, i, 1); /* accept all ports */ |
62 |
|
|
MidiAcceptType(hMidiFilter, i, 0); /* reject all types */ |
63 |
|
|
} |
64 |
|
|
|
65 |
|
|
for (int i = 0 ; i < 16; i++) { |
66 |
|
|
MidiAcceptChan(hMidiFilter, i, 1); /* accept all chan */ |
67 |
|
|
} |
68 |
|
|
/* accept only the following types */ |
69 |
|
|
MidiAcceptType(hMidiFilter, typeNote, 1); |
70 |
|
|
MidiAcceptType(hMidiFilter, typeKeyOn, 1); |
71 |
|
|
MidiAcceptType(hMidiFilter, typeKeyOff, 1); |
72 |
|
|
MidiAcceptType(hMidiFilter, typeCtrlChange, 1); |
73 |
schoenebeck |
2559 |
MidiAcceptType(hMidiFilter, typeProgChange, 1); |
74 |
schoenebeck |
201 |
MidiAcceptType(hMidiFilter, typePitchWheel, 1); |
75 |
schoenebeck |
2559 |
MidiAcceptType(hMidiFilter, typeChanPress, 1); |
76 |
|
|
MidiAcceptType(hMidiFilter, typeKeyPress, 1); |
77 |
schoenebeck |
201 |
|
78 |
|
|
/* set the filter */ |
79 |
|
|
MidiSetFilter(hRefnum, hMidiFilter); |
80 |
|
|
|
81 |
|
|
MidiSetRcvAlarm(hRefnum,ReceiveEvents); |
82 |
|
|
MidiSetApplAlarm(hRefnum,ApplAlarm); |
83 |
|
|
MidiSetInfo(hRefnum,this); |
84 |
|
|
MidiConnect(0,hRefnum,true); |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
|
88 |
|
|
MidiInputDeviceMidiShare::~MidiInputDeviceMidiShare() |
89 |
|
|
{ |
90 |
|
|
#if defined(MIDISHARE_DRIVER) |
91 |
|
|
CloseDriver(); |
92 |
|
|
#else |
93 |
|
|
CloseAppl(); |
94 |
|
|
#endif |
95 |
|
|
MidiFreeFilter(hMidiFilter); |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
void MidiInputDeviceMidiShare::OpenAppl() |
99 |
|
|
{ |
100 |
|
|
hRefnum = MidiOpen(MSHDriverName); |
101 |
|
|
if (hRefnum < 0) { |
102 |
|
|
throw MidiInputException("MidiShare client can not be opened"); |
103 |
|
|
} |
104 |
|
|
MidiSetRcvAlarm(hRefnum,ReceiveEvents); |
105 |
|
|
MidiSetApplAlarm(hRefnum,ApplAlarm); |
106 |
|
|
} |
107 |
|
|
|
108 |
|
|
void MidiInputDeviceMidiShare::CloseAppl() |
109 |
|
|
{ |
110 |
|
|
MidiClose(hRefnum); |
111 |
|
|
} |
112 |
|
|
|
113 |
|
|
void MidiInputDeviceMidiShare::OpenDriver() |
114 |
|
|
{ |
115 |
|
|
/* gcc wanted me to use {0,0} to initialize the reserved[2] fields */ |
116 |
|
|
TDriverInfos infos = { MSHDriverName, 100, 0, { 0, 0 } }; |
117 |
|
|
TDriverOperation op = { WakeUp, Sleep, { 0, 0, 0 } }; |
118 |
|
|
hRefnum = MidiRegisterDriver(&infos, &op); |
119 |
|
|
if (hRefnum < 0) { |
120 |
|
|
throw MidiInputException("MidiShare driver can not be opened"); |
121 |
|
|
} |
122 |
|
|
hSlotRef = MidiAddSlot(hRefnum,MSHSlotName,MidiOutputSlot); |
123 |
|
|
MidiSetRcvAlarm(hRefnum,ReceiveEvents); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
void MidiInputDeviceMidiShare::CloseDriver() |
127 |
|
|
{ |
128 |
|
|
MidiUnregisterDriver(hRefnum); |
129 |
|
|
} |
130 |
|
|
|
131 |
|
|
void MidiInputDeviceMidiShare::WakeUp(short r) |
132 |
|
|
{ |
133 |
|
|
MidiConnect(MidiShareDrvRef, r, true); |
134 |
|
|
MidiConnect(r, MidiShareDrvRef, true); |
135 |
|
|
} |
136 |
|
|
|
137 |
|
|
void MidiInputDeviceMidiShare::Sleep(short r){} |
138 |
|
|
|
139 |
|
|
|
140 |
|
|
void MidiInputDeviceMidiShare::SetInputPort(const char * MidiSource) |
141 |
|
|
{ |
142 |
|
|
|
143 |
|
|
} |
144 |
|
|
|
145 |
|
|
void MidiInputDeviceMidiShare::ApplAlarm(short ref, long code) |
146 |
|
|
{ |
147 |
|
|
|
148 |
|
|
} |
149 |
|
|
|
150 |
|
|
void MidiInputDeviceMidiShare::KeyOffTask(long date, short ref, long a1, long a2, long a3) |
151 |
|
|
{ |
152 |
|
|
MidiInputDeviceMidiShare* driver = (MidiInputDeviceMidiShare*)MidiGetInfo(ref); |
153 |
|
|
MidiEvPtr ev =(MidiEvPtr)a1; |
154 |
|
|
driver->DispatchNoteOn(Pitch(ev),Vel(ev),Chan(ev)); |
155 |
|
|
MidiFreeEv(ev); |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
void MidiInputDeviceMidiShare::ReceiveEvents(short ref) |
159 |
|
|
{ |
160 |
|
|
MidiInputDeviceMidiShare* driver = (MidiInputDeviceMidiShare*)MidiGetInfo(ref); |
161 |
|
|
MidiEvPtr ev; |
162 |
|
|
|
163 |
|
|
while ((ev = MidiGetEv(ref))) |
164 |
|
|
|
165 |
|
|
switch(EvType(ev)) { |
166 |
|
|
|
167 |
|
|
case typeCtrlChange: |
168 |
schoenebeck |
947 |
if (MidiGetField(ev,0) == 0) |
169 |
|
|
driver->DispatchBankSelectMsb(MidiGetField(ev,0),Chan(ev)); |
170 |
|
|
else if (MidiGetField(ev,0) == 32) |
171 |
|
|
driver->DispatchBankSelectLsb(MidiGetField(ev,0),Chan(ev)); |
172 |
schoenebeck |
1715 |
driver->DispatchControlChange(MidiGetField(ev,0),MidiGetField(ev,0),Chan(ev)); |
173 |
schoenebeck |
201 |
MidiFreeEv(ev); |
174 |
|
|
break; |
175 |
|
|
|
176 |
|
|
case typePitchWheel: |
177 |
|
|
driver->DispatchPitchbend(((MidiGetField(ev,0)+(MidiGetField(ev,1) << 7)) - 8192),Chan(ev)); |
178 |
|
|
MidiFreeEv(ev); |
179 |
|
|
break; |
180 |
schoenebeck |
2559 |
|
181 |
|
|
case typeChanPress: |
182 |
|
|
driver->DispatchChannelPressure(MidiGetField(ev,0),Chan(ev)); |
183 |
|
|
MidiFreeEv(ev); |
184 |
|
|
break; |
185 |
|
|
|
186 |
|
|
case typeKeyPress: |
187 |
|
|
driver->DispatchPolyphonicKeyPressure(Pitch(ev),Vel(ev),Chan(ev)); |
188 |
|
|
MidiFreeEv(ev); |
189 |
|
|
break; |
190 |
|
|
|
191 |
schoenebeck |
201 |
case typeNote: |
192 |
|
|
driver->DispatchNoteOn(Pitch(ev),Vel(ev),Chan(ev)); |
193 |
|
|
MidiTask(KeyOffTask,Date(ev)+Dur(ev),ref,(long)ev,0,0); |
194 |
|
|
break; |
195 |
|
|
|
196 |
|
|
case typeKeyOn: |
197 |
|
|
if (Vel(ev) > 0) |
198 |
|
|
driver->DispatchNoteOn(Pitch(ev),Vel(ev),Chan(ev)); |
199 |
|
|
else |
200 |
|
|
driver->DispatchNoteOff(Pitch(ev),Vel(ev),Chan(ev)); |
201 |
|
|
MidiFreeEv(ev); |
202 |
|
|
break; |
203 |
|
|
|
204 |
|
|
case typeKeyOff: |
205 |
|
|
driver->DispatchNoteOff(Pitch(ev),Vel(ev),Chan(ev)); |
206 |
|
|
MidiFreeEv(ev); |
207 |
|
|
break; |
208 |
|
|
} |
209 |
|
|
} |
210 |
|
|
|
211 |
|
|
|
212 |
|
|
} // namespace LinuxSampler |