18 #include "../stdafx.h" 19 #include "../os/macosx/macos.h" 21 #include "midifile.hpp" 23 #include "../base_media_base.h" 25 #include <CoreServices/CoreServices.h> 26 #include <AudioUnit/AudioUnit.h> 27 #include <AudioToolbox/AudioToolbox.h> 29 #include "../safeguards.h" 31 #if !defined(HAVE_OSX_1011_SDK) 32 #define kMusicSequenceFile_AnyType 0 38 static MusicPlayer _player = NULL;
39 static MusicSequence _sequence = NULL;
40 static MusicTimeStamp _seq_length = 0;
41 static bool _playing =
false;
42 static byte _volume = 127;
46 static void DoSetVolume()
48 if (_sequence == NULL)
return;
51 MusicSequenceGetAUGraph(_sequence, &graph);
53 AudioUnit output_unit = NULL;
56 UInt32 node_count = 0;
57 AUGraphGetNodeCount(graph, &node_count);
58 for (UInt32 i = 0; i < node_count; i++) {
60 AUGraphGetIndNode(graph, i, &node);
65 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 73 #if defined(__AUDIOCOMPONENT_H__) || defined(HAVE_OSX_107_SDK) 74 AudioComponentDescription desc;
76 ComponentDescription desc;
78 AUGraphNodeInfo(graph, node, &desc, &unit);
79 comp_type = desc.componentType;
83 #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) 84 ComponentDescription desc;
85 AUGraphGetNodeInfo(graph, node, &desc, NULL, NULL, &unit);
86 comp_type = desc.componentType;
90 if (comp_type == kAudioUnitType_Output) {
95 if (output_unit == NULL) {
96 DEBUG(driver, 1,
"cocoa_m: Failed to get output node to set volume");
100 Float32 vol = _volume / 127.0f;
101 AudioUnitSetParameter(output_unit, kHALOutputParam_Volume, kAudioUnitScope_Global, 0, vol, 0);
110 if (NewMusicPlayer(&_player) != noErr)
return "failed to create music player";
121 if (!_playing)
return false;
123 MusicTimeStamp time = 0;
124 MusicPlayerGetTime(_player, &time);
125 return time < _seq_length;
134 if (_player != NULL) DisposeMusicPlayer(_player);
135 if (_sequence != NULL) DisposeMusicSequence(_sequence);
148 DEBUG(driver, 2,
"cocoa_m: trying to play '%s'", filename.c_str());
151 if (_sequence != NULL) {
152 DisposeMusicSequence(_sequence);
156 if (filename.empty())
return;
158 if (NewMusicSequence(&_sequence) != noErr) {
159 DEBUG(driver, 0,
"cocoa_m: Failed to create music sequence");
163 const char *os_file =
OTTD2FS(filename.c_str());
164 CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (
const UInt8*)os_file, strlen(os_file),
false);
166 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 168 if (MusicSequenceFileLoad(_sequence, url, kMusicSequenceFile_AnyType, 0) != noErr) {
169 DEBUG(driver, 0,
"cocoa_m: Failed to load MIDI file");
176 #if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) 178 if (!CFURLGetFSRef(url, &ref_file)) {
179 DEBUG(driver, 0,
"cocoa_m: Failed to make FSRef");
183 if (MusicSequenceLoadSMFWithFlags(_sequence, &ref_file, 0) != noErr) {
184 DEBUG(driver, 0,
"cocoa_m: Failed to load MIDI file old style");
193 AUGraph graph = NULL;
195 MusicSequenceGetAUGraph(_sequence, &graph);
197 if (AUGraphInitialize(graph) != noErr) {
198 DEBUG(driver, 0,
"cocoa_m: Failed to initialize AU graph");
204 MusicSequenceGetTrackCount(_sequence, &num_tracks);
206 for (UInt32 i = 0; i < num_tracks; i++) {
207 MusicTrack track = NULL;
208 MusicTimeStamp track_length = 0;
209 UInt32 prop_size =
sizeof(MusicTimeStamp);
210 MusicSequenceGetIndTrack(_sequence, i, &track);
211 MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &track_length, &prop_size);
212 if (track_length > _seq_length) _seq_length = track_length;
218 MusicPlayerSetSequence(_player, _sequence);
219 MusicPlayerPreroll(_player);
220 if (MusicPlayerStart(_player) != noErr)
return;
223 DEBUG(driver, 3,
"cocoa_m: playing '%s'", filename.c_str());
232 MusicPlayerStop(_player);
233 MusicPlayerSetSequence(_player, NULL);
Metadata about a music track.
const char * Start(const char *const *param)
Start this driver.
void StopSong()
Stop playing the current song.
void PlaySong(const MusicSongInfo &song)
Play a particular song.
static bool MacOSVersionIsAtLeast(long major, long minor, long bugfix)
Check if we are at least running on the specified version of Mac OS.
Base of music playback via CoreAudio.
const TCHAR * OTTD2FS(const char *name, bool console_cp)
Convert from OpenTTD's encoding to that of the local environment.
#define DEBUG(name, level,...)
Output a line of debugging information.
static std::string GetSMFFile(const MusicSongInfo &song)
Get the name of a Standard MIDI File for a given song.
bool IsSongPlaying()
Are we currently playing a song?
void SetVolume(byte vol)
Set the volume, if possible.
void Stop()
Stop this driver.