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)
11 #include <IconUtils.h>
15 #include "DrawingTidbits.h"
16 #include "ScopeView.h"
18 #define SAMPLES_COUNT 20000
22 #define TRACE(x...) printf(x)
27 ScopeView::ScopeView(BRect rect
, uint32 resizeFlags
)
28 : BView(rect
, "scope", resizeFlags
, B_WILL_DRAW
| B_FRAME_EVENTS
),
39 fHeight
= Bounds().Height();
43 ScopeView::~ScopeView()
45 delete_sem(fRenderSem
);
50 ScopeView::AttachedToWindow()
52 SetViewColor(B_TRANSPARENT_COLOR
);
59 ScopeView::DetachedFromWindow()
66 ScopeView::Draw(BRect updateRect
)
68 BRect bounds
= Bounds();
72 DrawBitmapAsync(fBitmap
, BPoint(0, 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
));
90 fRenderSem
= create_sem(0, "scope rendering");
91 fThreadId
= spawn_thread(&RenderLaunch
, "Scope view", B_NORMAL_PRIORITY
,
95 resume_thread(fThreadId
);
101 delete_sem(fRenderSem
);
103 kill_thread(fThreadId
);
109 ScopeView::RenderLaunch(void *data
)
111 ScopeView
*scope
= (ScopeView
*) data
;
117 template<typename T
, typename U
>
119 ScopeView::ComputeRendering()
121 int64 framesCount
= fMediaTrack
->CountFrames() / SAMPLES_COUNT
;
122 if (framesCount
<= 0)
124 T samples
[fPlayFormat
.u
.raw_audio
.buffer_size
125 / (fPlayFormat
.u
.raw_audio
.format
126 & media_raw_audio_format::B_AUDIO_SIZE_MASK
)];
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
)
152 if (sumCount
>= framesCount
) {
153 // TRACE("computing block %ld, sumCount %ld\n", previewIndex,
155 fPreview
[previewIndex
] = (int32
)(sum
156 / fPlayFormat
.u
.raw_audio
.channel_count
/ framesCount
);
157 if (previewMax
< fPreview
[previewIndex
])
158 previewMax
= fPreview
[previewIndex
];
168 for (int i
= 0; i
< SAMPLES_COUNT
; i
++)
169 fPreview
[i
] = (int32
)(fPreview
[i
] * 1.0 / previewMax
175 ScopeView::RenderLoop()
177 while (acquire_sem(fRenderSem
) == B_OK
) {
180 switch (fPlayFormat
.u
.raw_audio
.format
) {
181 case media_raw_audio_format::B_AUDIO_FLOAT
:
182 ComputeRendering
<float, float>();
184 case media_raw_audio_format::B_AUDIO_INT
:
185 ComputeRendering
<int32
, int64
>();
187 case media_raw_audio_format::B_AUDIO_SHORT
:
188 ComputeRendering
<int16
, int64
>();
190 case media_raw_audio_format::B_AUDIO_UCHAR
:
191 ComputeRendering
<uchar
, uint32
>();
193 case media_raw_audio_format::B_AUDIO_CHAR
:
194 ComputeRendering
<char, int32
>();
198 TRACE("finished computing, rendering\n");
203 TRACE("rendering done\n");
207 fIsRendering
= false;
209 if (Window()->LockWithTimeout(5000) == B_OK
) {
211 TRACE("invalidate done\n");
219 ScopeView::SetMainTime(bigtime_t timestamp
)
221 fMainTime
= timestamp
;
223 TRACE("invalidate done\n");
228 ScopeView::SetTotalTime(bigtime_t timestamp
, bool reset
)
230 fTotalTime
= timestamp
;
234 fRightTime
= fTotalTime
;
237 TRACE("invalidate done\n");
242 ScopeView::SetLeftTime(bigtime_t timestamp
)
244 fLeftTime
= timestamp
;
247 TRACE("invalidate done\n");
251 ScopeView::SetRightTime(bigtime_t timestamp
)
253 fRightTime
= timestamp
;
256 TRACE("invalidate done\n");
261 ScopeView::RenderTrack(BMediaTrack
*track
, const media_format
&format
)
264 fPlayFormat
= format
;
265 release_sem(fRenderSem
);
270 ScopeView::CancelRendering()
272 fIsRendering
= false;
277 ScopeView::FrameResized(float width
, float height
)
282 TRACE("invalidate done\n");
287 ScopeView::MouseDown(BPoint position
)
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
);
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
) {
316 BBitmap
* bitmap
= new BBitmap(
317 BRect(0, 0, 31, 31), 0, B_RGBA32
);
318 if (BIconUtils::GetVectorIcon(data
, size
, bitmap
) < B_OK
) {
324 DragMessage(&drag
, bitmap
, B_OP_ALPHA
, BPoint(0,0));
330 ScopeView::InitBitmap()
333 fBitmap
->RemoveChild(fBitmapView
);
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
);
352 ScopeView::RenderBitmap()
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);
365 (fTotalTime
!= 0) ? fLeftTime
* 20000 / fTotalTime
: 0;
367 (fTotalTime
!= 0) ? fRightTime
* 20000 / fTotalTime
: 20000;
369 for (int32 i
= leftIndex
; i
<rightIndex
; i
++) {
370 BPoint
point((i
- leftIndex
) * width
/ (rightIndex
- leftIndex
),
372 //TRACE("point x %f y %f\n", point.x, point.y);
373 fBitmapView
->StrokeLine(point
, point
);