CoreAudioMidiDriver.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2003  The Pentagram Team
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #include "pent_include.h"
00020 #include "CoreAudioMidiDriver.h"
00021 
00022 #ifdef USE_CORE_AUDIO_MIDI
00023 
00024 #include <pthread.h>
00025 #include <sched.h>
00026 
00027 
00028 // Enable the following switch to make ScummVM try to use native MIDI hardware
00029 // on your computer for MIDI output. This is currently quite hackish, in 
00030 // particular you have no way to specify which device is used (it just always
00031 // uses the first output device it can find), nor is there a switch to
00032 // force it to use the soft synth instead of the MIDI HW.
00033 //#define ENABLE_HACKISH_NATIVE_MIDI_SUPPORT 1
00034 
00035 
00036 const MidiDriver::MidiDriverDesc CoreAudioMidiDriver::desc = 
00037                 MidiDriver::MidiDriverDesc ("CoreAudio", createInstance);
00038 
00039 CoreAudioMidiDriver::CoreAudioMidiDriver() : 
00040         au_MusicDevice(0), au_output(0),
00041         mClient(0), mOutPort(0), mDest(0)
00042 {
00043         OSStatus err;
00044         err = MIDIClientCreate(CFSTR("Pentagram MIDI Driver for OS X"), NULL, NULL, &mClient);
00045 
00046 }
00047 
00048 CoreAudioMidiDriver::~CoreAudioMidiDriver()
00049 {
00050         if (mClient)
00051                 MIDIClientDispose(mClient);
00052         mClient = 0;
00053 }
00054 
00055 int CoreAudioMidiDriver::open()
00056 {
00057         if (au_output || mDest)
00058                 return 1;
00059 
00060         OSStatus err = noErr;
00061 
00062         mOutPort = 0;
00063 #ifdef ENABLE_HACKISH_NATIVE_MIDI_SUPPORT
00064         int dests = MIDIGetNumberOfDestinations();
00065         if (dests > 0 && mClient) {
00066                 mDest = MIDIGetDestination(0);
00067                 err = MIDIOutputPortCreate( mClient, 
00068                                                                         CFSTR("scummvm_output_port"), 
00069                                                                         &mOutPort);
00070         }
00071 #endif
00072 
00073         if (err != noErr || !mOutPort) {
00074                 AudioUnitConnection auconnect;
00075                 ComponentDescription compdesc;
00076                 Component compid;
00077         
00078                 // Open the Music Device
00079                 compdesc.componentType = kAudioUnitComponentType;
00080                 compdesc.componentSubType = kAudioUnitSubType_MusicDevice;
00081                 compdesc.componentManufacturer = kAudioUnitID_DLSSynth;
00082                 compdesc.componentFlags = 0;
00083                 compdesc.componentFlagsMask = 0;
00084                 compid = FindNextComponent(NULL, &compdesc);
00085                 au_MusicDevice = static_cast<AudioUnit>(OpenComponent(compid));
00086         
00087                 // open the output unit
00088                 au_output = static_cast<AudioUnit>(OpenDefaultComponent(kAudioUnitComponentType, kAudioUnitSubType_Output));
00089         
00090                 // connect the units
00091                 auconnect.sourceAudioUnit = au_MusicDevice;
00092                 auconnect.sourceOutputNumber = 0;
00093                 auconnect.destInputNumber = 0;
00094                 err =
00095                         AudioUnitSetProperty(au_output, kAudioUnitProperty_MakeConnection, kAudioUnitScope_Input, 0,
00096                                                                                                          static_cast<void*>(&auconnect), sizeof(AudioUnitConnection));
00097         
00098                 // initialize the units
00099                 AudioUnitInitialize(au_MusicDevice);
00100                 AudioUnitInitialize(au_output);
00101         
00102                 // start the output
00103                 AudioOutputUnitStart(au_output);
00104         }
00105 
00106         return 0;
00107 }
00108 
00109 void CoreAudioMidiDriver::close()
00110 {
00111         if (mOutPort && mDest) {
00112                 MIDIPortDispose(mOutPort);
00113                 mOutPort = 0;
00114                 mDest = 0;
00115         } else {
00116                 // Stop the output
00117                 AudioOutputUnitStop(au_output);
00118         
00119                 // Cleanup
00120                 CloseComponent(au_output);
00121                 au_output = 0;
00122                 CloseComponent(au_MusicDevice);
00123                 au_MusicDevice = 0;
00124         }
00125 }
00126 
00127 void CoreAudioMidiDriver::send(uint32 message)
00128 {
00129         uint8 status_byte = (message & 0x000000FF);
00130         uint8 first_byte = (message & 0x0000FF00) >> 8;
00131         uint8 second_byte = (message & 0x00FF0000) >> 16;
00132 
00133         if (mOutPort && mDest) {
00134                 MIDIPacketList packetList;
00135                 MIDIPacket *packet = &packetList.packet[0];
00136                 
00137                 packetList.numPackets = 1;
00138         
00139                 packet->timeStamp = 0;
00140                 packet->length = 3;
00141                 packet->data[0] = status_byte;
00142                 packet->data[1] = first_byte;
00143                 packet->data[2] = second_byte;
00144         
00145                 MIDISend(mOutPort, mDest, &packetList);
00146         } else {
00147                 assert(au_output != NULL);
00148                 assert(au_MusicDevice != NULL);
00149                 MusicDeviceMIDIEvent(au_MusicDevice, status_byte, first_byte, second_byte, 0);
00150         }
00151 }
00152 
00153 void CoreAudioMidiDriver::send_sysex (uint8 status, const uint8 *msg, uint16 length)
00154 {
00155         uint8 buf[384];
00156 
00157         if (mOutPort && mDest) {
00158                 MIDIPacketList *packetList = (MIDIPacketList *)buf;
00159                 MIDIPacket *packet = packetList->packet;
00160 
00161                 assert(sizeof(buf) >= sizeof(UInt32) + sizeof(MIDITimeStamp) + sizeof(UInt16) + length + 2);
00162                 
00163                 packetList->numPackets = 1;
00164 
00165                 packet->timeStamp = 0;
00166                 
00167                 // Add SysEx frame
00168                 packet->length = length + 2;
00169                 packet->data[0] = status;
00170                 memcpy(packet->data + 1, msg, length);
00171                 packet->data[length + 1] = 0xF7;
00172         
00173                 MIDISend(mOutPort, mDest, packetList);
00174         } else {
00175                 assert(sizeof(buf) >= (size_t)length + 2);
00176                 assert(au_output != NULL);
00177                 assert(au_MusicDevice != NULL);
00178 
00179                 // Add SysEx frame
00180                 buf[0] = status;
00181                 memcpy(buf+1, msg, length);
00182                 buf[length+1] = 0xF7;
00183 
00184                 MusicDeviceSysEx(au_MusicDevice, buf, length + 2);
00185         }
00186 }
00187 
00188 void CoreAudioMidiDriver::increaseThreadPriority()
00189 {
00190         pthread_t self;
00191         int policy;
00192         struct sched_param param;
00193         
00194         self = pthread_self();
00195         pthread_getschedparam(self, &policy, &param);
00196         param.sched_priority = sched_get_priority_max(policy);
00197         pthread_setschedparam(self, policy, &param);
00198 }
00199 
00200 void CoreAudioMidiDriver::yield()
00201 {
00202         sched_yield();
00203 }
00204 
00205 #endif //MACOSX

Generated on Fri Jul 27 22:27:13 2007 for pentagram by  doxygen 1.4.7