Added volume control to Mac OS X Core MIDI native midi backend.
authorRyan C. Gordon <icculus@icculus.org>
Mon, 19 Oct 2009 00:41:30 +0000
changeset 4616f66102b0f72
parent 460 8c97da015305
child 462 028b317d01d2
Added volume control to Mac OS X Core MIDI native midi backend.
configure.in
native_midi/native_midi_macosx.c
     1.1 --- a/configure.in	Sun Oct 18 18:43:15 2009 +0000
     1.2 +++ b/configure.in	Mon Oct 19 00:41:30 2009 +0000
     1.3 @@ -284,7 +284,7 @@
     1.4                  ;;
     1.5              *-*-darwin*)
     1.6                  use_music_native_midi=yes
     1.7 -                EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,CoreServices"
     1.8 +                EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit -Wl,-framework,CoreServices"
     1.9                  ;;
    1.10          esac
    1.11          if test x$use_music_native_midi = xyes; then
     2.1 --- a/native_midi/native_midi_macosx.c	Sun Oct 18 18:43:15 2009 +0000
     2.2 +++ b/native_midi/native_midi_macosx.c	Mon Oct 19 00:41:30 2009 +0000
     2.3 @@ -27,8 +27,10 @@
     2.4  
     2.5  #if __MACOSX__
     2.6  
     2.7 +#include <Carbon/Carbon.h>
     2.8  #include <AudioToolbox/AudioToolbox.h>
     2.9  
    2.10 +#include "../SDL_mixer.h"
    2.11  #include "SDL_endian.h"
    2.12  #include "native_midi.h"
    2.13  
    2.14 @@ -38,9 +40,11 @@
    2.15      MusicPlayer player;
    2.16      MusicSequence sequence;
    2.17      MusicTimeStamp endTime;
    2.18 +    AudioUnit audiounit;
    2.19  };
    2.20  
    2.21  static NativeMidiSong *currentsong = NULL;
    2.22 +static int latched_volume = MIX_MAX_VOLUME;
    2.23  
    2.24  static OSStatus
    2.25  GetSequenceLength(MusicSequence sequence, MusicTimeStamp *_sequenceLength)
    2.26 @@ -80,6 +84,61 @@
    2.27  }
    2.28  
    2.29  
    2.30 +/* we're looking for the sequence output audiounit. */
    2.31 +static OSStatus
    2.32 +GetSequenceAudioUnit(MusicSequence sequence, AudioUnit *aunit)
    2.33 +{
    2.34 +    AUGraph graph;
    2.35 +    UInt32 nodecount, i;
    2.36 +    OSStatus err;
    2.37 +
    2.38 +    err = MusicSequenceGetAUGraph(sequence, &graph);
    2.39 +    if (err != noErr)
    2.40 +        return err;
    2.41 +
    2.42 +    err = AUGraphGetNodeCount(graph, &nodecount);
    2.43 +    if (err != noErr)
    2.44 +        return err;
    2.45 +
    2.46 +    for (i = 0; i < nodecount; i++) {
    2.47 +        AUNode node;
    2.48 +
    2.49 +        if (AUGraphGetIndNode(graph, i, &node) != noErr)
    2.50 +            continue;  /* better luck next time. */
    2.51 +
    2.52 +        #if 1 /* this is deprecated, but works back to 10.0 */
    2.53 +        {
    2.54 +            struct ComponentDescription desc;
    2.55 +            UInt32 classdatasize = 0;
    2.56 +            void *classdata = NULL;
    2.57 +            err = AUGraphGetNodeInfo(graph, node, &desc, &classdatasize,
    2.58 +                                     &classdata, aunit);
    2.59 +            if (err != noErr)
    2.60 +                continue;
    2.61 +            else if (desc.componentType != kAudioUnitType_Output)
    2.62 +                continue;
    2.63 +            else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput)
    2.64 +                continue;
    2.65 +        }
    2.66 +        #else  /* not deprecated, but requires 10.5 or later */
    2.67 +        {
    2.68 +            AudioComponentDescription desc;
    2.69 +            if (AUGraphNodeInfo(graph, node, &desc, aunit) != noErr)
    2.70 +                continue;
    2.71 +            else if (desc.componentType != kAudioUnitType_Output)
    2.72 +                continue;
    2.73 +            else if (desc.componentSubType != kAudioUnitSubType_DefaultOutput)
    2.74 +                continue;
    2.75 +        }
    2.76 +        #endif
    2.77 +
    2.78 +        return noErr;  /* found it! */
    2.79 +    }
    2.80 +
    2.81 +    return kAUGraphErr_NodeNotFound;
    2.82 +}
    2.83 +
    2.84 +
    2.85  int native_midi_detect()
    2.86  {
    2.87      return 1;  /* always available. */
    2.88 @@ -188,11 +247,13 @@
    2.89  
    2.90  void native_midi_start(NativeMidiSong *song)
    2.91  {
    2.92 +    int vol;
    2.93 +
    2.94      if (song == NULL)
    2.95          return;
    2.96  
    2.97 -	SDL_PauseAudio(1);
    2.98 -	SDL_UnlockAudio();
    2.99 +    SDL_PauseAudio(1);
   2.100 +    SDL_UnlockAudio();
   2.101  
   2.102      if (currentsong)
   2.103          MusicPlayerStop(currentsong->player);
   2.104 @@ -200,19 +261,25 @@
   2.105      currentsong = song;
   2.106      MusicPlayerStart(song->player);
   2.107  
   2.108 -	SDL_LockAudio();
   2.109 -	SDL_PauseAudio(0);
   2.110 +    GetSequenceAudioUnit(song->sequence, &song->audiounit);
   2.111 +
   2.112 +    vol = latched_volume;
   2.113 +    latched_volume++;  /* just make this not match. */
   2.114 +    native_midi_setvolume(vol);
   2.115 +
   2.116 +    SDL_LockAudio();
   2.117 +    SDL_PauseAudio(0);
   2.118  }
   2.119  
   2.120  void native_midi_stop()
   2.121  {
   2.122      if (currentsong) {
   2.123 -    	SDL_PauseAudio(1);
   2.124 -	    SDL_UnlockAudio();
   2.125 +        SDL_PauseAudio(1);
   2.126 +        SDL_UnlockAudio();
   2.127          MusicPlayerStop(currentsong->player);
   2.128          currentsong = NULL;
   2.129 -    	SDL_LockAudio();
   2.130 -	    SDL_PauseAudio(0);
   2.131 +        SDL_LockAudio();
   2.132 +        SDL_PauseAudio(0);
   2.133      }
   2.134  }
   2.135  
   2.136 @@ -229,8 +296,15 @@
   2.137  
   2.138  void native_midi_setvolume(int volume)
   2.139  {
   2.140 -    /* !!! FIXME: call MusicSequenceGetAUGraph(), figure out where the output
   2.141 -       !!! FIXME:  audio unit is, and change its gain */
   2.142 +    if (latched_volume == volume)
   2.143 +        return;
   2.144 +
   2.145 +    latched_volume = volume;
   2.146 +    if ((currentsong) && (currentsong->audiounit)) {
   2.147 +        const float floatvol = ((float) volume) / ((float) MIX_MAX_VOLUME);
   2.148 +        AudioUnitSetParameter(currentsong->audiounit, kHALOutputParam_Volume,
   2.149 +                              kAudioUnitScope_Global, 0, floatvol, 0);
   2.150 +    }
   2.151  }
   2.152  
   2.153  const char *native_midi_error(void)