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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 201 by schoenebeck, Tue Jul 13 22:10:21 2004 UTC revision 903 by persson, Sat Jul 22 14:22:53 2006 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *   *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6     *   Copyright (C) 2005, 2006 Christian Schoenebeck                        *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 23  Line 24 
24  #include "MidiInputDeviceAlsa.h"  #include "MidiInputDeviceAlsa.h"
25  #include "MidiInputDeviceFactory.h"  #include "MidiInputDeviceFactory.h"
26    
27    #define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
28    
29  namespace LinuxSampler {  namespace LinuxSampler {
30    
31          REGISTER_MIDI_INPUT_DRIVER(MidiInputDeviceAlsa);  // *************** ParameterName ***************
32    // *
33    
34          /* Common parameters */      MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterName::ParameterName(MidiInputPort* pPort) throw (Exception) : MidiInputPort::ParameterName(pPort, "Port " + ToString(pPort->GetPortNumber())) {
35          REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterActive);          OnSetValue(ValueAsString()); // initialize port name
36          REGISTER_MIDI_INPUT_DRIVER_PARAMETER(MidiInputDeviceAlsa, ParameterPorts);      }
37    
38      MidiInputDeviceAlsa::MidiInputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters) : MidiInputDevice(Parameters), Thread(true, 1, -1) {      void MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterName::OnSetValue(String s) throw (Exception) {
39          if (snd_seq_open(&hAlsaSeq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {          if (s.size() > 16) throw Exception("Name too long for ALSA MIDI input port (max. 16 characters)");
40              throw MidiInputException("Error opening ALSA sequencer");          snd_seq_port_info_t* hInfo;
41            snd_seq_port_info_malloc(&hInfo);
42            snd_seq_get_port_info(((MidiInputDeviceAlsa*)pPort->GetDevice())->hAlsaSeq, pPort->GetPortNumber(), hInfo);
43            snd_seq_port_info_set_name(hInfo, s.c_str());
44            snd_seq_set_port_info(((MidiInputDeviceAlsa*)pPort->GetDevice())->hAlsaSeq, pPort->GetPortNumber(), hInfo);
45            snd_seq_port_info_free(hInfo);
46        }
47    
48    
49    
50    // *************** ParameterAlsaSeqBindings ***************
51    // *
52    
53    
54        MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::ParameterAlsaSeqBindings(MidiInputPortAlsa* pPort) : DeviceRuntimeParameterStrings( std::vector<String>() ) {
55            this->pPort = pPort;
56        }
57    
58        String MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Description() {
59            return "Bindings to other Alsa sequencer clients";
60        }
61        bool MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::Fix() {
62            return false;
63        }
64    
65        std::vector<String> MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::PossibilitiesAsString() {
66            std::vector<String> res;
67            snd_seq_client_info_t* cinfo;
68            snd_seq_port_info_t* pinfo;
69    
70            snd_seq_client_info_alloca(&cinfo);
71            snd_seq_port_info_alloca(&pinfo);
72            snd_seq_client_info_set_client(cinfo, -1);
73            while (snd_seq_query_next_client(pPort->pDevice->hAlsaSeq, cinfo) >= 0) {
74                snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
75                snd_seq_port_info_set_port(pinfo, -1);
76                while (snd_seq_query_next_port(pPort->pDevice->hAlsaSeq, pinfo) >= 0) {
77                    if (perm_ok(pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ)) {
78                            String seq_id = ToString(snd_seq_client_info_get_client(cinfo)) + ":" +
79                                            ToString(snd_seq_port_info_get_port(pinfo));
80                            res.push_back(seq_id);
81                    }
82                }
83          }          }
84          this->hAlsaSeqClient = snd_seq_client_id(hAlsaSeq);  
85          snd_seq_set_client_name(hAlsaSeq, "LinuxSampler");          return res;
         AcquirePorts(((DeviceCreationParameterInt*)Parameters["ports"])->ValueAsInt());  
         if (((DeviceCreationParameterBool*)Parameters["active"])->ValueAsBool()) {  
                 Listen();  
         }  
86      }      }
87    
88      MidiInputDeviceAlsa::~MidiInputDeviceAlsa() {      void MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqBindings::OnSetValue(std::vector<String> vS) throw (Exception) {
89              snd_seq_close(hAlsaSeq);          std::vector<String>::iterator iter = vS.begin();
90            for (; iter != vS.end(); iter++) pPort->ConnectToAlsaMidiSource((*iter).c_str());
91      }      }
92    
93      MidiInputDeviceAlsa::MidiInputPortAlsa::MidiInputPortAlsa(MidiInputDeviceAlsa* pDevice, int alsaPort) : MidiInputPort(pDevice, alsaPort) {  
94              Parameters["alsa_seq_bindings"] = new ParameterAlsaSeqBindings(this);  
95              this->pDevice = pDevice;  // *************** ParameterAlsaSeqId ***************
96    // *
97    
98        MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqId::ParameterAlsaSeqId(MidiInputPortAlsa* pPort)
99            : DeviceRuntimeParameterString(ToString(pPort->pDevice->hAlsaSeqClient) + ":" + ToString(pPort->portNumber)) {
100      }      }
101    
102      MidiInputDeviceAlsa::MidiInputPortAlsa::~MidiInputPortAlsa() {      String MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqId::Description() {
103              snd_seq_delete_simple_port(pDevice->hAlsaSeq, portNumber);          return "ALSA Sequencer ID";
104      }      }
105    
106      MidiInputDeviceAlsa::MidiInputPortAlsa* MidiInputDeviceAlsa::CreateMidiPort() {      bool MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqId::Fix() {
107              int alsaPort;          return true;
             if ((alsaPort = snd_seq_create_simple_port(hAlsaSeq, "LinuxSampler",  
                                             SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,  
                                             SND_SEQ_PORT_TYPE_APPLICATION)) < 0) {  
                     throw MidiInputException("Error creating sequencer port");  
             }  
             return ( new MidiInputPortAlsa(this, alsaPort) );  
108      }      }
109    
110      String MidiInputDeviceAlsa::Name() {      std::vector<String> MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqId::PossibilitiesAsString() {
111              return "Alsa";          return std::vector<String>(); // nothing
112      }      }
113    
114      String MidiInputDeviceAlsa::Driver() {      void MidiInputDeviceAlsa::MidiInputPortAlsa::ParameterAlsaSeqId::OnSetValue(String s) {
115              return Name();          // not possible as parameter is 'fix'
116      }      }
117    
118      void MidiInputDeviceAlsa::Listen() {  
119          StartThread();  
120    // *************** MidiInputPortAlsa ***************
121    // *
122    
123        MidiInputDeviceAlsa::MidiInputPortAlsa::MidiInputPortAlsa(MidiInputDeviceAlsa* pDevice) throw (MidiInputException) : MidiInputPort(pDevice, -1) {
124            this->pDevice = pDevice;
125    
126            // create Alsa sequencer port
127            int alsaPort = snd_seq_create_simple_port(pDevice->hAlsaSeq, "unnamed port",
128                                                      SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
129                                                      SND_SEQ_PORT_TYPE_APPLICATION);
130            if (alsaPort < 0) throw MidiInputException("Error creating sequencer port");
131            this->portNumber = alsaPort;
132    
133            Parameters["NAME"]              = new ParameterName(this);
134            Parameters["ALSA_SEQ_BINDINGS"] = new ParameterAlsaSeqBindings(this);
135            Parameters["ALSA_SEQ_ID"]       = new ParameterAlsaSeqId(this);
136      }      }
137    
138      void MidiInputDeviceAlsa::StopListen() {      MidiInputDeviceAlsa::MidiInputPortAlsa::~MidiInputPortAlsa() {
139          StopThread();              snd_seq_delete_simple_port(pDevice->hAlsaSeq, portNumber);
140      }      }
141    
142      /**      /**
143      * Connects this Alsa midi input device with an Alsa MIDI source.       * Connects this Alsa midi input device with an Alsa MIDI source.
144      *       *
145      * @param Client - Alsa sequencer client and port ID of a MIDI source       * @param Client - Alsa sequencer client and port ID of a MIDI source
146      *                (e.g. "64:0")       *                (e.g. "64:0")
147      * @throws MidiInputException  if connection cannot be established       * @throws MidiInputException  if connection cannot be established
148      */       */
149      void MidiInputDeviceAlsa::MidiInputPortAlsa::ConnectToAlsaMidiSource(const char* MidiSource) {      void MidiInputDeviceAlsa::MidiInputPortAlsa::ConnectToAlsaMidiSource(const char* MidiSource) {
150          snd_seq_addr_t sender, dest;          snd_seq_addr_t sender, dest;
151          snd_seq_port_subscribe_t* subs;          snd_seq_port_subscribe_t* subs;
# Line 109  namespace LinuxSampler { Line 166  namespace LinuxSampler {
166              throw MidiInputException(String("Unable to connect to Alsa seq client \'") + MidiSource + "\' (" + snd_strerror(errno) + ")");              throw MidiInputException(String("Unable to connect to Alsa seq client \'") + MidiSource + "\' (" + snd_strerror(errno) + ")");
167      }      }
168    
169    
170    
171    // *************** MidiInputDeviceAlsa ***************
172    // *
173    
174        MidiInputDeviceAlsa::MidiInputDeviceAlsa(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler), Thread(true, true, 1, -1) {
175            if (snd_seq_open(&hAlsaSeq, "default", SND_SEQ_OPEN_INPUT, 0) < 0) {
176                throw MidiInputException("Error opening ALSA sequencer");
177            }
178            this->hAlsaSeqClient = snd_seq_client_id(hAlsaSeq);
179            snd_seq_set_client_name(hAlsaSeq, "LinuxSampler");
180            AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
181            if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
182                    Listen();
183            }
184        }
185    
186        MidiInputDeviceAlsa::~MidiInputDeviceAlsa() {
187                snd_seq_close(hAlsaSeq);
188        }
189    
190        MidiInputDeviceAlsa::MidiInputPortAlsa* MidiInputDeviceAlsa::CreateMidiPort() {
191            return new MidiInputPortAlsa(this);
192        }
193    
194        String MidiInputDeviceAlsa::Name() {
195                return "ALSA";
196        }
197    
198        String MidiInputDeviceAlsa::Driver() {
199                return Name();
200        }
201    
202        void MidiInputDeviceAlsa::Listen() {
203            StartThread();
204        }
205    
206        void MidiInputDeviceAlsa::StopListen() {
207            StopThread();
208        }
209    
210      String MidiInputDeviceAlsa::Description() {      String MidiInputDeviceAlsa::Description() {
211              return "Advanced Linux Sound Architecture";              return "Advanced Linux Sound Architecture";
212      }      }
213    
214      String MidiInputDeviceAlsa::Version() {      String MidiInputDeviceAlsa::Version() {
215              String s = "$Revision: 1.8 $";              String s = "$Revision: 1.17 $";
216              return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword              return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
217      }      }
218    
# Line 130  namespace LinuxSampler { Line 228  namespace LinuxSampler {
228              if (poll(pfd, npfd, 100000) > 0) {              if (poll(pfd, npfd, 100000) > 0) {
229                  do {                  do {
230                      snd_seq_event_input(hAlsaSeq, &ev);                      snd_seq_event_input(hAlsaSeq, &ev);
231                      int port = (int) ev->dest.port;                      int port = (int) ev->dest.port;
232                      MidiInputPort* pMidiInputPort = Ports[port];                      MidiInputPort* pMidiInputPort = Ports[port];
233    
234                      switch (ev->type) {                      switch (ev->type) {
235                          case SND_SEQ_EVENT_CONTROLLER:                          case SND_SEQ_EVENT_CONTROLLER:
236                              pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);                              pMidiInputPort->DispatchControlChange(ev->data.control.param, ev->data.control.value, ev->data.control.channel);
237                              break;                              break;
238    
239                            case SND_SEQ_EVENT_CHANPRESS:
240                                pMidiInputPort->DispatchControlChange(128, ev->data.control.value, ev->data.control.channel);
241                                break;
242    
243                          case SND_SEQ_EVENT_PITCHBEND:                          case SND_SEQ_EVENT_PITCHBEND:
                           //  fprintf(stderr, "Pitchbender event on Channel %2d: %5d   \n",  
                           //          ev->data.control.channel, ev->data.control.value);  
244                              pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);                              pMidiInputPort->DispatchPitchbend(ev->data.control.value, ev->data.control.channel);
245                              break;                              break;
246    
# Line 156  namespace LinuxSampler { Line 256  namespace LinuxSampler {
256                          case SND_SEQ_EVENT_NOTEOFF:                          case SND_SEQ_EVENT_NOTEOFF:
257                              pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);                              pMidiInputPort->DispatchNoteOff(ev->data.note.note, ev->data.note.velocity, ev->data.control.channel);
258                              break;                              break;
259    
260                            case SND_SEQ_EVENT_SYSEX:
261                                pMidiInputPort->DispatchSysex(ev->data.ext.ptr, ev->data.ext.len);
262                                break;
263    
264                            case SND_SEQ_EVENT_PGMCHANGE:
265                                pMidiInputPort->DispatchProgramChange(ev->data.control.value, ev->data.control.channel);
266                                break;
267                      }                      }
268                      snd_seq_free_event(ev);                      snd_seq_free_event(ev);
269                  } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);                  } while (snd_seq_event_input_pending(hAlsaSeq, 0) > 0);

Legend:
Removed from v.201  
changed lines
  Added in v.903

  ViewVC Help
Powered by ViewVC