Cocoa Port:

- Refactor audio playback code for better code modularity.
- Improve overall performance of audio playback.
- Fix compile issue with the legacy build.
- Add a method for setting the emulator core's file paths directly by using a dictionary. This method can be used as an alternative to reading FileTypeInfo.plist.
- Add file handling support for the upcoming OpenEmu Plug-in build target.
This commit is contained in:
rogerman 2012-03-03 02:16:24 +00:00
parent ab53131bd8
commit 8a7fd2445f
18 changed files with 936 additions and 787 deletions

View File

@ -392,6 +392,14 @@
ABBF053114B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; }; ABBF053114B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; };
ABBF053214B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; }; ABBF053214B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; };
ABBF053314B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; }; ABBF053314B5436E00E505A0 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABBF052F14B5436E00E505A0 /* cocoa_file.mm */; };
ABD0A5661501AC5C0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */; };
ABD0A5671501AC5C0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */; };
ABD0A5681501AC5C0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */; };
ABD0A5691501AC5C0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */; };
ABD0A56A1501AC5C0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */; };
ABD0A56B1501AC5C0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */; };
ABD0A56C1501AC5C0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */; };
ABD0A56D1501AC5C0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */; };
ABE240FF14BE3169006EA2D5 /* cocoa_input_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F414BE3169006EA2D5 /* cocoa_input_legacy.mm */; }; ABE240FF14BE3169006EA2D5 /* cocoa_input_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F414BE3169006EA2D5 /* cocoa_input_legacy.mm */; };
ABE2410014BE3169006EA2D5 /* input_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F614BE3169006EA2D5 /* input_legacy.mm */; }; ABE2410014BE3169006EA2D5 /* input_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F614BE3169006EA2D5 /* input_legacy.mm */; };
ABE2410114BE3169006EA2D5 /* nds_control_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F814BE3169006EA2D5 /* nds_control_legacy.mm */; }; ABE2410114BE3169006EA2D5 /* nds_control_legacy.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABE240F814BE3169006EA2D5 /* nds_control_legacy.mm */; };
@ -787,6 +795,10 @@
ABBF04CD14B51BC900E505A0 /* Romanian */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Romanian; path = translations/Romanian.lproj/Localizable.strings; sourceTree = "<group>"; }; ABBF04CD14B51BC900E505A0 /* Romanian */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Romanian; path = translations/Romanian.lproj/Localizable.strings; sourceTree = "<group>"; };
ABBF052F14B5436E00E505A0 /* cocoa_file.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_file.mm; sourceTree = "<group>"; }; ABBF052F14B5436E00E505A0 /* cocoa_file.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_file.mm; sourceTree = "<group>"; };
ABBF053B14B543B600E505A0 /* cocoa_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_file.h; sourceTree = "<group>"; }; ABBF053B14B543B600E505A0 /* cocoa_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_file.h; sourceTree = "<group>"; };
ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreaudiosound.cpp; sourceTree = "<group>"; };
ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ringbuffer.cpp; sourceTree = "<group>"; };
ABD0A5641501AC5C0074A094 /* coreaudiosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreaudiosound.h; sourceTree = "<group>"; };
ABD0A5651501AC5C0074A094 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; };
ABE240E514BE30FC006EA2D5 /* Info (Legacy Debug).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (Legacy Debug).plist"; sourceTree = "<group>"; }; ABE240E514BE30FC006EA2D5 /* Info (Legacy Debug).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (Legacy Debug).plist"; sourceTree = "<group>"; };
ABE240E614BE30FC006EA2D5 /* Info (Legacy).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (Legacy).plist"; sourceTree = "<group>"; }; ABE240E614BE30FC006EA2D5 /* Info (Legacy).plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info (Legacy).plist"; sourceTree = "<group>"; };
ABE240F314BE3169006EA2D5 /* cocoa_input_legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_input_legacy.h; sourceTree = "<group>"; }; ABE240F314BE3169006EA2D5 /* cocoa_input_legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_input_legacy.h; sourceTree = "<group>"; };
@ -870,15 +882,19 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ABC3ADEC14B7DC6E00D5B13D /* userinterface */, ABC3ADEC14B7DC6E00D5B13D /* userinterface */,
ABD0A5621501AC5C0074A094 /* coreaudiosound.cpp */,
ABD0A5631501AC5C0074A094 /* ringbuffer.cpp */,
ABF4007E14B4F1C000578AE7 /* sndOSX.cpp */, ABF4007E14B4F1C000578AE7 /* sndOSX.cpp */,
ABBF053B14B543B600E505A0 /* cocoa_file.h */, ABBF053B14B543B600E505A0 /* cocoa_file.h */,
ABF95B4714B4F4FC007912B8 /* cocoa_globals.h */, ABF95B4714B4F4FC007912B8 /* cocoa_globals.h */,
ABE240F314BE3169006EA2D5 /* cocoa_input_legacy.h */, ABE240F314BE3169006EA2D5 /* cocoa_input_legacy.h */,
AB8FE37414B652EC009E20B1 /* cocoa_util.h */, AB8FE37414B652EC009E20B1 /* cocoa_util.h */,
ABD0A5641501AC5C0074A094 /* coreaudiosound.h */,
ABE240F514BE3169006EA2D5 /* input_legacy.h */, ABE240F514BE3169006EA2D5 /* input_legacy.h */,
AB8FE30A14B647D6009E20B1 /* macosx_10_4_compat.h */, AB8FE30A14B647D6009E20B1 /* macosx_10_4_compat.h */,
ABE240F714BE3169006EA2D5 /* nds_control_legacy.h */, ABE240F714BE3169006EA2D5 /* nds_control_legacy.h */,
ABE240F914BE3169006EA2D5 /* preferences_legacy.h */, ABE240F914BE3169006EA2D5 /* preferences_legacy.h */,
ABD0A5651501AC5C0074A094 /* ringbuffer.h */,
ABE240FB14BE3169006EA2D5 /* screen_state_legacy.h */, ABE240FB14BE3169006EA2D5 /* screen_state_legacy.h */,
AB06CB49135B8A4D00E977B3 /* sndOSX.h */, AB06CB49135B8A4D00E977B3 /* sndOSX.h */,
ABE240FD14BE3169006EA2D5 /* video_output_view_legacy.h */, ABE240FD14BE3169006EA2D5 /* video_output_view_legacy.h */,
@ -1744,6 +1760,8 @@
ABE2410E14BE3169006EA2D5 /* preferences_legacy.mm in Sources */, ABE2410E14BE3169006EA2D5 /* preferences_legacy.mm in Sources */,
ABE2410F14BE3169006EA2D5 /* screen_state_legacy.m in Sources */, ABE2410F14BE3169006EA2D5 /* screen_state_legacy.m in Sources */,
ABE2411014BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */, ABE2411014BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */,
ABD0A5681501AC5C0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A5691501AC5C0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -1851,6 +1869,8 @@
ABE2411414BE3169006EA2D5 /* preferences_legacy.mm in Sources */, ABE2411414BE3169006EA2D5 /* preferences_legacy.mm in Sources */,
ABE2411514BE3169006EA2D5 /* screen_state_legacy.m in Sources */, ABE2411514BE3169006EA2D5 /* screen_state_legacy.m in Sources */,
ABE2411614BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */, ABE2411614BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */,
ABD0A56C1501AC5C0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A56D1501AC5C0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -1958,6 +1978,8 @@
ABE2410214BE3169006EA2D5 /* preferences_legacy.mm in Sources */, ABE2410214BE3169006EA2D5 /* preferences_legacy.mm in Sources */,
ABE2410314BE3169006EA2D5 /* screen_state_legacy.m in Sources */, ABE2410314BE3169006EA2D5 /* screen_state_legacy.m in Sources */,
ABE2410414BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */, ABE2410414BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */,
ABD0A5661501AC5C0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A5671501AC5C0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -2065,6 +2087,8 @@
ABE2410814BE3169006EA2D5 /* preferences_legacy.mm in Sources */, ABE2410814BE3169006EA2D5 /* preferences_legacy.mm in Sources */,
ABE2410914BE3169006EA2D5 /* screen_state_legacy.m in Sources */, ABE2410914BE3169006EA2D5 /* screen_state_legacy.m in Sources */,
ABE2410A14BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */, ABE2410A14BE3169006EA2D5 /* video_output_view_legacy.mm in Sources */,
ABD0A56A1501AC5C0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A56B1501AC5C0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -296,6 +296,10 @@
ABC5720D1344346600E7B0B1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97324FDCFA39411CA2CEA /* AppKit.framework */; }; ABC5720D1344346600E7B0B1 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97324FDCFA39411CA2CEA /* AppKit.framework */; };
ABC572101344347000E7B0B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; }; ABC572101344347000E7B0B1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97325FDCFA39411CA2CEA /* Foundation.framework */; };
ABC719E2138CB25E002827A9 /* DefaultKeyMappings.plist in Resources */ = {isa = PBXBuildFile; fileRef = ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */; }; ABC719E2138CB25E002827A9 /* DefaultKeyMappings.plist in Resources */ = {isa = PBXBuildFile; fileRef = ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */; };
ABD0A5381501AA5A0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */; };
ABD0A5391501AA5A0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */; };
ABD0A53A1501AA5A0074A094 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */; };
ABD0A53B1501AA5A0074A094 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */; };
ABD1041C1346652500AF11D1 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; }; ABD1041C1346652500AF11D1 /* cocoa_input.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104111346652500AF11D1 /* cocoa_input.mm */; };
ABD1041D1346652500AF11D1 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; }; ABD1041D1346652500AF11D1 /* cocoa_core.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104121346652500AF11D1 /* cocoa_core.mm */; };
ABD1041E1346652500AF11D1 /* cocoa_rom.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104131346652500AF11D1 /* cocoa_rom.mm */; }; ABD1041E1346652500AF11D1 /* cocoa_rom.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABD104131346652500AF11D1 /* cocoa_rom.mm */; };
@ -530,6 +534,10 @@
ABC570D0134431CE00E7B0B1 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; ABC570D0134431CE00E7B0B1 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
ABC570D4134431DA00E7B0B1 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; ABC570D4134431DA00E7B0B1 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DefaultKeyMappings.plist; sourceTree = "<group>"; }; ABC719E1138CB25E002827A9 /* DefaultKeyMappings.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = DefaultKeyMappings.plist; sourceTree = "<group>"; };
ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreaudiosound.cpp; sourceTree = "<group>"; };
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ringbuffer.cpp; sourceTree = "<group>"; };
ABD0A5361501AA5A0074A094 /* coreaudiosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreaudiosound.h; sourceTree = "<group>"; };
ABD0A5371501AA5A0074A094 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = "<group>"; };
ABD103FE1346652500AF11D1 /* cocoa_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_core.h; sourceTree = "<group>"; }; ABD103FE1346652500AF11D1 /* cocoa_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_core.h; sourceTree = "<group>"; };
ABD103FF1346652500AF11D1 /* cocoa_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_input.h; sourceTree = "<group>"; }; ABD103FF1346652500AF11D1 /* cocoa_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_input.h; sourceTree = "<group>"; };
ABD104001346652500AF11D1 /* cocoa_rom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_rom.h; sourceTree = "<group>"; }; ABD104001346652500AF11D1 /* cocoa_rom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_rom.h; sourceTree = "<group>"; };
@ -776,6 +784,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
AB3ACB6514C2361100D7D192 /* userinterface */, AB3ACB6514C2361100D7D192 /* userinterface */,
ABD0A5341501AA5A0074A094 /* coreaudiosound.cpp */,
ABD0A5351501AA5A0074A094 /* ringbuffer.cpp */,
ABD104141346652500AF11D1 /* sndOSX.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */,
AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */, AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
@ -790,13 +800,15 @@
ABD104001346652500AF11D1 /* cocoa_rom.h */, ABD104001346652500AF11D1 /* cocoa_rom.h */,
AB80E050142BC4FA00A52038 /* cocoa_util.h */, AB80E050142BC4FA00A52038 /* cocoa_util.h */,
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */, ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */,
ABD0A5361501AA5A0074A094 /* coreaudiosound.h */,
ABD0A5371501AA5A0074A094 /* ringbuffer.h */,
ABD104011346652500AF11D1 /* sndOSX.h */, ABD104011346652500AF11D1 /* sndOSX.h */,
AB817A34143EE2DB00A7DFE9 /* videofilter.h */, AB817A34143EE2DB00A7DFE9 /* videofilter.h */,
AB350B691478A5B3007165AC /* cocoa_hid.mm */,
ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */, ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */,
ABD104121346652500AF11D1 /* cocoa_core.mm */, ABD104121346652500AF11D1 /* cocoa_core.mm */,
AB58F32C1364F44B0074C376 /* cocoa_file.mm */, AB58F32C1364F44B0074C376 /* cocoa_file.mm */,
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */, ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */,
AB350B691478A5B3007165AC /* cocoa_hid.mm */,
ABD104111346652500AF11D1 /* cocoa_input.mm */, ABD104111346652500AF11D1 /* cocoa_input.mm */,
ABD9A46413DB99B300777194 /* cocoa_mic.mm */, ABD9A46413DB99B300777194 /* cocoa_mic.mm */,
AB3E34C8134AF4500056477A /* cocoa_output.mm */, AB3E34C8134AF4500056477A /* cocoa_output.mm */,
@ -1665,6 +1677,8 @@
ABFE150B14C92FF5005D6699 /* hq4x.cpp in Sources */, ABFE150B14C92FF5005D6699 /* hq4x.cpp in Sources */,
ABFE150D14C92FF5005D6699 /* lq2x.cpp in Sources */, ABFE150D14C92FF5005D6699 /* lq2x.cpp in Sources */,
ABFE150E14C92FF5005D6699 /* scanline.cpp in Sources */, ABFE150E14C92FF5005D6699 /* scanline.cpp in Sources */,
ABD0A5381501AA5A0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A5391501AA5A0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -1787,6 +1801,8 @@
ABFE151314C92FF5005D6699 /* hq4x.cpp in Sources */, ABFE151314C92FF5005D6699 /* hq4x.cpp in Sources */,
ABFE151514C92FF5005D6699 /* lq2x.cpp in Sources */, ABFE151514C92FF5005D6699 /* lq2x.cpp in Sources */,
ABFE151614C92FF5005D6699 /* scanline.cpp in Sources */, ABFE151614C92FF5005D6699 /* scanline.cpp in Sources */,
ABD0A53A1501AA5A0074A094 /* coreaudiosound.cpp in Sources */,
ABD0A53B1501AA5A0074A094 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -104,6 +104,12 @@
AB0F29C914BE7213009ABC6F /* Icon_Speaker_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */; }; AB0F29C914BE7213009ABC6F /* Icon_Speaker_420x420.png in Resources */ = {isa = PBXBuildFile; fileRef = AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */; };
AB15CA7214A29EE500B8A6A4 /* cpu_detect_x86_gcc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6613AF1D6D00502E1E /* cpu_detect_x86_gcc.cpp */; }; AB15CA7214A29EE500B8A6A4 /* cpu_detect_x86_gcc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABAD3E6613AF1D6D00502E1E /* cpu_detect_x86_gcc.cpp */; };
AB181D0013B66889006CA82D /* datetime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF1F1345ACBF00AF11D1 /* datetime.cpp */; }; AB181D0013B66889006CA82D /* datetime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF1F1345ACBF00AF11D1 /* datetime.cpp */; };
AB1B9E631501A78000464647 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */; };
AB1B9E641501A78000464647 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */; };
AB1B9E651501A78000464647 /* coreaudiosound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */; };
AB1B9E661501A78000464647 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E601501A78000464647 /* ringbuffer.cpp */; };
AB1B9E671501A78000464647 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E601501A78000464647 /* ringbuffer.cpp */; };
AB1B9E681501A78000464647 /* ringbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB1B9E601501A78000464647 /* ringbuffer.cpp */; };
AB1F468413A0ADE400B80DE6 /* SndOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF7A1345ACFA00AF11D1 /* SndOut.cpp */; }; AB1F468413A0ADE400B80DE6 /* SndOut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF7A1345ACFA00AF11D1 /* SndOut.cpp */; };
AB1F469813A0AE2F00B80DE6 /* Timestretcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF9B1345ACFA00AF11D1 /* Timestretcher.cpp */; }; AB1F469813A0AE2F00B80DE6 /* Timestretcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABD1FF9B1345ACFA00AF11D1 /* Timestretcher.cpp */; };
AB350B6A1478A5B3007165AC /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; }; AB350B6A1478A5B3007165AC /* cocoa_hid.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB350B691478A5B3007165AC /* cocoa_hid.mm */; };
@ -648,6 +654,10 @@
AB0F29A314BE7213009ABC6F /* Icon_RotateCW_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_RotateCW_420x420.png; path = images/Icon_RotateCW_420x420.png; sourceTree = "<group>"; }; AB0F29A314BE7213009ABC6F /* Icon_RotateCW_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_RotateCW_420x420.png; path = images/Icon_RotateCW_420x420.png; sourceTree = "<group>"; };
AB0F29A414BE7213009ABC6F /* Icon_ShowHUD_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_ShowHUD_420x420.png; path = images/Icon_ShowHUD_420x420.png; sourceTree = "<group>"; }; AB0F29A414BE7213009ABC6F /* Icon_ShowHUD_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_ShowHUD_420x420.png; path = images/Icon_ShowHUD_420x420.png; sourceTree = "<group>"; };
AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speaker_420x420.png; path = images/Icon_Speaker_420x420.png; sourceTree = "<group>"; }; AB0F29A514BE7213009ABC6F /* Icon_Speaker_420x420.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_Speaker_420x420.png; path = images/Icon_Speaker_420x420.png; sourceTree = "<group>"; };
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreaudiosound.cpp; sourceTree = SOURCE_ROOT; };
AB1B9E601501A78000464647 /* ringbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ringbuffer.cpp; sourceTree = SOURCE_ROOT; };
AB1B9E611501A78000464647 /* coreaudiosound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreaudiosound.h; sourceTree = SOURCE_ROOT; };
AB1B9E621501A78000464647 /* ringbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ringbuffer.h; sourceTree = SOURCE_ROOT; };
AB350B681478A5B3007165AC /* cocoa_hid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_hid.h; sourceTree = "<group>"; }; AB350B681478A5B3007165AC /* cocoa_hid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_hid.h; sourceTree = "<group>"; };
AB350B691478A5B3007165AC /* cocoa_hid.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_hid.mm; sourceTree = "<group>"; }; AB350B691478A5B3007165AC /* cocoa_hid.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_hid.mm; sourceTree = "<group>"; };
AB350BA41478AC96007165AC /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; AB350BA41478AC96007165AC /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
@ -985,6 +995,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
AB3ACB6514C2361100D7D192 /* userinterface */, AB3ACB6514C2361100D7D192 /* userinterface */,
AB1B9E5F1501A78000464647 /* coreaudiosound.cpp */,
AB1B9E601501A78000464647 /* ringbuffer.cpp */,
ABD104141346652500AF11D1 /* sndOSX.cpp */, ABD104141346652500AF11D1 /* sndOSX.cpp */,
AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */, AB817A35143EE2DB00A7DFE9 /* videofilter.cpp */,
ABA6574914511EC90077E5E9 /* cocoa_cheat.h */, ABA6574914511EC90077E5E9 /* cocoa_cheat.h */,
@ -999,13 +1011,15 @@
ABD104001346652500AF11D1 /* cocoa_rom.h */, ABD104001346652500AF11D1 /* cocoa_rom.h */,
AB80E050142BC4FA00A52038 /* cocoa_util.h */, AB80E050142BC4FA00A52038 /* cocoa_util.h */,
ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */, ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */,
AB1B9E611501A78000464647 /* coreaudiosound.h */,
AB1B9E621501A78000464647 /* ringbuffer.h */,
ABD104011346652500AF11D1 /* sndOSX.h */, ABD104011346652500AF11D1 /* sndOSX.h */,
AB817A34143EE2DB00A7DFE9 /* videofilter.h */, AB817A34143EE2DB00A7DFE9 /* videofilter.h */,
AB350B691478A5B3007165AC /* cocoa_hid.mm */,
ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */, ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */,
ABD104121346652500AF11D1 /* cocoa_core.mm */, ABD104121346652500AF11D1 /* cocoa_core.mm */,
AB58F32C1364F44B0074C376 /* cocoa_file.mm */, AB58F32C1364F44B0074C376 /* cocoa_file.mm */,
ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */, ABE7F53D13EE1C7900FD3A71 /* cocoa_firmware.mm */,
AB350B691478A5B3007165AC /* cocoa_hid.mm */,
ABD104111346652500AF11D1 /* cocoa_input.mm */, ABD104111346652500AF11D1 /* cocoa_input.mm */,
ABD9A46413DB99B300777194 /* cocoa_mic.mm */, ABD9A46413DB99B300777194 /* cocoa_mic.mm */,
AB3E34C8134AF4500056477A /* cocoa_output.mm */, AB3E34C8134AF4500056477A /* cocoa_output.mm */,
@ -1554,7 +1568,7 @@
29B97313FDCFA39411CA2CEA /* Project object */ = { 29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0420; LastUpgradeCheck = 0430;
ORGANIZATIONNAME = "DeSmuME Team"; ORGANIZATIONNAME = "DeSmuME Team";
}; };
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 4)" */; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DeSmuME (XCode 4)" */;
@ -1990,6 +2004,8 @@
ABFE150B14C92FF5005D6699 /* hq4x.cpp in Sources */, ABFE150B14C92FF5005D6699 /* hq4x.cpp in Sources */,
ABFE150D14C92FF5005D6699 /* lq2x.cpp in Sources */, ABFE150D14C92FF5005D6699 /* lq2x.cpp in Sources */,
ABFE150E14C92FF5005D6699 /* scanline.cpp in Sources */, ABFE150E14C92FF5005D6699 /* scanline.cpp in Sources */,
AB1B9E631501A78000464647 /* coreaudiosound.cpp in Sources */,
AB1B9E661501A78000464647 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -2112,6 +2128,8 @@
ABFE151314C92FF5005D6699 /* hq4x.cpp in Sources */, ABFE151314C92FF5005D6699 /* hq4x.cpp in Sources */,
ABFE151514C92FF5005D6699 /* lq2x.cpp in Sources */, ABFE151514C92FF5005D6699 /* lq2x.cpp in Sources */,
ABFE151614C92FF5005D6699 /* scanline.cpp in Sources */, ABFE151614C92FF5005D6699 /* scanline.cpp in Sources */,
AB1B9E641501A78000464647 /* coreaudiosound.cpp in Sources */,
AB1B9E671501A78000464647 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -2234,6 +2252,8 @@
ABB715FB14E386740027FE88 /* hq4x.cpp in Sources */, ABB715FB14E386740027FE88 /* hq4x.cpp in Sources */,
ABB715FC14E386740027FE88 /* lq2x.cpp in Sources */, ABB715FC14E386740027FE88 /* lq2x.cpp in Sources */,
ABB715FD14E386740027FE88 /* scanline.cpp in Sources */, ABB715FD14E386740027FE88 /* scanline.cpp in Sources */,
AB1B9E651501A78000464647 /* coreaudiosound.cpp in Sources */,
AB1B9E681501A78000464647 /* ringbuffer.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -2389,7 +2409,6 @@
GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Info.plist;
LLVM_LTO = NO;
PRODUCT_NAME = DeSmuME; PRODUCT_NAME = DeSmuME;
SDKROOT = macosx10.7; SDKROOT = macosx10.7;
STRIP_INSTALLED_PRODUCT = NO; STRIP_INSTALLED_PRODUCT = NO;

View File

@ -39,6 +39,13 @@
<key>Save State</key> <key>Save State</key>
<string>${APPSUPPORT}</string> <string>${APPSUPPORT}</string>
</dict> </dict>
<key>OpenEmu</key>
<dict>
<key>ROM Save</key>
<string>${OPENEMU}</string>
<key>Save State</key>
<string>${OPENEMU}</string>
</dict>
</dict> </dict>
</dict> </dict>
<key>DirectoryNames</key> <key>DirectoryNames</key>

View File

@ -28,6 +28,9 @@
} }
+ (NSMutableDictionary *) URLDictionary;
+ (void) addURLToURLDictionary:(NSURL *)theURL groupKey:(NSString *)groupKey fileKind:(NSString *)fileKind;
+ (void) removeURLFromURLDictionaryByGroupKey:(NSString *)groupKey fileKind:(NSString *)fileKind;
+ (BOOL) loadState:(NSURL *)saveStateURL; + (BOOL) loadState:(NSURL *)saveStateURL;
+ (BOOL) saveState:(NSURL *)saveStateURL; + (BOOL) saveState:(NSURL *)saveStateURL;
+ (BOOL) loadRom:(NSURL *)romURL; + (BOOL) loadRom:(NSURL *)romURL;
@ -38,6 +41,8 @@
+ (BOOL) romSaveExists:(NSURL *)romURL; + (BOOL) romSaveExists:(NSURL *)romURL;
+ (BOOL) romSaveExistsWithRom:(NSURL *)romURL; + (BOOL) romSaveExistsWithRom:(NSURL *)romURL;
+ (void) setupAllFilePaths; + (void) setupAllFilePaths;
+ (void) setupAllFilePathsWithURLDictionary:(NSString *)URLDictionaryKey;
+ (void) setupAllFilePathsForVersion:(NSString *)versionString port:(NSString *)portString;
+ (BOOL) setupAllAppDirectories; + (BOOL) setupAllAppDirectories;
+ (NSURL *) saveStateURL; + (NSURL *) saveStateURL;
+ (BOOL) saveScreenshot:(NSURL *)fileURL bitmapData:(NSBitmapImageRep *)bitmapImageRep fileType:(NSBitmapImageFileType)fileType; + (BOOL) saveScreenshot:(NSURL *)fileURL bitmapData:(NSBitmapImageRep *)bitmapImageRep fileType:(NSBitmapImageFileType)fileType;

View File

@ -28,6 +28,110 @@
@implementation CocoaDSFile @implementation CocoaDSFile
// Global dictionary that can be used for storing URLs.
//
// Usually, it's best to add directory paths to FileTypeInfo.plist, and then
// use directoryByKind:version:port for getting a URL, but this method only
// works for application build targets. Other target types, such as plug-in
// targets, don't read FileTypeInfo.plist correctly, so we include a global
// URL dictionary so that we can manually set and get URLs at runtime.
static NSMutableDictionary *_gURLDictionary = nil;
/********************************************************************************************
URLDictionary
Returns the global URL dictionary.
Takes:
Nothing.
Returns:
A reference to the NSMutableDictionary URLDictionary.
Details:
This should always be used for getting the global URL dictionary. Never try to
reference the global URL dictionary directly, since this may change between
versions. The first time this method is called, it will automatically allocate
the memory for the global URL dictionary.
********************************************************************************************/
+ (NSMutableDictionary *) URLDictionary
{
if (_gURLDictionary == nil)
{
_gURLDictionary = [[NSMutableDictionary alloc] initWithCapacity:8];
}
return _gURLDictionary;
}
/********************************************************************************************
addURLToURLDictionary:groupKey:fileKind:
Adds a URL to the global URL dictionary.
Takes:
theURL - An NSURL used to store a URL into the dictionary.
groupKey - An NSString that represents the key used to group a set URLs together.
fileKind - An NSString that represents the file type.
Returns:
Nothing.
Details:
This should always be used for adding a URL to the global URL dictionary. Never
try to add a URL directly, since this may change between versions.
********************************************************************************************/
+ (void) addURLToURLDictionary:(NSURL *)theURL groupKey:(NSString *)groupKey fileKind:(NSString *)fileKind
{
if (theURL == nil || groupKey == nil || fileKind == nil)
{
return;
}
NSMutableDictionary *urlDictionary = [CocoaDSFile URLDictionary];
NSMutableDictionary *groupDictionary = (NSMutableDictionary *)[urlDictionary valueForKey:groupKey];
if (groupDictionary == nil)
{
groupDictionary = [NSMutableDictionary dictionaryWithCapacity:16];
[urlDictionary setValue:groupDictionary forKey:groupKey];
}
[groupDictionary setValue:theURL forKey:fileKind];
}
/********************************************************************************************
removeURLFromURLDictionaryByGroupKey:fileKind:
Removes a URL from the global URL dictionary.
Takes:
groupKey - An NSString that represents the key used to group a set URLs together.
fileKind - An NSString that represents the file type.
Returns:
Nothing.
Details:
This should always be used for removing a URL from the global URL dictionary.
Never try to remove a URL directly, since this may change between versions.
********************************************************************************************/
+ (void) removeURLFromURLDictionaryByGroupKey:(NSString *)groupKey fileKind:(NSString *)fileKind
{
if (groupKey == nil || fileKind == nil)
{
return;
}
NSMutableDictionary *urlDictionary = [CocoaDSFile URLDictionary];
NSMutableDictionary *groupDictionary = (NSMutableDictionary *)[urlDictionary valueForKey:groupKey];
if (groupDictionary != nil)
{
[groupDictionary setValue:nil forKey:fileKind];
}
}
+ (BOOL) loadState:(NSURL *)saveStateURL + (BOOL) loadState:(NSURL *)saveStateURL
{ {
BOOL result = NO; BOOL result = NO;
@ -107,6 +211,7 @@
switch (fileTypeID) switch (fileTypeID)
{ {
#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
case ROMSAVEFORMAT_DESMUME: case ROMSAVEFORMAT_DESMUME:
{ {
NSString *destinationPath = [[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE]; NSString *destinationPath = [[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE];
@ -115,7 +220,7 @@
[fileManager release]; [fileManager release];
break; break;
} }
#endif
case ROMSAVEFORMAT_NOGBA: case ROMSAVEFORMAT_NOGBA:
{ {
const char *destinationPath = [[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_NOGBA] cStringUsingEncoding:NSUTF8StringEncoding]; const char *destinationPath = [[[destinationURL path] stringByAppendingPathExtension:@FILE_EXT_ROM_SAVE_NOGBA] cStringUsingEncoding:NSUTF8StringEncoding];
@ -191,57 +296,174 @@
return exists; return exists;
} }
/********************************************************************************************
setupAllFilePaths
Sets up all application file paths using the current version of the default port.
Takes:
Nothing.
Returns:
Nothing.
Details:
This method uses setupAllFilePathsForVersion:port: for its implementation.
********************************************************************************************/
+ (void) setupAllFilePaths + (void) setupAllFilePaths
{ {
NSURL *romURL = [CocoaDSFile directoryURLByKind:@"ROM"]; [CocoaDSFile setupAllFilePathsForVersion:nil port:nil];
}
/********************************************************************************************
setupAllFilePathsForVersion:port:
Sets up all application file paths, reading the paths from FileTypeInfo.plist.
Takes:
versionString - An NSString that represents the application version. If nil is
used, this method assumes the current version.
portString - An NSString that represents the port version. If nil is used, this
method assumes the default port version.
Returns:
Nothing.
Details:
This is an Objective-C to C wrapper function for assigning file paths to the
emulation layer.
********************************************************************************************/
+ (void) setupAllFilePathsForVersion:(NSString *)versionString port:(NSString *)portString
{
NSURL *romURL = [CocoaDSFile directoryURLByKind:@"ROM" version:versionString port:portString];
if (romURL != nil) if (romURL != nil)
{ {
strlcpy(path.pathToRoms, [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToRoms, [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *romSaveURL = [CocoaDSFile directoryURLByKind:@"ROM Save"]; NSURL *romSaveURL = [CocoaDSFile directoryURLByKind:@"ROM Save" version:versionString port:portString];
if (romSaveURL != nil) if (romSaveURL != nil)
{ {
strlcpy(path.pathToBattery, [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToBattery, [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *saveStateURL = [CocoaDSFile directoryURLByKind:@"Save State"]; NSURL *saveStateURL = [CocoaDSFile directoryURLByKind:@"Save State" version:versionString port:portString];
if (saveStateURL != nil) if (saveStateURL != nil)
{ {
strlcpy(path.pathToStates, [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToStates, [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *screenshotURL = [CocoaDSFile directoryURLByKind:@"Screenshot"]; NSURL *screenshotURL = [CocoaDSFile directoryURLByKind:@"Screenshot" version:versionString port:portString];
if (screenshotURL != nil) if (screenshotURL != nil)
{ {
strlcpy(path.pathToScreenshots, [[screenshotURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToScreenshots, [[screenshotURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *aviURL = [CocoaDSFile directoryURLByKind:@"Video"]; NSURL *aviURL = [CocoaDSFile directoryURLByKind:@"Video" version:versionString port:portString];
if (aviURL != nil) if (aviURL != nil)
{ {
strlcpy(path.pathToAviFiles, [[aviURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToAviFiles, [[aviURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *cheatURL = [CocoaDSFile directoryURLByKind:@"Cheat"]; NSURL *cheatURL = [CocoaDSFile directoryURLByKind:@"Cheat" version:versionString port:portString];
if (cheatURL != nil) if (cheatURL != nil)
{ {
strlcpy(path.pathToCheats, [[cheatURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToCheats, [[cheatURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *soundSamplesURL = [CocoaDSFile directoryURLByKind:@"Sound Sample"]; NSURL *soundSamplesURL = [CocoaDSFile directoryURLByKind:@"Sound Sample" version:versionString port:portString];
if (soundSamplesURL != nil) if (soundSamplesURL != nil)
{ {
strlcpy(path.pathToSounds, [[soundSamplesURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToSounds, [[soundSamplesURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *firmwareURL = [CocoaDSFile directoryURLByKind:@"Firmware Configuration"]; NSURL *firmwareURL = [CocoaDSFile directoryURLByKind:@"Firmware Configuration" version:versionString port:portString];
if (firmwareURL != nil) if (firmwareURL != nil)
{ {
strlcpy(path.pathToFirmware, [[firmwareURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToFirmware, [[firmwareURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
} }
NSURL *luaURL = [CocoaDSFile directoryURLByKind:@"Lua Script"]; NSURL *luaURL = [CocoaDSFile directoryURLByKind:@"Lua Script" version:versionString port:portString];
if (luaURL != nil)
{
strlcpy(path.pathToLua, [[luaURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
}
/********************************************************************************************
setupAllFilePathsWithURLDictionary:
Sets up all application file paths using the global URLDictionary. This method exists
in the case where reading the paths from FileTypeInfo.plist impossible or impractical.
Takes:
URLDictionaryKey - An NSString that is a group key to the URLDictionary.
Returns:
Nothing.
Details:
This is an Objective-C to C wrapper function for assigning file paths to the
emulation layer.
********************************************************************************************/
+ (void) setupAllFilePathsWithURLDictionary:(NSString *)URLDictionaryKey
{
if (URLDictionaryKey == nil)
{
return;
}
NSDictionary *URLDictionary = (NSDictionary *)[(NSDictionary *)[CocoaDSFile URLDictionary] valueForKey:URLDictionaryKey];
NSURL *romURL = (NSURL *)[URLDictionary valueForKey:@"ROM"];
if (romURL != nil)
{
strlcpy(path.pathToRoms, [[romURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *romSaveURL = (NSURL *)[URLDictionary valueForKey:@"ROM Save"];
if (romSaveURL != nil)
{
strlcpy(path.pathToBattery, [[romSaveURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *saveStateURL = (NSURL *)[URLDictionary valueForKey:@"Save State"];
if (saveStateURL != nil)
{
strlcpy(path.pathToStates, [[saveStateURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *screenshotURL = (NSURL *)[URLDictionary valueForKey:@"Screenshot"];
if (screenshotURL != nil)
{
strlcpy(path.pathToScreenshots, [[screenshotURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *aviURL = (NSURL *)[URLDictionary valueForKey:@"Video"];
if (aviURL != nil)
{
strlcpy(path.pathToAviFiles, [[aviURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *cheatURL = (NSURL *)[URLDictionary valueForKey:@"Cheat"];
if (cheatURL != nil)
{
strlcpy(path.pathToCheats, [[cheatURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *soundSamplesURL = (NSURL *)[URLDictionary valueForKey:@"Sound Sample"];
if (soundSamplesURL != nil)
{
strlcpy(path.pathToSounds, [[soundSamplesURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *firmwareURL = (NSURL *)[URLDictionary valueForKey:@"Firmware Configuration"];
if (firmwareURL != nil)
{
strlcpy(path.pathToFirmware, [[firmwareURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
}
NSURL *luaURL = (NSURL *)[URLDictionary valueForKey:@"Lua Script"];
if (luaURL != nil) if (luaURL != nil)
{ {
strlcpy(path.pathToLua, [[luaURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH); strlcpy(path.pathToLua, [[luaURL path] cStringUsingEncoding:NSUTF8StringEncoding], MAX_PATH);
@ -283,6 +505,11 @@
result = NO; result = NO;
} }
} }
else if ([dirPath isEqualToString:@PATH_OPEN_EMU])
{
// OpenEmu uses its own directory structure, so no need to setup here.
continue;
}
else if ([dirPath isEqualToString:@PATH_WITH_ROM]) else if ([dirPath isEqualToString:@PATH_WITH_ROM])
{ {
continue; continue;
@ -583,6 +810,14 @@
{ {
fileURL = [CocoaDSFile userAppSupportURL:dirName version:lookupVersionStr]; fileURL = [CocoaDSFile userAppSupportURL:dirName version:lookupVersionStr];
} }
else if ([dirPath isEqualToString:@PATH_OPEN_EMU])
{
NSMutableDictionary *urlDictionary = (NSMutableDictionary *)[[CocoaDSFile URLDictionary] valueForKey:dirPath];
if (urlDictionary != nil)
{
fileURL = (NSURL *)[urlDictionary valueForKey:fileKind];
}
}
else if ([dirPath isEqualToString:@PATH_WITH_ROM]) else if ([dirPath isEqualToString:@PATH_WITH_ROM])
{ {
return fileURL; return fileURL;

View File

@ -113,6 +113,7 @@
#define PATH_CONFIG_DIRECTORY_0_9_6 "~/.config/desmume" #define PATH_CONFIG_DIRECTORY_0_9_6 "~/.config/desmume"
#define PATH_USER_APP_SUPPORT "${APPSUPPORT}" #define PATH_USER_APP_SUPPORT "${APPSUPPORT}"
#define PATH_OPEN_EMU "${OPENEMU}"
#define PATH_WITH_ROM "${WITHROM}" #define PATH_WITH_ROM "${WITHROM}"
#define FILE_EXT_FIRMWARE_CONFIG "dfc" #define FILE_EXT_FIRMWARE_CONFIG "dfc"
@ -162,8 +163,9 @@
#define SPU_SAMPLE_RATE 44100 // Samples per second #define SPU_SAMPLE_RATE 44100 // Samples per second
#define SPU_SAMPLE_RESOLUTION 16 // Bits per sample; must be a multiple of 8 #define SPU_SAMPLE_RESOLUTION 16 // Bits per sample; must be a multiple of 8
#define SPU_STEREO_SAMPLE_SIZE ((SPU_SAMPLE_RESOLUTION / 8) * 2) // Bytes per sample, multiply by 2 for stereo #define SPU_NUMBER_CHANNELS 2 // Number of channels
#define SPU_BUFFER_BYTES ((SPU_SAMPLE_RATE / DS_FRAMES_PER_SECOND) * SPU_STEREO_SAMPLE_SIZE) #define SPU_SAMPLE_SIZE ((SPU_SAMPLE_RESOLUTION / 8) * SPU_NUMBER_CHANNELS) // Bytes per sample, multiplied by the number of channels
#define SPU_BUFFER_BYTES ((SPU_SAMPLE_RATE / DS_FRAMES_PER_SECOND) * SPU_SAMPLE_SIZE)
#define CLOCKWISE_DEGREES(x) (360.0 - x) // Converts an angle in degrees from normal-direction to clockwise-direction. #define CLOCKWISE_DEGREES(x) (360.0 - x) // Converts an angle in degrees from normal-direction to clockwise-direction.

View File

@ -62,10 +62,6 @@
- (id) initWithVolume:(CGFloat)vol; - (id) initWithVolume:(CGFloat)vol;
- (void) dealloc; - (void) dealloc;
+ (BOOL) startupSPU;
+ (void) shutdownSPU;
+ (BOOL) isSPUStarted;
- (void) setVolume:(float)vol; - (void) setVolume:(float)vol;
- (float) volume; - (float) volume;
- (void) setAudioOutputEngine:(NSInteger)methodID; - (void) setAudioOutputEngine:(NSInteger)methodID;

View File

@ -22,7 +22,6 @@
#import "cocoa_util.h" #import "cocoa_util.h"
#include <OpenGL/OpenGL.h> #include <OpenGL/OpenGL.h>
#include "sndOSX.h"
#include "../NDSSystem.h" #include "../NDSSystem.h"
#include "../GPU.h" #include "../GPU.h"
@ -40,12 +39,6 @@ GPU3DInterface *core3DList[] = {
NULL NULL
}; };
SoundInterface_struct *SNDCoreList[] = {
&SNDDummy,
&SNDOSX,
NULL
};
@implementation CocoaDSOutput @implementation CocoaDSOutput
@synthesize isStateChanged; @synthesize isStateChanged;
@ -133,8 +126,6 @@ SoundInterface_struct *SNDCoreList[] = {
@synthesize bufferSize; @synthesize bufferSize;
static BOOL isSPUStarted = NO;
- (id)init - (id)init
{ {
return [self initWithVolume:MAX_VOLUME]; return [self initWithVolume:MAX_VOLUME];
@ -161,7 +152,7 @@ static BOOL isSPUStarted = NO;
[property setValue:[NSNumber numberWithFloat:(float)vol] forKey:@"volume"]; [property setValue:[NSNumber numberWithFloat:(float)vol] forKey:@"volume"];
[property setValue:[NSNumber numberWithBool:NO] forKey:@"mute"]; [property setValue:[NSNumber numberWithBool:NO] forKey:@"mute"];
[property setValue:[NSNumber numberWithInteger:0] forKey:@"filter"]; [property setValue:[NSNumber numberWithInteger:0] forKey:@"filter"];
[property setValue:[NSNumber numberWithInteger:SNDCORE_OSX] forKey:@"audioOutputEngine"]; [property setValue:[NSNumber numberWithInteger:SNDCORE_DUMMY] forKey:@"audioOutputEngine"];
[property setValue:[NSNumber numberWithBool:NO] forKey:@"spuAdvancedLogic"]; [property setValue:[NSNumber numberWithBool:NO] forKey:@"spuAdvancedLogic"];
[property setValue:[NSNumber numberWithInteger:SPUInterpolation_None] forKey:@"spuInterpolationMode"]; [property setValue:[NSNumber numberWithInteger:SPUInterpolation_None] forKey:@"spuInterpolationMode"];
[property setValue:[NSNumber numberWithInteger:SPU_SYNC_MODE_DUAL_SYNC_ASYNC] forKey:@"spuSyncMode"]; [property setValue:[NSNumber numberWithInteger:SPU_SYNC_MODE_DUAL_SYNC_ASYNC] forKey:@"spuSyncMode"];
@ -175,43 +166,6 @@ static BOOL isSPUStarted = NO;
[super dealloc]; [super dealloc];
} }
+ (BOOL) startupSPU
{
NSInteger result = -1;
if (isSPUStarted)
{
return isSPUStarted;
}
SNDOSXStartup();
result = SPU_ChangeSoundCore(SNDCORE_OSX, (int)SPU_BUFFER_BYTES);
if(result == -1)
{
SPU_ChangeSoundCore(SNDCORE_DUMMY, 0);
isSPUStarted = NO;
return isSPUStarted;
}
SPU_SetVolume(0);
isSPUStarted = YES;
return isSPUStarted;
}
+ (void) shutdownSPU
{
SPU_ChangeSoundCore(SNDCORE_DUMMY, 0);
SNDOSXShutdown();
isSPUStarted = NO;
}
+ (BOOL) isSPUStarted
{
return isSPUStarted;
}
- (void) setVolume:(float)vol - (void) setVolume:(float)vol
{ {
if (vol < 0.0f) if (vol < 0.0f)
@ -227,12 +181,7 @@ static BOOL isSPUStarted = NO;
[property setValue:[NSNumber numberWithFloat:vol] forKey:@"volume"]; [property setValue:[NSNumber numberWithFloat:vol] forKey:@"volume"];
OSSpinLockUnlock(&spinlockVolume); OSSpinLockUnlock(&spinlockVolume);
if (isSPUStarted)
{
//pthread_mutex_lock(self.mutexOutputFrame);
SPU_SetVolume((int)vol); SPU_SetVolume((int)vol);
//pthread_mutex_unlock(self.mutexOutputFrame);
}
} }
- (float) volume - (float) volume
@ -253,15 +202,10 @@ static BOOL isSPUStarted = NO;
pthread_mutex_lock(self.mutexOutputFrame); pthread_mutex_lock(self.mutexOutputFrame);
NSInteger result = -1; NSInteger result = -1;
switch (methodID)
{
case SNDCORE_OSX:
result = SPU_ChangeSoundCore(methodID, (int)SPU_BUFFER_BYTES);
break;
default: if (methodID != SNDCORE_DUMMY)
SPU_ChangeSoundCore(SNDCORE_DUMMY, 0); {
break; result = SPU_ChangeSoundCore(methodID, (int)SPU_BUFFER_BYTES);
} }
if(result == -1) if(result == -1)
@ -377,8 +321,6 @@ static BOOL isSPUStarted = NO;
{ {
[property setValue:[NSNumber numberWithBool:mute] forKey:@"mute"]; [property setValue:[NSNumber numberWithBool:mute] forKey:@"mute"];
if (isSPUStarted)
{
if (mute) if (mute)
{ {
SPU_SetVolume(0); SPU_SetVolume(0);
@ -387,7 +329,6 @@ static BOOL isSPUStarted = NO;
{ {
SPU_SetVolume((int)[self volume]); SPU_SetVolume((int)[self volume]);
} }
}
} }
- (NSInteger) filter - (NSInteger) filter
@ -400,16 +341,6 @@ static BOOL isSPUStarted = NO;
[property setValue:[NSNumber numberWithInteger:filter] forKey:@"filter"]; [property setValue:[NSNumber numberWithInteger:filter] forKey:@"filter"];
} }
- (void) runThread:(id)object
{
[CocoaDSSpeaker startupSPU];
SPU_SetVolume((int)[self volume]);
[super runThread:object];
[CocoaDSSpeaker shutdownSPU];
}
- (void)handlePortMessage:(NSPortMessage*)portMessage - (void)handlePortMessage:(NSPortMessage*)portMessage
{ {
NSInteger message = (NSInteger)[portMessage msgid]; NSInteger message = (NSInteger)[portMessage msgid];

View File

@ -0,0 +1,211 @@
/*
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "coreaudiosound.h"
#include "cocoa_globals.h"
CoreAudioSound::CoreAudioSound(size_t bufferSamples, size_t sampleSize)
{
OSStatus error = noErr;
_spinlockAU = (OSSpinLock *)malloc(sizeof(OSSpinLock));
*_spinlockAU = OS_SPINLOCK_INIT;
_buffer = new RingBuffer(bufferSamples, sampleSize);
_volume = 1.0f;
// Create a new audio unit
ComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
Component comp = FindNextComponent(NULL, &desc);
if (comp == NULL)
{
return;
}
error = OpenAComponent(comp, &_au);
if (comp == NULL)
{
return;
}
// Set the render callback
AURenderCallbackStruct callback;
callback.inputProc = &RenderCallback;
callback.inputProcRefCon = _buffer;
error = AudioUnitSetProperty(_au,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callback,
sizeof(callback) );
if(error != noErr)
{
return;
}
// Set up the audio unit for audio streaming
AudioStreamBasicDescription audio_format;
audio_format.mSampleRate = SPU_SAMPLE_RATE;
audio_format.mFormatID = kAudioFormatLinearPCM;
audio_format.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kLinearPCMFormatFlagIsPacked;
audio_format.mBytesPerPacket = SPU_SAMPLE_SIZE;
audio_format.mFramesPerPacket = 1;
audio_format.mBytesPerFrame = SPU_SAMPLE_SIZE;
audio_format.mChannelsPerFrame = SPU_NUMBER_CHANNELS;
audio_format.mBitsPerChannel = SPU_SAMPLE_RESOLUTION;
error = AudioUnitSetProperty(_au,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audio_format,
sizeof(audio_format) );
if(error != noErr)
{
return;
}
// Initialize our new audio unit
error = AudioUnitInitialize(_au);
if(error != noErr)
{
return;
}
}
CoreAudioSound::~CoreAudioSound()
{
OSSpinLockLock(_spinlockAU);
if(_au != NULL)
{
AudioOutputUnitStop(_au);
AudioUnitUninitialize(_au);
_au = NULL;
}
OSSpinLockUnlock(_spinlockAU);
delete _buffer;
_buffer = NULL;
free(_spinlockAU);
_spinlockAU = NULL;
}
RingBuffer* CoreAudioSound::getBuffer()
{
return this->_buffer;
}
void CoreAudioSound::start()
{
this->clearBuffer();
OSSpinLockLock(this->_spinlockAU);
AudioUnitReset(this->_au, kAudioUnitScope_Global, 0);
AudioOutputUnitStart(this->_au);
OSSpinLockUnlock(this->_spinlockAU);
}
void CoreAudioSound::stop()
{
OSSpinLockLock(this->_spinlockAU);
AudioOutputUnitStop(this->_au);
OSSpinLockUnlock(this->_spinlockAU);
this->clearBuffer();
}
void CoreAudioSound::writeToBuffer(const void *buffer, size_t numberBytes)
{
this->getBuffer()->write(buffer, numberBytes);
}
void CoreAudioSound::clearBuffer()
{
this->_buffer->clear();
}
void CoreAudioSound::mute()
{
OSSpinLockLock(this->_spinlockAU);
AudioUnitSetParameter(this->_au, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, 0.0f, 0);
OSSpinLockUnlock(this->_spinlockAU);
}
void CoreAudioSound::unmute()
{
OSSpinLockLock(this->_spinlockAU);
AudioUnitSetParameter(this->_au, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, this->_volume, 0);
OSSpinLockUnlock(this->_spinlockAU);
}
size_t CoreAudioSound::getAvailableSamples()
{
return this->_buffer->getAvailableElements();
}
float CoreAudioSound::getVolume()
{
return this->_volume;
}
void CoreAudioSound::setVolume(float vol)
{
this->_volume = vol;
OSSpinLockLock(this->_spinlockAU);
AudioUnitSetParameter(this->_au, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, vol, 0);
OSSpinLockUnlock(this->_spinlockAU);
}
OSStatus RenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
RingBuffer *__restrict__ audioBuffer = (RingBuffer *)inRefCon;
UInt8 *__restrict__ playbackBuffer = (UInt8 *)ioData->mBuffers[0].mData;
const size_t totalReadSize = inNumberFrames * audioBuffer->getElementSize();
const size_t bytesRead = audioBuffer->read(playbackBuffer, totalReadSize);
// Pad any remaining samples.
if (bytesRead < totalReadSize)
{
memset(playbackBuffer + bytesRead, 0, totalReadSize - bytesRead);
}
// Copy to other channels.
for (UInt32 channel = 1; channel < ioData->mNumberBuffers; channel++)
{
memcpy(ioData->mBuffers[channel].mData, playbackBuffer, ioData->mBuffers[0].mDataByteSize);
}
return noErr;
}

View File

@ -0,0 +1,58 @@
/*
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _COREAUDIOSOUND_
#define _COREAUDIOSOUND_
#include <CoreServices/CoreServices.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <libkern/OSAtomic.h>
#include "ringbuffer.h"
class CoreAudioSound
{
private:
AudioUnit _au;
RingBuffer *_buffer;
OSSpinLock *_spinlockAU;
float _volume;
public:
CoreAudioSound(size_t bufferSamples, size_t sampleSize);
~CoreAudioSound();
void start();
void stop();
void writeToBuffer(const void *buffer, size_t numberBytes);
void clearBuffer();
size_t getAvailableSamples();
RingBuffer* getBuffer();
void mute();
void unmute();
float getVolume();
void setVolume(float vol);
};
OSStatus RenderCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData);
#endif

View File

@ -53,12 +53,6 @@ GPU3DInterface *core3DList[] = {
NULL NULL
}; };
SoundInterface_struct *SNDCoreList[] = {
&SNDDummy,
&SNDOSX,
NULL
};
struct NDS_fw_config_data macDS_firmware; struct NDS_fw_config_data macDS_firmware;

View File

@ -0,0 +1,184 @@
/*
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ringbuffer.h"
RingBuffer::RingBuffer(size_t numberElements, size_t newBufferElementSize)
{
_buffer = (uint8_t *)calloc(numberElements + 1, newBufferElementSize);
_bufferSize = (numberElements + 1) * newBufferElementSize;
_numElements = numberElements;
_elementSize = newBufferElementSize;
_readPosition = newBufferElementSize - 1;
_writePosition = newBufferElementSize;
_bufferFillSize = 0;
}
RingBuffer::~RingBuffer()
{
free(_buffer);
_buffer = NULL;
}
void RingBuffer::clear()
{
this->_readPosition = this->_elementSize - 1;
this->_writePosition = this->_elementSize;
this->_bufferFillSize = 0;
memset(_buffer, 0, this->_bufferSize);
}
size_t RingBuffer::read(void *__restrict__ destBuffer, size_t requestedNumberBytes)
{
if (destBuffer == NULL)
{
return 0;
}
size_t hiBufferAvailable = 0;
size_t loBufferAvailable = 0;
const uint8_t *__restrict__ inputData = this->_buffer;
size_t inputDataReadPos = this->_readPosition;
const size_t inputDataWritePos = this->_writePosition;
const size_t inputDataSize = this->_bufferSize;
// Check buffer availability
if (inputDataReadPos < inputDataWritePos)
{
hiBufferAvailable = inputDataWritePos - inputDataReadPos - 1;
}
else if (inputDataReadPos > inputDataWritePos)
{
hiBufferAvailable = inputDataSize - inputDataReadPos - 1;
loBufferAvailable = inputDataWritePos;
}
// Bounds check for buffer overrun
if (requestedNumberBytes > hiBufferAvailable + loBufferAvailable)
{
requestedNumberBytes = hiBufferAvailable + loBufferAvailable;
requestedNumberBytes -= requestedNumberBytes % this->_elementSize;
}
// Copy ring buffer to destination buffer
if (requestedNumberBytes <= hiBufferAvailable)
{
memcpy(destBuffer, inputData + inputDataReadPos + 1, requestedNumberBytes);
}
else
{
memcpy(destBuffer, inputData + inputDataReadPos + 1, hiBufferAvailable);
memcpy((uint8_t *)destBuffer + hiBufferAvailable, inputData, requestedNumberBytes - hiBufferAvailable);
}
// Advance the read position
inputDataReadPos += requestedNumberBytes;
if (inputDataReadPos >= inputDataSize)
{
inputDataReadPos -= inputDataSize;
}
this->_readPosition = inputDataReadPos;
// Decrease the fill size now that we're done reading.
OSAtomicAdd32Barrier(-(int32_t)requestedNumberBytes, &this->_bufferFillSize);
return requestedNumberBytes;
}
size_t RingBuffer::write(const void *__restrict__ srcBuffer, size_t requestedNumberBytes)
{
if (srcBuffer == NULL)
{
return 0;
}
size_t hiBufferAvailable = 0;
size_t loBufferAvailable = 0;
uint8_t *__restrict__ inputData = this->_buffer;
const size_t inputDataReadPos = this->_readPosition;
size_t inputDataWritePos = this->_writePosition;
const size_t inputDataSize = this->_bufferSize;
// Check buffer availability.
if (inputDataWritePos >= inputDataReadPos)
{
hiBufferAvailable = inputDataSize - inputDataWritePos;
loBufferAvailable = inputDataReadPos;
// Subtract a sample's worth of bytes
if (loBufferAvailable > 0)
{
loBufferAvailable -= 1;
}
else
{
hiBufferAvailable -= 1;
}
}
else // (inputDataWritePos < inputDataReadPos)
{
hiBufferAvailable = inputDataReadPos - inputDataWritePos - 1;
}
// Bounds check for buffer overrun
if (requestedNumberBytes > hiBufferAvailable + loBufferAvailable)
{
requestedNumberBytes = hiBufferAvailable + loBufferAvailable;
requestedNumberBytes -= requestedNumberBytes % this->_elementSize;
}
// Increase the fill size before writing anything.
OSAtomicAdd32Barrier((int32_t)requestedNumberBytes, &this->_bufferFillSize);
// Copy source buffer to ring buffer.
if (requestedNumberBytes <= hiBufferAvailable)
{
memcpy(inputData + inputDataWritePos, srcBuffer, requestedNumberBytes);
}
else
{
memcpy(inputData + inputDataWritePos, srcBuffer, hiBufferAvailable);
memcpy(inputData, (uint8_t *)srcBuffer + hiBufferAvailable, requestedNumberBytes - hiBufferAvailable);
}
// Advance the write position.
inputDataWritePos += requestedNumberBytes;
if (inputDataWritePos >= inputDataSize)
{
inputDataWritePos -= inputDataSize;
}
this->_writePosition = inputDataWritePos;
return requestedNumberBytes;
}
size_t RingBuffer::getAvailableElements()
{
return ((this->_bufferSize - this->_bufferFillSize) / this->_elementSize) - 1;
}
size_t RingBuffer::getElementSize()
{
return this->_elementSize;
}

View File

@ -0,0 +1,49 @@
/*
Copyright (C) 2012 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This file 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _RINGBUFFER_
#define _RINGBUFFER_
#include <stdlib.h>
#include <string.h>
#include <libkern/OSAtomic.h>
class RingBuffer
{
private:
uint8_t *_buffer;
uint8_t *_bufferEnd;
size_t _bufferSize;
size_t _numElements;
size_t _elementSize;
int32_t _bufferFillSize;
size_t _readPosition;
size_t _writePosition;
public:
RingBuffer(size_t numberElements, size_t newBufferElementSize);
~RingBuffer();
void clear();
size_t read(void *__restrict__ destBuffer, size_t requestedNumberBytes);
size_t write(const void *__restrict__ srcBuffer, size_t requestedNumberBytes);
size_t getAvailableElements();
size_t getElementSize();
};
#endif

View File

@ -18,362 +18,57 @@
#include "sndOSX.h" #include "sndOSX.h"
#include <CoreServices/CoreServices.h> #include "coreaudiosound.h"
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#include <pthread.h>
#include "cocoa_globals.h" #include "cocoa_globals.h"
//globals // Global sound playback manager
static AudioUnit output_unit = NULL; //pointer to our audio device static CoreAudioSound *coreAudioPlaybackManager = NULL;
static UInt8 *sound_data = NULL; //buffer where we hold data between getting it from the emulator and sending it to the device
static size_t sound_buffer_size = 0; //size in bytes of sound_data
static size_t sound_offset = SPU_STEREO_SAMPLE_SIZE; //position in the buffer that we have copied to from the emu
static size_t sound_position = 0; //position in the buffer that we have played to
static float current_volume_scalar = 1.0f; //for volume/muting
//file output // Sound interface to the SPU
static bool file_open = false; SoundInterface_struct SNDOSX = {
//static ExtAudioFileRef outfile; SNDCORE_OSX,
"OS X Core Audio Sound Interface",
SNDOSXInit,
SNDOSXDeInit,
SNDOSXUpdateAudio,
SNDOSXGetAudioSpace,
SNDOSXMuteAudio,
SNDOSXUnMuteAudio,
SNDOSXSetVolume,
SNDOSXClearBuffer
};
static pthread_mutex_t *mutexSoundData = NULL; SoundInterface_struct *SNDCoreList[] = {
static pthread_mutex_t *mutexAudioUnit = NULL; &SNDDummy,
&SNDOSX,
////////////////////////////////////////////////////////////////////////////// NULL
};
//This is the callback where we will stick the sound data we've gotten from
//the emulator into a core audio buffer to be processed and sent to the sound driver
OSStatus soundMixer(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData)
{
//printf("SOUND CALLBACK %u off%u pos%u\n", inNumberFrames * 4, sound_offset, sound_position);
UInt8 *__restrict__ outputData = (UInt8 *)ioData->mBuffers[0].mData;
const size_t copySize = inNumberFrames * SPU_STEREO_SAMPLE_SIZE;
size_t hiBufferAvailable = 0;
size_t loBufferAvailable = 0;
pthread_mutex_lock(mutexSoundData);
if(sound_data != NULL)
{
const UInt8 *__restrict__ inputData = sound_data;
const size_t inputDataReadPos = sound_position;
const size_t inputDataWritePos = sound_offset;
const size_t inputDataSize = sound_buffer_size;
// Determine buffer availability
if (inputDataReadPos < inputDataWritePos)
{
hiBufferAvailable = inputDataWritePos - inputDataReadPos - 1;
}
else if (inputDataReadPos > inputDataWritePos)
{
hiBufferAvailable = inputDataSize - inputDataReadPos - 1;
loBufferAvailable = inputDataWritePos;
}
// Copy sound data from buffer
if (copySize <= hiBufferAvailable)
{
memcpy(outputData, inputData + inputDataReadPos + 1, copySize);
sound_position += copySize;
}
else
{
memcpy(outputData, inputData + inputDataReadPos + 1, hiBufferAvailable);
if (copySize - hiBufferAvailable <= loBufferAvailable)
{
memcpy(outputData + hiBufferAvailable, inputData, copySize - hiBufferAvailable);
sound_position = copySize - hiBufferAvailable - 1;
}
else
{
memcpy(outputData + hiBufferAvailable, inputData, loBufferAvailable);
if (inputDataWritePos == 0)
{
sound_position = inputDataSize - 1;
}
else
{
sound_position = inputDataWritePos - 1;
}
// Pad any remaining samples with null samples
const size_t totalAvailable = hiBufferAvailable + loBufferAvailable;
if (copySize > totalAvailable)
{
memset(outputData + totalAvailable, 0, copySize - totalAvailable);
}
}
}
}
else
{
memset(outputData, 0, copySize);
}
pthread_mutex_unlock(mutexSoundData);
//copy to other channels
for (UInt32 channel = 1; channel < ioData->mNumberBuffers; channel++)
{
memcpy(ioData->mBuffers[channel].mData, outputData, ioData->mBuffers[0].mDataByteSize);
}
//record to file
if(file_open)
{
//ExtAudioFileWrite(outfile, inNumberFrames, ioData);
}
return noErr;
}
//////////////////////////////////////////////////////////////////////////////
void SNDOSXStartup()
{
OSStatus error = noErr;
if (mutexSoundData == NULL)
{
mutexSoundData = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexSoundData, NULL);
}
if (mutexAudioUnit == NULL)
{
mutexAudioUnit = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutexAudioUnit, NULL);
}
//Setup the sound buffer -------------------------------------------
pthread_mutex_lock(mutexSoundData);
sound_data = (UInt8 *)calloc((SPU_SAMPLE_RATE / DS_FRAMES_PER_SECOND) + 1, SPU_STEREO_SAMPLE_SIZE);
if(sound_data == NULL)
{
pthread_mutex_unlock(mutexSoundData);
return;
}
sound_position = 0;
sound_offset = SPU_STEREO_SAMPLE_SIZE;
sound_buffer_size = ((SPU_SAMPLE_RATE / DS_FRAMES_PER_SECOND) + 1) * SPU_STEREO_SAMPLE_SIZE;
pthread_mutex_unlock(mutexSoundData);
//grab the default audio unit -------------------------
pthread_mutex_lock(mutexAudioUnit);
current_volume_scalar = 1.0f;
ComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
Component comp = FindNextComponent(NULL, &desc);
if (comp == NULL)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
error = OpenAComponent(comp, &output_unit);
if (comp == NULL)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
//then setup the callback where we will send the audio -------
AURenderCallbackStruct callback;
callback.inputProc = soundMixer;
callback.inputProcRefCon = NULL;
error = AudioUnitSetProperty(output_unit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callback,
sizeof(callback) );
if(error != noErr)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
//now begin running the audio unit-- ----------------------
AudioStreamBasicDescription audio_format;
audio_format.mSampleRate = SPU_SAMPLE_RATE;
audio_format.mFormatID = kAudioFormatLinearPCM;
audio_format.mFormatFlags = kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kLinearPCMFormatFlagIsPacked;
audio_format.mBytesPerPacket = 4;
audio_format.mFramesPerPacket = 1;
audio_format.mBytesPerFrame = 4;
audio_format.mChannelsPerFrame = 2;
audio_format.mBitsPerChannel = SPU_SAMPLE_RESOLUTION;
error = AudioUnitSetProperty(output_unit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
0,
&audio_format,
sizeof(audio_format) );
if(error != noErr)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
// Initialize unit
error = AudioUnitInitialize(output_unit);
if(error != noErr)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
pthread_mutex_unlock(mutexAudioUnit);
//we call the CFRunLoopRunInMode to service any notifications that the audio
//system has to deal with
//CFRunLoopRunInMode(kCFRunLoopDefaultMode, 2, false);
//verify_noerr (AudioOutputUnitStop (output_unit));
}
void SNDOSXShutdown()
{
pthread_mutex_lock(mutexAudioUnit);
//closes the audio unit (errors are ignored here)
if(output_unit != NULL)
{
AudioOutputUnitStop(output_unit);
AudioUnitUninitialize(output_unit);
output_unit = NULL;
}
pthread_mutex_unlock(mutexAudioUnit);
pthread_mutex_lock(mutexSoundData);
if(sound_data != NULL)
{
free(sound_data);
sound_data = NULL;
sound_position = 0;
sound_offset = SPU_STEREO_SAMPLE_SIZE;
sound_buffer_size = 0;
}
pthread_mutex_unlock(mutexSoundData);
if (mutexSoundData != NULL)
{
pthread_mutex_destroy(mutexSoundData);
free(mutexSoundData);
mutexSoundData = NULL;
}
if (mutexAudioUnit != NULL)
{
pthread_mutex_destroy(mutexAudioUnit);
free(mutexAudioUnit);
mutexAudioUnit = NULL;
}
}
int SNDOSXInit(int buffer_size) int SNDOSXInit(int buffer_size)
{ {
OSStatus error = noErr; if (coreAudioPlaybackManager != NULL)
const size_t singleSampleSize = SPU_STEREO_SAMPLE_SIZE;
UInt8 *newSoundData = NULL;
//Setup the sound buffer -------------------------------------------
pthread_mutex_lock(mutexSoundData);
//add one more since sound position can never catch up to
//sound_offset - because if they were the same it would signify
//that the buffer is empty
sound_buffer_size = buffer_size + singleSampleSize;
newSoundData = (UInt8 *)realloc(sound_data, sound_buffer_size);
if(newSoundData == NULL)
{ {
free(sound_data); CoreAudioSound *oldcoreAudioPlaybackManager = coreAudioPlaybackManager;
pthread_mutex_unlock(mutexSoundData); coreAudioPlaybackManager = new CoreAudioSound(buffer_size / SPU_SAMPLE_SIZE, SPU_SAMPLE_SIZE);
return -1; delete oldcoreAudioPlaybackManager;
}
else
{
coreAudioPlaybackManager = new CoreAudioSound(buffer_size / SPU_SAMPLE_SIZE, SPU_SAMPLE_SIZE);
} }
memset(newSoundData, 0, sound_buffer_size); coreAudioPlaybackManager->start();
sound_data = newSoundData;
sound_position = 0;
sound_offset = singleSampleSize;
pthread_mutex_unlock(mutexSoundData);
//------------------------------------------------------------------
//Start the rendering
//The DefaultOutputUnit will do any format conversions to the format of the default device
pthread_mutex_lock(mutexAudioUnit);
if (output_unit != NULL)
{
AudioUnitReset(output_unit, kAudioUnitScope_Global, 0);
error = AudioOutputUnitStart(output_unit);
if(error != noErr)
{
pthread_mutex_unlock(mutexAudioUnit);
return -1;
}
}
pthread_mutex_unlock(mutexAudioUnit);
return 0; return 0;
} }
//////////////////////////////////////////////////////////////////////////////
void SNDOSXDeInit() void SNDOSXDeInit()
{ {
pthread_mutex_lock(mutexAudioUnit); delete coreAudioPlaybackManager;
coreAudioPlaybackManager = NULL;
if(output_unit != NULL)
{
AudioOutputUnitStop(output_unit);
}
pthread_mutex_unlock(mutexAudioUnit);
SNDOSXClearBuffer();
SNDOSXCloseFile(); //end recording to file if needed
} }
//////////////////////////////////////////////////////////////////////////////
int SNDOSXReset() int SNDOSXReset()
{ {
SNDOSXClearBuffer(); SNDOSXClearBuffer();
@ -383,169 +78,44 @@ int SNDOSXReset()
void SNDOSXUpdateAudio(s16 *buffer, u32 num_samples) void SNDOSXUpdateAudio(s16 *buffer, u32 num_samples)
{ {
const size_t singleSampleSize = SPU_STEREO_SAMPLE_SIZE; if (coreAudioPlaybackManager != NULL)
size_t copySize = num_samples * singleSampleSize;
size_t hiBufferAvailable = 0; // Buffer space ahead of offset
size_t loBufferAvailable = 0; // Buffer space before read position
pthread_mutex_lock(mutexSoundData);
if(sound_data == NULL)
{ {
pthread_mutex_unlock(mutexSoundData); coreAudioPlaybackManager->writeToBuffer(buffer, coreAudioPlaybackManager->getBuffer()->getElementSize() * (size_t)num_samples);
return;
} }
UInt8 *__restrict__ inputData = sound_data;
const size_t inputDataReadPos = sound_position;
const size_t inputDataWritePos = sound_offset;
const size_t inputDataSize = sound_buffer_size;
if (inputDataWritePos >= inputDataReadPos)
{
hiBufferAvailable = inputDataSize - inputDataWritePos;
loBufferAvailable = inputDataReadPos;
// Subtract a sample's worth of bytes
if (loBufferAvailable > 0)
{
loBufferAvailable -= 1;
}
else
{
hiBufferAvailable -= 1;
}
}
else // (inputDataWritePos < inputDataReadPos)
{
hiBufferAvailable = inputDataReadPos - inputDataWritePos - 1;
}
if (copySize > hiBufferAvailable + loBufferAvailable)
{
//this shouldn't happen as the emulator core generally asks how much
//space is available before sending stuff, but just in case
int bytesShort = copySize - hiBufferAvailable - loBufferAvailable;
printf("SNDOSXUpdateAudio() ERROR: Not enough space in buffer -- %i bytes short.\n", bytesShort);
copySize = hiBufferAvailable + loBufferAvailable;
copySize -= copySize % singleSampleSize;
}
if (copySize <= hiBufferAvailable)
{
memcpy(inputData + inputDataWritePos, buffer, copySize);
}
else
{
memcpy(inputData + inputDataWritePos, buffer, hiBufferAvailable);
memcpy(inputData, ((UInt8 *)buffer) + hiBufferAvailable, copySize - hiBufferAvailable);
}
// Advance the offset
sound_offset += copySize;
if (sound_offset >= inputDataSize)
{
sound_offset -= inputDataSize;
}
pthread_mutex_unlock(mutexSoundData);
} }
//////////////////////////////////////////////////////////////////////////////
u32 SNDOSXGetAudioSpace() u32 SNDOSXGetAudioSpace()
{ {
const size_t singleSampleSize = SPU_STEREO_SAMPLE_SIZE; u32 availableSamples = 0;
size_t free_space = 0;
pthread_mutex_lock(mutexSoundData); if (coreAudioPlaybackManager != NULL)
if(sound_data == NULL)
{ {
pthread_mutex_unlock(mutexSoundData); availableSamples = (u32)coreAudioPlaybackManager->getAvailableSamples();
return 0;
} }
if(sound_offset >= sound_position) return availableSamples;
{
free_space = (sound_buffer_size - sound_offset) + sound_position;
}
else // (sound_offset < sound_position)
{
free_space = sound_position - sound_offset;
}
pthread_mutex_unlock(mutexSoundData);
if (free_space >= singleSampleSize)
{
free_space -= singleSampleSize;
}
else
{
free_space = 0;
}
return (u32)(free_space / singleSampleSize);
} }
//////////////////////////////////////////////////////////////////////////////
void SNDOSXMuteAudio() void SNDOSXMuteAudio()
{ {
OSStatus error = noErr; if (coreAudioPlaybackManager != NULL)
pthread_mutex_lock(mutexAudioUnit);
if(output_unit == NULL)
{ {
pthread_mutex_unlock(mutexAudioUnit); coreAudioPlaybackManager->mute();
return;
}
error = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, 0, 0);
pthread_mutex_unlock(mutexAudioUnit);
if(error != noErr)
{
printf("SNDOSXMuteAudio() ERROR: Could not set Audio Unit parameter -- Volume=0.0%%\n");
} }
} }
//////////////////////////////////////////////////////////////////////////////
void SNDOSXUnMuteAudio() void SNDOSXUnMuteAudio()
{ {
OSStatus error = noErr; if (coreAudioPlaybackManager != NULL)
float volumeScalar = 0.0f;
pthread_mutex_lock(mutexAudioUnit);
if(output_unit == NULL)
{ {
pthread_mutex_unlock(mutexAudioUnit); coreAudioPlaybackManager->unmute();
return;
}
volumeScalar = current_volume_scalar;
error = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, volumeScalar, 0);
pthread_mutex_unlock(mutexAudioUnit);
if(error != noErr)
{
printf("SNDOSXUnMuteAudio() ERROR: Could not set Audio Unit parameter -- Volume=%1.1f%%\n", volumeScalar * 100.0f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
void SNDOSXSetVolume(int volume) void SNDOSXSetVolume(int volume)
{ {
OSStatus error = noErr; if (coreAudioPlaybackManager != NULL)
{
float newVolumeScalar = (float)volume / 100.0f; float newVolumeScalar = (float)volume / 100.0f;
if(volume > 100) if(volume > 100)
@ -557,156 +127,14 @@ void SNDOSXSetVolume(int volume)
newVolumeScalar = 0.0f; newVolumeScalar = 0.0f;
} }
pthread_mutex_lock(mutexAudioUnit); coreAudioPlaybackManager->setVolume(newVolumeScalar);
if(output_unit == NULL)
{
pthread_mutex_unlock(mutexAudioUnit);
return;
}
current_volume_scalar = newVolumeScalar;
error = AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, newVolumeScalar, 0);
pthread_mutex_unlock(mutexAudioUnit);
if(error != noErr)
{
printf("SNDOSXSetVolume() ERROR: Could not set Audio Unit parameter -- Volume=%1.1f%%\n", newVolumeScalar * 100.0f);
} }
} }
void SNDOSXClearBuffer() void SNDOSXClearBuffer()
{ {
pthread_mutex_lock(mutexSoundData); if (coreAudioPlaybackManager != NULL)
if(sound_data != NULL)
{ {
memset(sound_data, 0, sound_buffer_size); coreAudioPlaybackManager->clearBuffer();
sound_position = 0;
sound_offset = SPU_STEREO_SAMPLE_SIZE;
} }
pthread_mutex_unlock(mutexSoundData);
pthread_mutex_lock(mutexAudioUnit);
if(output_unit != NULL)
{
AudioUnitReset(output_unit, kAudioUnitScope_Global, 0);
}
pthread_mutex_unlock(mutexAudioUnit);
} }
//////////////////////////////////////////////////////////////////////////////
SoundInterface_struct SNDOSX = {
SNDCORE_OSX,
"Core Audio Sound Interface",
SNDOSXInit,
SNDOSXDeInit,
SNDOSXUpdateAudio,
SNDOSXGetAudioSpace,
SNDOSXMuteAudio,
SNDOSXUnMuteAudio,
SNDOSXSetVolume,
SNDOSXClearBuffer
};
//////////////////////////////////////////////////////////////////////////////
//Sound recording
//////////////////////////////////////////////////////////////////////////////
bool SNDOSXOpenFile(void *fname)
{
/*
if(sound_data == NULL)return false;
SNDOSXCloseFile();
if(!fname)return false;
NSString *filename = (NSString*)fname;
FSRef ref;
if(FSPathMakeRef((const UInt8*)[[filename stringByDeletingLastPathComponent] fileSystemRepresentation], &ref, NULL) != noErr)
{
SNDOSXStopRecording();
return false;
}
AudioStreamBasicDescription audio_format;
audio_format.mSampleRate = SPU_SAMPLE_RATE;
audio_format.mFormatID = kAudioFormatLinearPCM;
audio_format.mFormatFlags = kAudioFormatFlagIsSignedInteger
| kAudioFormatFlagsNativeEndian
| kLinearPCMFormatFlagIsPacked;
audio_format.mBytesPerPacket = 4;
audio_format.mFramesPerPacket = 1;
audio_format.mBytesPerFrame = 4;
audio_format.mChannelsPerFrame = 2;
audio_format.mBitsPerChannel = SPU_SAMPLE_RESOLUTION;
if(ExtAudioFileCreateNew(&ref, (CFStringRef)[[filename pathComponents] lastObject], kAudioFileWAVEType, &audio_format, NULL, &outfile) != noErr)
return false;
file_open = true;
return true;
*/
return false;
}
void SNDOSXStartRecording()
{
pthread_mutex_lock(mutexSoundData);
if(sound_data == NULL)
{
pthread_mutex_unlock(mutexSoundData);
return;
}
pthread_mutex_unlock(mutexSoundData);
}
void SNDOSXStopRecording()
{
pthread_mutex_lock(mutexSoundData);
if(sound_data == NULL)
{
pthread_mutex_unlock(mutexSoundData);
return;
}
pthread_mutex_unlock(mutexSoundData);
}
void SNDOSXCloseFile()
{
pthread_mutex_lock(mutexSoundData);
if(sound_data == NULL)
{
pthread_mutex_unlock(mutexSoundData);
return;
}
if(file_open)
{
file_open = false;
//if it's rendering sound, wait until it's not
//so we dont close the file while writing to it
// Do something here, just not implemented yet...
//ExtAudioFileDispose(outfile);
}
pthread_mutex_unlock(mutexSoundData);
}
///////////////////////////////////////////////////////////////////////////

View File

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2007 Jeff Bland Copyright (C) 2007 Jeff Bland
Copyright (C) 2007-2011 DeSmuME team Copyright (C) 2007-2012 DeSmuME team
This file is free software: you can redistribute it and/or modify This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -16,17 +16,17 @@
along with the this software. If not, see <http://www.gnu.org/licenses/>. along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _OSXSOUNDINTERFACE_
#define _OSXSOUNDINTERFACE_
#include "../SPU.h" #include "../SPU.h"
#define SNDCORE_OSX 58325 //hopefully this is unique number #define SNDCORE_OSX 58325 //hopefully this is unique number
// Sound interface to the SPU
// This is the sound interface so the emulator core can send us sound info and whatnot
extern SoundInterface_struct SNDOSX; extern SoundInterface_struct SNDOSX;
// Sound interface extensions for CoreAudio // Core Audio functions for the sound interface
void SNDOSXStartup();
void SNDOSXShutdown();
int SNDOSXInit(int buffer_size); int SNDOSXInit(int buffer_size);
void SNDOSXDeInit(); void SNDOSXDeInit();
int SNDOSXReset(); int SNDOSXReset();
@ -37,9 +37,4 @@ void SNDOSXUnMuteAudio();
void SNDOSXSetVolume(int volume); void SNDOSXSetVolume(int volume);
void SNDOSXClearBuffer(); void SNDOSXClearBuffer();
// Recording #endif // _OSXSOUNDINTERFACE_
// Not supported as of 2011/12/28 - rogerman
bool SNDOSXOpenFile(void *fname); //opens a file for recording (if filename is the currently opened one, it will restart the file), fname is an NSString
void SNDOSXStartRecording(); //begins recording to the currently open file if there is an open file
void SNDOSXStopRecording(); //pauses recording (you can continue recording later)
void SNDOSXCloseFile(); //closes the file, making sure it's saved

View File

@ -188,8 +188,7 @@
[NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil]; [NSThread detachNewThreadSelector:@selector(runThread:) toTarget:newSpeaker withObject:nil];
// Wait until the GPU and SPU are finished starting up. // Wait until the GPU and SPU are finished starting up.
while (!([CocoaDSSpeaker isSPUStarted] && while ([newComboDisplay thread] == nil || [newSpeaker thread] == nil)
[newComboDisplay thread] != nil && [newSpeaker thread] != nil))
{ {
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]]; [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
} }

View File

@ -117,8 +117,6 @@ void joinThread_gdb(void *thread_handle)
[aboutWindowController setContent:aboutWindowProperties]; [aboutWindowController setContent:aboutWindowProperties];
SNDOSXStartup();
//Set default values for all preferences //Set default values for all preferences
//(this wont override saved preferences as //(this wont override saved preferences as
//they work in different preference domains) //they work in different preference domains)
@ -192,8 +190,6 @@ void joinThread_gdb(void *thread_handle)
[cdsCore release]; [cdsCore release];
[cdsCoreController setContent:nil]; [cdsCoreController setContent:nil];
SNDOSXShutdown();
} }
- (IBAction) showSupportFolderInFinder:(id)sender - (IBAction) showSupportFolderInFinder:(id)sender