scide: LookupDialog - redo lookup on classes after partial lookup
[supercollider.git] / SCClassLibrary / Common / GUI / osx / scide_scapp / Base / SCSoundFileView.sc
blobb7183b1d88fc0c282a4c872fffd59d4e48f961b8
1 SCSoundFileView : SCScope{
2         var < soundfile;
3         var <>metaAction, <elasticMode, <drawsWaveForm=true, <readProgress;
4         var <startFrame, <numFrames;
5         var zoomOne, <>dataFrames, <viewFrames, <scrollPos, <>block=64;
7         init{ arg argParent, argBounds;
8                 super.init(argParent, argBounds);
9                 soundfile = SoundFile.new;
10         }
12         soundfile_{|snd|
13                 soundfile = snd;
14                 if(soundfile.isOpen){^this};
15                 if(soundfile.openRead.not){^this};
16                 soundfile.close;
17         }
19         read { |startframe=0, frames, block=64, closeFile=true|
20                 this.block = block;
21                 if(soundfile.isOpen.not){
22                         if(soundfile.openRead.not){
23                                 ^this
24                         };
25                 };
26                 startFrame = startframe;
27                 frames = frames ? soundfile.numFrames;
29                 if (frames == -1) { frames = soundfile.numFrames };
30                 numFrames = frames.clip(0, soundfile.numFrames);
32                 this.readFile(soundfile, startframe, frames, block);
33                 if(closeFile){soundfile.close};
34         }
36         readWithTask{|startframe=0, frames, block=64, doneAction, showProgress=true|
37                 this.readFileWithTask(soundfile, startframe, frames, block, doneAction, showProgress);
38         }
40         makeProgressWindow{
41                 this.addDependant(SoundFileViewProgressWindow(soundfile.path.split.last));
42         }
44         // needs an open soundfile;
45         readFileWithTask{|soundfile, startframe=0, frames, block=64,
46                                                 doneAction, showProgress=true|
47                 var zoomx, o, readtime, data, resampleFrames;
48                 this.block = block;
49                 if(showProgress){
50                         this.makeProgressWindow;
51                 };
52                 frames = frames ? soundfile.numFrames;
53                 resampleFrames = frames/block;
54                 this.drawsWaveForm_(false);
55                 o = 2**19;
56                 zoomx = (resampleFrames/(this.bounds.width-2));
57                 Task({
58                         var times, frame, data, spec;
59                         data = Array(resampleFrames*soundfile.numChannels);
60                         frame = startframe;
61                         times = (frames/o).ceil;
62                         spec = [0, times].asSpec;
63                         times.do{|i|
64                                 readtime = {
65                                         this.read(frame, o, block, false);
66                                         frame = frame + o;
67                                         readProgress = spec.unmap(i);
68                                 }.bench(false);
69                                 (readtime*0.001).wait;
70                                         data.addAll(this.data);
71                                         this.changed(\progress);
72                                 (readtime*0.05).wait;
73                         };
74                         this.setData(data, block, startframe, soundfile.numChannels, soundfile.sampleRate);
75                         this.xZoom_(zoomx).drawsWaveForm_(true).refresh;
77                         this.updateData;
79                         doneAction.value(this);
80                         soundfile.close;
81                         this.changed(\progressFinished);
82                 }).play(AppClock);
83         }
85         readFile{|asoundfile, startframe=0, frames=0, block=0, closefile=true|
86                 this.setProperty(\readSndFile,
87                         [asoundfile, startframe, frames, block,
88                         soundfile.sampleRate,
89                         soundfile.numFrames,
90                         soundfile.numChannels]);
91                 this.updateData;
92         }
94         mouseEndTrack{|x,y|
95 //              mouseUpAction.value(this, x,y)
96         }
98         doMetaAction{
99                 metaAction.value(this)
100         }
102         currentSelection_{|index|
103                 this.setProperty(\currentSelection, index);
104         }
106         currentSelection{
107                 ^this.getProperty(\currentSelection);
108         }
110         setSelectionStart{|index,frame|
111                 this.setProperty(\selectionStart, [index,frame]);
112         }
114         setSelectionSize{|index,frame|
115                 this.setProperty(\selectionSize, [index,frame]);
116         }
118         setEditableSelectionStart{|index, bool|
119                 this.setProperty(\selectionStartIsEditable, [index, bool]);
120         }
122         setEditableSelectionSize{|index, bool|
123                 this.setProperty(\selectionSizeIsEditable, [index, bool]);
124         }
126         setSelectionColor{|index,color|
127                 this.setProperty(\selectionColor, [index, color]);
128         }
130         selections{
131                 var array;
132                 array = Array.fill(64, {[0,0]});
133                 ^this.getProperty(\selections, array);
134         }
136         selectionStart{|index|
137                 ^this.getProperty(\selectionStart, index);
138         }
140         selectionSize{|index|
141                 ^this.getProperty(\selectionSize, index);
142         }
144         selection { |index|
145                 ^[this.selectionStart(index), this.selectionSize(index)]
146         }
147         setSelection { |index, selection|
148                 this.setSelectionStart(index, selection[0])
149                         .setSelectionSize(index, selection[1]);
150         }
152         selectionStartTime{|index|
153                 ^this.getProperty(\selectionStartTime, index);
154         }
156         selectionDuration{|index|
157                 ^this.getProperty(\selectionDuration, index);
158         }
160         readSelection{ |block=64, closeFile=true|
161                 this.read(
162                         this.selectionStart(this.currentSelection),
163                         this.selectionSize(this.currentSelection),
164                         block,
165                         closeFile
166                 );
167         }
169         readSelectionWithTask{
170                 this.readWithTask(
171                         this.selectionStart(this.currentSelection),
172                         this.selectionSize(this.currentSelection)
173                 );
174         }
176         gridOn_{|boolean|
177                 this.setProperty(\gridOn, boolean);
178         }
180         gridResolution_{|resolution|
181                 this.setProperty(\gridResolution, resolution);
182         }
184         gridOn { ^this.getProperty(\gridOn) }
185         gridResolution { ^this.getProperty(\gridResolution) }
186         gridColor { ^this.getProperty(\gridColor, Color.new) }
187         timeCursorOn { ^this.getProperty(\timeCursorOn) }
188         timeCursorPosition { ^this.getProperty(\timeCursorPosition) }
189         timeCursorColor { ^this.getProperty(\timeCursorColor, Color.new) }
191         dataNumSamples{
192                 ^this.getProperty(\getViewNumSamples);
193         }
195         data{
196                 var arr;
197                 arr = Array.newClear(this.dataNumSamples);
198                 ^this.getProperty(\getViewData, arr);
199         }
201         data_{|arr|
202                 this.setData(arr, 64, 0, soundfile.numChannels, soundfile.sampleRate);
203         }
205         setData{|arr, block=64, startframe = 0, channels=1, samplerate=44100|
206                 this.block = block;
207                 this.setProperty(\setViewData, [arr, block, startframe, channels, samplerate]);
208         }
210         elasticMode_{arg mode;
211                 elasticMode =mode;
212                 this.setProperty(\elasticResizeMode, mode);
213         }
215         drawsWaveForm_{|bool|
216                 drawsWaveForm = bool;
217                 this.setProperty(\drawsWaveForm, bool);
218         }
220         timeCursorPosition_{|frame|
221                 this.setProperty(\timeCursorPosition, frame);
222         }
224         timeCursorOn_{|bool|
225                 this.setProperty(\showTimeCursor, bool)
226         }
228         timeCursorColor_{|color|
229                 this.setProperty(\timeCursorColor, color)
230         }
232         zoom {| factor |        // zoom factor n or 1/n.
233                 this.xZoom = zoomOne.min(this.xZoom * factor);
234                 viewFrames = dataFrames * block * (this.xZoom / zoomOne);
235                 if ( this.x > (soundfile.numFrames - viewFrames), {
236                         this.x_(soundfile.numFrames - viewFrames)
237                 });
238                 this.refresh;
239                 this.updateScroll
240         }
241         zoomToFrac { arg frac; // 0..1
242                 this.xZoom = (frac * zoomOne);
243                 viewFrames = dataFrames * block * (this.xZoom / zoomOne);
244                 if ( this.x > (soundfile.numFrames - viewFrames), {
245                         this.x_(soundfile.numFrames - viewFrames)
246                 });
247                 this.refresh;
248                 this.updateScroll
249         }
250         zoomAllOut {
251                 this.x_(0); this.xZoom = zoomOne; this.refresh;
252                 viewFrames = dataFrames * block * (this.xZoom / zoomOne);
253                 this.updateScroll;
254         }
256         zoomSelection {| index |        // selection index
257                 if ( this.selectionSize(index) > 0, {
258                         this.x_(this.selectionStart(index));
259                         this.xZoom = this.selectionSize(index) / (this.bounds.width-2) / block;
260                         viewFrames = dataFrames * block * (this.xZoom / zoomOne);
261                         this.refresh;
262                         this.updateScroll
263                 })
264         }
266         scrollTo { | position |         // absolute. from 0 to 1
267                 this.x_((soundfile.numFrames - viewFrames) * position).refresh;
268                 this.updateScroll;
269         }
271         scroll {| amount |      // +/- range in viewFrames
272                 this.x_((this.x + (amount*viewFrames))
273                         .clip(0,soundfile.numFrames - viewFrames)).refresh;
274                 this.updateScroll
275         }
277         scrollToStart {
278                 this.x_(0).refresh;
279                 scrollPos = 0;
280         }
282         scrollToEnd {
283                 this.x_(soundfile.numFrames  - viewFrames ).refresh;
284                 scrollPos = 1;
285         }
287         selectAll {| index |    // selection index
288                 this.setSelectionStart(index, 0); this.setSelectionSize(index, this.soundfile.numFrames)
289         }
291         selectNone {| index |    // selection index
292                 this.setSelectionSize(index, 0); // sends x to 0 when selection is not full width visible? ( thus update scrollPos )
293                 this.updateScroll
294         }
296         gridOffset_{|offset|
297                 this.setProperty(\gridOffset, offset);
298         }
300 /* private methods*/
302         updateScroll {
303                 scrollPos = this.x / (soundfile.numFrames - viewFrames)
304         }
306         updateData {
307                 scrollPos = 0;
308                 dataFrames = this.dataNumSamples/this.soundfile.numChannels;
309                 zoomOne = dataFrames / (this.bounds.width-2);
310                 viewFrames = dataFrames * block * (this.xZoom / zoomOne);
311         }
313         *paletteExample { arg parent, bounds;
314                 var example, file;
315                 example = this.new(parent, bounds);
316                 file = SoundFile.new;
317                 file.openRead("sounds/a11wlk01.wav");
318                 example.soundfile = file;
319                 example.read(0, file.numFrames);
320                 ^example
321         }
325 SoundFileViewProgressWindow{
326         var win, slider;
328         *new{|name|
329                 ^super.new.makeWindow(name)
330         }
332         makeWindow{|name|
333                 win = SCWindow.new("reading: " ++ name,
334                                  Rect(100,100,300, 40), false).front;
335                 win.view.decorator = FlowLayout(win.view.bounds);
336                 slider = SCRangeSlider(win, Rect(4,4,290,10));
337         }
339         update{|changed, changer|
341                 if(changer === \progress){
342                         {slider.lo_(0).hi_(changed.readProgress)}.defer
343                         ^this
344                 };
345                 if(changer === \progressFinished){
346                         {win.close;
347                         changed.removeDependant(this)}.defer;
348                         ^this
349                 };
351         }
354 /* jan truetzschler 2005 */