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;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.