[Pentagram-cvs] SF.net SVN: pentagram:[2549] pentagram/trunk
Status: Pre-Alpha
Brought to you by:
wjpalenstijn
|
From: <do...@us...> - 2013-04-05 00:45:01
|
Revision: 2549
http://pentagram.svn.sourceforge.net/pentagram/?rev=2549&view=rev
Author: dominus
Date: 2013-04-05 00:44:54 +0000 (Fri, 05 Apr 2013)
Log Message:
-----------
backported CoreAudio changes from ScummVM and Exult.
Modified Paths:
--------------
pentagram/trunk/ChangeLog
pentagram/trunk/audio/midi/CoreAudioMidiDriver.cpp
pentagram/trunk/audio/midi/CoreAudioMidiDriver.h
Modified: pentagram/trunk/ChangeLog
===================================================================
--- pentagram/trunk/ChangeLog 2013-02-11 22:17:25 UTC (rev 2548)
+++ pentagram/trunk/ChangeLog 2013-04-05 00:44:54 UTC (rev 2549)
@@ -1,3 +1,7 @@
+2013-04-05 Dominik Reichardt <do...@us...>
+ * audio/midi/CoreAudioMidiDriver.*: backported changes from ScummVM
+ and Exult.
+
2013-01-06 Willem Jan Palenstijn <wjp...@us...>
* misc/Console.cpp: Fix crash when using removed console commands
Modified: pentagram/trunk/audio/midi/CoreAudioMidiDriver.cpp
===================================================================
--- pentagram/trunk/audio/midi/CoreAudioMidiDriver.cpp 2013-02-11 22:17:25 UTC (rev 2548)
+++ pentagram/trunk/audio/midi/CoreAudioMidiDriver.cpp 2013-04-05 00:44:54 UTC (rev 2549)
@@ -1,5 +1,8 @@
/*
-Copyright (C) 2003-2009 The Pentagram Team
+Code originally written by Max Horn for ScummVM,
+later improvements by Matthew Hoops,
+minor tweaks by various other people of the ScummVM, Pentagram
+and Exult teams.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -18,6 +21,7 @@
#include "pent_include.h"
#include "CoreAudioMidiDriver.h"
+#include "SettingManager.h"
#ifdef USE_CORE_AUDIO_MIDI
@@ -26,194 +30,190 @@
#include <iostream>
-// Enable the following switch to make ScummVM try to use native MIDI hardware
-// on your computer for MIDI output. This is currently quite hackish, in
-// particular you have no way to specify which device is used (it just always
-// uses the first output device it can find), nor is there a switch to
-// force it to use the soft synth instead of the MIDI HW.
-//#define ENABLE_HACKISH_NATIVE_MIDI_SUPPORT 1
+// With the release of Mac OS X 10.5 in October 2007, Apple deprecated the
+// AUGraphNewNode & AUGraphGetNodeInfo APIs in favor of the new AUGraphAddNode &
+// AUGraphNodeInfo APIs. While it is easy to switch to those, it breaks
+// compatibility with all pre-10.5 systems.
+//
+// Since 10.5 was the last system to support PowerPC, we use the old, deprecated
+// APIs on PowerPC based systems by default. On all other systems (such as Mac
+// OS X running on Intel hardware, or iOS running on ARM), we use the new API by
+// default.
+//
+// This leaves Mac OS X 10.4 running on x86 processors as the only system
+// combination that this code will not support by default. It seems quite
+// reasonable to assume that anybody with an Intel system has since then moved
+// on to a newer Mac OS X release. But if for some reason you absolutely need to
+// build an x86 version of this code using the old, deprecated API, you can
+// simply do so by manually enable the USE_DEPRECATED_COREAUDIO_API switch (e.g.
+// by adding setting it suitably in CPPFLAGS).
+#if !defined(USE_DEPRECATED_COREAUDIO_API)
+# if TARGET_CPU_PPC || TARGET_CPU_PPC64
+# define USE_DEPRECATED_COREAUDIO_API 1
+# else
+# define USE_DEPRECATED_COREAUDIO_API 0
+# endif
+#endif
+// A macro to simplify error handling a bit.
+#define RequireNoErr(error) \
+do { \
+err = error; \
+if (err != noErr) \
+goto bail; \
+} while (false)
+
const MidiDriver::MidiDriverDesc CoreAudioMidiDriver::desc =
MidiDriver::MidiDriverDesc ("CoreAudio", createInstance);
-CoreAudioMidiDriver::CoreAudioMidiDriver() :
- au_MusicDevice(0), au_output(0),
- mClient(0), mOutPort(0), mDest(0)
-{
- OSStatus err;
- err = MIDIClientCreate(CFSTR("Pentagram MIDI Driver for OS X"), NULL, NULL, &mClient);
+CoreAudioMidiDriver::CoreAudioMidiDriver() :
+ _auGraph(0) {
+ }
-}
-
-CoreAudioMidiDriver::~CoreAudioMidiDriver()
-{
- if (mClient)
- MIDIClientDispose(mClient);
- mClient = 0;
-}
-
-int CoreAudioMidiDriver::open()
-{
- if (au_output || mDest)
+int CoreAudioMidiDriver::open() {
+ OSStatus err = noErr;
+ SettingManager* setting = SettingManager::get_instance();
+
+ if (_auGraph)
return 1;
- OSStatus err = noErr;
+ // Open the Music Device.
+ RequireNoErr(NewAUGraph(&_auGraph));
+ AUNode outputNode, synthNode;
+ // OS X 10.5 SDK doesn't know AudioComponentDescription desc;
+#if USE_DEPRECATED_COREAUDIO_API || (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
+ ComponentDescription desc;
+#else
+ AudioComponentDescription desc;
+#endif
+
+ // The default output device
+ desc.componentType = kAudioUnitType_Output;
+ desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+ desc.componentFlags = 0;
+ desc.componentFlagsMask = 0;
+#if USE_DEPRECATED_COREAUDIO_API
+ RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &outputNode));
+#else
+ RequireNoErr(AUGraphAddNode(_auGraph, &desc, &outputNode));
+#endif
- mOutPort = 0;
-#ifdef ENABLE_HACKISH_NATIVE_MIDI_SUPPORT
- int dests = MIDIGetNumberOfDestinations();
- if (dests > 0 && mClient) {
- mDest = MIDIGetDestination(0);
- err = MIDIOutputPortCreate( mClient,
- CFSTR("scummvm_output_port"),
- &mOutPort);
- }
+ // The built-in default (softsynth) music device
+ desc.componentType = kAudioUnitType_MusicDevice;
+ desc.componentSubType = kAudioUnitSubType_DLSSynth;
+ desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+#if USE_DEPRECATED_COREAUDIO_API
+ RequireNoErr(AUGraphNewNode(_auGraph, &desc, 0, NULL, &synthNode));
+#else
+ RequireNoErr(AUGraphAddNode(_auGraph, &desc, &synthNode));
#endif
- if (err != noErr || !mOutPort) {
- AudioUnitConnection auconnect;
- ComponentDescription compdesc;
- Component compid;
+ // Connect the softsynth to the default output
+ RequireNoErr(AUGraphConnectNodeInput(_auGraph, synthNode, 0, outputNode, 0));
- // Open the Music Device
- compdesc.componentType = kAudioUnitType_MusicDevice;
- compdesc.componentSubType = kAudioUnitSubType_DLSSynth;
- compdesc.componentManufacturer = kAudioUnitManufacturer_Apple;
- compdesc.componentFlags = 0;
- compdesc.componentFlagsMask = 0;
- compid = FindNextComponent(NULL, &compdesc);
- au_MusicDevice = static_cast<AudioUnit>(OpenComponent(compid));
+ // Open and initialize the whole graph
+ RequireNoErr(AUGraphOpen(_auGraph));
+ RequireNoErr(AUGraphInitialize(_auGraph));
- // open the output unit
- au_output = static_cast<AudioUnit>(OpenDefaultComponent(kAudioUnitType_Output, kAudioUnitSubType_DefaultOutput));
+ // Get the music device from the graph.
+#if USE_DEPRECATED_COREAUDIO_API
+ RequireNoErr(AUGraphGetNodeInfo(_auGraph, synthNode, NULL, NULL, NULL, &_synth));
+#else
+ RequireNoErr(AUGraphNodeInfo(_auGraph, synthNode, NULL, &_synth));
+#endif
- // connect the units
- auconnect.sourceAudioUnit = au_MusicDevice;
- auconnect.sourceOutputNumber = 0;
- auconnect.destInputNumber = 0;
- err =
- AudioUnitSetProperty(au_output, kAudioUnitProperty_MakeConnection,
- kAudioUnitScope_Input, 0,
- static_cast<void*>(&auconnect),
- sizeof(AudioUnitConnection));
-
- // initialize the units
- AudioUnitInitialize(au_MusicDevice);
- AudioUnitInitialize(au_output);
-
- // load a soundfont
- std::string soundfont = getConfigSetting("soundfont", "");
- pout << "Loading CoreAudio SoundFont '" << soundfont << "'... ";
- if (soundfont != "") {
- FSRef soundfontRef;
- err = FSPathMakeRef((const UInt8*)soundfont.c_str(),
- &soundfontRef, NULL);
- if (!err) {
- err = AudioUnitSetProperty(
- au_MusicDevice,
- kMusicDeviceProperty_SoundBankFSRef,
- kAudioUnitScope_Global,
- 0,
- &soundfontRef,
- sizeof(soundfontRef)
- );
+ // Load custom soundfont, if specified
+ if (setting->exists("soundfont")){
+ std::string soundfont = getConfigSetting("soundfont", "");
+ if (soundfont != "") {
+ pout << "Loading CoreAudio SoundFont '" << soundfont << "'" << std::endl;
+ OSErr err;
+#if USE_DEPRECATED_COREAUDIO_API
+ FSRef fsref;
+ err = FSPathMakeRef(reinterpret_cast<const UInt8 *>(soundfont.c_str()), &fsref, NULL);
if (!err) {
+ err = AudioUnitSetProperty(
+ _synth, kMusicDeviceProperty_SoundBankFSRef,
+ kAudioUnitScope_Global, 0, &fsref, sizeof(fsref));
+ }
+#else
+ // kMusicDeviceProperty_SoundBankFSSpec is present on 10.6+, but broken
+ // kMusicDeviceProperty_SoundBankURL was added in 10.5 as a replacement
+ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
+ reinterpret_cast<const UInt8 *>(soundfont.c_str()),
+ soundfont.size(), false);
+ if (url) {
+ err = AudioUnitSetProperty(
+ _synth, kMusicDeviceProperty_SoundBankURL,
+ kAudioUnitScope_Global, 0, &url, sizeof(url));
+ CFRelease(url);
+ } else {
+ pout << "Failed to allocate CFURLRef from '" << soundfont << "'" << std::endl;
+ }
+#endif
+ if (!err) {
pout << "Loaded CoreAudio SoundFont!" << std::endl;
} else {
- pout << "Error loading CoreAudio SoundFont" << std::endl;
+ pout << "Error loading CoreAudio SoundFont '" << soundfont << "'" << std::endl;
+ // after trying and failing to load a soundfont it's better
+ // to fail initializing the CoreAudio driver or it might crash
+ return 1;
}
} else {
pout << "CoreAudio SoundFont Path Error" << std::endl;
}
}
-
- // start the output
- AudioOutputUnitStart(au_output);
- }
- return 0;
-}
+ // Finally: Start the graph!
+ RequireNoErr(AUGraphStart(_auGraph));
-void CoreAudioMidiDriver::close()
-{
- if (mOutPort && mDest) {
- MIDIPortDispose(mOutPort);
- mOutPort = 0;
- mDest = 0;
- } else {
- // Stop the output
- AudioOutputUnitStop(au_output);
-
- // Cleanup
- CloseComponent(au_output);
- au_output = 0;
- CloseComponent(au_MusicDevice);
- au_MusicDevice = 0;
+ return 0;
+
+bail:
+ if (_auGraph) {
+ AUGraphStop(_auGraph);
+ DisposeAUGraph(_auGraph);
+ _auGraph = 0;
+ }
+ return 0;
+}
+
+void CoreAudioMidiDriver::close() {
+ // Stop the output
+ if (_auGraph) {
+ AUGraphStop(_auGraph);
+ DisposeAUGraph(_auGraph);
+ _auGraph = 0;
}
}
-void CoreAudioMidiDriver::send(uint32 message)
-{
+void CoreAudioMidiDriver::send(uint32 message) {
uint8 status_byte = (message & 0x000000FF);
uint8 first_byte = (message & 0x0000FF00) >> 8;
uint8 second_byte = (message & 0x00FF0000) >> 16;
- if (mOutPort && mDest) {
- MIDIPacketList packetList;
- MIDIPacket *packet = &packetList.packet[0];
-
- packetList.numPackets = 1;
-
- packet->timeStamp = 0;
- packet->length = 3;
- packet->data[0] = status_byte;
- packet->data[1] = first_byte;
- packet->data[2] = second_byte;
-
- MIDISend(mOutPort, mDest, &packetList);
- } else {
- assert(au_output != NULL);
- assert(au_MusicDevice != NULL);
- MusicDeviceMIDIEvent(au_MusicDevice, status_byte, first_byte, second_byte, 0);
- }
+ assert(_auGraph != NULL);
+ MusicDeviceMIDIEvent(_synth, status_byte, first_byte, second_byte, 0);
}
-void CoreAudioMidiDriver::send_sysex (uint8 status, const uint8 *msg, uint16 length)
-{
+
+void CoreAudioMidiDriver::send_sysex(uint8 status, const uint8 *msg, uint16 length) {
uint8 buf[384];
- if (mOutPort && mDest) {
- MIDIPacketList *packetList = (MIDIPacketList *)buf;
- MIDIPacket *packet = packetList->packet;
+ assert(sizeof(buf) >= static_cast<size_t>(length) + 2);
+ assert(_auGraph != NULL);
- assert(sizeof(buf) >= sizeof(UInt32) + sizeof(MIDITimeStamp) + sizeof(UInt16) + length + 2);
-
- packetList->numPackets = 1;
+ // Add SysEx frame
+ buf[0] = status;
+ memcpy(buf + 1, msg, length);
+ buf[length + 1] = 0xF7;
- packet->timeStamp = 0;
-
- // Add SysEx frame
- packet->length = length + 2;
- packet->data[0] = status;
- memcpy(packet->data + 1, msg, length);
- packet->data[length + 1] = 0xF7;
-
- MIDISend(mOutPort, mDest, packetList);
- } else {
- assert(sizeof(buf) >= (size_t)length + 2);
- assert(au_output != NULL);
- assert(au_MusicDevice != NULL);
+ MusicDeviceSysEx(_synth, buf, length + 2);
+}
- // Add SysEx frame
- buf[0] = status;
- memcpy(buf+1, msg, length);
- buf[length+1] = 0xF7;
- MusicDeviceSysEx(au_MusicDevice, buf, length + 2);
- }
-}
-
void CoreAudioMidiDriver::increaseThreadPriority()
{
pthread_t self;
Modified: pentagram/trunk/audio/midi/CoreAudioMidiDriver.h
===================================================================
--- pentagram/trunk/audio/midi/CoreAudioMidiDriver.h 2013-02-11 22:17:25 UTC (rev 2548)
+++ pentagram/trunk/audio/midi/CoreAudioMidiDriver.h 2013-04-05 00:44:54 UTC (rev 2549)
@@ -1,5 +1,7 @@
/*
-Copyright (C) 2003-2009 The Pentagram Team
+Code originally written by Max Horn for ScummVM,
+minor tweaks by various other people of the ScummVM, Pentagram
+and Exult teams.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -16,6 +18,7 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+
#ifndef COREAUDIOMIDIDRIVER_H_INCLUDED
#define COREAUDIOMIDIDRIVER_H_INCLUDED
@@ -24,19 +27,14 @@
#include "LowLevelMidiDriver.h"
-#include <AudioUnit/AudioUnit.h>
-#include <CoreMIDI/CoreMIDI.h>
+#include <AudioToolbox/AUGraph.h>
#include <CoreServices/CoreServices.h>
class CoreAudioMidiDriver : public LowLevelMidiDriver
{
- AudioUnit au_MusicDevice;
- AudioUnit au_output;
+ AUGraph _auGraph;
+ AudioUnit _synth;
- MIDIClientRef mClient;
- MIDIPortRef mOutPort;
- MIDIEndpointRef mDest;
-
static const MidiDriverDesc desc;
static MidiDriver *createInstance() {
return new CoreAudioMidiDriver();
@@ -46,7 +44,6 @@
static const MidiDriverDesc* getDesc() { return &desc; }
CoreAudioMidiDriver();
- ~CoreAudioMidiDriver();
protected:
virtual int open();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|