DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/gui/midi_coreaudio.h
00001 /*
00002  *  Copyright (C) 2002-2013  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (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 
00020 #include <AudioToolbox/AUGraph.h>
00021 #include <CoreServices/CoreServices.h>
00022 
00023 // A macro to simplify error handling a bit.
00024 #define RequireNoErr(error)                                         \
00025 do {                                                                \
00026         err = error;                                                    \
00027         if (err != noErr)                                               \
00028                 goto bail;                                                  \
00029 } while (false)
00030 
00031 class MidiHandler_coreaudio : public MidiHandler {
00032 private:
00033         AUGraph m_auGraph;
00034         AudioUnit m_synth;
00035         const char *soundfont;
00036 public:
00037         MidiHandler_coreaudio() : m_auGraph(0), m_synth(0) {}
00038         const char * GetName(void) { return "coreaudio"; }
00039         bool Open(const char * conf) {
00040                 OSStatus err = 0;
00041 
00042                 if (m_auGraph)
00043                         return false;
00044 
00045                 // Open the Music Device.
00046                 RequireNoErr(NewAUGraph(&m_auGraph));
00047 
00048                 AUNode outputNode, synthNode;
00049                 ComponentDescription desc;
00050 
00051                 // The default output device
00052                 desc.componentType = kAudioUnitType_Output;
00053                 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
00054                 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
00055                 desc.componentFlags = 0;
00056                 desc.componentFlagsMask = 0;
00057                 RequireNoErr(AUGraphNewNode(m_auGraph, &desc, 0, NULL, &outputNode));
00058 
00059                 // The built-in default (softsynth) music device
00060                 desc.componentType = kAudioUnitType_MusicDevice;
00061                 desc.componentSubType = kAudioUnitSubType_DLSSynth;
00062                 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
00063                 RequireNoErr(AUGraphNewNode(m_auGraph, &desc, 0, NULL, &synthNode));
00064 
00065                 // Connect the softsynth to the default output
00066                 RequireNoErr(AUGraphConnectNodeInput(m_auGraph, synthNode, 0, outputNode, 0));
00067 
00068                 // Open and initialize the whole graph
00069                 RequireNoErr(AUGraphOpen(m_auGraph));
00070                 RequireNoErr(AUGraphInitialize(m_auGraph));
00071 
00072                 // Get the music device from the graph.
00073                 RequireNoErr(AUGraphGetNodeInfo(m_auGraph, synthNode, NULL, NULL, NULL, &m_synth));
00074 
00075                 // Optionally load a soundfont 
00076                 if (conf && conf[0]) {
00077                   soundfont = conf;
00078                   FSRef soundfontRef;
00079                   RequireNoErr(FSPathMakeRef((const UInt8*)soundfont, &soundfontRef, NULL));
00080                   RequireNoErr(AudioUnitSetProperty(
00081                                                     m_synth,
00082                                                     kMusicDeviceProperty_SoundBankFSRef, 
00083                                                     kAudioUnitScope_Global,
00084                                                     0,
00085                                                     &soundfontRef,
00086                                                     sizeof(soundfontRef)
00087                                                     ));
00088                   LOG_MSG("MIDI:coreaudio: loaded soundfont: %s",soundfont);
00089                 } 
00090 
00091                 // Finally: Start the graph!
00092                 RequireNoErr(AUGraphStart(m_auGraph));
00093 
00094                 return true;
00095 
00096         bail:
00097                 if (m_auGraph) {
00098                         AUGraphStop(m_auGraph);
00099                         DisposeAUGraph(m_auGraph);
00100                         m_auGraph = 0;
00101                 }
00102                 return false;
00103         }
00104 
00105         void Close(void) {
00106                 if (m_auGraph) {
00107                         AUGraphStop(m_auGraph);
00108                         DisposeAUGraph(m_auGraph);
00109                         m_auGraph = 0;
00110                 }
00111         }
00112 
00113         void PlayMsg(Bit8u * msg) {
00114                 MusicDeviceMIDIEvent(m_synth, msg[0], msg[1], msg[2], 0);
00115         }       
00116 
00117         void PlaySysex(Bit8u * sysex, Bitu len) {
00118                 MusicDeviceSysEx(m_synth, sysex, len);
00119         }
00120 };
00121 
00122 #undef RequireNoErr
00123 
00124 MidiHandler_coreaudio Midi_coreaudio;