// -*-objc-*- // Calando - Volume Fading for OS X // Copyright (C) 2007 Greg Heartsfield #import "VolumeFader.h" @implementation VolumeFader + (void)fadeSystemVolumeThreaded:(id)anObject { NSLog(@"Starting fade volume thread..."); // Create new autorelease pool for the thread, which will // automatically release itself at thread termination. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Do thread work here [anObject fadeSystemVolume:[anObject getFinalVolume] withSecondsDuration:[anObject getSecondsDuration]]; NSLog(@"fadeSystemVolumeThreaded method finished"); } - (void)setFinalVolume:(Float32)volume { finalVolume = volume; } - (void)setSecondsDuration:(int)duration { fadeDuration = duration; } - (Float32)getFinalVolume { return finalVolume; } - (int)getSecondsDuration { return fadeDuration; } - (bool)isFadeRunning { return !finished; } - (void)stopFade { fadeShouldStop = YES; } - (void)setNotifyFinished:(id)object { notifyFinishedObject = object; } - (void)fadeSystemVolume:(Float32)volume withSecondsDuration:(int)duration { finished = NO; fadeShouldStop = NO; // Get Default Output Device OSStatus theStatus; UInt32 theSize; AudioDeviceID theID; theSize = sizeof(AudioDeviceID); MTCoreAudioVolumeInfo rv; rv.theVolume = 0.0; Float32 currVolume; int i; Float32 startingVolume; Float32 prevVolume; Float32 endVolume; Float32 volumeDiff; theStatus = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice, &theSize, &theID); if (theStatus != 0) NSLog(@"Problem with output device!"); // Every second from now until duration ends, decrease the volume // First, get current system volume, for our starting point theStatus = AudioDeviceGetProperty(theID, 1, 0, kAudioDevicePropertyVolumeScalar, &theSize, &rv.theVolume); if (theStatus != 0) NSLog(@"Error getting audio device volume"); currVolume = rv.theVolume; startingVolume = rv.theVolume; // calculate what the ending volume should be endVolume = currVolume * volume; for (i=0; i < duration; i++) { // get current volume theStatus = AudioDeviceGetProperty(theID, 1, 0, kAudioDevicePropertyVolumeScalar, &theSize, &rv.theVolume); if (theStatus != 0) NSLog(@"Error getting audio device volume"); volumeDiff = rv.theVolume - currVolume; if (fabs(volumeDiff) > 0.05) { NSLog (@"Volume changed from external source, stopping fade."); //TODO: make finished action a private method fadeShouldStop = YES; } currVolume = startingVolume - ((startingVolume - endVolume) / duration) * i; prevVolume = currVolume; // set volume of channel 1 theStatus = AudioDeviceSetProperty (theID, NULL, 1, 0, kAudioDevicePropertyVolumeScalar, sizeof(Float32), &currVolume); // set volume of channel 2 theStatus = AudioDeviceSetProperty (theID, NULL, 2, 0, kAudioDevicePropertyVolumeScalar, sizeof(Float32), &currVolume); // Log current volume every 10 seconds to console if (i%10 == 0) { NSLog(@"Setting the volume to %f", currVolume); } // sleep for one second id sleepUntil = [NSDate dateWithTimeIntervalSinceNow:1]; [NSThread sleepUntilDate:sleepUntil]; if (fadeShouldStop) { // skip to end of duration loop i = duration; } } [notifyFinishedObject volumeFadeFinished]; finished=YES; } @end