summaryrefslogtreecommitdiff
path: root/libs/midi++2/coremidi_midiport.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/midi++2/coremidi_midiport.cc')
-rw-r--r--libs/midi++2/coremidi_midiport.cc144
1 files changed, 144 insertions, 0 deletions
diff --git a/libs/midi++2/coremidi_midiport.cc b/libs/midi++2/coremidi_midiport.cc
new file mode 100644
index 0000000000..8d1d927b7b
--- /dev/null
+++ b/libs/midi++2/coremidi_midiport.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2004 Paul Davis
+ Copyright (C) 2004 Grame
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <fcntl.h>
+#include <cerrno>
+
+#include <midi++/coremidi_midiport.h>
+#include <midi++/types.h>
+#include <midi++/port_request.h>
+#include <mach/mach_time.h>
+
+#include <pbd/pthread_utils.h>
+
+using namespace std;
+using namespace MIDI;
+
+MIDITimeStamp CoreMidi_MidiPort::MIDIGetCurrentHostTime()
+{
+ return mach_absolute_time();
+}
+
+CoreMidi_MidiPort::CoreMidi_MidiPort (PortRequest &req) : Port (req)
+{
+ firstrecv = true;
+ int err;
+ if (0 == (err = Open(req))) {
+ _ok = true;
+ req.status = PortRequest::OK;
+ } else
+ req.status = PortRequest::Unknown;
+}
+
+CoreMidi_MidiPort::~CoreMidi_MidiPort () {Close();}
+
+void CoreMidi_MidiPort::Close ()
+{
+ if (midi_destination) MIDIEndpointDispose(midi_destination);
+ if (midi_source) MIDIEndpointDispose(midi_source);
+ if (midi_client) MIDIClientDispose(midi_client);
+}
+
+int CoreMidi_MidiPort::write (byte *msg, size_t msglen)
+{
+ OSStatus err;
+ MIDIPacketList* pktlist = (MIDIPacketList*)midi_buffer;
+ MIDIPacket* packet = MIDIPacketListInit(pktlist);
+ packet = MIDIPacketListAdd(pktlist,sizeof(midi_buffer),packet,MIDIGetCurrentHostTime(),msglen,msg);
+
+ if (packet) {
+
+ err = MIDIReceived(midi_source,pktlist);
+ if (err != noErr) {
+ //error << "MIDIReceived error" << err << endmsg.
+ }
+
+ bytes_written += msglen;
+ return msglen;
+ }else{
+ return 0;
+ }
+}
+
+int CoreMidi_MidiPort::Open (PortRequest &req)
+{
+ OSStatus err;
+ CFStringRef coutputStr;
+ string str;
+
+ coutputStr = CFStringCreateWithCString(0, req.devname, CFStringGetSystemEncoding());
+ err = MIDIClientCreate(coutputStr, 0, 0, &midi_client);
+ CFRelease(coutputStr);
+ if (!midi_client) {
+ //error << "Cannot open CoreMidi client : " << err << endmsg.
+ goto error;
+ }
+
+ str = req.tagname + string("_in");
+ coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
+ err = MIDIDestinationCreate(midi_client, coutputStr, read_proc, this, &midi_destination);
+ CFRelease(coutputStr);
+ if (!midi_destination) {
+ //error << "Cannot create CoreMidi destination : " << err << endmsg.
+ goto error;
+ }
+
+ str = req.tagname + string("_out");
+ coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
+ err = MIDISourceCreate(midi_client, coutputStr, &midi_source);
+ CFRelease(coutputStr);
+ if (!midi_source) {
+ //error << "Cannot create CoreMidi source : " << err << endmsg.
+ goto error;
+ }
+
+ return err;
+
+error:
+ Close();
+ return err;
+}
+
+void CoreMidi_MidiPort::read_proc (const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
+{
+ CoreMidi_MidiPort* driver = (CoreMidi_MidiPort*)refCon;
+ MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
+
+ if (driver->firstrecv) {
+ driver->firstrecv = false;
+ PBD::ThreadCreated (pthread_self(), "COREMIDI");
+ }
+
+ for (unsigned int i = 0; i < pktlist->numPackets; ++i) {
+
+ driver->bytes_read += packet->length;
+
+ if (driver->input_parser) {
+ driver->input_parser->raw_preparse (*driver->input_parser, packet->data, packet->length);
+ for (int i = 0; i < packet->length; i++) {
+ driver->input_parser->scanner (packet->data[i]);
+ }
+ driver->input_parser->raw_postparse (*driver->input_parser, packet->data, packet->length);
+ }
+
+ packet = MIDIPacketNext(packet);
+ }
+}
+