1 /*****************************************************************************
2 * MediaControlView.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: MediaControlView.cpp,v 1.3 2002/09/30 18:30:27 titer Exp $
7 * Authors: Tony Castley <tony@castley.net>
8 * Stephan Aßmus <stippi@yellowbites.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
26 #include <InterfaceKit.h>
34 /* BeOS interface headers */
35 #include "VlcWrapper.h"
37 #include "DrawingTidbits.h"
38 #include "InterfaceWindow.h"
40 #include "TransportButton.h"
41 #include "ListViews.h"
42 #include "MediaControlView.h"
44 #define BORDER_INSET 6.0
46 #define SPEAKER_SLIDER_DIST 6.0
47 #define VOLUME_MIN_WIDTH 70.0
49 #define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0
50 #define SEEK_SLIDER_KNOB_WIDTH 8.0
52 // slider colors are hardcoded here, because that's just
53 // what they currently are within those bitmaps
54 const rgb_color kGreen = (rgb_color){ 152, 203, 152, 255 };
55 const rgb_color kGreenShadow = (rgb_color){ 102, 152, 102, 255 };
56 const rgb_color kBackground = (rgb_color){ 216, 216, 216, 255 };
57 const rgb_color kSeekGreen = (rgb_color){ 171, 221, 161, 255 };
58 const rgb_color kSeekGreenShadow = (rgb_color){ 144, 186, 136, 255 };
59 const rgb_color kSeekRed = (rgb_color){ 255, 0, 0, 255 };
60 const rgb_color kSeekRedLight = (rgb_color){ 255, 152, 152, 255 };
61 const rgb_color kSeekRedShadow = (rgb_color){ 178, 0, 0, 255 };
63 const char* kDisabledSeekMessage = "Drop files to play";
69 MSG_SKIP_BACKWARDS = 'skpb',
70 MSG_SKIP_FORWARD = 'skpf',
74 MediaControlView::MediaControlView(BRect frame)
75 : BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
78 fCurrentRate(DEFAULT_RATE),
79 fCurrentStatus(UNDEF_S),
80 fBottomControlHeight(0.0)
82 BRect frame(0.0, 0.0, 10.0, 10.0);
85 fSeekSlider = new SeekSlider(frame, "seek slider", this, 0, 2047);
86 fSeekSlider->SetValue(0);
87 fSeekSlider->ResizeToPreferred();
88 AddChild( fSeekSlider );
92 frame.SetRightBottom(kSkipButtonSize);
93 fBottomControlHeight = kRewindBitmapHeight - 1.0;
94 fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
96 kPressedSkipBackBitmapBits,
97 kDisabledSkipBackBitmapBits,
98 new BMessage(MSG_SKIP_BACKWARDS));
99 AddChild( fSkipBack );
102 frame.SetRightBottom(kPlayButtonSize);
103 if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
104 fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
105 fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
106 kPlayButtonBitmapBits,
107 kPressedPlayButtonBitmapBits,
108 kDisabledPlayButtonBitmapBits,
109 kPlayingPlayButtonBitmapBits,
110 kPressedPlayingPlayButtonBitmapBits,
111 kPausedPlayButtonBitmapBits,
112 kPressedPausedPlayButtonBitmapBits,
113 new BMessage(START_PLAYBACK));
115 AddChild( fPlayPause );
118 frame.SetRightBottom(kSkipButtonSize);
119 fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
120 kSkipForwardBitmapBits,
121 kPressedSkipForwardBitmapBits,
122 kDisabledSkipForwardBitmapBits,
123 new BMessage(MSG_SKIP_FORWARD));
124 AddChild( fSkipForward );
127 fForward = new TransportButton(frame, B_EMPTY_STRING,
129 kPressedForwardBitmapBits,
130 kDisabledForwardBitmapBits,
131 new BMessage(MSG_FORWARD));
132 // AddChild( fForward );
135 fRewind = new TransportButton(frame, B_EMPTY_STRING,
137 kPressedRewindBitmapBits,
138 kDisabledRewindBitmapBits,
139 new BMessage(MSG_REWIND));
140 // AddChild( fRewind );
143 frame.SetRightBottom(kStopButtonSize);
144 if (fBottomControlHeight < kStopBitmapHeight - 1.0)
145 fBottomControlHeight = kStopBitmapHeight - 1.0;
146 fStop = new TransportButton(frame, B_EMPTY_STRING,
147 kStopButtonBitmapBits,
148 kPressedStopButtonBitmapBits,
149 kDisabledStopButtonBitmapBits,
150 new BMessage(STOP_PLAYBACK));
154 frame.SetRightBottom(kSpeakerButtonSize);
155 if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
156 fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
157 fMute = new TransportButton(frame, B_EMPTY_STRING,
159 kPressedSpeakerIconBits,
161 new BMessage(VOLUME_MUTE));
166 fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
167 kVolumeSliderBitmapHeight - 1.0),
168 "volume slider", 1, AOUT_VOLUME_MAX,
169 new BMessage(VOLUME_CHG));
170 fVolumeSlider->SetValue(AOUT_VOLUME_DEFAULT);
171 AddChild( fVolumeSlider );
175 MediaControlView::~MediaControlView()
181 MediaControlView::AttachedToWindow()
183 // we are now a valid BHandler
184 fRewind->SetTarget(this);
185 fForward->SetTarget(this);
186 fSkipBack->SetTarget(this);
187 fSkipForward->SetTarget(this);
188 fVolumeSlider->SetTarget(Window());
190 BRect r(_MinFrame());
191 if (BMenuBar* menuBar = Window()->KeyMenuBar())
192 r.bottom += menuBar->Bounds().Height();
194 Window()->SetSizeLimits(r.Width(), r.Width() * 2.0, r.Height(), r.Height() * 2.0);
195 if (!Window()->Bounds().Contains(r))
196 Window()->ResizeTo(r.Width(), r.Height());
198 FrameResized(Bounds().Width(), Bounds().Height());
200 // get pulse message every two frames
201 Window()->SetPulseRate(80000);
206 MediaControlView::FrameResized(float width, float height)
209 // make sure we don't leave dirty pixels
210 // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
211 if (fOldBounds.Width() < r.Width())
212 Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
213 fOldBounds.right, fOldBounds.bottom - 1.0));
215 Invalidate(BRect(r.right, r.top + 1.0,
216 r.right, r.bottom - 1.0));
217 if (fOldBounds.Height() < r.Height())
218 Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
219 fOldBounds.right - 1.0, fOldBounds.bottom));
221 Invalidate(BRect(r.left + 1.0, r.bottom,
222 r.right - 1.0, r.bottom));
223 // remember for next time
226 r.InsetBy(BORDER_INSET, BORDER_INSET);
232 MediaControlView::GetPreferredSize(float* width, float* height)
236 BRect r(_MinFrame());
238 *height = r.Height();
244 MediaControlView::MessageReceived(BMessage* message)
246 switch (message->what)
252 case MSG_SKIP_BACKWARDS:
253 Window()->PostMessage(NAVIGATE_PREV);
255 case MSG_SKIP_FORWARD:
256 Window()->PostMessage(NAVIGATE_NEXT);
259 BBox::MessageReceived(message);
266 MediaControlView::Pulse()
268 InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
269 if (window && window->IsStopped())
270 fPlayPause->SetStopped();
275 MediaControlView::SetProgress(uint64 seek, uint64 size)
277 fSeekSlider->SetPosition((float)seek / (float)size);
282 MediaControlView::SetStatus(int status, int rate)
284 // we need to set the button status periodically
285 // (even if it is the same) to get a blinking button
286 fCurrentStatus = status;
293 fPlayPause->SetPlaying();
296 fPlayPause->SetPaused();
301 fPlayPause->SetStopped();
304 if (rate != fCurrentRate)
307 if ( rate < DEFAULT_RATE )
316 MediaControlView::SetEnabled(bool enabled)
318 fSkipBack->SetEnabled(enabled);
319 fPlayPause->SetEnabled(enabled);
320 fSkipForward->SetEnabled(enabled);
321 fStop->SetEnabled(enabled);
322 fMute->SetEnabled(enabled);
323 fVolumeSlider->SetEnabled(enabled);
324 fSeekSlider->SetEnabled(enabled);
325 fRewind->SetEnabled(enabled);
326 fForward->SetEnabled(enabled);
331 MediaControlView::SetAudioEnabled(bool enabled)
333 fMute->SetEnabled(enabled);
334 fVolumeSlider->SetEnabled(enabled);
339 MediaControlView::GetSeekTo() const
341 return fSeekSlider->Value();
346 MediaControlView::GetVolume() const
348 return fVolumeSlider->Value();
353 MediaControlView::SetSkippable(bool backward, bool forward)
355 fSkipBack->SetEnabled(backward);
356 fSkipForward->SetEnabled(forward);
361 MediaControlView::SetMuted(bool mute)
363 fVolumeSlider->SetMuted(mute);
368 MediaControlView::_LayoutControls(BRect frame) const
372 r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
373 _LayoutControl(fSeekSlider, r, true);
374 // calculate absolutly minimal width
375 float minWidth = fSkipBack->Bounds().Width();
376 // minWidth += fRewind->Bounds().Width();
377 minWidth += fStop->Bounds().Width();
378 minWidth += fPlayPause->Bounds().Width();
379 // minWidth += fForward->Bounds().Width();
380 minWidth += fSkipForward->Bounds().Width();
381 minWidth += fMute->Bounds().Width();
382 minWidth += VOLUME_MIN_WIDTH;
383 float currentWidth = frame.Width();
384 float space = (currentWidth - minWidth) / 6.0;//8.0;
386 space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
387 // layout controls with "space" inbetween
388 r.top = r.bottom + MIN_SPACE + 1.0;
389 r.bottom = frame.bottom;
391 r.right = r.left + fSkipBack->Bounds().Width();
392 _LayoutControl(fSkipBack, r);
394 // r.left = r.right + space;
395 // r.right = r.left + fRewind->Bounds().Width();
396 // _LayoutControl(fRewind, r);
398 r.left = r.right + space;
399 r.right = r.left + fStop->Bounds().Width();
400 _LayoutControl(fStop, r);
402 r.left = r.right + space;
403 r.right = r.left + fPlayPause->Bounds().Width();
404 _LayoutControl(fPlayPause, r);
406 // r.left = r.right + space;
407 // r.right = r.left + fForward->Bounds().Width();
408 // _LayoutControl(fForward, r);
410 r.left = r.right + space;
411 r.right = r.left + fSkipForward->Bounds().Width();
412 _LayoutControl(fSkipForward, r);
414 r.left = r.right + space + space;
415 r.right = r.left + fMute->Bounds().Width();
416 _LayoutControl(fMute, r);
418 r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
419 r.right = frame.right;
420 _LayoutControl(fVolumeSlider, r, true);
425 MediaControlView::_MinFrame() const
427 // add up width of controls along bottom (seek slider will likely adopt)
428 float minWidth = 2 * BORDER_INSET;
429 minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
430 // minWidth += fRewind->Bounds().Width() + MIN_SPACE;
431 minWidth += fStop->Bounds().Width() + MIN_SPACE;
432 minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
433 // minWidth += fForward->Bounds().Width() + MIN_SPACE;
434 minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
435 minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
436 minWidth += VOLUME_MIN_WIDTH;
438 // add up height of seek slider and heighest control on bottom
439 float minHeight = 2 * BORDER_INSET;
440 minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
441 minHeight += fBottomControlHeight;
442 return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
447 MediaControlView::_LayoutControl(BView* view, BRect frame, bool resize) const
450 frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
452 frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
453 view->MoveTo(frame.LeftTop());
455 view->ResizeTo(frame.Width(), view->Bounds().Height());
460 /*****************************************************************************
462 *****************************************************************************/
463 SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
464 int32 minValue, int32 maxValue)
465 : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
466 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
472 BFont font(be_plain_font);
477 SeekSlider::~SeekSlider()
482 /*****************************************************************************
483 * VolumeSlider::AttachedToWindow
484 *****************************************************************************/
486 SeekSlider::AttachedToWindow()
488 BControl::AttachedToWindow();
489 SetViewColor(B_TRANSPARENT_32_BIT);
492 /*****************************************************************************
494 *****************************************************************************/
496 SeekSlider::Draw(BRect updateRect)
499 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
500 float sliderStart = (r.left + knobWidth2);
501 float sliderEnd = (r.right - knobWidth2);
502 float knobPos = sliderStart
503 + floorf((sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
504 / (fMaxValue - fMinValue) + 0.5);
505 // draw both sides (the original from Be doesn't seem
506 // to make a difference for enabled/disabled state)
507 // DrawBitmapAsync(fLeftSideBits, r.LeftTop());
508 // DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
509 // colors for the slider area between the two bitmaps
510 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
511 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
512 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
513 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
514 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
515 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
516 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
517 rgb_color green = kSeekGreen;
518 rgb_color greenShadow = kSeekGreenShadow;
519 rgb_color black = kBlack;
520 rgb_color dotGrey = midShadow;
521 rgb_color dotGreen = greenShadow;
523 _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
525 _StrokeFrame(r, black, black, light, light);
530 _StrokeFrame(r, greenShadow, greenShadow, green, green);
533 _StrokeFrame(r, greenShadow, greenShadow, green, green);
539 int32 dotCount = (int32)(r.Width() / 6.0);
541 dotPos.y = r.top + 2.0;
542 SetHighColor(dotGreen);
543 for (int32 i = 0; i < dotCount; i++)
545 dotPos.x = sliderStart + i * 6.0 + 5.0;
546 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
551 r.left = knobPos - knobWidth2;
552 r.right = knobPos + knobWidth2;
554 float handleBottomSize = 2.0;
555 float handleArrowSize = 6.0;
558 AddLine(BPoint(r.left, r.top + handleBottomSize),
559 BPoint(r.left, r.top), black);
560 AddLine(BPoint(r.left + 1.0, r.top),
561 BPoint(r.right, r.top), black);
562 AddLine(BPoint(r.right, r.top + 1.0),
563 BPoint(r.right, r.top + handleBottomSize), black);
564 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
565 BPoint(knobPos, r.top + handleArrowSize), black);
566 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
567 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
569 AddLine(BPoint(r.left, r.bottom),
570 BPoint(r.left, r.bottom - handleBottomSize), black);
571 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
572 BPoint(knobPos, r.bottom - handleArrowSize), black);
573 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
574 BPoint(r.right, r.bottom - handleBottomSize), black);
575 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
576 BPoint(r.right, r.bottom), black);
577 AddLine(BPoint(r.right - 1.0, r.bottom),
578 BPoint(r.left + 1.0, r.bottom), black);
580 // inner red light and shadow lines
583 handleArrowSize -= 2.0;
586 AddLine(BPoint(r.left, r.top + handleBottomSize),
587 BPoint(r.left, r.top), kSeekRedLight);
588 AddLine(BPoint(r.left + 1.0, r.top),
589 BPoint(r.right, r.top), kSeekRedLight);
590 AddLine(BPoint(r.right, r.top + 1.0),
591 BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
592 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
593 BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
594 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
595 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
597 AddLine(BPoint(r.left, r.bottom),
598 BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
599 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
600 BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
601 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
602 BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
603 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
604 BPoint(r.right, r.bottom), kSeekRedShadow);
605 AddLine(BPoint(r.right - 1.0, r.bottom),
606 BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
608 // fill rest of handles with red
609 SetHighColor(kSeekRed);
611 handleArrowSize -= 2.0;
613 // upper handle arrow
616 arrow[1].x = r.right;
618 arrow[2].x = knobPos;
619 arrow[2].y = r.top + handleArrowSize;
620 FillPolygon(arrow, 3);
621 // lower handle arrow
623 arrow[0].y = r.bottom;
624 arrow[1].x = r.right;
625 arrow[1].y = r.bottom;
626 arrow[2].x = knobPos;
627 arrow[2].y = r.bottom - handleArrowSize;
628 FillPolygon(arrow, 3);
633 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
635 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
637 SetHighColor(darkShadow);
640 float width = floorf(StringWidth(kDisabledSeekMessage));
641 float textPos = r.left + r.Width() / 2.0 - width / 2.0;
642 pattern stripes = { 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 };
643 BRect stripesRect(r);
644 stripesRect.right = textPos - 5.0;
645 FillRect(stripesRect, stripes);
646 stripesRect.left = textPos + width + 3.0;
647 stripesRect.right = r.right;
648 FillRect(stripesRect, stripes);
650 r.left = textPos - 4.0;
651 r.right = textPos + width + 2.0;
653 SetHighColor(shadow);
654 SetLowColor(darkShadow);
657 DrawString(kDisabledSeekMessage, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
661 /*****************************************************************************
662 * SeekSlider::MouseDown
663 *****************************************************************************/
665 SeekSlider::MouseDown(BPoint where)
667 if (IsEnabled() && Bounds().Contains(where))
669 SetValue(_ValueFor(where.x));
671 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
676 /*****************************************************************************
677 * SeekSlider::MouseMoved
678 *****************************************************************************/
680 SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
684 SetValue(_ValueFor(where.x));
689 /*****************************************************************************
690 * SeekSlider::MouseUp
691 *****************************************************************************/
693 SeekSlider::MouseUp(BPoint where)
702 /*****************************************************************************
703 * SeekSlider::ResizeToPreferred
704 *****************************************************************************/
706 SeekSlider::ResizeToPreferred()
708 float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
709 ResizeTo(width, 17.0);
712 /*****************************************************************************
713 * SeekSlider::SetPosition
714 *****************************************************************************/
716 SeekSlider::SetPosition(float position)
718 SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
721 /*****************************************************************************
722 * SeekSlider::_ValueFor
723 *****************************************************************************/
725 SeekSlider::_ValueFor(float xPos) const
728 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
729 float sliderStart = (r.left + knobWidth2);
730 float sliderEnd = (r.right - knobWidth2);
731 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
732 / (sliderEnd - sliderStart - 1.0));
733 if (value < fMinValue)
735 if (value > fMaxValue)
740 /*****************************************************************************
741 * SeekSlider::_StrokeFrame
742 *****************************************************************************/
744 SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
745 rgb_color right, rgb_color bottom)
748 AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
749 AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
750 AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
751 AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
755 /*****************************************************************************
756 * SeekSlider::_BeginSeek
757 *****************************************************************************/
759 SeekSlider::_BeginSeek()
761 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
762 if (fOwner->fScrubSem >= B_OK)
763 release_sem(fOwner->fScrubSem);
766 /*****************************************************************************
768 *****************************************************************************/
772 if (fOwner->fScrubSem >= B_OK)
773 delete_sem(fOwner->fScrubSem);
774 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
775 if (fOwner->fScrubSem >= B_OK)
776 release_sem(fOwner->fScrubSem);
779 /*****************************************************************************
780 * SeekSlider::_EndSeek
781 *****************************************************************************/
783 SeekSlider::_EndSeek()
785 if (fOwner->fScrubSem >= B_OK)
786 delete_sem(fOwner->fScrubSem);
787 fOwner->fScrubSem = B_ERROR;
791 /*****************************************************************************
793 *****************************************************************************/
794 VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
795 BMessage* message, BHandler* target)
796 : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
797 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
799 fRightSideBits(NULL),
809 BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
810 fLeftSideBits = new BBitmap(r, B_CMAP8);
811 fRightSideBits = new BBitmap(r, B_CMAP8);
812 r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
813 fKnobBits = new BBitmap(r, B_CMAP8);
818 /*****************************************************************************
819 * VolumeSlider destructor
820 *****************************************************************************/
821 VolumeSlider::~VolumeSlider()
823 delete fLeftSideBits;
824 delete fRightSideBits;
828 /*****************************************************************************
829 * VolumeSlider::AttachedToWindow
830 *****************************************************************************/
832 VolumeSlider::AttachedToWindow()
834 BControl::AttachedToWindow();
835 SetViewColor(B_TRANSPARENT_32_BIT);
838 /*****************************************************************************
839 * VolumeSlider::SetValue
840 *****************************************************************************/
842 VolumeSlider::SetValue(int32 value)
844 if (value != Value())
846 BControl::SetValue(value);
851 /*****************************************************************************
852 * VolumeSlider::SetEnabled
853 *****************************************************************************/
855 VolumeSlider::SetEnabled(bool enable)
857 if (enable != IsEnabled())
859 BControl::SetEnabled(enable);
865 /*****************************************************************************
867 *****************************************************************************/
869 VolumeSlider::Draw(BRect updateRect)
874 float sliderSideWidth = kVolumeSliderBitmapWidth;
875 float sliderStart = (r.left + sliderSideWidth);
876 float sliderEnd = (r.right - sliderSideWidth);
877 float knobPos = sliderStart
878 + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
879 / (fMaxValue - fMinValue);
880 // draw both sides (the original from Be doesn't seem
881 // to make a difference for enabled/disabled state)
882 DrawBitmapAsync(fLeftSideBits, r.LeftTop());
883 DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
884 // colors for the slider area between the two bitmaps
885 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
886 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
887 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
888 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
889 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
890 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
891 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
892 rgb_color green = kGreen;
893 rgb_color greenShadow = kGreenShadow;
894 rgb_color black = kBlack;
895 rgb_color dotGrey = midShadow;
896 rgb_color dotGreen = greenShadow;
897 // make dimmed version of colors if we're disabled
900 shadow = (rgb_color){ 200, 200, 200, 255 };
901 softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
902 darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
904 light = dimmed_color_cmap8(light, background, DIM_LEVEL);
905 softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
906 green = dimmed_color_cmap8(green, background, DIM_LEVEL);
907 greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
908 black = dimmed_color_cmap8(black, background, DIM_LEVEL);
913 green = tint_color(kBackground, B_DARKEN_3_TINT);
914 greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
915 dotGreen = greenShadow;
917 // draw slider edges between bitmaps
919 AddLine(BPoint(sliderStart, r.top),
920 BPoint(sliderEnd, r.top), softShadow);
921 AddLine(BPoint(sliderStart, r.bottom),
922 BPoint(sliderEnd, r.bottom), softLight);
924 AddLine(BPoint(sliderStart, r.top),
925 BPoint(sliderEnd, r.top), black);
926 AddLine(BPoint(sliderStart, r.bottom),
927 BPoint(sliderEnd, r.bottom), light);
929 AddLine(BPoint(sliderStart, r.top),
930 BPoint(knobPos, r.top), greenShadow);
931 AddLine(BPoint(knobPos, r.top),
932 BPoint(sliderEnd, r.top), midShadow);
934 AddLine(BPoint(sliderStart, r.top),
935 BPoint(knobPos, r.top), greenShadow);
937 // fill rest inside of slider
939 r.left = sliderStart;
942 FillRect(r, B_SOLID_HIGH);
943 r.left = knobPos + 1.0;
946 SetHighColor(shadow);
947 FillRect(r, B_SOLID_HIGH);
948 // draw little dots inside
949 int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
951 dotPos.y = r.top + 4.0;
952 for (int32 i = 0; i < dotCount; i++)
954 dotPos.x = sliderStart + i * 5.0 + 4.0;
955 SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
956 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
960 SetDrawingMode(B_OP_OVER); // part of knob is transparent
961 DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
964 fprintf(stderr, "VolumeSlider::Draw() - Error: no valid bitmaps!");
967 /*****************************************************************************
968 * VolumeSlider::MouseDown
969 *****************************************************************************/
971 VolumeSlider::MouseDown(BPoint where)
973 if (Bounds().Contains(where) && IsEnabled())
976 SetValue(_ValueFor(where.x));
977 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
981 /*****************************************************************************
982 * VolumeSlider::MouseMoved
983 *****************************************************************************/
985 VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
988 SetValue(_ValueFor(where.x));
991 /*****************************************************************************
992 * VolumeSlider::MouseUp
993 *****************************************************************************/
995 VolumeSlider::MouseUp(BPoint where)
1001 /*****************************************************************************
1002 * VolumeSlider::IsValid
1003 *****************************************************************************/
1005 VolumeSlider::IsValid() const
1007 return (fLeftSideBits && fLeftSideBits->IsValid()
1008 && fRightSideBits && fRightSideBits->IsValid()
1009 && fKnobBits && fKnobBits->IsValid());
1012 /*****************************************************************************
1013 * VolumeSlider::SetMuted
1014 *****************************************************************************/
1016 VolumeSlider::SetMuted(bool mute)
1026 /*****************************************************************************
1027 * VolumeSlider::_MakeBitmaps
1028 *****************************************************************************/
1030 VolumeSlider::_MakeBitmaps()
1034 // left side of slider
1035 memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
1036 fLeftSideBits->BitsLength());
1037 // right side of slider
1038 memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
1039 fRightSideBits->BitsLength());
1041 int32 length = fKnobBits->BitsLength();
1042 memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
1043 uint8* bits = (uint8*)fKnobBits->Bits();
1044 // black was used in the knob to represent transparency
1045 // use screen to get index for the "transarent" color used in the bitmap
1046 BScreen screen(B_MAIN_SCREEN_ID);
1047 uint8 blackIndex = screen.IndexForColor(kBlack);
1048 // replace black index with transparent index
1049 for (int32 i = 0; i < length; i++)
1050 if (bits[i] == blackIndex)
1051 bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
1055 // make ghosted versions of the bitmaps
1056 dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
1057 dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
1058 dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
1062 // replace green color (and shadow) in left slider side
1063 bits = (uint8*)fLeftSideBits->Bits();
1064 length = fLeftSideBits->BitsLength();
1065 uint8 greenIndex = screen.IndexForColor(kGreen);
1066 uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
1067 rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
1068 rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
1069 uint8 replaceIndex = screen.IndexForColor(shadow);
1070 uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
1071 for (int32 i = 0; i < length; i++)
1073 if (bits[i] == greenIndex)
1074 bits[i] = replaceIndex;
1075 else if (bits[i] == greenShadowIndex)
1076 bits[i] = replaceShadowIndex;
1082 /*****************************************************************************
1083 * VolumeSlider::_ValueFor
1084 *****************************************************************************/
1086 VolumeSlider::_ValueFor(float xPos) const
1089 float sliderStart = (r.left + kVolumeSliderBitmapWidth);
1090 float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
1091 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
1092 / (sliderEnd - sliderStart - 1.0));
1093 if (value < fMinValue)
1095 if (value > fMaxValue)