Annotation of Examples/SoundAndMusic/SoundKit/SoundEditor/SoundDocument.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * You may freely copy, distribute and reuse the code in this example.  
                      3:  * NeXT disclaims any warranty of any kind, expressed or implied, as to 
                      4:  * its fitness for any particular use.
                      5:  */
                      6: 
                      7: 
                      8: #import "SoundDocument.h"
                      9: #import "SoundController.h"
                     10: #import "ScrollingSound.h"
                     11: #import <soundkit/soundkit.h>
                     12: #import <appkit/Application.h>
                     13: #import <appkit/Window.h>
                     14: #import <appkit/Panel.h>
                     15: #import <appkit/Cursor.h>
                     16: #import <stdlib.h>
                     17: #import <string.h>
                     18: #import <objc/NXStringTable.h>
                     19: 
                     20: extern int access();
                     21: 
                     22: @implementation SoundDocument
                     23: 
                     24: static void newLocation(NXPoint *p)
                     25: {
                     26:     static count = 0;
                     27:     p->x += (20.0 * count);
                     28:     p->y -= (25.0 * count);
                     29:     count = (count > 10)? 0 : count+1;
                     30: }
                     31: 
                     32: - init
                     33: {
                     34:     NXRect theFrame;
                     35:     
                     36:     [super init];
                     37:     [NXApp loadNibSection:"SoundDocument.nib" owner:self];
                     38:     [window setDelegate:self];
                     39:     [window getFrame:&theFrame];
                     40:     newLocation(&theFrame.origin);
                     41:     [window moveTo:theFrame.origin.x :theFrame.origin.y];
                     42:     [window makeKeyAndOrderFront:nil];
                     43:     mySoundView = [view docView];      /* view is the ScrollingSound 
                     44:                                           in the nib file */
                     45:     [mySoundView setSound:[[Sound alloc] init]];
                     46:     return self;
                     47: }
                     48: 
                     49: 
                     50: - setFileName:(char *)aName
                     51: {
                     52:     if (fileName)
                     53:        free(fileName);
                     54:     fileName = (char *)malloc(strlen(aName)+1);
                     55:     strcpy(fileName,aName);
                     56:     [window setTitleAsFilename:fileName];
                     57:     return self;
                     58: }
                     59: 
                     60: - (char *)fileName
                     61: {
                     62:     return fileName;
                     63: }
                     64: 
                     65: - sound
                     66: {
                     67:     return [mySoundView sound];
                     68: }
                     69: 
                     70: - saveError:(const char *)msg arg: (char *)arg;
                     71: {
                     72:     if (!stringTable)
                     73:        stringTable = [[NXApp delegate] stringTable];
                     74:     NXRunAlertPanel([stringTable valueForStringKey:"Save"],
                     75:        [stringTable valueForStringKey:msg],
                     76:        [stringTable valueForStringKey:"OK"],
                     77:        NULL,NULL,arg);
                     78:     return nil;
                     79: }
                     80: 
                     81: - saveToFormat:templateSound fileName:(char *)fn
                     82: {
                     83:     if (fn) {
                     84:        int err;
                     85:        id theSound = [[mySoundView sound] copy];
                     86:        if (templateSound && theSound) {
                     87:            [theSound copySound:theSound];
                     88:            err = [theSound convertToFormat:[templateSound dataFormat]
                     89:                            samplingRate:[templateSound samplingRate]
                     90:                            channelCount:[templateSound channelCount]];
                     91:            if (err) {
                     92:                /* The DSP is required for compression or decompression */
                     93:                return [self saveError: 
                     94:                        "Cannot do format conversion %s (DSP busy?)" arg:""];
                     95:            }
                     96:        }
                     97:        if (!access(fn, 0)) {   /* file exists */
                     98:            char fileBuf[1024];
                     99:            strcpy(fileBuf,fn);
                    100:            strcat(fileBuf,"~");
                    101:            rename(fn,fileBuf);
                    102:        }
                    103:        err = [theSound writeSoundfile:fn];
                    104:        if (err) {
                    105:            return [self saveError:"Cannot write %s" arg:fn];
                    106:        }
                    107:        else 
                    108:          [window setDocEdited:NO];
                    109:        [theSound free];
                    110:     }
                    111:     return self;
                    112: }
                    113: 
                    114: - save:sender
                    115: {
                    116:     return [self saveToFormat:nil fileName:fileName];
                    117: }
                    118: 
                    119: - load:sender
                    120: {
                    121:     if (fileName) {
                    122:        id newSound, oldSound = [mySoundView sound];
                    123:        newSound = [[Sound alloc] initFromSoundfile:fileName];
                    124:        if (newSound) {
                    125:            if (![mySoundView setSound:newSound]) { /* not displayable */
                    126:                if ([newSound convertToFormat:SND_FORMAT_LINEAR_16]) {
                    127:                    if (!stringTable)
                    128:                      stringTable = [[NXApp delegate] stringTable];
                    129:                    NXRunAlertPanel([stringTable valueForStringKey:"Open"],
                    130:                                    [stringTable valueForStringKey:
                    131:                                     "Cannot convert format for display "
                    132:                                     "(DSP busy?)"],
                    133:                                    [stringTable valueForStringKey:"OK"],
                    134:                                    NULL,NULL);
                    135:                    return nil;
                    136:                } else
                    137:                  [mySoundView setSound:newSound];
                    138:            }
                    139:            [oldSound free];
                    140:        }
                    141:     }
                    142:     [window setDocEdited:NO];
                    143:     return self;
                    144: }
                    145: 
                    146: - revertToSaved:sender
                    147: {
                    148:     if([window isDocEdited] && fileName
                    149:             && strcmp(strrchr (fileName,'/'),"/UNTITLED")) {
                    150:        if (!stringTable)
                    151:            stringTable = [[NXApp delegate] stringTable];
                    152:        if (NXRunAlertPanel([stringTable valueForStringKey:"Revert"],           
                    153:                [stringTable valueForStringKey:"Revert to saved version"
                    154:                    " of %s?"],
                    155:                [stringTable valueForStringKey:"Revert"],
                    156:                [stringTable valueForStringKey:"Cancel"], 
                    157:                    0,fileName) == NX_ALERTDEFAULT)
                    158:            [self load:nil];
                    159:     }
                    160:     return self;
                    161: }
                    162:   
                    163: - play:sender
                    164: {
                    165:     [mySoundView play:sender];
                    166:     return self;
                    167: }
                    168: 
                    169: - stop:sender
                    170: {
                    171:     [mySoundView stop:sender];
                    172:     return self;
                    173: }
                    174: 
                    175: - pause:sender
                    176: {
                    177:     [mySoundView pause:sender];
                    178:     return self;
                    179: }
                    180: 
                    181: - resume:sender
                    182: {
                    183:     [mySoundView resume:sender];
                    184:     return self;
                    185: }
                    186: 
                    187: - record:sender
                    188: {
                    189:     [mySoundView record:sender];
                    190:     [window setDocEdited:YES];
                    191:     return self;
                    192: }
                    193: 
                    194: - touch
                    195: {
                    196:     [window setDocEdited:YES];
                    197:     return self;
                    198: }
                    199: 
                    200: - setDelegate:anObject
                    201: {
                    202:     [mySoundView setDelegate:anObject];
                    203:     return self;
                    204: }
                    205: 
                    206: - windowDidBecomeMain:sender
                    207: {
                    208:     [[NXApp delegate] setDocument:self];
                    209:     [window makeFirstResponder:mySoundView];
                    210:     [mySoundView showCursor];
                    211:     return self;
                    212: }
                    213: 
                    214: - windowDidResignMain:sender
                    215: {
                    216:     id theController = [NXApp delegate];
                    217:     if ([theController document] == self)
                    218:        [theController setDocument:nil];
                    219:     [mySoundView hideCursor];
                    220:     return self;
                    221: }
                    222: 
                    223: - windowDidMiniaturize:sender
                    224: {
                    225:     [mySoundView stop:sender];
                    226:     [mySoundView hideCursor];
                    227:     return self;
                    228: }
                    229: 
                    230: - windowWillClose:sender
                    231: {
                    232:     int choice;
                    233: 
                    234:     if ([window isDocEdited]) {
                    235:        if (!stringTable)
                    236:            stringTable = [[NXApp delegate] stringTable];
                    237:        choice = NXRunAlertPanel([stringTable valueForStringKey:"Close"],
                    238:             [stringTable valueForStringKey:"Sound is modified.\nSave it?"],
                    239:            [stringTable valueForStringKey:"Yes"],
                    240:            [stringTable valueForStringKey:"No"],
                    241:            [stringTable valueForStringKey:"Cancel"]); 
                    242:        switch (choice) {
                    243:            case NX_ALERTALTERNATE:
                    244:                break;
                    245:            case NX_ALERTDEFAULT:
                    246:                [[NXApp delegate] save:nil];
                    247:                break;
                    248:            case NX_ALERTOTHER:
                    249:                return nil;
                    250:        }
                    251:     }
                    252:     [self windowDidResignMain:nil];
                    253:     [window setDelegate:nil];
                    254:     [self free];
                    255:     return sender;
                    256: }
                    257: 
                    258: 
                    259: static int calcFormat(SNDSoundStruct *s)
                    260: {
                    261:     if (s->dataFormat == SND_FORMAT_MULAW_8)
                    262:        return SND_FORMAT_MULAW_8;
                    263:     else if (s->dataFormat == SND_FORMAT_INDIRECT) {
                    264:        SNDSoundStruct **iBlock = (SNDSoundStruct **)s->dataLocation;
                    265: 
                    266:        if (*iBlock)
                    267:            return (*iBlock)->dataFormat;
                    268:        else
                    269:            return SND_FORMAT_UNSPECIFIED;
                    270:     } else
                    271:        return s->dataFormat;
                    272: }
                    273: 
                    274: - (BOOL)isRecordable
                    275: {
                    276:     int format;
                    277:     id theSound = [mySoundView sound];
                    278:     SNDSoundStruct *soundStruct = [theSound soundStruct];
                    279: 
                    280:     if (!soundStruct) return YES;
                    281:     format = calcFormat(soundStruct);
                    282:     if (format == SND_FORMAT_MULAW_8 &&
                    283:        soundStruct->samplingRate == (int)SND_RATE_CODEC &&
                    284:        soundStruct->channelCount == 1 )
                    285:        return YES;
                    286:     else
                    287:        return NO;
                    288: }
                    289: 
                    290: - (BOOL) isPlayable
                    291: {
                    292:     return [mySoundView isPlayable];
                    293: }
                    294: 
                    295: @end

unix.superglobalmegacorp.com

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