/[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 2369 by persson, Sat Apr 18 08:17:16 2009 UTC revision 2370 by schoenebeck, Wed Sep 19 13:11:45 2012 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   Copyright (C) 2004, 2005 Grame                                        *   *   Copyright (C) 2004, 2005 Grame                                        *
4   *   Copyright (C) 2005 - 2009 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2012 Christian Schoenebeck                       *
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 23  Line 23 
23  #include "MidiInputDeviceFactory.h"  #include "MidiInputDeviceFactory.h"
24    
25  namespace LinuxSampler {  namespace LinuxSampler {
26            
27          int MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::pPortID = 0;  // *************** 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          MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::ParameterName(MidiInputPort* pPort) throw (Exception) : MidiInputPort::ParameterName(pPort, "Port " + ToString(pPort->GetPortNumber())) {          MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ParameterName::ParameterName(MidiInputPort* pPort) throw (Exception) : 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 (Exception) {      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 50  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 (Exception) {      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             /*  20080105 Toshi Nagata  */             /*  20080105 Toshi Nagata  */
# Line 78  namespace LinuxSampler { Line 153  namespace LinuxSampler {
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() {
# Line 87  namespace LinuxSampler { Line 163  namespace LinuxSampler {
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                    port->ProcessMidiEvents(pktlist);
167            }
168            
169            void MidiInputDeviceCoreMidi::MidiInputPortCoreMidi::ProcessMidiEvents(const MIDIPacketList *pktlist) {
170                  MIDIPacket *packet = (MIDIPacket *)pktlist->packet;                  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                          // To be checked : several events per packet                          DispatchRaw(packet->data);
   
                         port->DispatchRaw(packet->data);  
   
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                    //TODO: remove source from 'bindings' list eventually
210            }
211    
212    
213  // *************** MidiInputDeviceCoreMidi ***************  // *************** MidiInputDeviceCoreMidi ***************
# Line 105  namespace LinuxSampler { Line 215  namespace LinuxSampler {
215    
216      MidiInputDeviceCoreMidi::MidiInputDeviceCoreMidi(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler)      MidiInputDeviceCoreMidi::MidiInputDeviceCoreMidi(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler)
217          {          {
218                  MIDIClientCreate(CFSTR("LinuxSampler"), NotifyProc, NULL, &hCoreMidiClient);                  MIDIClientCreate(CFSTR("LinuxSampler"), NotifyProc, this, &hCoreMidiClient);
219                  if (!hCoreMidiClient) throw MidiInputException("Error opening CoreMidi client");                  if (!hCoreMidiClient) throw MidiInputException("Error opening CoreMidi client");
220                    
221                    OSStatus status = MIDIInputPortCreate(hCoreMidiClient, CFSTR("bridge"), _bridgeInputEvent, this, &pBridge);
222                    if (status != noErr) throw MidiInputException("Could not create bridge port for CoreMIDI client");
223                                                            
224                  AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());                  AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
225          }          }
226    
# Line 140  namespace LinuxSampler { Line 254  namespace LinuxSampler {
254    
255          void MidiInputDeviceCoreMidi::NotifyProc(const MIDINotification* message, void* refCon)          void MidiInputDeviceCoreMidi::NotifyProc(const MIDINotification* message, void* refCon)
256          {          {
257                  // to be finished                  MidiInputDeviceCoreMidi* pDevice = (MidiInputDeviceCoreMidi*) refCon;
258                  if (message->messageID == kMIDIMsgSetupChanged) {                  
259                          printf("kMIDIMsgSetupChanged\n");                  switch (message->messageID) {
260                            case kMIDIMsgObjectAdded: {
261                                    MIDIObjectAddRemoveNotification* notification = (MIDIObjectAddRemoveNotification*) message;
262                                    if (notification->childType == kMIDIObjectType_Source) {
263                                            for (std::map<int,MidiInputPort*>::iterator iter = pDevice->Ports.begin();
264                                                     iter != pDevice->Ports.end(); ++iter)
265                                            {
266                                                    MidiInputPortCoreMidi* pPort = (MidiInputPortCoreMidi*) iter->second;
267                                                    MIDIEndpointRef source = (MIDIEndpointRef) notification->child;
268                                                    pPort->onNewSourceAppeared(source);
269                                            }
270                                    }
271                                    break;
272                            }
273                                    
274                            case kMIDIMsgObjectRemoved: {
275                                    MIDIObjectAddRemoveNotification* notification = (MIDIObjectAddRemoveNotification*) message;
276                                    if (notification->childType == kMIDIObjectType_Source) {
277                                            for (std::map<int,MidiInputPort*>::iterator iter = pDevice->Ports.begin();
278                                                     iter != pDevice->Ports.end(); ++iter)
279                                            {
280                                                    MidiInputPortCoreMidi* pPort = (MidiInputPortCoreMidi*) iter->second;
281                                                    MIDIEndpointRef source = (MIDIEndpointRef) notification->child;
282                                                    pPort->onNewSourceDisappeared(source);
283                                            }
284                                    }
285                                    break;
286                            }
287                                    
288                            case kMIDIMsgSetupChanged:
289                            case kMIDIMsgPropertyChanged:
290                            case kMIDIMsgThruConnectionsChanged:
291                            case kMIDIMsgSerialPortOwnerChanged:
292                            case kMIDIMsgIOError:
293                                    break;
294                  }                  }
295          }          }
296    
   
297  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2369  
changed lines
  Added in v.2370

  ViewVC Help
Powered by ViewVC