From 389cd87bcbfdb6371770a652f49e0a058f299357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 1 Sep 2010 11:37:52 +0000 Subject: [PATCH] Made the PeakView multi-channel capable. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38489 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/mediaplayer/interface/PeakView.cpp | 229 ++++++++++++-------- src/apps/mediaplayer/interface/PeakView.h | 22 +- 2 files changed, 146 insertions(+), 105 deletions(-) diff --git a/src/apps/mediaplayer/interface/PeakView.cpp b/src/apps/mediaplayer/interface/PeakView.cpp index 90e4aa2d0a..92691706d9 100644 --- a/src/apps/mediaplayer/interface/PeakView.cpp +++ b/src/apps/mediaplayer/interface/PeakView.cpp @@ -1,10 +1,12 @@ /* + * Copyright (C) 2001-2010 Stephan Aßmus. All rights reserved. + * Distributed under the terms of the MIT license. + * * Copyright (C) 1998-1999 Be Incorporated. All rights reseved. * Distributed under the terms of the Be Sample Code license. - * - * Copyright (C) 2001-2008 Stephan Aßmus. All rights reserved. - * Distributed under the terms of the MIT license. */ + + #include "PeakView.h" #include @@ -21,66 +23,60 @@ using std::nothrow; + enum { MSG_PULSE = 'puls', MSG_LOCK_PEAKS = 'lpks' }; -// constructor + PeakView::PeakView(const char* name, bool useGlobalPulse, bool displayLabels) - : BView(BRect(0.0, 0.0, 155.0 + 4.0, 10.0 + 4.0), + : + BView(BRect(0.0, 0.0, 155.0 + 4.0, 10.0 + 4.0), name, B_FOLLOW_LEFT | B_FOLLOW_TOP, - useGlobalPulse ? B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS + useGlobalPulse ? B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS : B_WILL_DRAW | B_FRAME_EVENTS), - fUseGlobalPulse(useGlobalPulse), - fDisplayLabels(displayLabels), - fPeakLocked(false), + fUseGlobalPulse(useGlobalPulse), + fDisplayLabels(displayLabels), + fPeakLocked(false), - fRefreshDelay(20000), - fPulse(NULL), + fRefreshDelay(20000), + fPulse(NULL), - fCurrentMaxL(0.0), - fLastMaxL(0.0), - fOvershotL(false), + fChannelInfos(NULL), + fChannelCount(0), - fCurrentMaxR(0.0), - fLastMaxR(0.0), - fOvershotR(false), - - fBackBitmap(new BBitmap(BRect(0.0, 0.0, 256.0, 18.0), B_CMAP8)), - fPeakNotificationWhat(0) + fBackBitmap(NULL), + fPeakNotificationWhat(0) { GetFontHeight(&fFontHeight); SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(B_TRANSPARENT_COLOR); - FrameResized(Bounds().Width(), Bounds().Height()); - if (fDisplayLabels) ResizeBy(0, ceilf(fFontHeight.ascent + fFontHeight.descent)); + + SetChannelCount(2); } -// destructor + PeakView::~PeakView() { delete fPulse; delete fBackBitmap; + delete[] fChannelInfos; } -// MessageReceived + void PeakView::MessageReceived(BMessage* message) { if (message->what == fPeakNotificationWhat) { - float maxL; - if (message->FindFloat("max", 0, &maxL) < B_OK) - maxL = 0.0; - float maxR; - if (message->FindFloat("max", 1, &maxR) < B_OK) - maxR = 0.0; - SetMax(maxL, maxR); - return; + float max; + for (int32 i = 0; message->FindFloat("max", i, &max) == B_OK; i++) + SetMax(max, i); + return; } switch (message->what) { @@ -98,7 +94,7 @@ PeakView::MessageReceived(BMessage* message) } } -// AttachedToWindow + void PeakView::AttachedToWindow() { @@ -106,11 +102,11 @@ PeakView::AttachedToWindow() delete fPulse; BMessage message(MSG_PULSE); fPulse = new BMessageRunner(BMessenger(this), &message, - fRefreshDelay); + fRefreshDelay); } } -// DetachedFromWindow + void PeakView::DetachedFromWindow() { @@ -118,7 +114,7 @@ PeakView::DetachedFromWindow() fPulse = NULL; } -// MouseDown + void PeakView::MouseDown(BPoint where) { @@ -127,13 +123,17 @@ PeakView::MouseDown(BPoint where) buttons = B_PRIMARY_MOUSE_BUTTON; if (buttons & B_PRIMARY_MOUSE_BUTTON) { - fOvershotL = false; - fOvershotR = false; - fLastMaxL = fCurrentMaxL; - fLastMaxR = fCurrentMaxR; + // Reset the overshot flag and set the observed max to the current + // value. + for (uint32 i = 0; i < fChannelCount; i++) { + fChannelInfos[i].overshot = false; + fChannelInfos[i].last_max = fChannelInfos[i].current_max; + } } else if (buttons & B_TERTIARY_MOUSE_BUTTON) { + // Toggle locking of the observed max value. fPeakLocked = !fPeakLocked; } else { + // Display context menu BPopUpMenu* menu = new BPopUpMenu("peak context menu"); BMenuItem* item = new BMenuItem("Lock Peaks", new BMessage(MSG_LOCK_PEAKS)); @@ -158,7 +158,7 @@ PeakView::MouseDown(BPoint where) } } -// Draw + void PeakView::Draw(BRect area) { @@ -171,7 +171,7 @@ PeakView::Draw(BRect area) float width = r.Width(); r.InsetBy(-2.0, -2.0); // frame - BeginLineArray(9); + BeginLineArray(8); AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), lightShadow); AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), lightShadow); @@ -188,8 +188,6 @@ PeakView::Draw(BRect area) AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), lightShadow); r.InsetBy(1.0, 1.0); - AddLine(BPoint(r.left, (r.top + r.bottom) / 2.0), - BPoint(r.right, (r.top + r.bottom) / 2.0), black); EndLineArray(); // peak bitmap @@ -208,39 +206,39 @@ PeakView::Draw(BRect area) } } -// FrameResized + void PeakView::FrameResized(float width, float height) { BRect bitmapFrame = _BackBitmapFrame(); - _ResizeBackBitmap(bitmapFrame.IntegerWidth() + 1); + _ResizeBackBitmap(bitmapFrame.IntegerWidth() + 1, fChannelCount); _UpdateBackBitmap(); } -// Pulse + void PeakView::Pulse() { - if (!fBackBitmap) + if (fBackBitmap == NULL) return; if (!fPeakLocked) { - fLastMaxL = 0.90 * fLastMaxL; - if (fCurrentMaxL > fLastMaxL) - fLastMaxL = fCurrentMaxL; - fLastMaxR = 0.90 * fLastMaxR; - if (fCurrentMaxR > fLastMaxR) - fLastMaxR = fCurrentMaxR; + for (uint32 i = 0; i < fChannelCount; i++) { + fChannelInfos[i].last_max *= 0.90f; + if (fChannelInfos[i].current_max > fChannelInfos[i].last_max) + fChannelInfos[i].last_max = fChannelInfos[i].current_max; + } } _UpdateBackBitmap(); - fCurrentMaxL = 0.0; - fCurrentMaxR = 0.0; + + for (uint32 i = 0; i < fChannelCount; i++) + fChannelInfos[i].current_max = 0.0f; _DrawBitmap(); Flush(); } -// GetPreferredSize + void PeakView::GetPreferredSize(float* _width, float* _height) { @@ -262,49 +260,74 @@ PeakView::GetPreferredSize(float* _width, float* _height) *_height = minHeight; } -// IsValid + bool PeakView::IsValid() const { - return fBackBitmap && fBackBitmap->IsValid(); + return fBackBitmap != NULL && fBackBitmap->IsValid() + && fChannelInfos != NULL; } -// SetPeakRefreshDelay + void PeakView::SetPeakRefreshDelay(bigtime_t delay) { if (fRefreshDelay == delay) return; + fRefreshDelay = delay; - if (fPulse) + + if (fPulse != NULL) fPulse->SetInterval(fRefreshDelay); } -// SetPeakNotificationWhat + void PeakView::SetPeakNotificationWhat(uint32 what) { fPeakNotificationWhat = what; } -// SetMax -void -PeakView::SetMax(float maxL, float maxR) -{ - if (fCurrentMaxL < maxL) - fCurrentMaxL = maxL; - if (fCurrentMaxR < maxR) - fCurrentMaxR = maxR; - if (fCurrentMaxL > 1.0) - fOvershotL = true; - if (fCurrentMaxR > 1.0) - fOvershotR = true; +void +PeakView::SetChannelCount(uint32 channelCount) +{ + if (channelCount == fChannelCount) + return; + + delete[] fChannelInfos; + fChannelInfos = new(std::nothrow) ChannelInfo[channelCount]; + if (fChannelInfos != NULL) { + fChannelCount = channelCount; + for (uint32 i = 0; i < fChannelCount; i++) { + fChannelInfos[i].current_max = 0.0f; + fChannelInfos[i].last_max = 0.0f; + fChannelInfos[i].overshot = false; + } + _ResizeBackBitmap(_BackBitmapFrame().IntegerWidth() + 1, + fChannelCount); + } else + fChannelCount = 0; } + +void +PeakView::SetMax(float max, uint32 channel) +{ + if (channel >= fChannelCount) + return; + + if (fChannelInfos[channel].current_max < max) + fChannelInfos[channel].current_max = max; + + if (fChannelInfos[channel].current_max > 1.0) + fChannelInfos[channel].overshot = true; +} + + // #pragma mark - -// _BackBitmapFrame + BRect PeakView::_BackBitmapFrame() const { @@ -315,17 +338,23 @@ PeakView::_BackBitmapFrame() const return frame; } -// _ResizeBackBitmap + void -PeakView::_ResizeBackBitmap(int32 width) +PeakView::_ResizeBackBitmap(int32 width, int32 channels) { - if (fBackBitmap) { - if (fBackBitmap->Bounds().IntegerWidth() + 1 == width) + if (fBackBitmap != NULL) { + if (fBackBitmap->Bounds().IntegerWidth() + 1 == width + && fBackBitmap->Bounds().IntegerHeight() + 1 == channels) { return; + } } + if (channels <= 0) + channels = 2; + delete fBackBitmap; - fBackBitmap = new (nothrow) BBitmap(BRect(0, 0, width - 1, 1), 0, B_RGB32); - if (!fBackBitmap || !fBackBitmap->IsValid()) { + BRect bounds(0, 0, width - 1, channels - 1); + fBackBitmap = new(std::nothrow) BBitmap(bounds, 0, B_RGB32); + if (fBackBitmap == NULL || !fBackBitmap->IsValid()) { delete fBackBitmap; fBackBitmap = NULL; return; @@ -333,21 +362,23 @@ PeakView::_ResizeBackBitmap(int32 width) memset(fBackBitmap->Bits(), 0, fBackBitmap->BitsLength()); } -// _UpdateBackBitmap + void PeakView::_UpdateBackBitmap() { if (!fBackBitmap) return; - uint8* l = (uint8*)fBackBitmap->Bits(); - uint8* r = l + fBackBitmap->BytesPerRow(); + uint8* span = (uint8*)fBackBitmap->Bits(); uint32 width = fBackBitmap->Bounds().IntegerWidth() + 1; - _RenderSpan(l, width, fCurrentMaxL, fLastMaxL, fOvershotL); - _RenderSpan(r, width, fCurrentMaxR, fLastMaxR ,fOvershotR); + for (uint32 i = 0; i < fChannelCount; i++) { + _RenderSpan(span, width, fChannelInfos[i].current_max, + fChannelInfos[i].last_max, fChannelInfos[i].overshot); + span += fBackBitmap->BytesPerRow(); + } } -// _RenderSpan + void PeakView:: _RenderSpan(uint8* span, uint32 width, float current, float peak, bool overshot) @@ -412,20 +443,26 @@ PeakView:: _RenderSpan(uint8* span, uint32 width, float current, float peak, } } -// _DrawBitmap + void PeakView::_DrawBitmap() { - BRect r = _BackBitmapFrame(); - BRect topHalf = r; - topHalf.bottom = (r.top + r.bottom) / 2.0 - 1; - BRect bottomHalf = r; - bottomHalf.top = topHalf.bottom + 2; + SetHighColor(0, 0, 0); + BRect bitmapFrame = _BackBitmapFrame(); BRect bitmapRect = fBackBitmap->Bounds(); bitmapRect.bottom = bitmapRect.top; - DrawBitmapAsync(fBackBitmap, bitmapRect, topHalf); - bitmapRect.OffsetBy(0, 1); - DrawBitmapAsync(fBackBitmap, bitmapRect, bottomHalf); + float channelHeight = (bitmapFrame.Height() + 2) / fChannelCount; + for (uint32 i = 0; i < fChannelCount; i++) { + BRect viewRect(bitmapFrame); + viewRect.top += floorf(i * channelHeight); + viewRect.bottom = viewRect.top + ceilf(channelHeight - 2); + DrawBitmapAsync(fBackBitmap, bitmapRect, viewRect); + if (i < fChannelCount - 1) { + StrokeLine(BPoint(viewRect.left, viewRect.bottom + 1), + BPoint(viewRect.right, viewRect.bottom + 1)); + } + bitmapRect.OffsetBy(0, 1); + } } diff --git a/src/apps/mediaplayer/interface/PeakView.h b/src/apps/mediaplayer/interface/PeakView.h index 224788109f..f591001a7a 100644 --- a/src/apps/mediaplayer/interface/PeakView.h +++ b/src/apps/mediaplayer/interface/PeakView.h @@ -58,16 +58,19 @@ public: bool IsValid() const; void SetPeakRefreshDelay(bigtime_t delay); void SetPeakNotificationWhat(uint32 what); - void SetMax(float maxL, float maxR); - private: + void SetChannelCount(uint32 count); + void SetMax(float max, uint32 channel); + +private: BRect _BackBitmapFrame() const; - void _ResizeBackBitmap(int32 width); + void _ResizeBackBitmap(int32 width, int32 channels); void _UpdateBackBitmap(); void _RenderSpan(uint8* span, uint32 width, float current, float peak, bool overshot); void _DrawBitmap(); +private: bool fUseGlobalPulse; bool fDisplayLabels; bool fPeakLocked; @@ -75,13 +78,14 @@ public: bigtime_t fRefreshDelay; BMessageRunner* fPulse; - float fCurrentMaxL; - float fLastMaxL; - bool fOvershotL; + struct ChannelInfo { + float current_max; + float last_max; + bool overshot; + }; - float fCurrentMaxR; - float fLastMaxR; - bool fOvershotR; + ChannelInfo* fChannelInfos; + uint32 fChannelCount; BBitmap* fBackBitmap; font_height fFontHeight;