Annotation of Examples/AppKit/BreakApp/SoundEffect.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * SoundEffect.m, class to play sounds
        !             3:  * Originally by Terry Donahue, modified by Ali Ozer
        !             4:  *
        !             5:  * SoundEffect is a class which conveniently groups the 3.0
        !             6:  * sound stream functionality with sound data using the Sound
        !             7:  * class.
        !             8:  *
        !             9:  *  You may freely copy, distribute and reuse the code in this example.
        !            10:  *  NeXT disclaims any warranty of any kind, expressed or implied,
        !            11:  *  as to its fitness for any particular use.
        !            12:  */
        !            13: 
        !            14: #import "SoundEffect.h"
        !            15: #import <soundkit/NXSoundOut.h>
        !            16: #import <appkit/nextstd.h>
        !            17: #import <objc/List.h>
        !            18: 
        !            19: @implementation SoundEffect
        !            20: 
        !            21: static BOOL soundEnabled = NO;
        !            22: 
        !            23: #define DEFAULTMAXSOUNDSTREAMS 20
        !            24: 
        !            25: static List *soundStreams = nil;               // List of currently idle sound streams
        !            26: static unsigned int soundStreamsAllocated = 0; // Total number of sound streams allocated
        !            27: static unsigned int maxSoundStreams = DEFAULTMAXSOUNDSTREAMS;  // Max allowed
        !            28: 
        !            29: // After calling this, you may call soundEnabled to check to see if it was successful.
        !            30: 
        !            31: + (void)setSoundEnabled:(BOOL)flag
        !            32: {
        !            33:     if (flag && !soundEnabled) {
        !            34:        NXPlayStream *testStream = [self soundStream];
        !            35:        if (testStream) {
        !            36:            soundEnabled = YES;     
        !            37:            [self releaseSoundStream:testStream];
        !            38:        } else {
        !            39:            NXLogError ("Can't enable sounds.");
        !            40:        }
        !            41:     } else if (!flag && soundEnabled) {
        !            42:        soundEnabled = flag;
        !            43:        soundStreamsAllocated -= [soundStreams count];
        !            44:        [soundStreams freeObjects];
        !            45:     }
        !            46: }
        !            47: 
        !            48: + (BOOL)soundEnabled
        !            49: {
        !            50:     return soundEnabled;
        !            51: }
        !            52: 
        !            53: // These two methods let the client set/get the maximum number of
        !            54: // sound streams to allocate. If this number is exceeded, sound requests
        !            55: // are simply not honored until sound streams are freed up.
        !            56: 
        !            57: + (void)setMaxSoundStreams:(unsigned int)max
        !            58: {
        !            59:     maxSoundStreams = max;
        !            60: }
        !            61: 
        !            62: + (unsigned int)maxSoundStreams
        !            63: {
        !            64:     return maxSoundStreams;
        !            65: }
        !            66: 
        !            67: // This method returns a sound stream to be used in playing a sound.
        !            68: // Sound streams allocated through this method should be given back
        !            69: // via releaseSoundStream:. Note that this is for internal use only;
        !            70: // it however might be overridden if necessary.
        !            71: 
        !            72: + (NXPlayStream *)soundStream
        !            73: {
        !            74:     static BOOL cantPlaySounds = NO;
        !            75:     static NXSoundOut *dev = nil;                      // We only have one instance of this...
        !            76:     NXPlayStream *newStream = nil;
        !            77: 
        !            78:     if (cantPlaySounds) return nil;    // If we've tried before and failed, just give up.
        !            79:     
        !            80:     if (!dev && !(dev = [[NXSoundOut alloc] init])) {  // We allocate this from the default zone so that
        !            81:        NXLogError ("Couldn't create NXSoundOut");      //  freeing this zone won't accidentally blast it
        !            82:        cantPlaySounds = YES;
        !            83:         return nil;
        !            84:     }
        !            85: 
        !            86:     if (!soundStreams) {
        !            87:        soundStreams = [[List alloc] init];
        !            88:     }
        !            89: 
        !            90:     if (![soundStreams count]) {
        !            91:        if (soundStreamsAllocated < maxSoundStreams) {
        !            92:            newStream = [[NXPlayStream alloc] initOnDevice:dev];
        !            93:            soundStreamsAllocated++;
        !            94:        }
        !            95:     } else {
        !            96:         newStream = [soundStreams removeLastObject];
        !            97:     }
        !            98:     
        !            99:     if (newStream) {
        !           100:        if (![newStream isActive] && ([newStream activate] != NX_SoundDeviceErrorNone)) {
        !           101:            [newStream free];
        !           102:            newStream = nil;
        !           103:            soundStreamsAllocated--;
        !           104:        }
        !           105:     }
        !           106: 
        !           107:     return newStream;
        !           108: }
        !           109: 
        !           110: // When a sound stream is released, put it on the idle list unless sounds were disabled;
        !           111: // then just free it.
        !           112: 
        !           113: + (void)releaseSoundStream:(NXPlayStream *)soundStream
        !           114: {
        !           115:     if ([self soundEnabled]) {
        !           116:        [soundStreams addObject:soundStream];
        !           117:     } else {
        !           118:        [soundStream free];     // This also deactivates.
        !           119:        soundStreamsAllocated--;
        !           120:     }
        !           121: }
        !           122: 
        !           123: // This method lets you create new instances of SoundEffect. If the specified
        !           124: // sound file does not exist, the allocated instance is freed and nil is returned.
        !           125: 
        !           126: - initFromSection:(const char *)path
        !           127: {
        !           128:     [super init];
        !           129: 
        !           130:     if (!(sound = [[Sound allocFromZone:[self zone]] initFromSection:path])) {
        !           131:        NXLogError ("Couldn't load sound from %s", path);
        !           132:        [self free];
        !           133:        return nil;
        !           134:     }
        !           135: 
        !           136:     return self;
        !           137: }
        !           138: 
        !           139: // Free frees the SoundEffect. If this sound effect is being played at the time,
        !           140: // the free is delayed and happens as soon as all pending sounds are finished.
        !           141: 
        !           142: - free
        !           143: {
        !           144:     if (flags.refCount) {
        !           145:        flags.freeWhenDone = YES;
        !           146:        return nil;
        !           147:     } else {
        !           148:        if (sound) [sound free];
        !           149:        return [super free];
        !           150:     }
        !           151: }
        !           152: 
        !           153: // These two methods play the sound effect.
        !           154: 
        !           155: - play
        !           156: {
        !           157:     return [self play:1.0 pan:0.0];
        !           158: }
        !           159: 
        !           160: - play:(float)volume pan:(float)pan
        !           161: {
        !           162:     float left, right;
        !           163:     NXPlayStream *soundStream;
        !           164:     
        !           165:     if (![[self class] soundEnabled]) {
        !           166:        return self;
        !           167:     }
        !           168: 
        !           169:     if (!(soundStream = [[self class] soundStream])) {
        !           170:        return self;
        !           171:     }
        !           172:     
        !           173:     [soundStream setDelegate:self];
        !           174: 
        !           175:     left = right = volume;
        !           176:     if (pan > 0.0) left  *= 1.0 - pan;
        !           177:     else if (pan < 0.0) right *= 1.0 + pan;
        !           178:     [soundStream setGainLeft:left right:right];
        !           179:     if ([soundStream playBuffer:(void *)[sound data]
        !           180:                            size:(unsigned int)[sound dataSize]
        !           181:                            tag:0
        !           182:                    channelCount:(unsigned int)[sound channelCount]
        !           183:                    samplingRate:[sound samplingRate]] == NX_SoundDeviceErrorNone) {
        !           184:        flags.refCount++;
        !           185:     } else {
        !           186:        [[self class] releaseSoundStream:soundStream];
        !           187:     }
        !           188: 
        !           189:     return self;
        !           190: }
        !           191: 
        !           192: // Delegate methods for internal use only.
        !           193: 
        !           194: - soundStream:sender didCompleteBuffer:(int)tag
        !           195: {
        !           196:     flags.refCount--;
        !           197:     [[self class] releaseSoundStream:sender];
        !           198:     if (flags.freeWhenDone && flags.refCount == 0) {
        !           199:        [self free];
        !           200:     }
        !           201:     return sender;
        !           202: }
        !           203: 
        !           204: - soundStreamDidAbort:sender deviceReserved:(BOOL)flag
        !           205: {
        !           206:     return [self soundStream:sender didCompleteBuffer:0];
        !           207: }
        !           208: 
        !           209: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.