This is ScrollingSound.m in view mode; [Download] [Up]
/* ScrollingSound.m -- Implementation of ScrollingSound class * * Original code by Lee Boynton * Revision by James Pritchett, 10/89 * Version 1.01, 11/89 * -- tidied code, added support for EdSoundView * Version 1.1, 12/89 * -- Added sizeToSelection: * Version 1.2, 1/90 * -- Fixed bug that caused selection to get screwed up when changing * reduction factor * Update for 2.0, 3/91 * -- Removed NXWait/NXArrow calls */ #import "ScrollingSound.h" #import "EdSoundView.h" #import <appkit/Application.h> #import <appkit/Cursor.h> @implementation ScrollingSound /* newFrame: -- create a new ScrollingSound. This method overrides * the standard newFrame: for a ScrollView. It creates a new * ScrollView, creates a new EdSoundView, and sets the EdSoundView * as the ScrollView's docView. Also sets various ScrollView * parameters. */ + newFrame:(NXRect const *)theFrame /* theFrame = coordinates of * ScrollView frame */ { NXRect tempRect = *theFrame; /* Size of content area goes here */ id sndview; /* The SoundView for this object */ int borderType = NX_LINE; /* Border type of ScrollView */ /* Figure the content size of the ScrollView and create a SoundView * with this size. */ [ScrollView getContentSize:&tempRect.size forFrameSize:&theFrame->size horizScroller:YES vertScroller:NO borderType:borderType]; sndview = [EdSoundView newFrame:&tempRect]; /* Create the ScrollView using the newFrame: method and set all the * parameters. */ self = [super newFrame:theFrame]; /* Use the ScrollView newFrame: */ [self setBorderType:borderType]; [self setHorizScrollerRequired:YES]; [self setDynamicScrolling:YES]; /* What does this do? */ [self setView:sndview]; [self setBackgroundGray:NX_WHITE]; [self setAutoresizeSubviews:YES]; [self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE]; [self setSound:[Sound new]]; [sndview setReductionFactor:50.0]; rfact = 50.0; [[sndview superview] setAutoresizeSubviews:YES]; [sndview setAutosizing:NX_HEIGHTSIZABLE]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setDelegate -- Set a delegate for this ScrollingSound. * The delegate can receive the displayChanged: message to handle * any scrolling events. */ - setDelegate:anObject /* anObject = delegate */ { delegate = anObject; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setView: -- Change the attached EdSoundView * Argument is a pointer to an EdSoundView object. */ - setView:aSoundView { if (view) [view free]; view = aSoundView; [self setDocView:view]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setSound: -- Attach a Sound object to the EdSoundView * Argument is pointer to Sound object. Never change the sound * any other way, since this is how the ScrollingSound keeps * track of the sampling rate. */ - setSound:aSound { if ([view sound]) [[view sound] free]; [view setSound:aSound]; srate = [aSound samplingRate]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setRfact: -- Change the reduction factor in the EdSoundView. * Argument is a float. Never change the reduction factor any other * way, since the ScrollingSound has to keep track of it for * various other methods. This method also keeps the selection * intact when changing scales (that it wouldn't otherwise is * probably a bug in SoundView?) */ - setRfact:(float)rf { int start,size; [view getSelection:&start size:&size]; rfact = rf; [view setReductionFactor:rf]; [view setSelection:start size:size]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* delegate -- Returns the delegate of this object */ - delegate { return delegate; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* view -- Returns the EdSoundView of this object */ - view { return view; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* duration -- Get the duration of the Sound object * Returns a float. */ - (float)duration { if (srate == 0) return 0; else return [[view sound] sampleCount] / srate; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* getStart:Size: -- Get the start time and size of the display * Arguments are pointers to floats. */ - getStart:(float *)stptr Size:(float *)sizptr { NXRect aRect; /* dimensions of visible view */ /* If this is a new Sound object with no data (and hence no sampling * rate), just return zeroes */ if (srate == 0) { *stptr = *sizptr = 0; return self; } /* Get the graphic dimensions of the currently visible portion of the * EdSoundView and convert those graphic coordinates to times. */ [self getDocVisibleRect:&aRect]; *stptr = aRect.origin.x * rfact / srate; *sizptr = aRect.size.width * rfact / srate; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* getSelStart:Size: -- Get the start time and size of the current selection. * Arguments are pointers to floats. */ - getSelStart:(float *)stptr Size:(float *)sizptr { int startsamp; /* First sample of selection */ int nsamps; /* Samples in selection */ if (srate == 0) { *stptr = *sizptr = 0; return self; } /* The EdSoundView returns the selection start and size in samples, * which are then converted to timings. */ [view getSelection:&startsamp size:&nsamps]; *stptr = startsamp / srate; *sizptr = nsamps / srate; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setStart: -- Change the start time of the display * Argument is a float. */ - setStart:(float)start { NXRect aRect; /* Visible part of SoundView */ float oldstart,size,dur; if (srate == 0) return self; /* Get the coordinates of the visible part of the EdSoundView, * change its origin, and force a scroll. */ [self getDocVisibleRect:&aRect]; [self getStart:&oldstart Size:&size]; dur = [self duration]; /* dur = duration of file */ if (start > dur-size) /* Don't scroll past end of sound */ start = dur-size; aRect.origin.x = start * srate / rfact; [view scrollRectToVisible:&aRect]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setSize: -- Change the duration of the display. * Argument is a float. The change in duration is accomplished by * changing the reduction factor while keeping the graphic * size of the EdSoundView constant. */ - setSize:(float)size { NXRect aRect; /* Visible part of SoundView */ if (srate == 0) return self; /* Get the width of the display and calculate the new reduction factor * needed to fit the requested duration within that size. */ [self getDocVisibleRect:&aRect]; rfact = size * srate / aRect.size.width; if (rfact < 1) /* rfact can't be < 1 */ rfact = 1; [self setRfact:rfact]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* setSelStart:Size: -- Set the start time and duration of selection * Arguments are floats. */ - setSelStart:(float)start Size:(float)size { int startsamp; /* Starting sample of selection */ int nsamps; /* Size of selection in samples */ if (srate == 0) return self; /* Convert timings to samples and set the selection */ startsamp = start * srate; nsamps = size * srate; [view setSelection:startsamp size:nsamps]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* sizeToSelection: -- Set the display start/size to the start/size of * current selection. * This is, in effect, a "zoom" action, and can be connected to an * action cell. */ - sizeToSelection:sender { float selstart, selsize; [self getSelStart:&selstart Size:&selsize]; if (!selsize) return self; [self setSize:selsize]; [self setStart:selstart]; /* Be sure to notify the delegate that our display changed */ if (delegate && [delegate respondsTo:@selector(displayChanged:)]) [delegate perform:@selector(displayChanged:) with:self]; return self; } /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */ /* reflectScroll: -- handle a change in the relationship between * the contentView and the docView. This method overrides * the standard ScrollView method so as to send a displayChanged: * message to the delegate. */ - reflectScroll:sender { [super reflectScroll:sender]; /* Do the default actions */ if (srate == 0) srate = [[view sound] samplingRate]; if (delegate && [delegate respondsTo:@selector(displayChanged:)]) [delegate perform:@selector(displayChanged:) with:self]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.