Browse Source

iOS/macOS seperate native_midi wrapper for future usage

Pal Lockheart 7 years ago
parent
commit
f8b1c6f8c1

+ 1 - 1
.gitignore

@@ -241,7 +241,7 @@ android/so
 *.keystore
 resources
 
-sdlpal
+unix/sdlpal
 data
 
 *.xcscmblueprint

+ 4 - 4
ios/SDLPal/SDLPal.xcodeproj/project.pbxproj

@@ -105,7 +105,7 @@
 		C63505731EA6570300186049 /* midi.c in Sources */ = {isa = PBXBuildFile; fileRef = C635056B1EA6570300186049 /* midi.c */; };
 		C63505741EA6570300186049 /* private.c in Sources */ = {isa = PBXBuildFile; fileRef = C635056C1EA6570300186049 /* private.c */; };
 		C635057F1EA6578700186049 /* native_midi_common.c in Sources */ = {isa = PBXBuildFile; fileRef = C635057B1EA6578700186049 /* native_midi_common.c */; };
-		C63505801EA6578700186049 /* native_midi_macosx.c in Sources */ = {isa = PBXBuildFile; fileRef = C635057D1EA6578700186049 /* native_midi_macosx.c */; };
+		C63505801EA6578700186049 /* native_midi_ios.c in Sources */ = {isa = PBXBuildFile; fileRef = C635057D1EA6578700186049 /* native_midi_ios.c */; };
 		C6E974A21E49C24500F76B17 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C6E9749D1E49C22D00F76B17 /* libSDL2.a */; };
 /* End PBXBuildFile section */
 
@@ -352,7 +352,7 @@
 		C635057A1EA6578700186049 /* native_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = native_midi.h; sourceTree = "<group>"; };
 		C635057B1EA6578700186049 /* native_midi_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = native_midi_common.c; sourceTree = "<group>"; };
 		C635057C1EA6578700186049 /* native_midi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = native_midi_common.h; sourceTree = "<group>"; };
-		C635057D1EA6578700186049 /* native_midi_macosx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = native_midi_macosx.c; sourceTree = "<group>"; };
+		C635057D1EA6578700186049 /* native_midi_ios.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = native_midi_ios.c; path = ../iOS/SDLPal/SDLPal/native_midi_ios.c; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -745,7 +745,7 @@
 				C635057A1EA6578700186049 /* native_midi.h */,
 				C635057B1EA6578700186049 /* native_midi_common.c */,
 				C635057C1EA6578700186049 /* native_midi_common.h */,
-				C635057D1EA6578700186049 /* native_midi_macosx.c */,
+				C635057D1EA6578700186049 /* native_midi_ios.c */,
 			);
 			name = native_midi;
 			path = ../../native_midi;
@@ -900,7 +900,7 @@
 				C63505731EA6570300186049 /* midi.c in Sources */,
 				57FB01481B7A50B0005FCF4C /* floor0.c in Sources */,
 				7165526F195BB6DB006E1227 /* fixed.c in Sources */,
-				C63505801EA6578700186049 /* native_midi_macosx.c in Sources */,
+				C63505801EA6578700186049 /* native_midi_ios.c in Sources */,
 				71655270195BB6DB006E1227 /* frame.c in Sources */,
 				71655271195BB6DB006E1227 /* huffman.c in Sources */,
 				71655273195BB6DB006E1227 /* layer12.c in Sources */,

+ 316 - 0
ios/SDLPal/SDLPal/native_midi_ios.c

