/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputDeviceAlsa.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/drivers/midi/MidiInputDeviceAlsa.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 221 - (show annotations) (download)
Fri Aug 20 17:25:19 2004 UTC (19 years, 7 months ago) by schoenebeck
File size: 9779 byte(s)
* src/drivers/midi/MidiInputDeviceAlsa.cpp: implemented port parameter
 "NAME" which now updates the registered ALSA seq port name as well, fixed
  port parameter "ALSA_SEQ_BINDINGS" to allow more than one binding
* src/network/lscp.y: fixed symbol STRINGVAL (that is strings encapsulated
  into apostrophes) which didn't allow space characters
* changed all driver names and driver paramaters to upper case
* fixed typo in LSCP documentation
  (section 5.3.12, was: "SET MIDI_INPUT_PORT PARAMETER",
   should be: "SET MIDI_INPUT_PORT_PARAMETER")

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "MidiInputDeviceAlsa.h"
24 #include "MidiInputDeviceFactory.h"
25
26 namespace LinuxSampler {
27
28 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceAlsa);
29
30 /* Common parameters */
31 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterActive);
32 REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterPorts);
33
34
35
36 // *************** ParameterName ***************
37 // *
38
39 MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterName::ParameterName(MidiInputPort* pPort) throw (LinuxSamplerException) : MidiInputPort::ParameterName(pPort, "Port " + ToString(pPort->GetPortNumber())) {
40 OnSetValue(ValueAsString()); // initialize port name
41 }
42
43 void MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {
44 if (s.size() > 16) throw LinuxSamplerException("Name too long for ALSA MIDI input port (max. 16 characters)");
45 snd_seq_port_info_t* hInfo;
46 snd_seq_port_info_malloc(&hInfo);
47 snd_seq_get_port_info(((MidiInputDeviceAlsa*)pPort->GetDevice())->hAlsaSeq, pPort->GetPortNumber(), hInfo);
48 snd_seq_port_info_set_name(hInfo, s.c_str());
49 snd_seq_set_port_info(((MidiInputDeviceAlsa*)pPort->GetDevice())->hAlsaSeq, pPort->GetPortNumber(), hInfo);
50 snd_seq_port_info_free(hInfo);
51 }
52
53
54
55 // *************** ParameterAlsaSeqBindings ***************
56 // *
57
58
59 MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::ParameterAlsaSeqBindings(MidiInputPortAlsa* pPort) : DeviceRuntimeParameterStrings( std::vector<String>() ) {
60 this->pPort = pPort;
61 }
62
63 String MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Description() {
64 return "Bindings to other Alsa sequencer clients";
65 }
66 bool MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Fix() {
67 return false;
68 }
69
70 std::vector<String> MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::PossibilitiesAsString() {
71 return std::vector<String>(); //TODO
72 }
73
74 void MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::OnSetValue(std::vector<String> vS) throw (LinuxSamplerException) {
75 std::vector<String>::iterator iter = vS.begin();
76 for (; iter != vS.end(); iter++) pPort->ConnectToAlsaMidiSource((*iter).c_str());
77 }
78
79
80
81 // *************** MidiInputPortAlsa ***************
82 // *
83
84 MidiInputDeviceAlsa::MidiInputPortAlsa::MidiInputPortAlsa(MidiInputDeviceAlsa* pDevice) throw (MidiInputException) : MidiInputPort(pDevice, -1) {
85 this->pDevice = pDevice;
86
87 // create Alsa sequencer port
88 int alsaPort = snd_seq_create_simple_port(pDevice->hAlsaSeq, "unnamed port",
89 SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
90 SND_SEQ_PORT_TYPE_APPLICATION);
91 if (alsaPort < 0) throw MidiInputException("Error creating sequencer port");
92 this->portNumber = alsaPort;
93
94 Parameters["NAME"] = new ParameterName(this);
95 Parameters["ALSA_SEQ_BINDINGS"] = new ParameterAlsaSeqBindings(this);
96 }
97
98 MidiInputDeviceAlsa::MidiInputPortAlsa::~MidiInputPortAlsa() {
99 snd_seq_delete_simple_port(pDevice->hAlsaSeq, portNumber);
100 }
101
102 /**
103 * Connects this Alsa midi input device with an Alsa MIDI source.
104 *
105 * @param Client - Alsa sequencer client and port ID of a MIDI source
106 * (e.g. "64:0")
107 * @throws MidiInputException if connection cannot be established
108 */
109 void MidiInputDeviceAlsa::MidiInputPortAlsa::ConnectToAlsaMidiSource(const char* MidiSource) {
110 snd_seq_addr_t sender, dest;
111 snd_seq_port_subscribe_t* subs;
112 int hExtClient, hExtPort;
113
114 sscanf(MidiSource, "%d:%d", &hExtClient, &hExtPort);
115 sender.client = (char) hExtClient;
116 sender.port = (char) hExtPort;
117 dest.client = (char) pDevice->hAlsaSeqClient;
118 dest.port = (char) portNumber;
119 snd_seq_port_subscribe_alloca(&subs);
120 snd_seq_port_subscribe_set_sender(subs, &sender);
121 snd_seq_port_subscribe_set_dest(subs, &dest);
122 snd_seq_port_subscribe_set_queue(subs, 1);
123 snd_seq_port_subscribe_set_time_update(subs, 1);
124 snd_seq_port_subscribe_set_time_real(subs, 1);
125 if (snd_seq_subscribe_port(pDevice->hAlsaSeq, subs) < 0)
126 throw MidiInputException(String("Unable to connect to Alsa seq client \'") + MidiSource + "\' (" + snd_strerror(errno) + ")");
127 }
128
129
130
131 // *************** MidiInputDeviceAlsa ***************
132 // *
133
134 MidiInputDeviceAlsa::MidiInputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : MidiInputDevice(Parameters), Thread(true, 1, -1) {
135 if (snd_seq_open(&hAlsaSeq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
136 throw MidiInputException("Error opening ALSA sequencer");
137 }
138 this->hAlsaSeqClient = snd_seq_client_id(hAlsaSeq);
139 snd_seq_set_client_name(hAlsaSeq, "LinuxSampler");
140 AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
141 if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
142 Listen();
143 }
144 }
145
146 MidiInputDeviceAlsa::~MidiInputDeviceAlsa() {
147 snd_seq_close(hAlsaSeq);
148 }
149
150 MidiInputDeviceAlsa::MidiInputPortAlsa* MidiInputDeviceAlsa::CreateMidiPort() {
151 return new MidiInputPortAlsa(this);
152 }
153
154 String MidiInputDeviceAlsa::Name() {
155 return "ALSA";
156 }
157
158 String MidiInputDeviceAlsa::Driver() {
159 return Name();
160 }
161
162 void MidiInputDeviceAlsa::Listen() {
163 StartThread();
164 }
165
166 void MidiInputDeviceAlsa::StopListen() {
167 StopThread();
168 }
169
170 String MidiInputDeviceAlsa::Description() {
171 return "Advanced Linux Sound Architecture";
172 }
173
174 String MidiInputDeviceAlsa::Version() {
175 String s = "$Revision: 1.9 $";
176 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
177 }
178
179 int MidiInputDeviceAlsa::Main() {
180 int npfd;
181 struct pollfd* pfd;
182 snd_seq_event_t* ev;
183
184 npfd = snd_seq_poll_descriptors_count(hAlsaSeq, POLLIN);
185 pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd));
186 snd_seq_poll_descriptors(hAlsaSeq, pfd, npfd, POLLIN);
187 while (true) {
188 if (poll(pfd, npfd, 100000) > 0) {
189 do {
190 snd_seq_event_input(hAlsaSeq, &ev);
191 int port = (int) ev->dest.port;
192 MidiInputPort* pMidiInputPort = Ports[port];
193
194 switch (ev->type) {
195 case SND_SEQ_EVENT_CONTROLLER:
196 pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);
197 break;
198
199 case SND_SEQ_EVENT_PITCHBEND:
200 // fprintf(stderr, "Pitchbender event on Channel %2d: %5d \n",
201 // ev->data.control.channel, ev->data.control.value);
202 pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);
203 break;
204
205 case SND_SEQ_EVENT_NOTEON:
206 if (ev->data.note.velocity != 0) {
207 pMidiInputPort->DispatchNoteOn(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
208 }
209 else {
210 pMidiInputPort->DispatchNoteOff(ev->data.note.note, 0, ev->data.control.channel);
211 }
212 break;
213
214 case SND_SEQ_EVENT_NOTEOFF:
215 pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
216 break;
217 }
218 snd_seq_free_event(ev);
219 } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);
220 }
221 }
222 }
223
224 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC