This is eTAudioComponent.m in view mode; [Download] [Up]
/////////////////////////////////////////////////////////////////////////////// // FILENAME: eTAudioComponent.h // SUMMARY: Implementation for a container of audio data. // SUPERCLASS: Object // INTERFACE: None, but it "exports" eTAudioComponentIcon and IconH. // PROTOCOLS: <ComponentData, // ETFDSupport,HTMDSupport,LaTeXSupport> // AUTHOR: Rohit Khare // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project /////////////////////////////////////////////////////////////////////////////// // IMPLEMENTATION COMMENTS // This is a subclass that externalizes audio components. Manages // a Sound object. useSound:... has been included to allow passing // in Sounds that are not on disk (as with paste:s) // We eventually want to support WAV and AIFF types (which NX Sound // does not. Perhaps adopt SOX code (talk to nick christopher)? /////////////////////////////////////////////////////////////////////////////// // HISTORY // 07/14/94: Created. Aliases the NeXTSTEP Sound API. /////////////////////////////////////////////////////////////////////////////// #import "eTAudioComponent.h" #define _eTAudioComponentVERSION 10 @implementation eTAudioComponent // id theSound; - theSound { if (!theSound) theSound = [[Sound alloc] init]; return theSound; } + newSoundNamed:(const char *)theName { // This is a fake implementation. see eTImageComponent for a real one. id newObj; newObj = [[eTAudioComponent alloc] initInDoc:nil linked:NO]; theSound = [Sound findSoundFor:theName]; componentName = NXUniqueString(theName); return newObj; } - useSound:(Sound *)newSound name:(const char *) newComponentName path:(const char *) newCurrentPath { theSound = newSound; componentName = NXUniqueString(newComponentName); currentPath = NXUniqueString(newCurrentPath); shouldEdit &= !isLinked; // should we ever muck with linked snds? return self; } - readComponentFromPath:(NXAtom)newPath { [super readComponentFromPath:newPath]; // attempt to load from currentPath theSound = nil; if (currentPath && *currentPath) { theSound = [[Sound alloc] initFromSoundfile:currentPath]; shouldEdit &= !isLinked; // should we ever muck with linked snds? } if (!theSound){ theSound = [Sound findSoundFor:"SystemBeep"]; shouldEdit = NO; } return self; } - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat { const char *tmp; char target[MAXPATHLEN]; id altSound; switch(theFormat) { case ETFD_FMT: // if it's not (a link) or (clean and the target is found), // if the (source is found and it's clean), copy // else write. sprintf(target,"%s/%s",path,componentName); if (!((isLinked) || ((!isDirty) && (!access(target,F_OK|R_OK))))){ if ((!isDirty) && *currentPath && (!access(currentPath, F_OK|R_OK))) { // copy char cmd[2*MAXPATHLEN]; sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target); system(cmd); currentPath = NXUniqueString(target); } else { if (!rindex(target, '.') || strcasecmp(".snd", rindex(target, '.'))) strcat(target, ".snd"); [theSound writeSoundfile:target]; currentPath = NXUniqueString(target); componentName = NXUniqueString(rindex(target,'/')+1); } isDirty=NO; } [etDoc registerComponent:componentName]; break; case HTMD_FMT: case TeXD_FMT: // Always is an .au. If it doesn't exist, copy an .au or create one. if (componentName) tmp = componentName; else if ([theSound name]) tmp = [theSound name]; else tmp = [[self class] name]; sprintf(target,"%s/%s",path,tmp); if (!rindex(target, '.') || strcasecmp(".au", rindex(target, '.'))) strcat(target, ".au"); if (access(target,F_OK|R_OK) || isDirty) { // if currentPath is an .au, copy. if (rindex(currentPath, '.') && (!strcasecmp(".au", rindex(currentPath, '.'))) && (!access(currentPath,F_OK|R_OK))) { char cmd[2*MAXPATHLEN]; sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target); system(cmd); } else { altSound = [[Sound alloc] init]; [altSound copySound:theSound]; [altSound convertToFormat:SND_FORMAT_MULAW_8 samplingRate:SND_RATE_CODEC channelCount:1]; [altSound writeSoundfile:target]; altSound = [altSound free]; } } [etDoc registerComponent:rindex(target,'/')+1]; break; } return self; } - writeComponentToPboard:thePboard { [thePboard declareTypes:&NXSoundPboard num:1 owner:nil]; [theSound writeToPasteboard:thePboard]; // here we copy code from the superclass because of the order of // addTypes: calls and the preference-order of Pasteboard [thePboard addTypes:&NXFilenamePboardType num:1 owner:nil]; [thePboard writeType:NXFilenamePboardType data:currentPath length:strlen(currentPath)]; return self; } - addToPboard:pboard { NXStream *memstream; memstream = NXOpenMemory(NULL, 0, NX_READWRITE); if (memstream) { [theSound writeSoundToStream:memstream]; [pboard addTypes:&NXSoundPboardType num:1 owner:nil]; [pboard writeType:NXSoundPboardType fromStream:memstream]; NXCloseMemory(memstream, NX_FREEBUFFER); } return self; } - readComponentFromPboard:thePboard { [super readComponentFromPboard:thePboard]; // ok, so now we have a quasi-valid entry in currentPath // If the sound can init from thePboard, go right ahead. theSound = [[Sound alloc] initFromPasteboard:thePboard]; if (!theSound) { //ok, there's no NXSoundPboardType data. Can we get a file? if (currentPath && *currentPath) { theSound = [[Sound alloc] initFromSoundfile:currentPath]; } shouldEdit &= !isLinked; // should we ever muck with linked snds? if (!theSound){ theSound = [Sound findSoundFor:"SystemBeep"]; shouldEdit = NO; } } // special case: If we paste raw audio data and there's no path, // componentName is currently "Untitled-%d"; we need to cat ".snd" if (!(currentPath && *currentPath)) { char tmp[MAXPATHLEN]; // hey, it's only stack space... :) strcpy(tmp, componentName); if (!rindex(tmp, '.') || strcasecmp(".snd", rindex(tmp, '.'))) strcat(tmp, ".snd"); componentName = NXUniqueString(tmp); } return self; } - readRichText:(NXStream *)stream forView:view { [super readRichText:stream forView:view]; if (currentPath && *currentPath) { theSound = [[Sound alloc] initFromSoundfile:currentPath]; } shouldEdit &= !isLinked; // should we ever muck with linked snds? if (!theSound){ theSound = [Sound findSoundFor:"SystemBeep"]; shouldEdit = NO; } return self; } - writeRichText:(NXStream *)stream forView:view { // since this method is called before any writeComponents, we attempt // to precompute whether an extension will be added char target[MAXPATHLEN]; /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23 strcpy(target, componentName); if (!rindex(target, '.') || strcasecmp(".snd", rindex(target, '.'))) { strcat(target, ".snd"); componentName = NXUniqueString(target); } return [super writeRichText:stream forView:view]; } - writeHTML:(NXStream *)stream forView:view {return [self writeHTML:stream forView:view andClose:YES];} - writeHTML:(NXStream *)stream forView:view andClose:(BOOL)closeIt { const char *tmp; /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23 if (componentName) tmp = componentName; else if ([theSound name]) tmp = [theSound name]; else tmp = [[self class] name]; NXPrintf(stream, "<A HREF=\"%V%V\">",tmp, ((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":"")); if (closeIt) { NXPrintf(stream, "%v</A>",tmp); } return self; } - writeLaTeX:(NXStream *)stream forView:view { const char *tmp; /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared images, 12/23 if (componentName) tmp = componentName; else if ([theSound name]) tmp = [theSound name]; else tmp = [[self class] name]; NXPrintf(stream, "\n\\footnote{A reference to the sound %w%w}", tmp,((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":"")); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.