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

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

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

revision 509 by letz, Tue May 3 16:55:28 2005 UTC revision 2375 by schoenebeck, Thu Oct 4 17:45:22 2012 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   Copyright (C) 2004, 2005 Grame                                        *
4   *                                                                         *   *   Copyright (C) 2005 - 2012 Christian Schoenebeck                       *
  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *  
  *   Copyright (C) 2004 Grame                                                                                      *  
5   *                                                                         *   *                                                                         *
6   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
7   *   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 25  Line 23 
23  #include "MidiInputDeviceFactory.h"  #include "MidiInputDeviceFactory.h"
24    
25  namespace LinuxSampler {  namespace LinuxSampler {
26            
27    // *************** privat static functions ***************
28    // *
29            
30            static void _bridgeInputEvent(const MIDIPacketList* packetList, void* /*device*/, void* port) {
31                    //MidiInputDeviceCoreMidi* pDevice = (MidiInputDeviceCoreMidi*) device;
32                    MidiInputDeviceCoreMidi::MidiInputPortCoreMidi* pPort = (MidiInputDeviceCoreMidi::MidiInputPortCoreMidi*) port;
33                    pPort->ProcessMidiEvents(packetList);
34            }
35            
36            static String _getDisplayName(MIDIObjectRef object) {
37                    CFStringRef name = nil;
38                    if (MIDIObjectGetStringProperty(object, kMIDIPropertyDisplayName, &name) != noErr) {
39                            dmsg(1,("CoreMIDI: could not resolve display name of object\n"));
40                            return "";
41                    }
42                    // convert NSString to C string
43                    char* buf = new char[256];
44                    if (!CFStringGetCString(name, buf, 256, kCFStringEncodingUTF8)) {
45                            dmsg(1,("CoreMIDI: could not convert display name string\n"));
46                            delete buf;
47                            return "";
48                    }
49                    String result = buf;
50                    delete buf;
51                    return result;
52            }
53            
54            
55    // *************** ParameterName ***************
56    // *
57    
58          int MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::pPortID = 0;          MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::ParameterName(MidiInputPort* pPort) throw (Exception) : MidiInputPort::ParameterName(pPort, "Port " + ToString(pPort->GetPortNumber())) {
   
         MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::ParameterName(MidiInputPort* pPort) throw (LinuxSamplerException) : MidiInputPort::ParameterName(pPort, "Port " + ToString(pPort->GetPortNumber())) {  
59          OnSetValue(ValueAsString()); // initialize port name          OnSetValue(ValueAsString()); // initialize port name
60      }      }
61    
62      void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::OnSetValue(String s) throw (LinuxSamplerException) {      void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::OnSetValue(String s) throw (Exception) {
63                            //TODO: renaming of port to be implemented
64      }        }
65            
66          // *************** ParameterCoreMidiBindings ***************  // *************** ParameterCoreMidiBindings ***************
67          // *  // *
68    
69      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::ParameterCoreMidiBindings(MidiInputPortCoreMidi* pPort) : DeviceRuntimeParameterStrings( std::vector<String>() ) {      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::ParameterCoreMidiBindings(MidiInputPortCoreMidi* pPort) : DeviceRuntimeParameterStrings( std::vector<String>() ) {
70          this->pPort = pPort;          this->pPort = pPort;
# Line 52  namespace LinuxSampler { Line 79  namespace LinuxSampler {
79    
80      std::vector<String> MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::PossibilitiesAsString() {      std::vector<String> MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::PossibilitiesAsString() {
81          std::vector<String> res;          std::vector<String> res;
82                  // Connections                  
83                    const ItemCount sourceCount = MIDIGetNumberOfSources();
84                    for (ItemCount i = 0; i < sourceCount; ++i) {
85                            MIDIEndpointRef source = MIDIGetSource(i);
86                            res.push_back(
87                                    _getDisplayName(source)
88                            );
89                    }
90                    
91                  return res;                  return res;
92      }      }
93    
94      void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::OnSetValue(std::vector<String> vS) throw (LinuxSamplerException) {      void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterCoreMidiBindings::OnSetValue(std::vector<String> vS) throw (Exception) {
95          // to finish          for (int k = 0; k < vS.size(); ++k) {
96                            const ItemCount sourceCount = MIDIGetNumberOfSources();
97                            for (ItemCount i = 0; i < sourceCount; ++i) {
98                                    MIDIEndpointRef source = MIDIGetSource(i);
99                                    String name = _getDisplayName(source);
100                                    if (name == vS[k]) {
101                                            pPort->connectToSource(source);
102                                            goto matchFound;
103                                    }
104                            }
105                            throw MidiInputException("No CoreMIDI source '" + vS[k] + "' found to connect to");
106                            matchFound:
107                            ; // noop
108                    }
109      }      }
110            
111    // *************** ParameterAutoBind ***************
112    // *
113            
114            MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterAutoBind::ParameterAutoBind(MidiInputPortCoreMidi* pPort)
115                    : DeviceRuntimeParameterBool(false)
116            {
117                    this->pPort = pPort;
118            }
119            
120            String MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterAutoBind::Description() {
121                    return "Whether port shall automatically be connected to all CoreMIDI source endpoints.";
122            }
123            
124            bool MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterAutoBind::Fix() {
125                    return false;
126            }
127            
128            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterAutoBind::OnSetValue(bool b) throw (Exception) {
129                    if (b) pPort->connectToAllSources();
130            }
131    
132    
133  // *************** MidiInputPortCoreMidi ***************  // *************** MidiInputPortCoreMidi ***************
134  // *  // *
135            
136            int MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::pPortID = 0;
137    
138      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::MidiInputPortCoreMidi(MidiInputDeviceCoreMidi* pDevice) throw (MidiInputException) : MidiInputPort(pDevice, -1) {      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::MidiInputPortCoreMidi(MidiInputDeviceCoreMidi* pDevice) throw (MidiInputException) : MidiInputPort(pDevice, -1) {
139                    this->pDevice = pDevice;
140                    
141          // create CoreMidi virtual destination          // create CoreMidi virtual destination
142                    
143                  MIDIDestinationCreate(pDevice->hCoreMidiClient, CFSTR("LinuxSampler_in"), ReadProc, this, &pDestination);             /*  20080105 Toshi Nagata  */
144                    char buf[32];
145                    CFStringRef str;
146                    snprintf(buf, sizeof buf, "LinuxSampler_in_%d", pPortID);
147                    str = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
148                    MIDIDestinationCreate(pDevice->hCoreMidiClient, str, ReadProc, this, &pDestination);
149                    /*  */
150    
151                  if (!pDestination) throw MidiInputException("Error creating CoreMidi virtual destination");                  if (!pDestination) throw MidiInputException("Error creating CoreMidi virtual destination");
152                  this->portNumber = pPortID++;                  this->portNumber = pPortID++;
153                    
154          Parameters["NAME"]      = new ParameterName(this);          Parameters["NAME"]      = new ParameterName(this);
155          Parameters["CORE_MIDI_BINDINGS"] = new ParameterCoreMidiBindings(this);          Parameters["CORE_MIDI_BINDINGS"] = new ParameterCoreMidiBindings(this);
156                    Parameters["AUTO_BIND"] = new ParameterAutoBind(this);
157      }      }
158    
159      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::~MidiInputPortCoreMidi() {      MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::~MidiInputPortCoreMidi() {
160                  MIDIEndpointDispose(pDestination);                  MIDIEndpointDispose(pDestination);
161      }      }
162            
163          void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ReadProc(const MIDIPacketList* pktlist, void* refCon, void* connRefCon)          void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ReadProc(const MIDIPacketList* pktlist, void* refCon, void* connRefCon)
164          {          {
165                  MidiInputPortCoreMidi* port = (MidiInputPortCoreMidi*)refCon;                  MidiInputPortCoreMidi* port = (MidiInputPortCoreMidi*)refCon;
166                  MIDIPacket *packet = (MIDIPacket *)pktlist->packet;                      port->ProcessMidiEvents(pktlist);
167            }
168            
169            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ProcessMidiEvents(const MIDIPacketList *pktlist) {
170                    MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
171                  for (unsigned int i = 0; i < pktlist->numPackets; ++i) {                  for (unsigned int i = 0; i < pktlist->numPackets; ++i) {
172                                            //TODO: To be checked : several events per packet ?
173                          int cin = packet->data[0] & 0xF0;                          DispatchRaw(packet->data);
                           
                         // To be checked : several events per packet  
                   
                         switch(cin) { // status byte  
                           
                                 case 0xB0:  
                                         port->DispatchControlChange(packet->data[1],packet->data[2],packet->data[0]&0x0F);  
                                         break;  
                                           
                                 case 0xE0:  
                                         port->DispatchPitchbend(packet->data[1],packet->data[0]&0x0F);  
                                         break;  
   
                                 case 0x90:  
                                         if (packet->data[1] < 0x80) {  
                                                 if (packet->data[2] > 0){  
                                                         port->DispatchNoteOn(packet->data[1],packet->data[2], packet->data[0]&0x0F);  
                                                 }else{  
                                                         port->DispatchNoteOff(packet->data[1],packet->data[2],packet->data[0]&0x0F);  
                                                 }  
                                         }  
                                         break;  
                                   
                                 case 0x80:  
                                         if (packet->data[1] < 0x80) {  
                                                 port->DispatchNoteOff(packet->data[1],packet->data[2],packet->data[0]&0x0F);  
                                         }  
                                         break;  
                         }  
                           
174                          packet = MIDIPacketNext(packet);                          packet = MIDIPacketNext(packet);
175                  }                        }
176            }
177            
178            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::connectToSource(MIDIEndpointRef source) {
179                    // check if we already have such a connection, if yes, disconnect it first
180                    for (uint i = 0; i < bindings.size(); ++i) {
181                            if (bindings[i] == source) {
182                                    MIDIPortDisconnectSource(pDevice->pBridge, source);
183                                    break;
184                            }
185                    }
186                    // now establish the CoreMIDI connection
187                    MIDIPortConnectSource(pDevice->pBridge, source, this);
188                    // and remember it
189                    bindings.push_back(source);
190            }
191            
192            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::connectToAllSources() {
193                    const ItemCount sourceCount = MIDIGetNumberOfSources();
194                    for (ItemCount i = 0; i < sourceCount; ++i) {
195                            MIDIEndpointRef source = MIDIGetSource(i);
196                            connectToSource(source);
197                            dmsg(1,("Auto binded to CoreMIDI source '%s'\n", _getDisplayName(source).c_str()));
198                    }
199            }
200            
201            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::onNewSourceAppeared(MIDIEndpointRef source) {
202                    if (((ParameterAutoBind*)Parameters["AUTO_BIND"])->ValueAsBool()) {
203                            connectToSource(source);
204                            dmsg(1,("Auto binded to new CoreMIDI source '%s'\n", _getDisplayName(source).c_str()));
205                    }
206          }          }
207            
208            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::onNewSourceDisappeared(MIDIEndpointRef source) {
209                    std::vector<MIDIEndpointRef>::iterator iter = std::find(bindings.begin(), bindings.end(), source);
210                    if (iter != bindings.end()) {
211                            dmsg(1,("CoreMIDI source '%s' disappeared, disconnecting it.\n", _getDisplayName(source).c_str()));
212                            bindings.erase(iter);
213                    }
214            }
215    
216    
217    // *************** MidiInputDeviceCoreMidi ***************
218    // *
219    
220      MidiInputDeviceCoreMidi::MidiInputDeviceCoreMidi(std::map<String,DeviceCreationParameter*> Parameters) : MidiInputDevice(Parameters)      MidiInputDeviceCoreMidi::MidiInputDeviceCoreMidi(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler)
221          {          {
222                  MIDIClientCreate(CFSTR("LinuxSampler"), NotifyProc, NULL, &hCoreMidiClient);                  MIDIClientCreate(CFSTR("LinuxSampler"), NotifyProc, this, &hCoreMidiClient);
223                  if (!hCoreMidiClient) throw MidiInputException("Error opening CoreMidi client");                  if (!hCoreMidiClient) throw MidiInputException("Error opening CoreMidi client");
224                    
225                    OSStatus status = MIDIInputPortCreate(hCoreMidiClient, CFSTR("bridge"), _bridgeInputEvent, this, &pBridge);
226                    if (status != noErr) throw MidiInputException("Could not create bridge port for CoreMIDI client");
227                                                            
228                  AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());                  AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
229          }          }
230    
231      MidiInputDeviceCoreMidi::~MidiInputDeviceCoreMidi()      MidiInputDeviceCoreMidi::~MidiInputDeviceCoreMidi()
232          {          {
233                  if (hCoreMidiClient) {                  if (hCoreMidiClient) {
234                          MIDIClientDispose(hCoreMidiClient);                          MIDIClientDispose(hCoreMidiClient);
235                  }                  }
236      }      }
237            
238          MidiInputDeviceCoreMidi::MidiInputPortCoreMidi* MidiInputDeviceCoreMidi::CreateMidiPort() {          MidiInputDeviceCoreMidi::MidiInputPortCoreMidi* MidiInputDeviceCoreMidi::CreateMidiPort() {
239                  return new MidiInputPortCoreMidi(this);                  return new MidiInputPortCoreMidi(this);
240      }      }
241            
242          String MidiInputDeviceCoreMidi::Name() {          String MidiInputDeviceCoreMidi::Name() {
243              return "COREMIDI";              return "COREMIDI";
244      }      }
# Line 146  namespace LinuxSampler { Line 246  namespace LinuxSampler {
246          String MidiInputDeviceCoreMidi::Driver() {          String MidiInputDeviceCoreMidi::Driver() {
247              return Name();              return Name();
248      }      }
249            
250           String MidiInputDeviceCoreMidi::Description() {           String MidiInputDeviceCoreMidi::Description() {
251              return "Apple CoreMidi";              return "Apple CoreMidi";
252      }      }
253    
254      String MidiInputDeviceCoreMidi::Version() {      String MidiInputDeviceCoreMidi::Version() {
255              String s = "$Revision: 1.5 $";              String s = "$Revision: 1.12 $";
256              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
257      }      }
258    
259          void MidiInputDeviceCoreMidi::NotifyProc(const MIDINotification* message, void* refCon)          void MidiInputDeviceCoreMidi::NotifyProc(const MIDINotification* message, void* refCon)
260          {          {
261                  // to be finished                  MidiInputDeviceCoreMidi* pDevice = (MidiInputDeviceCoreMidi*) refCon;
262                  if (message->messageID == kMIDIMsgSetupChanged) {                  
263                          printf("kMIDIMsgSetupChanged\n");                  switch (message->messageID) {
264                            case kMIDIMsgObjectAdded: {
265                                    MIDIObjectAddRemoveNotification* notification = (MIDIObjectAddRemoveNotification*) message;
266                                    if (notification->childType == kMIDIObjectType_Source) {
267                                            for (std::map<int,MidiInputPort*>::iterator iter = pDevice->Ports.begin();
268                                                     iter != pDevice->Ports.end(); ++iter)
269                                            {
270                                                    MidiInputPortCoreMidi* pPort = (MidiInputPortCoreMidi*) iter->second;
271                                                    MIDIEndpointRef source = (MIDIEndpointRef) notification->child;
272                                                    pPort->onNewSourceAppeared(source);
273                                            }
274                                    }
275                                    break;
276                            }
277                                    
278                            case kMIDIMsgObjectRemoved: {
279                                    MIDIObjectAddRemoveNotification* notification = (MIDIObjectAddRemoveNotification*) message;
280                                    if (notification->childType == kMIDIObjectType_Source) {
281                                            for (std::map<int,MidiInputPort*>::iterator iter = pDevice->Ports.begin();
282                                                     iter != pDevice->Ports.end(); ++iter)
283                                            {
284                                                    MidiInputPortCoreMidi* pPort = (MidiInputPortCoreMidi*) iter->second;
285                                                    MIDIEndpointRef source = (MIDIEndpointRef) notification->child;
286                                                    pPort->onNewSourceDisappeared(source);
287                                            }
288                                    }
289                                    break;
290                            }
291                                    
292                            case kMIDIMsgSetupChanged:
293                            case kMIDIMsgPropertyChanged:
294                            case kMIDIMsgThruConnectionsChanged:
295                            case kMIDIMsgSerialPortOwnerChanged:
296                            case kMIDIMsgIOError:
297                                    break;
298                  }                  }
299          }          }
           
300    
301  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.509  
changed lines
  Added in v.2375

  ViewVC Help
Powered by ViewVC