/[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 201 - (hide annotations) (download)
Tue Jul 13 22:10:21 2004 UTC (19 years, 9 months ago) by schoenebeck
File size: 7384 byte(s)
moved directory '/src/mididriver' -> '/src/drivers/midi'

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     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     MidiInputDeviceAlsa::MidiInputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : MidiInputDevice(Parameters), Thread(true, 1, -1) {
35     if (snd_seq_open(&hAlsaSeq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
36     throw MidiInputException("Error opening ALSA sequencer");
37     }
38     this->hAlsaSeqClient = snd_seq_client_id(hAlsaSeq);
39     snd_seq_set_client_name(hAlsaSeq, "LinuxSampler");
40     AcquirePorts(((DeviceCreationParameterInt*)Parameters["ports"])->ValueAsInt());
41     if (((DeviceCreationParameterBool*)Parameters["active"])->ValueAsBool()) {
42     Listen();
43     }
44     }
45    
46     MidiInputDeviceAlsa::~MidiInputDeviceAlsa() {
47     snd_seq_close(hAlsaSeq);
48     }
49    
50     MidiInputDeviceAlsa::MidiInputPortAlsa::MidiInputPortAlsa(MidiInputDeviceAlsa* pDevice, int alsaPort) : MidiInputPort(pDevice, alsaPort) {
51     Parameters["alsa_seq_bindings"] = new ParameterAlsaSeqBindings(this);
52     this->pDevice = pDevice;
53     }
54    
55     MidiInputDeviceAlsa::MidiInputPortAlsa::~MidiInputPortAlsa() {
56     snd_seq_delete_simple_port(pDevice->hAlsaSeq, portNumber);
57     }
58    
59     MidiInputDeviceAlsa::MidiInputPortAlsa* MidiInputDeviceAlsa::CreateMidiPort() {
60     int alsaPort;
61     if ((alsaPort = snd_seq_create_simple_port(hAlsaSeq, "LinuxSampler",
62     SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
63     SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {
64     throw MidiInputException("Error creating sequencer port");
65     }
66     return ( new MidiInputPortAlsa(this, alsaPort) );
67     }
68    
69     String MidiInputDeviceAlsa::Name() {
70     return "Alsa";
71     }
72    
73     String MidiInputDeviceAlsa::Driver() {
74     return Name();
75     }
76    
77     void MidiInputDeviceAlsa::Listen() {
78     StartThread();
79     }
80    
81     void MidiInputDeviceAlsa::StopListen() {
82     StopThread();
83     }
84    
85     /**
86     * Connects this Alsa midi input device with an Alsa MIDI source.
87     *
88     * @param Client - Alsa sequencer client and port ID of a MIDI source
89     * (e.g. "64:0")
90     * @throws MidiInputException if connection cannot be established
91     */
92     void MidiInputDeviceAlsa::MidiInputPortAlsa::ConnectToAlsaMidiSource(const char* MidiSource) {
93     snd_seq_addr_t sender, dest;
94     snd_seq_port_subscribe_t* subs;
95     int hExtClient, hExtPort;
96    
97     sscanf(MidiSource, "%d:%d", &hExtClient, &hExtPort);
98     sender.client = (char) hExtClient;
99     sender.port = (char) hExtPort;
100     dest.client = (char) pDevice->hAlsaSeqClient;
101     dest.port = (char) portNumber;
102     snd_seq_port_subscribe_alloca(&subs);
103     snd_seq_port_subscribe_set_sender(subs, &sender);
104     snd_seq_port_subscribe_set_dest(subs, &dest);
105     snd_seq_port_subscribe_set_queue(subs, 1);
106     snd_seq_port_subscribe_set_time_update(subs, 1);
107     snd_seq_port_subscribe_set_time_real(subs, 1);
108     if (snd_seq_subscribe_port(pDevice->hAlsaSeq, subs) < 0)
109     throw MidiInputException(String("Unable to connect to Alsa seq client \'") + MidiSource + "\' (" + snd_strerror(errno) + ")");
110     }
111    
112     String MidiInputDeviceAlsa::Description() {
113     return "Advanced Linux Sound Architecture";
114     }
115    
116     String MidiInputDeviceAlsa::Version() {
117     String s = "$Revision: 1.8 $";
118     return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
119     }
120    
121     int MidiInputDeviceAlsa::Main() {
122     int npfd;
123     struct pollfd* pfd;
124     snd_seq_event_t* ev;
125    
126     npfd = snd_seq_poll_descriptors_count(hAlsaSeq, POLLIN);
127     pfd = (struct pollfd*) alloca(npfd * sizeof(struct pollfd));
128     snd_seq_poll_descriptors(hAlsaSeq, pfd, npfd, POLLIN);
129     while (true) {
130     if (poll(pfd, npfd, 100000) > 0) {
131     do {
132     snd_seq_event_input(hAlsaSeq, &ev);
133     int port = (int) ev->dest.port;
134     MidiInputPort* pMidiInputPort = Ports[port];
135    
136     switch (ev->type) {
137     case SND_SEQ_EVENT_CONTROLLER:
138     pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);
139     break;
140    
141     case SND_SEQ_EVENT_PITCHBEND:
142     // fprintf(stderr, "Pitchbender event on Channel %2d: %5d \n",
143     // ev->data.control.channel, ev->data.control.value);
144     pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);
145     break;
146    
147     case SND_SEQ_EVENT_NOTEON:
148     if (ev->data.note.velocity != 0) {
149     pMidiInputPort->DispatchNoteOn(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
150     }
151     else {
152     pMidiInputPort->DispatchNoteOff(ev->data.note.note, 0, ev->data.control.channel);
153     }
154     break;
155    
156     case SND_SEQ_EVENT_NOTEOFF:
157     pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
158     break;
159     }
160     snd_seq_free_event(ev);
161     } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);
162     }
163     }
164     }
165    
166     } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC