Line data Source code
1 0 : /* 2 : 3 : OOMusicController.m 4 : 5 : 6 : Oolite 7 : Copyright (C) 2004-2013 Giles C Williams and contributors 8 : 9 : This program is free software; you can redistribute it and/or 10 : modify it under the terms of the GNU General Public License 11 : as published by the Free Software Foundation; either version 2 12 : of the License, or (at your option) any later version. 13 : 14 : This program is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU General Public License for more details. 18 : 19 : You should have received a copy of the GNU General Public License 20 : along with this program; if not, write to the Free Software 21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 22 : MA 02110-1301, USA. 23 : 24 : */ 25 : 26 : #import "OOMusicController.h" 27 : #import "OOSound.h" 28 : #import "OOCollectionExtractors.h" 29 : #import "ResourceManager.h" 30 : 31 : 32 0 : static id sSingleton = nil; 33 : 34 : 35 : @interface OOMusicController (Private) 36 : 37 0 : - (void) playiTunesPlaylist:(NSString *)playlistName; 38 0 : - (void) pauseiTunes; 39 : 40 : @end 41 : 42 : 43 : 44 : // Values for _special 45 0 : enum 46 : { 47 : kSpecialNone, 48 : kSpecialTheme, 49 : kSpecialDocking, 50 : kSpecialDocked, 51 : kSpecialMission 52 : }; 53 : 54 : 55 : @implementation OOMusicController 56 : 57 : + (OOMusicController *) sharedController 58 : { 59 : if (sSingleton == nil) 60 : { 61 : sSingleton = [[self alloc] init]; 62 : } 63 : 64 : return sSingleton; 65 : } 66 : 67 : 68 0 : - (id) init 69 : { 70 : self = [super init]; 71 : if (self != nil) 72 : { 73 : NSString *modeString = [[NSUserDefaults standardUserDefaults] stringForKey:@"music mode"]; 74 : if ([modeString isEqualToString:@"off"]) _mode = kOOMusicOff; 75 : else if ([modeString isEqualToString:@"iTunes"]) _mode = kOOMusicITunes; 76 : else _mode = kOOMusicOn; 77 : 78 : // Handle unlikely case of taking prefs from iTunes-enabled system to other. 79 : if (_mode > kOOMusicModeMax) _mode = kOOMusicModeMax; 80 : 81 : [self setMissionMusic:@"OoliteTheme.ogg"]; 82 : } 83 : 84 : return self; 85 : } 86 : 87 : 88 : - (void) playMusicNamed:(NSString *)name loop:(BOOL)loop 89 : { 90 : [self playMusicNamed:name loop:loop gain:OO_DEFAULT_SOUNDSOURCE_GAIN]; 91 : } 92 : 93 : 94 : - (void) playMusicNamed:(NSString *)name loop:(BOOL)loop gain:(float)gain 95 : { 96 : if ([self isPlaying] && [name isEqual:[self playingMusic]]) return; 97 : 98 : if (_mode == kOOMusicOn || (_mode == kOOMusicITunes && [name isEqualToString:@"OoliteTheme.ogg"])) 99 : { 100 : OOMusic *music = [ResourceManager ooMusicNamed:name inFolder:@"Music"]; 101 : if (music != nil) 102 : { 103 : [_current stop]; 104 : 105 : [music setMusicGain:OOClamp_0_1_f(gain)]; 106 : [music playLooped:loop]; 107 : 108 : [_current release]; 109 : _current = [music retain]; 110 : } 111 : } 112 : } 113 : 114 : 115 : - (void) playThemeMusic 116 : { 117 : _special = kSpecialTheme; 118 : [self playMusicNamed:@"OoliteTheme.ogg" loop:YES]; 119 : } 120 : 121 : 122 : - (void) playDockingMusic 123 : { 124 : _special = kSpecialDocking; 125 : 126 : if (_mode == kOOMusicITunes) 127 : { 128 : [self playiTunesPlaylist:@"Oolite-Docking"]; 129 : } 130 : else 131 : { 132 : [self playMusicNamed:@"BlueDanube.ogg" loop:YES]; 133 : } 134 : } 135 : 136 : 137 : - (void) playDockedMusic 138 : { 139 : _special = kSpecialDocked; 140 : 141 : if (_mode == kOOMusicITunes) 142 : { 143 : [self playiTunesPlaylist:@"Oolite-Docked"]; 144 : } 145 : else 146 : { 147 : [self playMusicNamed:@"OoliteDocked.ogg" loop:NO]; 148 : } 149 : } 150 : 151 : 152 : - (void) setMissionMusic:(NSString *)missionMusicName 153 : { 154 : [_missionMusic autorelease]; 155 : _missionMusic = [missionMusicName copy]; 156 : } 157 : 158 : 159 : - (void) playMissionMusic 160 : { 161 : if (_missionMusic != nil) 162 : { 163 : _special = kSpecialMission; 164 : [self playMusicNamed:_missionMusic loop:NO]; 165 : } 166 : } 167 : 168 : 169 : // Stop without switching iTunes to in-flight music. 170 : - (void) justStop 171 : { 172 : [_current stop]; 173 : [_current release]; 174 : _current = nil; 175 : _special = kSpecialNone; 176 : } 177 : 178 : 179 : - (void) stop 180 : { 181 : [self justStop]; 182 : 183 : if (_mode == kOOMusicITunes) 184 : { 185 : [self playiTunesPlaylist:@"Oolite-Inflight"]; 186 : } 187 : } 188 : 189 : 190 : - (void) stopMusicNamed:(NSString *)name 191 : { 192 : if ([name isEqual:[self playingMusic]]) [self stop]; 193 : } 194 : 195 : 196 : - (void) stopThemeMusic 197 : { 198 : if (_special == kSpecialTheme) 199 : { 200 : [self justStop]; 201 : [self playDockedMusic]; 202 : } 203 : } 204 : 205 : 206 : - (void) stopDockingMusic 207 : { 208 : if (_special == kSpecialDocking) [self stop]; 209 : } 210 : 211 : 212 : - (void) stopMissionMusic 213 : { 214 : if (_special == kSpecialMission) [self stop]; 215 : } 216 : 217 : 218 : - (void) toggleDockingMusic 219 : { 220 : if (_mode != kOOMusicOn) return; 221 : 222 : if (![self isPlaying]) [self playDockingMusic]; 223 : else if (_special == kSpecialDocking) [self stop]; 224 : } 225 : 226 : 227 : - (OOSoundSource *) soundSource 228 : { 229 : return [_current musicSoundSource]; 230 : } 231 : 232 : 233 : - (NSString *) playingMusic 234 : { 235 : return [_current name]; 236 : } 237 : 238 : 239 : - (BOOL) isPlaying 240 : { 241 : return [_current isPlaying]; 242 : } 243 : 244 : 245 : - (OOMusicMode) mode 246 : { 247 : return _mode; 248 : } 249 : 250 : 251 : - (void) setMode:(OOMusicMode)mode 252 : { 253 : if (mode <= kOOMusicModeMax && _mode != mode) 254 : { 255 : if (_mode == kOOMusicITunes) [self pauseiTunes]; 256 : _mode = mode; 257 : 258 : if (_mode == kOOMusicOff) [self stop]; 259 : else switch (_special) 260 : { 261 : case kSpecialNone: 262 : [self stop]; 263 : break; 264 : 265 : case kSpecialTheme: 266 : [self playThemeMusic]; 267 : break; 268 : 269 : case kSpecialDocked: 270 : [self playDockedMusic]; 271 : break; 272 : 273 : case kSpecialDocking: 274 : [self playDockingMusic]; 275 : break; 276 : 277 : case kSpecialMission: 278 : [self playMissionMusic]; 279 : break; 280 : } 281 : 282 : NSString *modeString = nil; 283 : switch (_mode) 284 : { 285 : case kOOMusicOff: modeString = @"off"; break; 286 : case kOOMusicOn: modeString = @"on"; break; 287 : case kOOMusicITunes: modeString = @"iTunes"; break; 288 : } 289 : [[NSUserDefaults standardUserDefaults] setObject:modeString forKey:@"music mode"]; 290 : } 291 : } 292 : 293 : @end 294 : 295 : 296 : 297 : @implementation OOMusicController (Singleton) 298 : 299 : /* Canonical singleton boilerplate. 300 : See Cocoa Fundamentals Guide: Creating a Singleton Instance. 301 : See also +sharedController above. 302 : 303 : NOTE: assumes single-threaded access. 304 : */ 305 : 306 0 : + (id) allocWithZone:(NSZone *)inZone 307 : { 308 : if (sSingleton == nil) 309 : { 310 : sSingleton = [super allocWithZone:inZone]; 311 : return sSingleton; 312 : } 313 : return nil; 314 : } 315 : 316 : 317 0 : - (id) copyWithZone:(NSZone *)inZone 318 : { 319 : return self; 320 : } 321 : 322 : 323 0 : - (id) retain 324 : { 325 : return self; 326 : } 327 : 328 : 329 0 : - (NSUInteger) retainCount 330 : { 331 : return UINT_MAX; 332 : } 333 : 334 : 335 0 : - (void) release 336 : {} 337 : 338 : 339 0 : - (id) autorelease 340 : { 341 : return self; 342 : } 343 : 344 : @end 345 : 346 : 347 : @implementation OOMusicController (Private) 348 : 349 : #if OOLITE_MAC_OS_X 350 : - (void) playiTunesPlaylist:(NSString *)playlistName 351 : { 352 : NSString *ootunesScriptString = 353 : [NSString stringWithFormat: 354 : @"with timeout of 1 second\n" 355 : " tell application \"iTunes\"\n" 356 : " copy playlist \"%@\" to thePlaylist\n" 357 : " if thePlaylist exists then\n" 358 : " play some track of thePlaylist\n" 359 : " end if\n" 360 : " end tell\n" 361 : "end timeout", 362 : playlistName]; 363 : 364 : NSAppleScript *ootunesScript = [[[NSAppleScript alloc] initWithSource:ootunesScriptString] autorelease]; 365 : NSDictionary *errDict = nil; 366 : 367 : [ootunesScript executeAndReturnError:&errDict]; 368 : if (errDict) 369 : OOLog(@"sound.music.iTunesIntegration.failed", @"ootunes returned :%@", errDict); 370 : } 371 : 372 : 373 : - (void) pauseiTunes 374 : { 375 : NSString *ootunesScriptString = [NSString stringWithFormat:@"try\nignoring application responses\ntell application \"iTunes\" to pause\nend ignoring\nend try"]; 376 : NSAppleScript *ootunesScript = [[NSAppleScript alloc] initWithSource:ootunesScriptString]; 377 : NSDictionary *errDict = nil; 378 : [ootunesScript executeAndReturnError:&errDict]; 379 : if (errDict) 380 : OOLog(@"sound.music.iTunesIntegration.failed", @"ootunes returned :%@", errDict); 381 : [ootunesScript release]; 382 : } 383 : #else 384 : - (void) playiTunesPlaylist:(NSString *)playlistName {} 385 : - (void) pauseiTunes {} 386 : #endif 387 : 388 : @end