home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-25 | 26.1 KB | 1,059 lines |
- /*
-
- MiscSoundView
- Version 1.2
- Copyright (c) 1995 by Sean Luke
- Donated to the MiscKit
-
- Permission to use, copy, modify, and distribute this material
- for any purpose and without fee, under the restrictions as noted
- in the MiscKit copyright notice, is hereby granted, provided that
- the MiscKit copyright notice and this permission notice
- appear in all source copies, and that the author's name shall not
- be used in advertising or publicity pertaining to this
- material without the specific, prior written permission
- of the author. SEAN O. LUKE MAKES NO REPRESENTATIONS ABOUT THE
- ACCURACY OR SUITABILITY OF THIS MATERIAL FOR ANY PURPOSE.
- IT IS PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
-
- */
-
- // Known Bugs:
-
- // 1) Play Mark doesn't disappear unless you tell it to.
- // 2) Rulers don't appear until explicitly told to.
- // 3) Ruler values slowly drift (rounding error)
-
- #import "MiscSoundView.h"
- #import <math.h>
- #import <stdio.h>
-
- // CONVENIENCE FUNCTIONS
-
- double scroll_to_reduction (double scrollValue, double ratio)
- // scrollValue must be a number between 1 and 0
- // ratio is sample count / display units
- // returns -1 if error
- // this function considers roundoff to integers,
- // and a maximum value at integer point
- {
- if (scrollValue>1.0||scrollValue<0.0)
- {
- printf ("scroll_to_reduction ERROR: scrollValue is %f, ratio is%f\n", scrollValue, ratio);
- return -1.0;
- }
- return ceil(pow(ceil(ratio),scrollValue));
- }
-
-
- double reduction_to_scroll (double reduction, double ratio)
- // reduction must be a number above 1, preferably < ratio
- // ratio is sample count / display units
- // returns -1 if error
- // this function does not consider roundoff to integers...
- // but does consider a maximum value at integer point
- {
- if (reduction<1.0)
- {
- printf ("reduction_to_scroll ERROR: reduction is %f, ratio is %f\n", reduction, ratio);
- return -1.0;
- }
- return log(reduction)/log(ceil(ratio));
- }
-
-
- // private function that rounds x to the nearest integer.
-
- int MISCSOUNDVIEW_round(float x)
- {
- if (fabs(ceil(x)-x)<=0.5) return (int) ceil(x);
- return (int) floor(x);
- }
-
-
- @implementation MiscSoundView
-
- // Private method that tells the SoundView to wipe itself clean when running
-
- - _wipeClean
- {
- wipe_clean=YES;
- return self;
- }
-
-
- // Private method that modify the bounds/frame rect...
-
- - _adjustBounds
- {
- // This assumes that MiscSoundView is in a scrollView!
- // It also does _not_ draw the MiscSoundView...
-
- id scroll_view;
- NXSize ThisSize;
-
- if ((scroll_view=[[self superview] superview])==NULL)
- {
- return NULL; // not in scrollView!
- }
-
- [scroll_view getContentSize: &ThisSize];
- [super sizeTo: bounds.size.width :
- ThisSize.height- (display_x_axis_marks ? MISCSOUNDVIEW_RULER_HEIGHT +
- MISCSOUNDVIEW_PLAY_MARK_HEIGHT : 0)];
- return self;
- }
-
- - adjustBounds:sender
- {
- if ([self _adjustBounds]==NULL) {return NULL;}
- [self _wipeClean];
- [self display];
- return self;
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- id returnval=[super sizeTo:width:height];
- [self _adjustBounds];
- [self _wipeClean];
- return returnval;
- }
-
-
- - initFrame:(const NXRect*) frameRect
- {
- id returnval=[super initFrame:frameRect];
- display_x_axis_marks=NO;
- display_y_axis_grid=NO;
- display_zero_line=NO;
- display_labels=YES;
- y_display_format=MISCSOUNDVIEW_YAXIS_DISPLAY_FORMAT_SIXTEEN;
- minor_tick_spacing=1000.0;
- minor_tick_spacing_format=MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES;
- major_tick_spacing=10;
- old_play_mark=-1;
- play_mark=-1;
- scroll_to_reflect_playing=NO;
- only_change_play_mark=NO;
- [self _wipeClean];
- [self _adjustBounds];
- return returnval;
- }
-
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
-
-
- //-------------------------------------
- // Some DrawSelf Free-Form Poetry:
- //
- // drawSelf is probably
- // the most evil monolithic Obj-C ever
- // created. I can't bother
- // prettifying it, though I might
- // make it
- // barely understandable.
- //-------------------------------------
-
-
-
- NXSize temp;
- BOOL display_minor_ticks;
- float maxval,lastval;
- int a;
- int numberOfSamples;
- float tick_height;
- int startsample,endsample,xx;
- id returnval=self;
- int true_sample_count=[sound sampleCount];
-
- // Draw SoundView stuff
- if (!only_change_play_mark)
- {
- [self setClipping:YES];
- returnval=[super drawSelf: rects: rectCount];
- }
- [self setClipping:NO];
-
- /*
- *
- *
- * Drawing the Y-Axis elements (Amplitude and Zero Line)...
- *
- *
- *
- */
-
- if (display_y_axis_grid&&!only_change_play_mark&&true_sample_count)
- {
- if (y_display_format==MISCSOUNDVIEW_YAXIS_DISPLAY_FORMAT_DECIBEL)
- {
- maxval=SNDConvertDecibelsToLinear(100.0);
- lastval=bounds.size.height/2;
-
- for (a=19;a>=10;a--)
- {
- temp.height=lastval-SNDConvertDecibelsToLinear
- ((float)a*5)/maxval*(bounds.size.height/2);
- temp.width=0;
- [self convertSize:&temp toView:nil];
- if (temp.height>2.0)
- {
- PSsetlinewidth(0);
- PSsetgray(NX_DKGRAY);
- PSmoveto (rects[0].origin.x,SNDConvertDecibelsToLinear
- ((float)a*5)/maxval*(bounds.size.height/2));
- PSrlineto(rects[0].size.width,0);
- PSsetlinewidth(0);
- PSmoveto (rects[0].origin.x,0-SNDConvertDecibelsToLinear
- ((float)a*5)/maxval*(bounds.size.height/2));
- PSrlineto(rects[0].size.width,0);
- PSstroke();
- }
- lastval=SNDConvertDecibelsToLinear
- ((float)a*5)/maxval*(bounds.size.height/2);
- }
- }
- else if (y_display_format==MISCSOUNDVIEW_YAXIS_DISPLAY_FORMAT_SIXTEEN)
- {
- for (a=1;a<8;a++)
- {
- PSsetlinewidth(0);
- PSsetgray(NX_DKGRAY);
- PSmoveto (rects[0].origin.x,(bounds.size.height/2)/8*a);
- PSrlineto(rects[0].size.width,0);
- PSsetlinewidth(0);
- PSmoveto (rects[0].origin.x,0-(bounds.size.height/2)/8*a);
- PSrlineto(rects[0].size.width,0);
- PSstroke();
- }
- }
- else if (y_display_format==MISCSOUNDVIEW_YAXIS_DISPLAY_FORMAT_TWENTY)
- {
- for (a=1;a<10;a++)
- {
- PSsetlinewidth(0);
- PSsetgray(NX_DKGRAY);
- PSmoveto (rects[0].origin.x,(bounds.size.height/2)/10*a);
- PSrlineto(rects[0].size.width,0);
- PSsetlinewidth(0);
- PSmoveto (rects[0].origin.x,0-(bounds.size.height/2)/10*a);
- PSrlineto(rects[0].size.width,0);
- PSstroke();
- }
- }
- else // y_display_format==MISCSOUNDVIEW_YAXIS_DISPLAY_FORMAT_TWENTYFOUR
- {
- for (a=1;a<12;a++)
- {
- PSsetlinewidth(0);
- PSsetgray(NX_DKGRAY);
- PSmoveto (rects[0].origin.x,(bounds.size.height/2)/12*a);
- PSrlineto(rects[0].size.width,0);
- PSsetlinewidth(0);
- PSmoveto (rects[0].origin.x,0-(bounds.size.height/2)/12*a);
- PSrlineto(rects[0].size.width,0);
- PSstroke();
- }
- }
- }
- if (display_zero_line&&!only_change_play_mark&&true_sample_count)
- {
- PSsetlinewidth(0);
- PSsetgray(NX_DKGRAY);
- PSmoveto (rects[0].origin.x,0);
- PSrlineto(rects[0].size.width,0);
- PSstroke();
- }
-
-
-
- /*
- *
- *
- * Drawing the X-Axis elements (Ruler and Play-Mark)...
- *
- *
- *
- */
-
-
- if (display_x_axis_marks&&(minor_tick_spacing!=0.0)&&major_tick_spacing)
-
-
- // display the axis
-
- {
- double scale_factor;
- NXRect temprect;
- char tempstring[20];
- float print_value;
- BOOL display_major_ticks;
- BOOL enough_room_for_labels;
-
- // to begin, figure out the scaling factor:
-
- scale_factor=bounds.size.height/frame.size.height;
-
- // then draw ticks
-
- tick_height=MISCSOUNDVIEW_RULER_HEIGHT/2;
-
- if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)
- // display in samples
- {
- numberOfSamples=(int)minor_tick_spacing;
- }
- else if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT)
- // display in percentage
- {
- numberOfSamples=(int)
- (minor_tick_spacing/100.0*[sound sampleCount]);
- }
- else // display in seconds
- {
- numberOfSamples=(int)(minor_tick_spacing*[sound samplingRate]);
- }
-
- if (!numberOfSamples) numberOfSamples=1; // for divide-by-zero
-
- startsample=(((int) (rects[0].origin.x*reductionFactor))
- /numberOfSamples)*numberOfSamples;
-
- // note the integer division above!!!! This
- // does automatic rounding properly...
-
- display_minor_ticks=(BOOL)(((float)numberOfSamples)/reductionFactor>=
- MISCSOUNDVIEW_TICK_MINIMUM_SPACING);
- display_major_ticks=(BOOL)(((float)numberOfSamples)
- *major_tick_spacing/reductionFactor>=
- MISCSOUNDVIEW_TICK_MINIMUM_SPACING);
- enough_room_for_labels=(BOOL)(((float)numberOfSamples)
- *major_tick_spacing/reductionFactor>=
- MISCSOUNDVIEW_TICK_MINIMUM_SPACING_WITH_LABELS);
-
- endsample=((int)(rects[0].size.width+rects[0].origin.x))
- *reductionFactor;
-
-
-
- // Erase ruler if needed...
-
- if (!only_change_play_mark&&true_sample_count)
- {
- // wipe the ruler clean if needed
-
- if (wipe_clean)
- {
- PSsetgray(NX_WHITE);
- temprect.origin.x=rects[0].origin.x;
- temprect.origin.y=bounds.size.height/2;
- temprect.size.width=rects[0].size.width;
- temprect.size.height=
- (MISCSOUNDVIEW_RULER_HEIGHT+MISCSOUNDVIEW_PLAY_MARK_HEIGHT)
- *scale_factor;
- PSrectfill(temprect.origin.x,temprect.origin.y,
- temprect.size.width,temprect.size.height);
- wipe_clean=NO; // finished
- }
-
- // Draw ruler lines
-
- PSsetlinewidth(0);
- PSsetgray(NX_BLACK);
- PSmoveto(rects[0].origin.x, bounds.size.height/2);
- PSrlineto(rects[0].size.width, 0);
- PSmoveto(rects[0].origin.x,bounds.size.height/2+
- MISCSOUNDVIEW_PLAY_MARK_HEIGHT*scale_factor);
- PSrlineto(rects[0].size.width,0);
- }
- PSstroke();
-
-
- // Next, erase old play mark (if any) and draw new play-mark
-
- if (old_play_mark!=-1)
- {
- PSsetgray(NX_WHITE);
- PSmoveto(old_play_mark/reductionFactor+bounds.origin.x,
- bounds.size.height/2+1*scale_factor);
- PSrlineto(0,2*scale_factor);
- PSrmoveto(-1,-1*scale_factor);
- PSrlineto(2,0);
- }
- PSstroke();
- old_play_mark=play_mark;
-
- if (old_play_mark!=-1&&true_sample_count) // don't draw if no samples
- {
- PSsetgray(NX_BLACK);
- PSmoveto(old_play_mark/reductionFactor+bounds.origin.x,
- bounds.size.height/2+1*scale_factor);
- PSrlineto(0,2*scale_factor);
- PSrmoveto(-1,-1*scale_factor);
- PSrlineto(2,0);
- }
- PSstroke();
-
-
-
- // finally, draw the ticks and add the labels
-
- if (!only_change_play_mark&&true_sample_count)
- {
- // here we draw the label equal to or directly to the left of
- // startsample, to fix a little bug in drawing that comes up
- // when scrolling.
-
- xx=(startsample/(numberOfSamples*major_tick_spacing))
- *(numberOfSamples*major_tick_spacing);
- // note integer division!!!
-
- PSmoveto(((float)xx)/reductionFactor+bounds.origin.x,
- bounds.size.height/2+(1+MISCSOUNDVIEW_PLAY_MARK_HEIGHT
- *scale_factor));
- // should the 1 be modified by the scale factor?
-
- PSrmoveto(0,tick_height*scale_factor);
- if (display_labels&&enough_room_for_labels)
- {
- if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)
- print_value=(float)xx;
- else if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT)
- print_value=((float)xx)/((float)[sound sampleCount])*100;
- else print_value=((float)xx)/(float)[sound samplingRate];
- PSgsave();
- PSinitmatrix();
- PSrmoveto(0,1);
- if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)
- sprintf(tempstring, " %d", (int)print_value);
- // use int value
-
- else if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT)
- sprintf(tempstring, " %d",
- MISCSOUNDVIEW_round(print_value));
- else sprintf(tempstring, " %.3f", print_value);
- // use float value
-
- PSselectfont("Helvetica",8);
- PSshow(tempstring);
- PSgrestore();
- }
-
- // end bug fix. We continue, now drawing the ticks
- // and adding labels...
-
-
- if (minor_tick_spacing!=0.0)
- for (xx=startsample;xx<=endsample;xx+=numberOfSamples)
- {
- // Prepare the ruler for labelling
-
- if (display_major_ticks&&major_tick_spacing&&
- (!(xx%(numberOfSamples*major_tick_spacing))))
- {
- PSsetgray(NX_BLACK);
- PSmoveto(((float)xx)/reductionFactor+bounds.origin.x,
- bounds.size.height/2+
- (1+MISCSOUNDVIEW_PLAY_MARK_HEIGHT*scale_factor));
- PSrlineto(0,tick_height*scale_factor);
- PSgsave();
- PSstroke();
- PSgrestore(); // preserves path and (more importantly)
- // currentpoint
-
- // And Add Label
-
- if (display_labels&&enough_room_for_labels)
- {
- if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)
- // display in samples
-
- print_value=(float)xx;
- else if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT)
- // display in percentage
-
- print_value=((float)xx)/
- ((float)[sound sampleCount])*100;
-
- else // display in seconds
- print_value=((float)xx)/(float)
- [sound samplingRate];
- PSgsave();
- PSinitmatrix();
- PSrmoveto(0,1);
- if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)
- sprintf(tempstring, " %d", (int)print_value);
- // use int value
-
- else if (minor_tick_spacing_format==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT)
- sprintf(tempstring, " %d",
- MISCSOUNDVIEW_round(print_value));
- // use rounded int value
-
- else sprintf(tempstring, " %.3f", print_value);
- // use float value
-
- PSselectfont("Helvetica",8);
- PSshow(tempstring);
- PSgrestore();
- }
- }
- else
- {
- if (display_minor_ticks)
- {
- PSsetgray(NX_LTGRAY);
- PSmoveto(((float)xx)/reductionFactor+
- bounds.origin.x,bounds.size.height/2+
- (1+MISCSOUNDVIEW_PLAY_MARK_HEIGHT*scale_factor));
- PSrlineto(0,tick_height/2*scale_factor);
- // minor ticks are 1/2 height of major ticks
-
- PSstroke();
- }
- }
- PSnewpath(); // deletes path saved when drawing major ticks.
- }
- } // play-mark bracket (see above)
- }
-
- // Return to normal...
- [self setClipping:YES];
- return returnval;
- }
-
-
-
- - getSelection:(int *)firstSample size:(int *)sampleCount
- // a fixed version of getSelection which returns the proper selected area
- // POSSIBLE BUG ALERT: NeXT's stuff may depend on the broken getSelection!
-
- {
- int samples=[[self sound] sampleCount];
- [super getSelection:firstSample size:sampleCount];
- // Now we check and modify accordingly:
- if (*firstSample+*sampleCount>samples) *sampleCount=samples-*firstSample;
- return self;
- }
-
-
-
- - setSelection:(int)firstSample size:(int)sampleCount
- // a fixed version of setSelection which sets the proper selected area
- // POSSIBLE BUG ALERT: NeXT's stuff may depend on the broken setSelection!
-
- {
- int samples=[[self sound] sampleCount];
- if (firstSample+sampleCount>=samples)
- // we make certain that the right amount is selected!
- // Note that you can't just set the selection beyond the sound
- // value, because the soundView doesn't allow it.
- // so here we physically set the soundView's selection rect...
- // hope this doesn't cause weird bugs...
- {
- [super setSelection:firstSample size:sampleCount];
- // as good as can be done...
- selectionRect.size.width*=1.1;
- // this makes the selection a tiny bit larger
- }
- else [super setSelection:firstSample size:sampleCount];
- return self;
- }
-
-
-
- - selectAll:sender
- // a fixed version of selectAll which sets the proper selected area
- // POSSIBLE BUG ALERT: NeXT's stuff may depend on the broken selectAll!
-
- {
- [self setSelection:0 size:[[self sound] sampleCount]];
- return self;
- }
-
-
- - set:
- (BOOL) displayXAxis:
- (BOOL) displayYAxis:
- (BOOL) displayLabels:
- (BOOL) displayZeroLine:
- (int) majorTickSpacing:
- (float) minorTickSpacing:
- (int) minorTickSpacingFormat:
- (int) yDisplayFormat:
- (BOOL) scrollToReflectPlaying
-
- // Sets these values...
-
-
- {
- display_x_axis_marks=displayXAxis;
- display_y_axis_grid=displayYAxis;
- display_labels=displayLabels;
- display_zero_line=displayZeroLine;
- scroll_to_reflect_playing=scrollToReflectPlaying;
-
- // first set the default spacing in case this spacing is invalid
- major_tick_spacing=5;
- if (minorTickSpacingFormat==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_PERCENT) minor_tick_spacing=10.0;
- else if (minorTickSpacingFormat==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES) minor_tick_spacing=1000;
- else if (minorTickSpacingFormat==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SECONDS) minor_tick_spacing=1;
-
- // then change to the user's spacing if his spacing is acceptable
- if (majorTickSpacing>0)
- major_tick_spacing=majorTickSpacing;
- if ((minorTickSpacing>0.0&&
- (minorTickSpacingFormat!=
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)) ||
- (minorTickSpacing>=1.0&&
- (minorTickSpacingFormat==
- MISCSOUNDVIEW_XAXIS_SPACING_FORMAT_SAMPLES)))
- minor_tick_spacing=minorTickSpacing;
-
- minor_tick_spacing_format=minorTickSpacingFormat;
- y_display_format=yDisplayFormat;
- [self _adjustBounds];
-
- return self;
- }
-
- - (BOOL) xAxisDisplayed
- {
- return display_x_axis_marks;
- }
-
- - (BOOL) yAxisDisplayed
- {
- return display_y_axis_grid;
- }
-
- - (BOOL) zeroLineDisplayed
- {
- return display_zero_line;
- }
-
- - (BOOL) labelsDisplayed
- {
- return display_labels;
- }
-
- - (BOOL) scrollToReflectPlaying
- {
- return scroll_to_reflect_playing;
- }
-
- - (int) majorTickSpacing
- {
- return major_tick_spacing;
- }
-
- - (float) minorTickSpacing
- {
- return minor_tick_spacing;
- }
-
- - (int) minorTickSpacingFormat
- {
- return minor_tick_spacing_format;
- }
-
- - (int) yDisplayFormat
- {
- return y_display_format;
- }
-
-
- - scrollToSelection:sender
- // scrolls if there's room to do so
- {
- int first_sample,number_of_samples;
- int total_samples;
- NXRect bounds_rect;
- NXRect visible_rect;
- NXPoint scroll_point;
- id currentScrollView=[[self superview] superview];
-
- if (currentScrollView==NULL) return NULL; // not in scrollView!
-
- total_samples=[[self sound] sampleCount];
- [self getSelection:&first_sample size:&number_of_samples];
- [self getBounds:&bounds_rect]; // get new bounds information if any
- [self getVisibleRect:&visible_rect];
-
- if (!total_samples) total_samples=1; // kills divide-by-zero
-
- scroll_point.x= ((bounds_rect.size.width*
- (double)first_sample)/(double) total_samples);
- scroll_point.y= (bounds_rect.origin.y);
- if (scroll_point.x+visible_rect.size.width>
- bounds.size.width)
- scroll_point.x=bounds.size.width-visible_rect.size.width;
-
- [self scrollPoint: &scroll_point];
- [currentScrollView reflectScroll: [self superview]];
- return self;
- }
-
- - scrollToSample:(int) samp
- // scrolls to samp if there's room to do so.
- {
- int first_sample,number_of_samples;
- int total_samples;
- NXRect bounds_rect;
- NXRect visible_rect;
- NXPoint scroll_point;
- id currentScrollView=[[self superview] superview];
-
- if (currentScrollView==NULL) return NULL; // not in scrollView!
-
- total_samples=[[self sound] sampleCount];
- first_sample=samp;
- number_of_samples=0;
- [self getBounds:&bounds_rect]; // get new bounds information if any
- [self getVisibleRect:&visible_rect];
-
- if (!total_samples) total_samples=1; // kills divide-by-zero
-
- scroll_point.x= ((bounds_rect.size.width*
- (double)first_sample)/(double) total_samples);
- scroll_point.y= (bounds_rect.origin.y);
- if (scroll_point.x+visible_rect.size.width>
- bounds.size.width)
- scroll_point.x=bounds.size.width-visible_rect.size.width;
-
- [self scrollPoint: &scroll_point];
- [currentScrollView reflectScroll: [self superview]];
- return self;
- }
-
- - (int)scrollSample
- // returns the current scrolled sample (leftmost)
- {
- int firstViewSample;
- NXRect visibleRect;
- double ReductionFactor;
-
- ReductionFactor= (double) [self reductionFactor];
- [self getVisibleRect: &visibleRect];
- firstViewSample=(int)(visibleRect.origin.x*ReductionFactor);
- if (sound)
- if (firstViewSample>=[sound sampleCount])
- firstViewSample=[sound sampleCount]-1;
- if (firstViewSample<0) firstViewSample=0;
- return firstViewSample;
- }
-
- - setPlayMark:(int)sample
- // -1 is default position
- {
- old_play_mark=play_mark;
- play_mark=(float)sample;
- if (display_x_axis_marks&&(minor_tick_spacing!=0.0)&&major_tick_spacing)
- // we're showing ticks...
- only_change_play_mark=YES;
- [self display];
- only_change_play_mark=NO;
- return self;
- }
-
-
-
-
- - (double) _scrollValue // a private method
- {
- NXSize content_size;
- id currentScrollView;
- currentScrollView=[[self superview] superview];
-
- if (currentScrollView==NULL) return 0; // not in scrollView!
-
- [currentScrollView getContentSize:&content_size];
-
- return reduction_to_scroll
- ( [self reductionFactor],
- ((double)[sound sampleCount])
- /(double)content_size.width);
- }
-
-
-
- - _setScrollValue:(double) this_value
- // private method. this_value must be between 1 and 0
- {
- NXSize content_size;
- double new_reduction_factor;
- int first_sample, number_of_samples;
- id currentScrollView=[[self superview] superview];
-
- if (currentScrollView==NULL) return NULL; // not in scrollView!
-
- [currentScrollView getContentSize:&content_size];
-
- [self getSelection:&first_sample size:&number_of_samples];
-
- new_reduction_factor= scroll_to_reduction
- // is this where the problem lies?
- ( this_value,
- ((double)[sound sampleCount])
- /(double)content_size.width);
-
- if (new_reduction_factor!=-1.0) // it's not an error
- {
- [self setReductionFactor:new_reduction_factor];
- [self setSelection:first_sample size: number_of_samples];
- return self;
- }
- else
- {
- [self setSelection:first_sample size: number_of_samples];
- return NULL;
- }
- }
-
-
-
- - _zoomTo:(double) scroll_value // a private method
- {
- id returnval;
- int first_sample, number_of_samples;
- [window disableFlushWindow];
- [self getSelection:&first_sample size:&number_of_samples];
-
- if (scroll_value>1.0) scroll_value=1.0;
- if (scroll_value<0.0) scroll_value=0.0;
- returnval=[self _setScrollValue:scroll_value];
- [self setSelection:first_sample size: number_of_samples];
- [self display];
- [window reenableFlushWindow];
- [window flushWindowIfNeeded];
- return returnval;
- }
-
- - getZoomValueFrom:sender
- {
- return [self _zoomTo:[sender floatValue]];
- }
-
- - takeIntValueFrom:sender
- {
- int temp_play_mark=[sender intValue];
- id snd=[self sound];
- int samples;
-
- if (snd==NULL) samples=0;
- else samples=[snd sampleCount];
-
- if (temp_play_mark>=0&&
- temp_play_mark<samples&&scroll_to_reflect_playing)
- {
- [self scrollToSample:temp_play_mark];
- [self setPlayMark:temp_play_mark];
- }
- else [self setPlayMark:-1];
- return self;
- }
-
- - zoomAllIn:this_soundview
- {
- [self _zoomTo:0.0];
- [self scrollToSelection:self];
- return self;
- }
-
-
- - zoomAllOut:this_soundview
- {
- [self _zoomTo:1.0];
- [self scrollToSelection:self];
- return self;
- }
-
-
-
- - zoomOutOneReduction:sender
- {
- id returnval=self;
- double scroll_value,reduction;
- int first_sample, number_of_samples;
-
- [window disableFlushWindow];
- [self getSelection:&first_sample size:&number_of_samples];
- reduction=[self reductionFactor];
- [self setReductionFactor:(int)reduction+1];
- scroll_value=[self _scrollValue];
-
- if (scroll_value>1.0||scroll_value<0.0)
- {
- if (scroll_value>1.0) scroll_value=1.0;
- if (scroll_value<0.0) scroll_value=0.0;
- returnval=[self _setScrollValue:scroll_value];
- }
- [self setSelection:first_sample size: number_of_samples];
- [self scrollToSelection:self];
- [window reenableFlushWindow];
- [window flushWindowIfNeeded];
- return returnval;
- }
-
-
- - zoomInOneReduction:sender
- {
- id returnval=self;
- double scroll_value;
- double reduction;
- int first_sample, number_of_samples;
-
- [window disableFlushWindow];
- [self getSelection:&first_sample size:&number_of_samples];
- reduction=[self reductionFactor];
- if (reduction>=1.0) [self setReductionFactor:(int)reduction-1];
- scroll_value=[self _scrollValue];
- if (scroll_value>1.0||scroll_value<0.0)
- {
- if (scroll_value>1.0) scroll_value=1.0;
- if (scroll_value<0.0) scroll_value=0.0;
- returnval=[self _setScrollValue:scroll_value];
- }
- [self setSelection:first_sample size: number_of_samples];
- [self scrollToSelection:self];
- [window reenableFlushWindow];
- [window flushWindowIfNeeded];
- return returnval;
- }
-
-
-
- - zoomToSelection:sender
- {
- int first_sample, number_of_samples, total_samples;
- double reduction_factor;
- NXRect visible_rect;
-
- // Step 0: Get preliminary information
-
- if (self==NULL) return NULL;
- [window disableFlushWindow];
-
- total_samples=[sound sampleCount];
- [self getSelection:&first_sample size:&number_of_samples];
-
- [self getVisibleRect:&visible_rect];
-
- // Step 1: Zoom to the right reduction
-
- reduction_factor=MISCSOUNDVIEW_round(
- ((double) number_of_samples) / ((double) visible_rect.size.width));
- if (reduction_factor<1.0) reduction_factor=1.0;
- [self setReductionFactor: reduction_factor];
- [self setSelection:first_sample size: number_of_samples];
-
-
- // Step 2: Move to the right spot
-
- [self scrollToSelection:self];
-
- // Step 3: Update Information
- [self display];
- [window reenableFlushWindow];
- [window flushWindowIfNeeded];
- return self;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
- NXReadTypes(stream,"ifiii", &display_x_axis_marks,&minor_tick_spacing,
- &minor_tick_spacing_format,&major_tick_spacing,
- &display_labels);
- play_mark=-1; old_play_mark=-1;
- NXReadTypes(stream,"iiii", &display_y_axis_grid,&display_zero_line,
- &y_display_format,&scroll_to_reflect_playing);
- only_change_play_mark=NO;
- [self _wipeClean];
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteTypes(stream,"ifiii",&display_x_axis_marks,&minor_tick_spacing,
- &minor_tick_spacing_format,&major_tick_spacing,
- &display_labels);
- NXWriteTypes(stream,"iiii", &display_y_axis_grid,&display_zero_line,
- &y_display_format,&scroll_to_reflect_playing);
- return self;
- }
-
- - awake
- {
- id returnval=[super awake];
- // do nothing for the time being...
- return returnval;
- }
-
- - awakeFromNib
- {
- id returnval=[super awakeFromNib];
- [self adjustBounds:self];
- return returnval;
- }
-
- - toggleXAxisDisplayed:sender
- {
- display_x_axis_marks=!display_x_axis_marks;
- return [self adjustBounds:self];
- }
-
- - toggleYAxisDisplayed:sender
- {
- display_y_axis_grid=!display_y_axis_grid;
- [self _wipeClean];
- [self display];
- return self;
- }
-
- - toggleLabelsDisplayed:sender
- {
- display_labels=!display_labels;
- [self _wipeClean];
- [self display];
- return self;
- }
-
- - toggleZeroLineDisplayed:sender
- {
- display_zero_line=!display_zero_line;
- [self _wipeClean];
- [self display];
- return self;
- }
-
- - toggleScrollToReflectPlaying:sender
- {
- scroll_to_reflect_playing=!scroll_to_reflect_playing;
- return self;
- }
-
- - (const char*) getInspectorClassName
- {
- return "MiscSoundViewInspector";
- }
-
- @end
-