@@ -0,0 +1,316 @@
+/*  
+    native_midi_macosx:  Native Midi support on Mac OS X for the SDL_mixer library
+    Copyright (C) 2009  Ryan C. Gordon
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Ryan C. Gordon
+    icculus@icculus.org
+*/
+
+#ifdef __APPLE__
+
+/* This is Mac OS X only, using Core MIDI.
+   Mac OS 9 support via QuickTime is in native_midi_mac.c */
+
+#include "SDL_config.h"
+
+#include <AudioToolbox/AudioToolbox.h>
+#include <AvailabilityMacros.h>
+
+#include "SDL.h"
+#include "SDL_endian.h"
+#include "native_midi.h"
+
+/* Native Midi song */
+struct _NativeMidiSong
+{
+    MusicPlayer player;
+    MusicSequence sequence;
+    MusicTimeStamp endTime;
+    AudioUnit audiounit;
+};
+
+static NativeMidiSong *currentsong = NULL;
+static int latched_volume = 128;
+
+static OSStatus
+GetSequenceLength(MusicSequence sequence, MusicTimeStamp *_sequenceLength)
+{
+    // http://lists.apple.com/archives/Coreaudio-api/2003/Jul/msg00370.html
+    // figure out sequence length
+    UInt32 ntracks, i;
+    MusicTimeStamp sequenceLength = 0;
+    OSStatus err;
+
+    err = MusicSequenceGetTrackCount(sequence, &ntracks);
+    if (err != noErr)
+        return err;
+
+    for (i = 0; i < ntracks; ++i)
+    {
+        MusicTrack track;
+        MusicTimeStamp tracklen = 0;
+        UInt32 tracklenlen = sizeof (tracklen);
+
+        err = MusicSequenceGetIndTrack(sequence, i, &track);
+        if (err != noErr)
+            return err;
+
+        err = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
+                                    &tracklen, &tracklenlen);
+        if (err != noErr)
+            return err;
+
+        if (sequenceLength < tracklen)
+            sequenceLength = tracklen;
+    }
+
+    *_sequenceLength = sequenceLength;
+
+    return noErr;
+}
+
+
+/* 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 MAC_OS_X_VERSION_MIN_REQUIRED < 1060 /* 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_GenericOutput)
+                continue;
+        }
+        #endif
+
+        return noErr;  /* found it! */
+    }
+
+    return kAUGraphErr_NodeNotFound;
+}
+
+
+int native_midi_detect()
+{
+    return 1;  /* always available. */
+}
+
+NativeMidiSong *native_midi_loadsong(const char *midifile)
+{
+    NativeMidiSong *retval = NULL;
+    SDL_RWops *rw = SDL_RWFromFile(midifile, "rb");
+    if (rw != NULL) {
+        retval = native_midi_loadsong_RW(rw);
+        SDL_RWclose(rw);
+    }
+
+    return retval;
+}
+
+NativeMidiSong *native_midi_loadsong_RW(SDL_RWops *rw)
+{
+    NativeMidiSong *retval = NULL;
+    void *buf = NULL;
+    int len = 0;
+    CFDataRef data = NULL;
+
+    if (SDL_RWseek(rw, 0, RW_SEEK_END) < 0)
+        goto fail;
+    len = SDL_RWtell(rw);
+    if (len < 0)
+        goto fail;
+    if (SDL_RWseek(rw, 0, RW_SEEK_SET) < 0)
+        goto fail;
+
+    buf = malloc(len);
+    if (buf == NULL)
+        goto fail;
+
+    if (SDL_RWread(rw, buf, len, 1) != 1)
+        goto fail;
+
+    retval = malloc(sizeof(NativeMidiSong));
+    if (retval == NULL)
+        goto fail;
+
+    memset(retval, '\0', sizeof (*retval));
+
+    if (NewMusicPlayer(&retval->player) != noErr)
+        goto fail;
+    if (NewMusicSequence(&retval->sequence) != noErr)
+        goto fail;
+
+    data = CFDataCreate(NULL, (const UInt8 *) buf, len);
+    if (data == NULL)
+        goto fail;
+
+    free(buf);
+    buf = NULL;
+
+    #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 /* this is deprecated, but works back to 10.3 */
+    if (MusicSequenceLoadSMFDataWithFlags(retval->sequence, data, 0) != noErr)
+        goto fail;
+    #else  /* not deprecated, but requires 10.5 or later */
+    if (MusicSequenceFileLoadData(retval->sequence, data, 0, 0) != noErr)
+        goto fail;
+    #endif
+
+    CFRelease(data);
+    data = NULL;
+
+    if (GetSequenceLength(retval->sequence, &retval->endTime) != noErr)
+        goto fail;
+
+    if (MusicPlayerSetSequence(retval->player, retval->sequence) != noErr)
+        goto fail;
+
+    return retval;
+
+fail:
+    if (retval) {
+        if (retval->sequence)
+            DisposeMusicSequence(retval->sequence);
+        if (retval->player)
+            DisposeMusicPlayer(retval->player);
+        free(retval);
+    }
+
+    if (data)
+        CFRelease(data);
+
+    if (buf)
+        free(buf);
+
+    return NULL;
+}
+
+void native_midi_freesong(NativeMidiSong *song)
+{
+    if (song != NULL) {
+        if (currentsong == song)
+            currentsong = NULL;
+        MusicPlayerStop(song->player);
+        DisposeMusicSequence(song->sequence);
+        DisposeMusicPlayer(song->player);
+        free(song);
+    }
+}
+
+void native_midi_start(NativeMidiSong *song)
+{
+    int vol;
+
+    if (song == NULL)
+        return;
+
+    SDL_PauseAudio(1);
+    SDL_UnlockAudio();
+
+    if (currentsong)
+        MusicPlayerStop(currentsong->player);
+
+    currentsong = song;
+    MusicPlayerStart(song->player);
+
+    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();
+        MusicPlayerStop(currentsong->player);
+        currentsong = NULL;
+        SDL_LockAudio();
+        SDL_PauseAudio(0);
+    }
+}
+
+int native_midi_active()
+{
+    MusicTimeStamp currentTime = 0;
+    if (currentsong == NULL)
+        return 0;
+
+    MusicPlayerGetTime(currentsong->player, &currentTime);
+    return ((currentTime < currentsong->endTime) ||
+            (currentTime >= kMusicTimeStamp_EndOfTrack));
+}
+
+void native_midi_setvolume(int volume)
+{
+    if (latched_volume == volume)
+        return;
+
+    latched_volume = volume;
+    if ((currentsong) && (currentsong->audiounit)) {
+        const float floatvol = ((float) volume) / ((float) 128);
+        AudioUnitSetParameter(currentsong->audiounit, kHALOutputParam_Volume,
+                              kAudioUnitScope_Global, 0, floatvol, 0);
+    }
+}
+
+const char *native_midi_error(void)
+{
+    return "";  /* !!! FIXME */
+}
+
+#endif
+

+ 1 - 1
macos/Pal.xcodeproj/project.pbxproj

@@ -323,7 +323,7 @@
 		C61464631EA6425700A76CC9 /* native_midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = native_midi.h; sourceTree = "<group>"; };
 		C61464641EA6425700A76CC9 /* native_midi_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = native_midi_common.c; sourceTree = "<group>"; };
 		C61464651EA6425700A76CC9 /* native_midi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = native_midi_common.h; sourceTree = "<group>"; };
-		C61464661EA6425700A76CC9 /* native_midi_macosx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = native_midi_macosx.c; sourceTree = "<group>"; };
+		C61464661EA6425700A76CC9 /* native_midi_macosx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = native_midi_macosx.c; path = ../macos/native_midi_macosx.c; sourceTree = "<group>"; };
 		C614646B1EA642F200A76CC9 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
 		C614646D1EA6430100A76CC9 /* CoreMIDI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMIDI.framework; path = System/Library/Frameworks/CoreMIDI.framework; sourceTree = SDKROOT; };
 		C614646F1EA643BD00A76CC9 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = "<group>"; };

native_midi/native_midi_macosx.c → macos/native_midi_macosx.c