|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.