BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / soundrecorder / ScopeView.cpp
blob4a847e06359ac471f6cefefca74bad2dba0094dd
1 /*
2 * Copyright 2005, Jérôme Duval. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Inspired by SoundCapture from Be newsletter (Media Kit Basics:
6 * Consumers and Producers)
7 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <IconUtils.h>
12 #include <MimeType.h>
13 #include <Screen.h>
14 #include <Window.h>
15 #include "DrawingTidbits.h"
16 #include "ScopeView.h"
18 #define SAMPLES_COUNT 20000
20 //#define TRACE 1
21 #ifdef TRACE
22 #define TRACE(x...) printf(x)
23 #else
24 #define TRACE(x...)
25 #endif
27 ScopeView::ScopeView(BRect rect, uint32 resizeFlags)
28 : BView(rect, "scope", resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS),
29 fThreadId(-1),
30 fBitmap(NULL),
31 fBitmapView(NULL),
32 fIsRendering(false),
33 fMediaTrack(NULL),
34 fMainTime(0),
35 fRightTime(1000000),
36 fLeftTime(0),
37 fTotalTime(1000000)
39 fHeight = Bounds().Height();
43 ScopeView::~ScopeView()
45 delete_sem(fRenderSem);
49 void
50 ScopeView::AttachedToWindow()
52 SetViewColor(B_TRANSPARENT_COLOR);
53 InitBitmap();
54 Run();
58 void
59 ScopeView::DetachedFromWindow()
61 Quit();
65 void
66 ScopeView::Draw(BRect updateRect)
68 BRect bounds = Bounds();
69 SetHighColor(0,0,0);
71 if (!fIsRendering)
72 DrawBitmapAsync(fBitmap, BPoint(0, 0));
73 else
74 FillRect(bounds);
76 float x = 0;
77 if (fTotalTime != 0)
78 x += (fMainTime - fLeftTime) * bounds.right
79 / (fRightTime - fLeftTime);
80 SetHighColor(60,255,40);
81 StrokeLine(BPoint(x, bounds.top), BPoint(x, bounds.bottom));
83 Sync();
87 void
88 ScopeView::Run()
90 fRenderSem = create_sem(0, "scope rendering");
91 fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY,
92 this);
93 if (fThreadId < 0)
94 return;
95 resume_thread(fThreadId);
98 void
99 ScopeView::Quit()
101 delete_sem(fRenderSem);
102 snooze(10000);
103 kill_thread(fThreadId);
108 int32
109 ScopeView::RenderLaunch(void *data)
111 ScopeView *scope = (ScopeView*) data;
112 scope->RenderLoop();
113 return B_OK;
117 template<typename T, typename U>
118 void
119 ScopeView::ComputeRendering()
121 int64 framesCount = fMediaTrack->CountFrames() / SAMPLES_COUNT;
122 if (framesCount <= 0)
123 return;
124 T samples[fPlayFormat.u.raw_audio.buffer_size
125 / (fPlayFormat.u.raw_audio.format
126 & media_raw_audio_format::B_AUDIO_SIZE_MASK)];
127 int64 frames = 0;
128 U sum = 0;
129 int64 sumCount = 0;
130 float middle = fHeight / 2;
131 int32 previewMax = 0;
132 //fMediaTrack->SeekToFrame(&frames);
134 TRACE("begin computing\n");
136 int32 previewIndex = 0;
138 while (fIsRendering && fMediaTrack->ReadFrames(samples, &frames) == B_OK) {
139 //TRACE("reading block\n");
140 int64 framesIndex = 0;
142 while (framesIndex < frames) {
143 for (; framesIndex < frames && sumCount < framesCount;
144 framesIndex++, sumCount++) {
145 sum += samples[2 * framesIndex];
146 sum += samples[2 * framesIndex + 1];
149 if (previewIndex >= SAMPLES_COUNT)
150 break;
152 if (sumCount >= framesCount) {
153 // TRACE("computing block %ld, sumCount %ld\n", previewIndex,
154 // sumCount);
155 fPreview[previewIndex] = (int32)(sum
156 / fPlayFormat.u.raw_audio.channel_count / framesCount);
157 if (previewMax < fPreview[previewIndex])
158 previewMax = fPreview[previewIndex];
159 sumCount = 0;
160 sum = 0;
161 previewIndex++;
166 if (previewMax <= 0)
167 return;
168 for (int i = 0; i < SAMPLES_COUNT; i++)
169 fPreview[i] = (int32)(fPreview[i] * 1.0 / previewMax
170 * middle + middle);
174 void
175 ScopeView::RenderLoop()
177 while (acquire_sem(fRenderSem) == B_OK) {
178 fIsRendering = true;
180 switch (fPlayFormat.u.raw_audio.format) {
181 case media_raw_audio_format::B_AUDIO_FLOAT:
182 ComputeRendering<float, float>();
183 break;
184 case media_raw_audio_format::B_AUDIO_INT:
185 ComputeRendering<int32, int64>();
186 break;
187 case media_raw_audio_format::B_AUDIO_SHORT:
188 ComputeRendering<int16, int64>();
189 break;
190 case media_raw_audio_format::B_AUDIO_UCHAR:
191 ComputeRendering<uchar, uint32>();
192 break;
193 case media_raw_audio_format::B_AUDIO_CHAR:
194 ComputeRendering<char, int32>();
195 break;
198 TRACE("finished computing, rendering\n");
200 /* rendering */
201 RenderBitmap();
203 TRACE("rendering done\n");
205 /* ask drawing */
207 fIsRendering = false;
209 if (Window()->LockWithTimeout(5000) == B_OK) {
210 Invalidate();
211 TRACE("invalidate done\n");
212 Window()->Unlock();
218 void
219 ScopeView::SetMainTime(bigtime_t timestamp)
221 fMainTime = timestamp;
222 Invalidate();
223 TRACE("invalidate done\n");
227 void
228 ScopeView::SetTotalTime(bigtime_t timestamp, bool reset)
230 fTotalTime = timestamp;
231 if (reset) {
232 fMainTime = 0;
233 fLeftTime = 0;
234 fRightTime = fTotalTime;
236 Invalidate();
237 TRACE("invalidate done\n");
241 void
242 ScopeView::SetLeftTime(bigtime_t timestamp)
244 fLeftTime = timestamp;
245 RenderBitmap();
246 Invalidate();
247 TRACE("invalidate done\n");
250 void
251 ScopeView::SetRightTime(bigtime_t timestamp)
253 fRightTime = timestamp;
254 RenderBitmap();
255 Invalidate();
256 TRACE("invalidate done\n");
260 void
261 ScopeView::RenderTrack(BMediaTrack *track, const media_format &format)
263 fMediaTrack = track;
264 fPlayFormat = format;
265 release_sem(fRenderSem);
269 void
270 ScopeView::CancelRendering()
272 fIsRendering = false;
276 void
277 ScopeView::FrameResized(float width, float height)
279 InitBitmap();
280 RenderBitmap();
281 Invalidate();
282 TRACE("invalidate done\n");
286 void
287 ScopeView::MouseDown(BPoint position)
289 if (!fMediaTrack)
290 return;
292 uint32 buttons;
293 BPoint point;
294 GetMouse(&point, &buttons);
296 if (buttons & B_PRIMARY_MOUSE_BUTTON) {
297 // fill the drag message
298 BMessage drag(B_SIMPLE_DATA);
299 drag.AddInt32("be:actions", B_COPY_TARGET);
300 drag.AddString("be:clip_name", "Audio Clip");
301 drag.AddString("be:types", B_FILE_MIME_TYPE);
303 uint8* data;
304 size_t size;
306 BMimeType wavType("audio/x-wav");
307 if (wavType.InitCheck() < B_OK
308 || wavType.GetIcon(&data, &size) < B_OK) {
309 wavType.SetTo("audio");
310 if (wavType.InitCheck() < B_OK
311 || wavType.GetIcon(&data, &size) < B_OK) {
312 return;
316 BBitmap* bitmap = new BBitmap(
317 BRect(0, 0, 31, 31), 0, B_RGBA32);
318 if (BIconUtils::GetVectorIcon(data, size, bitmap) < B_OK) {
319 delete[] data;
320 delete bitmap;
321 return;
323 delete[] data;
324 DragMessage(&drag, bitmap, B_OP_ALPHA, BPoint(0,0));
329 void
330 ScopeView::InitBitmap()
332 if (fBitmapView) {
333 fBitmap->RemoveChild(fBitmapView);
334 delete fBitmapView;
336 if (fBitmap)
337 delete fBitmap;
339 BRect rect = Bounds();
341 fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true);
342 memset(fBitmap->Bits(), 0, fBitmap->BitsLength());
344 rect.OffsetToSelf(B_ORIGIN);
345 fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView",
346 B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW);
347 fBitmap->AddChild(fBitmapView);
351 void
352 ScopeView::RenderBitmap()
354 if (!fMediaTrack)
355 return;
357 /* rendering */
358 fBitmap->Lock();
359 memset(fBitmap->Bits(), 0, fBitmap->BitsLength());
360 float width = fBitmapView->Bounds().Width() + 1;
362 fBitmapView->SetDrawingMode(B_OP_ADD);
363 fBitmapView->SetHighColor(15,60,15);
364 int32 leftIndex =
365 (fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0;
366 int32 rightIndex =
367 (fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000;
369 for (int32 i = leftIndex; i<rightIndex; i++) {
370 BPoint point((i - leftIndex) * width / (rightIndex - leftIndex),
371 fPreview[i]);
372 //TRACE("point x %f y %f\n", point.x, point.y);
373 fBitmapView->StrokeLine(point, point);
376 fBitmap->Unlock();