1 /*****************************************************************************
2 * MediaControlView.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: MediaControlView.cpp,v 1.4 2002/10/14 20:09:17 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,
86 0, SEEKSLIDER_RANGE - 1);
87 fSeekSlider->SetValue(0);
88 fSeekSlider->ResizeToPreferred();
89 AddChild( fSeekSlider );
93 frame.SetRightBottom(kSkipButtonSize);
94 fBottomControlHeight = kRewindBitmapHeight - 1.0;
95 fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
97 kPressedSkipBackBitmapBits,
98 kDisabledSkipBackBitmapBits,
99 new BMessage(MSG_SKIP_BACKWARDS));
100 AddChild( fSkipBack );
103 frame.SetRightBottom(kPlayButtonSize);
104 if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
105 fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
106 fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
107 kPlayButtonBitmapBits,
108 kPressedPlayButtonBitmapBits,
109 kDisabledPlayButtonBitmapBits,
110 kPlayingPlayButtonBitmapBits,
111 kPressedPlayingPlayButtonBitmapBits,
112 kPausedPlayButtonBitmapBits,
113 kPressedPausedPlayButtonBitmapBits,
114 new BMessage(START_PLAYBACK));
116 AddChild( fPlayPause );
119 frame.SetRightBottom(kSkipButtonSize);
120 fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
121 kSkipForwardBitmapBits,
122 kPressedSkipForwardBitmapBits,
123 kDisabledSkipForwardBitmapBits,
124 new BMessage(MSG_SKIP_FORWARD));
125 AddChild( fSkipForward );
128 fForward = new TransportButton(frame, B_EMPTY_STRING,
130 kPressedForwardBitmapBits,
131 kDisabledForwardBitmapBits,
132 new BMessage(MSG_FORWARD));
133 // AddChild( fForward );
136 fRewind = new TransportButton(frame, B_EMPTY_STRING,
138 kPressedRewindBitmapBits,
139 kDisabledRewindBitmapBits,
140 new BMessage(MSG_REWIND));
141 // AddChild( fRewind );
144 frame.SetRightBottom(kStopButtonSize);
145 if (fBottomControlHeight < kStopBitmapHeight - 1.0)
146 fBottomControlHeight = kStopBitmapHeight - 1.0;
147 fStop = new TransportButton(frame, B_EMPTY_STRING,
148 kStopButtonBitmapBits,
149 kPressedStopButtonBitmapBits,
150 kDisabledStopButtonBitmapBits,
151 new BMessage(STOP_PLAYBACK));
155 frame.SetRightBottom(kSpeakerButtonSize);
156 if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
157 fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
158 fMute = new TransportButton(frame, B_EMPTY_STRING,
160 kPressedSpeakerIconBits,
162 new BMessage(VOLUME_MUTE));
167 fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
168 kVolumeSliderBitmapHeight - 1.0),
169 "volume slider", 1, AOUT_VOLUME_MAX,
170 new BMessage(VOLUME_CHG));
171 fVolumeSlider->SetValue(AOUT_VOLUME_DEFAULT);
172 AddChild( fVolumeSlider );
176 MediaControlView::~MediaControlView()
182 MediaControlView::AttachedToWindow()
184 // we are now a valid BHandler
185 fRewind->SetTarget(this);
186 fForward->SetTarget(this);
187 fSkipBack->SetTarget(this);
188 fSkipForward->SetTarget(this);
189 fVolumeSlider->SetTarget(Window());
191 BRect r(_MinFrame());
192 if (BMenuBar* menuBar = Window()->KeyMenuBar())
193 r.bottom += menuBar->Bounds().Height();
195 Window()->SetSizeLimits(r.Width(), r.Width() * 2.0, r.Height(), r.Height() * 2.0);
196 if (!Window()->Bounds().Contains(r))
197 Window()->ResizeTo(r.Width(), r.Height());
199 FrameResized(Bounds().Width(), Bounds().Height());
201 // get pulse message every two frames
202 Window()->SetPulseRate(80000);
207 MediaControlView::FrameResized(float width, float height)
210 // make sure we don't leave dirty pixels
211 // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
212 if (fOldBounds.Width() < r.Width())
213 Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
214 fOldBounds.right, fOldBounds.bottom - 1.0));
216 Invalidate(BRect(r.right, r.top + 1.0,
217 r.right, r.bottom - 1.0));
218 if (fOldBounds.Height() < r.Height())
219 Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
220 fOldBounds.right - 1.0, fOldBounds.bottom));
222 Invalidate(BRect(r.left + 1.0, r.bottom,
223 r.right - 1.0, r.bottom));
224 // remember for next time
227 r.InsetBy(BORDER_INSET, BORDER_INSET);
233 MediaControlView::GetPreferredSize(float* width, float* height)
237 BRect r(_MinFrame());
239 *height = r.Height();
245 MediaControlView::MessageReceived(BMessage* message)
247 switch (message->what)
253 case MSG_SKIP_BACKWARDS:
254 Window()->PostMessage(NAVIGATE_PREV);
256 case MSG_SKIP_FORWARD:
257 Window()->PostMessage(NAVIGATE_NEXT);
260 BBox::MessageReceived(message);
267 MediaControlView::Pulse()
269 InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
270 if (window && window->IsStopped())
271 fPlayPause->SetStopped();
276 MediaControlView::SetProgress(uint64 seek, uint64 size)
278 fSeekSlider->SetPosition((float)seek / (float)size);
283 MediaControlView::SetStatus(int status, int rate)
285 // we need to set the button status periodically
286 // (even if it is the same) to get a blinking button
287 fCurrentStatus = status;
294 fPlayPause->SetPlaying();
297 fPlayPause->SetPaused();
302 fPlayPause->SetStopped();
305 if (rate != fCurrentRate)
308 if ( rate < DEFAULT_RATE )
317 MediaControlView::SetEnabled(bool enabled)
319 fSkipBack->SetEnabled(enabled);
320 fPlayPause->SetEnabled(enabled);
321 fSkipForward->SetEnabled(enabled);
322 fStop->SetEnabled(enabled);
323 fMute->SetEnabled(enabled);
324 fVolumeSlider->SetEnabled(enabled);
325 fSeekSlider->SetEnabled(enabled);
326 fRewind->SetEnabled(enabled);
327 fForward->SetEnabled(enabled);
332 MediaControlView::SetAudioEnabled(bool enabled)
334 fMute->SetEnabled(enabled);
335 fVolumeSlider->SetEnabled(enabled);
340 MediaControlView::GetSeekTo() const
342 return fSeekSlider->Value();
347 MediaControlView::GetVolume() const
349 return fVolumeSlider->Value();
354 MediaControlView::SetSkippable(bool backward, bool forward)
356 fSkipBack->SetEnabled(backward);
357 fSkipForward->SetEnabled(forward);
362 MediaControlView::SetMuted(bool mute)
364 fVolumeSlider->SetMuted(mute);
369 MediaControlView::_LayoutControls(BRect frame) const
373 r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
374 _LayoutControl(fSeekSlider, r, true);
375 // calculate absolutly minimal width
376 float minWidth = fSkipBack->Bounds().Width();
377 // minWidth += fRewind->Bounds().Width();
378 minWidth += fStop->Bounds().Width();
379 minWidth += fPlayPause->Bounds().Width();
380 // minWidth += fForward->Bounds().Width();
381 minWidth += fSkipForward->Bounds().Width();
382 minWidth += fMute->Bounds().Width();
383 minWidth += VOLUME_MIN_WIDTH;
384 float currentWidth = frame.Width();
385 float space = (currentWidth - minWidth) / 6.0;//8.0;
387 space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
388 // layout controls with "space" inbetween
389 r.top = r.bottom + MIN_SPACE + 1.0;
390 r.bottom = frame.bottom;
392 r.right = r.left + fSkipBack->Bounds().Width();
393 _LayoutControl(fSkipBack, r);
395 // r.left = r.right + space;
396 // r.right = r.left + fRewind->Bounds().Width();
397 // _LayoutControl(fRewind, r);
399 r.left = r.right + space;
400 r.right = r.left + fStop->Bounds().Width();
401 _LayoutControl(fStop, r);
403 r.left = r.right + space;
404 r.right = r.left + fPlayPause->Bounds().Width();
405 _LayoutControl(fPlayPause, r);
407 // r.left = r.right + space;
408 // r.right = r.left + fForward->Bounds().Width();
409 // _LayoutControl(fForward, r);
411 r.left = r.right + space;
412 r.right = r.left + fSkipForward->Bounds().Width();
413 _LayoutControl(fSkipForward, r);
415 r.left = r.right + space + space;
416 r.right = r.left + fMute->Bounds().Width();
417 _LayoutControl(fMute, r);
419 r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
420 r.right = frame.right;
421 _LayoutControl(fVolumeSlider, r, true);
426 MediaControlView::_MinFrame() const
428 // add up width of controls along bottom (seek slider will likely adopt)
429 float minWidth = 2 * BORDER_INSET;
430 minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
431 // minWidth += fRewind->Bounds().Width() + MIN_SPACE;
432 minWidth += fStop->Bounds().Width() + MIN_SPACE;
433 minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
434 // minWidth += fForward->Bounds().Width() + MIN_SPACE;
435 minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
436 minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
437 minWidth += VOLUME_MIN_WIDTH;
439 // add up height of seek slider and heighest control on bottom
440 float minHeight = 2 * BORDER_INSET;
441 minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
442 minHeight += fBottomControlHeight;
443 return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
448 MediaControlView::_LayoutControl(BView* view, BRect frame, bool resize) const
451 frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
453 frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
454 view->MoveTo(frame.LeftTop());
456 view->ResizeTo(frame.Width(), view->Bounds().Height());
461 /*****************************************************************************
463 *****************************************************************************/
464 SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
465 int32 minValue, int32 maxValue)
466 : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
467 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
473 BFont font(be_plain_font);
478 SeekSlider::~SeekSlider()
483 /*****************************************************************************
484 * VolumeSlider::AttachedToWindow
485 *****************************************************************************/
487 SeekSlider::AttachedToWindow()
489 BControl::AttachedToWindow();
490 SetViewColor(B_TRANSPARENT_32_BIT);
493 /*****************************************************************************
495 *****************************************************************************/
497 SeekSlider::Draw(BRect updateRect)
500 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
501 float sliderStart = (r.left + knobWidth2);
502 float sliderEnd = (r.right - knobWidth2);
503 float knobPos = sliderStart
504 + floorf((sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
505 / (fMaxValue - fMinValue) + 0.5);
506 // draw both sides (the original from Be doesn't seem
507 // to make a difference for enabled/disabled state)
508 // DrawBitmapAsync(fLeftSideBits, r.LeftTop());
509 // DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
510 // colors for the slider area between the two bitmaps
511 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
512 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
513 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
514 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
515 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
516 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
517 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
518 rgb_color green = kSeekGreen;
519 rgb_color greenShadow = kSeekGreenShadow;
520 rgb_color black = kBlack;
521 rgb_color dotGrey = midShadow;
522 rgb_color dotGreen = greenShadow;
524 _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
526 _StrokeFrame(r, black, black, light, light);
531 _StrokeFrame(r, greenShadow, greenShadow, green, green);
534 _StrokeFrame(r, greenShadow, greenShadow, green, green);
540 int32 dotCount = (int32)(r.Width() / 6.0);
542 dotPos.y = r.top + 2.0;
543 SetHighColor(dotGreen);
544 for (int32 i = 0; i < dotCount; i++)
546 dotPos.x = sliderStart + i * 6.0 + 5.0;
547 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
552 r.left = knobPos - knobWidth2;
553 r.right = knobPos + knobWidth2;
555 float handleBottomSize = 2.0;
556 float handleArrowSize = 6.0;
559 AddLine(BPoint(r.left, r.top + handleBottomSize),
560 BPoint(r.left, r.top), black);
561 AddLine(BPoint(r.left + 1.0, r.top),
562 BPoint(r.right, r.top), black);
563 AddLine(BPoint(r.right, r.top + 1.0),
564 BPoint(r.right, r.top + handleBottomSize), black);
565 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
566 BPoint(knobPos, r.top + handleArrowSize), black);
567 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
568 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
570 AddLine(BPoint(r.left, r.bottom),
571 BPoint(r.left, r.bottom - handleBottomSize), black);
572 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
573 BPoint(knobPos, r.bottom - handleArrowSize), black);
574 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
575 BPoint(r.right, r.bottom - handleBottomSize), black);
576 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
577 BPoint(r.right, r.bottom), black);
578 AddLine(BPoint(r.right - 1.0, r.bottom),
579 BPoint(r.left + 1.0, r.bottom), black);
581 // inner red light and shadow lines
584 handleArrowSize -= 2.0;
587 AddLine(BPoint(r.left, r.top + handleBottomSize),
588 BPoint(r.left, r.top), kSeekRedLight);
589 AddLine(BPoint(r.left + 1.0, r.top),
590 BPoint(r.right, r.top), kSeekRedLight);
591 AddLine(BPoint(r.right, r.top + 1.0),
592 BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
593 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
594 BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
595 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
596 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
598 AddLine(BPoint(r.left, r.bottom),
599 BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
600 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
601 BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
602 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
603 BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
604 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
605 BPoint(r.right, r.bottom), kSeekRedShadow);
606 AddLine(BPoint(r.right - 1.0, r.bottom),
607 BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
609 // fill rest of handles with red
610 SetHighColor(kSeekRed);
612 handleArrowSize -= 2.0;
614 // upper handle arrow
617 arrow[1].x = r.right;
619 arrow[2].x = knobPos;
620 arrow[2].y = r.top + handleArrowSize;
621 FillPolygon(arrow, 3);
622 // lower handle arrow
624 arrow[0].y = r.bottom;
625 arrow[1].x = r.right;
626 arrow[1].y = r.bottom;
627 arrow[2].x = knobPos;
628 arrow[2].y = r.bottom - handleArrowSize;
629 FillPolygon(arrow, 3);
634 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
636 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
638 SetHighColor(darkShadow);
641 float width = floorf(StringWidth(kDisabledSeekMessage));
642 float textPos = r.left + r.Width() / 2.0 - width / 2.0;
643 pattern stripes = { 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 };
644 BRect stripesRect(r);
645 stripesRect.right = textPos - 5.0;
646 FillRect(stripesRect, stripes);
647 stripesRect.left = textPos + width + 3.0;
648 stripesRect.right = r.right;
649 FillRect(stripesRect, stripes);
651 r.left = textPos - 4.0;
652 r.right = textPos + width + 2.0;
654 SetHighColor(shadow);
655 SetLowColor(darkShadow);
658 DrawString(kDisabledSeekMessage, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
662 /*****************************************************************************
663 * SeekSlider::MouseDown
664 *****************************************************************************/
666 SeekSlider::MouseDown(BPoint where)
668 if (IsEnabled() && Bounds().Contains(where))
670 SetValue(_ValueFor(where.x));
672 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
677 /*****************************************************************************
678 * SeekSlider::MouseMoved
679 *****************************************************************************/
681 SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
685 SetValue(_ValueFor(where.x));
690 /*****************************************************************************
691 * SeekSlider::MouseUp
692 *****************************************************************************/
694 SeekSlider::MouseUp(BPoint where)
703 /*****************************************************************************
704 * SeekSlider::ResizeToPreferred
705 *****************************************************************************/
707 SeekSlider::ResizeToPreferred()
709 float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
710 ResizeTo(width, 17.0);
713 /*****************************************************************************
714 * SeekSlider::SetPosition
715 *****************************************************************************/
717 SeekSlider::SetPosition(float position)
719 SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
722 /*****************************************************************************
723 * SeekSlider::_ValueFor
724 *****************************************************************************/
726 SeekSlider::_ValueFor(float xPos) const
729 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
730 float sliderStart = (r.left + knobWidth2);
731 float sliderEnd = (r.right - knobWidth2);
732 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
733 / (sliderEnd - sliderStart - 1.0));
734 if (value < fMinValue)
736 if (value > fMaxValue)
741 /*****************************************************************************
742 * SeekSlider::_StrokeFrame
743 *****************************************************************************/
745 SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
746 rgb_color right, rgb_color bottom)
749 AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
750 AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
751 AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
752 AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
756 /*****************************************************************************
757 * SeekSlider::_BeginSeek
758 *****************************************************************************/
760 SeekSlider::_BeginSeek()
762 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
763 if (fOwner->fScrubSem >= B_OK)
764 release_sem(fOwner->fScrubSem);
767 /*****************************************************************************
769 *****************************************************************************/
773 if (fOwner->fScrubSem >= B_OK)
774 delete_sem(fOwner->fScrubSem);
775 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
776 if (fOwner->fScrubSem >= B_OK)
777 release_sem(fOwner->fScrubSem);
780 /*****************************************************************************
781 * SeekSlider::_EndSeek
782 *****************************************************************************/
784 SeekSlider::_EndSeek()
786 if (fOwner->fScrubSem >= B_OK)
787 delete_sem(fOwner->fScrubSem);
788 fOwner->fScrubSem = B_ERROR;
792 /*****************************************************************************
794 *****************************************************************************/
795 VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
796 BMessage* message, BHandler* target)
797 : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
798 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
800 fRightSideBits(NULL),
810 BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
811 fLeftSideBits = new BBitmap(r, B_CMAP8);
812 fRightSideBits = new BBitmap(r, B_CMAP8);
813 r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
814 fKnobBits = new BBitmap(r, B_CMAP8);
819 /*****************************************************************************
820 * VolumeSlider destructor
821 *****************************************************************************/
822 VolumeSlider::~VolumeSlider()
824 delete fLeftSideBits;
825 delete fRightSideBits;
829 /*****************************************************************************
830 * VolumeSlider::AttachedToWindow
831 *****************************************************************************/
833 VolumeSlider::AttachedToWindow()
835 BControl::AttachedToWindow();
836 SetViewColor(B_TRANSPARENT_32_BIT);
839 /*****************************************************************************
840 * VolumeSlider::SetValue
841 *****************************************************************************/
843 VolumeSlider::SetValue(int32 value)
845 if (value != Value())
847 BControl::SetValue(value);
852 /*****************************************************************************
853 * VolumeSlider::SetEnabled
854 *****************************************************************************/
856 VolumeSlider::SetEnabled(bool enable)
858 if (enable != IsEnabled())
860 BControl::SetEnabled(enable);
866 /*****************************************************************************
868 *****************************************************************************/
870 VolumeSlider::Draw(BRect updateRect)
875 float sliderSideWidth = kVolumeSliderBitmapWidth;
876 float sliderStart = (r.left + sliderSideWidth);
877 float sliderEnd = (r.right - sliderSideWidth);
878 float knobPos = sliderStart
879 + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
880 / (fMaxValue - fMinValue);
881 // draw both sides (the original from Be doesn't seem
882 // to make a difference for enabled/disabled state)
883 DrawBitmapAsync(fLeftSideBits, r.LeftTop());
884 DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
885 // colors for the slider area between the two bitmaps
886 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
887 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
888 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
889 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
890 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
891 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
892 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
893 rgb_color green = kGreen;
894 rgb_color greenShadow = kGreenShadow;
895 rgb_color black = kBlack;
896 rgb_color dotGrey = midShadow;
897 rgb_color dotGreen = greenShadow;
898 // make dimmed version of colors if we're disabled
901 shadow = (rgb_color){ 200, 200, 200, 255 };
902 softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
903 darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
905 light = dimmed_color_cmap8(light, background, DIM_LEVEL);
906 softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
907 green = dimmed_color_cmap8(green, background, DIM_LEVEL);
908 greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
909 black = dimmed_color_cmap8(black, background, DIM_LEVEL);
914 green = tint_color(kBackground, B_DARKEN_3_TINT);
915 greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
916 dotGreen = greenShadow;
918 // draw slider edges between bitmaps
920 AddLine(BPoint(sliderStart, r.top),
921 BPoint(sliderEnd, r.top), softShadow);
922 AddLine(BPoint(sliderStart, r.bottom),
923 BPoint(sliderEnd, r.bottom), softLight);
925 AddLine(BPoint(sliderStart, r.top),
926 BPoint(sliderEnd, r.top), black);
927 AddLine(BPoint(sliderStart, r.bottom),
928 BPoint(sliderEnd, r.bottom), light);
930 AddLine(BPoint(sliderStart, r.top),
931 BPoint(knobPos, r.top), greenShadow);
932 AddLine(BPoint(knobPos, r.top),
933 BPoint(sliderEnd, r.top), midShadow);
935 AddLine(BPoint(sliderStart, r.top),
936 BPoint(knobPos, r.top), greenShadow);
938 // fill rest inside of slider
940 r.left = sliderStart;
943 FillRect(r, B_SOLID_HIGH);
944 r.left = knobPos + 1.0;
947 SetHighColor(shadow);
948 FillRect(r, B_SOLID_HIGH);
949 // draw little dots inside
950 int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
952 dotPos.y = r.top + 4.0;
953 for (int32 i = 0; i < dotCount; i++)
955 dotPos.x = sliderStart + i * 5.0 + 4.0;
956 SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
957 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
961 SetDrawingMode(B_OP_OVER); // part of knob is transparent
962 DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
965 fprintf(stderr, "VolumeSlider::Draw() - Error: no valid bitmaps!");
968 /*****************************************************************************
969 * VolumeSlider::MouseDown
970 *****************************************************************************/
972 VolumeSlider::MouseDown(BPoint where)
974 if (Bounds().Contains(where) && IsEnabled())
977 SetValue(_ValueFor(where.x));
978 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
982 /*****************************************************************************
983 * VolumeSlider::MouseMoved
984 *****************************************************************************/
986 VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
989 SetValue(_ValueFor(where.x));
992 /*****************************************************************************
993 * VolumeSlider::MouseUp
994 *****************************************************************************/
996 VolumeSlider::MouseUp(BPoint where)
1002 /*****************************************************************************
1003 * VolumeSlider::IsValid
1004 *****************************************************************************/
1006 VolumeSlider::IsValid() const
1008 return (fLeftSideBits && fLeftSideBits->IsValid()
1009 && fRightSideBits && fRightSideBits->IsValid()
1010 && fKnobBits && fKnobBits->IsValid());
1013 /*****************************************************************************
1014 * VolumeSlider::SetMuted
1015 *****************************************************************************/
1017 VolumeSlider::SetMuted(bool mute)
1027 /*****************************************************************************
1028 * VolumeSlider::_MakeBitmaps
1029 *****************************************************************************/
1031 VolumeSlider::_MakeBitmaps()
1035 // left side of slider
1036 memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
1037 fLeftSideBits->BitsLength());
1038 // right side of slider
1039 memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
1040 fRightSideBits->BitsLength());
1042 int32 length = fKnobBits->BitsLength();
1043 memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
1044 uint8* bits = (uint8*)fKnobBits->Bits();
1045 // black was used in the knob to represent transparency
1046 // use screen to get index for the "transarent" color used in the bitmap
1047 BScreen screen(B_MAIN_SCREEN_ID);
1048 uint8 blackIndex = screen.IndexForColor(kBlack);
1049 // replace black index with transparent index
1050 for (int32 i = 0; i < length; i++)
1051 if (bits[i] == blackIndex)
1052 bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
1056 // make ghosted versions of the bitmaps
1057 dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
1058 dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
1059 dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
1063 // replace green color (and shadow) in left slider side
1064 bits = (uint8*)fLeftSideBits->Bits();
1065 length = fLeftSideBits->BitsLength();
1066 uint8 greenIndex = screen.IndexForColor(kGreen);
1067 uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
1068 rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
1069 rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
1070 uint8 replaceIndex = screen.IndexForColor(shadow);
1071 uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
1072 for (int32 i = 0; i < length; i++)
1074 if (bits[i] == greenIndex)
1075 bits[i] = replaceIndex;
1076 else if (bits[i] == greenShadowIndex)
1077 bits[i] = replaceShadowIndex;
1083 /*****************************************************************************
1084 * VolumeSlider::_ValueFor
1085 *****************************************************************************/
1087 VolumeSlider::_ValueFor(float xPos) const
1090 float sliderStart = (r.left + kVolumeSliderBitmapWidth);
1091 float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
1092 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
1093 / (sliderEnd - sliderStart - 1.0));
1094 if (value < fMinValue)
1096 if (value > fMaxValue)