From d8d4fd294a7ed7b9e4933467aa389003303bb867 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 19 Oct 2009 00:41:30 +0000 Subject: [PATCH] Added volume control to Mac OS X Core MIDI native midi backend. --- configure.in | 2 +- native_midi/native_midi_macosx.c | 94 ++++++++++++++++++++++++++++---- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/configure.in b/configure.in index 9280107a..d8835c3e 100644 --- a/configure.in +++ b/configure.in @@ -284,7 +284,7 @@ AC_HELP_STRING([--enable-music-native-midi], [enable native MIDI music output [[ ;; *-*-darwin*) use_music_native_midi=yes - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,CoreServices" + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,CoreServices" ;; esac if test x$use_music_native_midi = xyes; then diff --git a/native_midi/native_midi_macosx.c b/native_midi/native_midi_macosx.c index 72e4f121..9424cdac 100644 --- a/native_midi/native_midi_macosx.c +++ b/native_midi/native_midi_macosx.c @@ -27,8 +27,10 @@ #if __MACOSX__ +#include #include +#include "../SDL_mixer.h" #include "SDL_endian.h" #include "native_midi.h" @@ -38,9 +40,11 @@ struct _NativeMidiSong MusicPlayer player; MusicSequence sequence; MusicTimeStamp endTime; + AudioUnit audiounit; }; static NativeMidiSong *currentsong = NULL; +static int latched_volume = MIX_MAX_VOLUME; static OSStatus GetSequenceLength(MusicSequence sequence, MusicTimeStamp *_sequenceLength) @@ -80,6 +84,61 @@ GetSequenceLength(MusicSequence sequence, MusicTimeStamp *_sequenceLength) } +/* we're looking for the sequence output audiounit. */ +static OSStatus +GetSequenceAudioUnit(MusicSequence sequence, AudioUnit *aunit) +{ + AUGraph graph; + UInt32 nodecount, i; + OSStatus err; + + err = MusicSequenceGetAUGraph(sequence, &graph); + if (err != noErr) + return err; + + err = AUGraphGetNodeCount(graph, &nodecount); + if (err != noErr) + return err; + + for (i = 0; i < nodecount; i++) { + AUNode node; + + if (AUGraphGetIndNode(graph, i, &node) != noErr) + continue; /* better luck next time. */ + + #if 1 /* this is deprecated, but works back to 10.0 */ + { + struct ComponentDescription desc; + UInt32 classdatasize = 0; + void *classdata = NULL; + err = AUGraphGetNodeInfo(graph, node, &desc, &classdatasize, + &classdata, aunit); + if (err != noErr) + continue; + else if (desc.componentType != kAudioUnitType_Output) + continue; + else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput) + continue; + } + #else /* not deprecated, but requires 10.5 or later */ + { + AudioComponentDescription desc; + if (AUGraphNodeInfo(graph, node, &desc, aunit) != noErr) + continue; + else if (desc.componentType != kAudioUnitType_Output) + continue; + else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput) + continue; + } + #endif + + return noErr; /* found it! */ + } + + return kAUGraphErr_NodeNotFound; +} + + int native_midi_detect() { return 1; /* always available. */ @@ -188,11 +247,13 @@ void native_midi_freesong(NativeMidiSong *song) void native_midi_start(NativeMidiSong *song) { + int vol; + if (song == NULL) return; - SDL_PauseAudio(1); - SDL_UnlockAudio(); + SDL_PauseAudio(1); + SDL_UnlockAudio(); if (currentsong) MusicPlayerStop(currentsong->player); @@ -200,19 +261,25 @@ void native_midi_start(NativeMidiSong *song) currentsong = song; MusicPlayerStart(song->player); - SDL_LockAudio(); - SDL_PauseAudio(0); + GetSequenceAudioUnit(song->sequence, &song->audiounit); + + vol = latched_volume; + latched_volume++; /* just make this not match. */ + native_midi_setvolume(vol); + + SDL_LockAudio(); + SDL_PauseAudio(0); } void native_midi_stop() { if (currentsong) { - SDL_PauseAudio(1); - SDL_UnlockAudio(); + SDL_PauseAudio(1); + SDL_UnlockAudio(); MusicPlayerStop(currentsong->player); currentsong = NULL; - SDL_LockAudio(); - SDL_PauseAudio(0); + SDL_LockAudio(); + SDL_PauseAudio(0); } } @@ -229,8 +296,15 @@ int native_midi_active() void native_midi_setvolume(int volume) { - /* !!! FIXME: call MusicSequenceGetAUGraph(), figure out where the output - !!! FIXME: audio unit is, and change its gain */ + if (latched_volume == volume) + return; + + latched_volume = volume; + if ((currentsong) && (currentsong->audiounit)) { + const float floatvol = ((float) volume) / ((float) MIX_MAX_VOLUME); + AudioUnitSetParameter(currentsong->audiounit, kHALOutputParam_Volume, + kAudioUnitScope_Global, 0, floatvol, 0); + } } const char *native_midi_error(void)