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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 221 - (hide 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 schoenebeck 201 /***************************************************************************
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 schoenebeck 221 REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceAlsa);
29 schoenebeck 201
30 schoenebeck 221 /* Common parameters */
31     REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterActive);
32     REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterPorts);
33 schoenebeck 201
34    
35 schoenebeck 221
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 schoenebeck 201 }
42    
43 schoenebeck 221 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 schoenebeck 201 }
52    
53 schoenebeck 221
54    
55     // *************** ParameterAlsaSeqBindings ***************
56     // *
57    
58    
59     MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::ParameterAlsaSeqBindings(MidiInputPortAlsa* pPort) : DeviceRuntimeParameterStrings( std::vector<String>() ) {
60     this->pPort = pPort;
61 schoenebeck 201 }
62    
63 schoenebeck 221 String MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Description() {
64     return "Bindings to other Alsa sequencer clients";
65 schoenebeck 201 }
66 schoenebeck 221 bool MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Fix() {
67     return false;
68     }
69 schoenebeck 201
70 schoenebeck 221 std::vector<String> MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::PossibilitiesAsString() {
71     return std::vector<String>(); //TODO
72 schoenebeck 201 }
73    
74 schoenebeck 221 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 schoenebeck 201 }
78    
79 schoenebeck 221
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 schoenebeck 201 }
97    
98 schoenebeck 221 MidiInputDeviceAlsa::MidiInputPortAlsa::~MidiInputPortAlsa() {
99     snd_seq_delete_simple_port(pDevice->hAlsaSeq, portNumber);
100 schoenebeck 201 }
101    
102     /**
103 schoenebeck 221 * 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 schoenebeck 201 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 schoenebeck 221
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 schoenebeck 201 String MidiInputDeviceAlsa::Description() {
171     return "Advanced Linux Sound Architecture";
172     }
173    
174     String MidiInputDeviceAlsa::Version() {
175 schoenebeck 221 String s = "$Revision: 1.9 $";
176 schoenebeck 201 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 schoenebeck 221 int port = (int) ev->dest.port;
192     MidiInputPort* pMidiInputPort = Ports[port];
193 schoenebeck 201
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