1 /*****************************************************************************
2 * MediaControlView.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: MediaControlView.cpp,v 1.13 2003/01/25 01:03:44 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>
35 /* BeOS interface headers */
36 #include "VlcWrapper.h"
38 #include "DrawingTidbits.h"
39 #include "InterfaceWindow.h"
41 #include "TransportButton.h"
42 #include "ListViews.h"
43 #include "MediaControlView.h"
45 #define BORDER_INSET 6.0
47 #define SPEAKER_SLIDER_DIST 6.0
48 #define VOLUME_MIN_WIDTH 70.0
50 #define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0
51 #define SEEK_SLIDER_KNOB_WIDTH 8.0
53 // slider colors are hardcoded here, because that's just
54 // what they currently are within those bitmaps
55 const rgb_color kGreen = (rgb_color){ 152, 203, 152, 255 };
56 const rgb_color kGreenShadow = (rgb_color){ 102, 152, 102, 255 };
57 const rgb_color kBackground = (rgb_color){ 216, 216, 216, 255 };
58 const rgb_color kSeekGreen = (rgb_color){ 171, 221, 161, 255 };
59 const rgb_color kSeekGreenShadow = (rgb_color){ 144, 186, 136, 255 };
60 const rgb_color kSeekRed = (rgb_color){ 255, 0, 0, 255 };
61 const rgb_color kSeekRedLight = (rgb_color){ 255, 152, 152, 255 };
62 const rgb_color kSeekRedShadow = (rgb_color){ 178, 0, 0, 255 };
64 const char* kDisabledSeekMessage = "Drop files to play";
70 MSG_SKIP_BACKWARDS = 'skpb',
71 MSG_SKIP_FORWARD = 'skpf',
75 MediaControlView::MediaControlView(BRect frame, intf_thread_t *p_interface)
76 : BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
79 fCurrentRate(DEFAULT_RATE),
80 fCurrentStatus(UNDEF_S),
81 fBottomControlHeight(0.0),
86 BRect frame(0.0, 0.0, 10.0, 10.0);
89 fSeekSlider = new SeekSlider(frame, "seek slider", this,
90 0, SEEKSLIDER_RANGE - 1);
91 fSeekSlider->SetValue(0);
92 fSeekSlider->ResizeToPreferred();
93 AddChild( fSeekSlider );
97 frame.SetRightBottom(kSkipButtonSize);
98 fBottomControlHeight = kRewindBitmapHeight - 1.0;
99 fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
101 kPressedSkipBackBitmapBits,
102 kDisabledSkipBackBitmapBits,
103 new BMessage(MSG_SKIP_BACKWARDS));
104 AddChild( fSkipBack );
107 frame.SetRightBottom(kPlayButtonSize);
108 if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
109 fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
110 fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
111 kPlayButtonBitmapBits,
112 kPressedPlayButtonBitmapBits,
113 kDisabledPlayButtonBitmapBits,
114 kPlayingPlayButtonBitmapBits,
115 kPressedPlayingPlayButtonBitmapBits,
116 kPausedPlayButtonBitmapBits,
117 kPressedPausedPlayButtonBitmapBits,
118 new BMessage(START_PLAYBACK));
120 AddChild( fPlayPause );
123 frame.SetRightBottom(kSkipButtonSize);
124 fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
125 kSkipForwardBitmapBits,
126 kPressedSkipForwardBitmapBits,
127 kDisabledSkipForwardBitmapBits,
128 new BMessage(MSG_SKIP_FORWARD));
129 AddChild( fSkipForward );
132 fForward = new TransportButton(frame, B_EMPTY_STRING,
134 kPressedForwardBitmapBits,
135 kDisabledForwardBitmapBits,
136 new BMessage(MSG_FORWARD));
137 // AddChild( fForward );
140 fRewind = new TransportButton(frame, B_EMPTY_STRING,
142 kPressedRewindBitmapBits,
143 kDisabledRewindBitmapBits,
144 new BMessage(MSG_REWIND));
145 // AddChild( fRewind );
148 frame.SetRightBottom(kStopButtonSize);
149 if (fBottomControlHeight < kStopBitmapHeight - 1.0)
150 fBottomControlHeight = kStopBitmapHeight - 1.0;
151 fStop = new TransportButton(frame, B_EMPTY_STRING,
152 kStopButtonBitmapBits,
153 kPressedStopButtonBitmapBits,
154 kDisabledStopButtonBitmapBits,
155 new BMessage(STOP_PLAYBACK));
159 frame.SetRightBottom(kSpeakerButtonSize);
160 if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
161 fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
162 fMute = new TransportButton(frame, B_EMPTY_STRING,
164 kPressedSpeakerIconBits,
166 new BMessage(VOLUME_MUTE));
171 fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
172 kVolumeSliderBitmapHeight - 1.0),
173 "volume slider", 1, AOUT_VOLUME_MAX,
174 new BMessage(VOLUME_CHG));
175 fVolumeSlider->SetValue(AOUT_VOLUME_DEFAULT);
176 AddChild( fVolumeSlider );
178 // Position Info View
179 fPositionInfo = new PositionInfoView(BRect(0.0, 0.0, 10.0, 10.0), "led",
181 fPositionInfo->ResizeToPreferred();
182 AddChild( fPositionInfo );
186 MediaControlView::~MediaControlView()
192 MediaControlView::AttachedToWindow()
194 // we are now a valid BHandler
195 fRewind->SetTarget(this);
196 fForward->SetTarget(this);
197 fSkipBack->SetTarget(this);
198 fSkipForward->SetTarget(this);
199 fVolumeSlider->SetTarget(Window());
201 BRect r(_MinFrame());
202 if (BMenuBar* menuBar = Window()->KeyMenuBar())
203 r.bottom += menuBar->Bounds().Height();
205 Window()->SetSizeLimits(r.Width(), r.Width() * 1.8, r.Height(), r.Height() * 1.3);
206 if (!Window()->Bounds().Contains(r))
207 Window()->ResizeTo(r.Width(), r.Height());
209 FrameResized(Bounds().Width(), Bounds().Height());
211 // get pulse message every two frames
212 Window()->SetPulseRate(80000);
217 MediaControlView::FrameResized(float width, float height)
220 // make sure we don't leave dirty pixels
221 // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
222 if (fOldBounds.Width() < r.Width())
223 Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
224 fOldBounds.right, fOldBounds.bottom - 1.0));
226 Invalidate(BRect(r.right, r.top + 1.0,
227 r.right, r.bottom - 1.0));
228 if (fOldBounds.Height() < r.Height())
229 Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
230 fOldBounds.right - 1.0, fOldBounds.bottom));
232 Invalidate(BRect(r.left + 1.0, r.bottom,
233 r.right - 1.0, r.bottom));
234 // remember for next time
237 r.InsetBy(BORDER_INSET, BORDER_INSET);
243 MediaControlView::GetPreferredSize(float* width, float* height)
247 BRect r(_MinFrame());
249 *height = r.Height();
255 MediaControlView::MessageReceived(BMessage* message)
257 switch (message->what)
263 case MSG_SKIP_BACKWARDS:
264 Window()->PostMessage(NAVIGATE_PREV);
266 case MSG_SKIP_FORWARD:
267 Window()->PostMessage(NAVIGATE_NEXT);
270 BBox::MessageReceived(message);
277 MediaControlView::Pulse()
279 InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
280 if (window && window->IsStopped())
281 fPlayPause->SetStopped();
286 MediaControlView::SetProgress( float position )
288 fSeekSlider->SetPosition( position );
293 MediaControlView::SetStatus(int status, int rate)
295 // we need to set the button status periodically
296 // (even if it is the same) to get a blinking button
297 fCurrentStatus = status;
304 fPlayPause->SetPlaying();
307 fPlayPause->SetPaused();
312 fPlayPause->SetStopped();
315 if (rate != fCurrentRate)
318 if ( rate < DEFAULT_RATE )
327 MediaControlView::SetEnabled(bool enabled)
329 if( ( enabled && fIsEnabled ) ||
330 ( !enabled && !fIsEnabled ) )
332 /* do not redraw if it is not necessary */
338 fSkipBack->SetEnabled( enabled );
339 fPlayPause->SetEnabled( enabled );
340 fSkipForward->SetEnabled( enabled );
341 fStop->SetEnabled( enabled );
342 fMute->SetEnabled( enabled );
343 fVolumeSlider->SetEnabled( enabled );
344 fSeekSlider->SetEnabled( enabled );
345 fRewind->SetEnabled( enabled );
346 fForward->SetEnabled( enabled );
348 fIsEnabled = enabled;
354 MediaControlView::SetAudioEnabled(bool enabled)
356 fMute->SetEnabled(enabled);
357 fVolumeSlider->SetEnabled(enabled);
362 MediaControlView::GetSeekTo() const
364 return fSeekSlider->Value();
369 MediaControlView::GetVolume() const
371 return fVolumeSlider->Value();
376 MediaControlView::SetSkippable(bool backward, bool forward)
378 fSkipBack->SetEnabled(backward);
379 fSkipForward->SetEnabled(forward);
384 MediaControlView::SetMuted(bool mute)
386 fVolumeSlider->SetMuted(mute);
391 MediaControlView::_LayoutControls(BRect frame) const
395 // calculate absolutly minimal width
396 float minWidth = fSkipBack->Bounds().Width();
397 // minWidth += fRewind->Bounds().Width();
398 minWidth += fStop->Bounds().Width();
399 minWidth += fPlayPause->Bounds().Width();
400 // minWidth += fForward->Bounds().Width();
401 minWidth += fSkipForward->Bounds().Width();
402 minWidth += fMute->Bounds().Width();
403 minWidth += VOLUME_MIN_WIDTH;
405 // layout time slider and info view
407 fPositionInfo->GetBigPreferredSize( &width, &height );
408 float ratio = width / height;
409 width = r.Height() * ratio;
410 if (frame.Width() - minWidth - MIN_SPACE >= width
411 && frame.Height() >= height)
413 r.right = r.left + width;
414 fPositionInfo->SetMode(PositionInfoView::MODE_BIG);
415 _LayoutControl(fPositionInfo, r, true, true);
416 frame.left = r.right + MIN_SPACE;
418 r.right = frame.right;
419 // r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
420 r.bottom = r.top + fSeekSlider->Bounds().Height();
421 _LayoutControl(fSeekSlider, r, true);
425 fPositionInfo->GetPreferredSize( &width, &height );
426 fPositionInfo->SetMode(PositionInfoView::MODE_SMALL);
427 fPositionInfo->ResizeTo(width, height);
428 r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
429 r.right = r.left + fPositionInfo->Bounds().Width();
430 _LayoutControl(fPositionInfo, r, true );
431 r.left = r.right + MIN_SPACE;
432 r.right = frame.right;
433 _LayoutControl(fSeekSlider, r, true);
435 float currentWidth = frame.Width();
436 float space = (currentWidth - minWidth) / 6.0;//8.0;
438 space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
439 // layout controls with "space" inbetween
441 r.top = r.bottom + MIN_SPACE + 1.0;
442 r.bottom = frame.bottom;
444 r.right = r.left + fSkipBack->Bounds().Width();
445 _LayoutControl(fSkipBack, r);
447 // r.left = r.right + space;
448 // r.right = r.left + fRewind->Bounds().Width();
449 // _LayoutControl(fRewind, r);
451 r.left = r.right + space;
452 r.right = r.left + fStop->Bounds().Width();
453 _LayoutControl(fStop, r);
455 r.left = r.right + space;
456 r.right = r.left + fPlayPause->Bounds().Width();
457 _LayoutControl(fPlayPause, r);
459 // r.left = r.right + space;
460 // r.right = r.left + fForward->Bounds().Width();
461 // _LayoutControl(fForward, r);
463 r.left = r.right + space;
464 r.right = r.left + fSkipForward->Bounds().Width();
465 _LayoutControl(fSkipForward, r);
467 r.left = r.right + space + space;
468 r.right = r.left + fMute->Bounds().Width();
469 _LayoutControl(fMute, r);
471 r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
472 r.right = frame.right;
473 _LayoutControl(fVolumeSlider, r, true);
478 MediaControlView::_MinFrame() const
480 // add up width of controls along bottom (seek slider will likely adopt)
481 float minWidth = 2 * BORDER_INSET;
482 minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
483 // minWidth += fRewind->Bounds().Width() + MIN_SPACE;
484 minWidth += fStop->Bounds().Width() + MIN_SPACE;
485 minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
486 // minWidth += fForward->Bounds().Width() + MIN_SPACE;
487 minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
488 minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
489 minWidth += VOLUME_MIN_WIDTH;
491 // add up height of seek slider and heighest control on bottom
492 float minHeight = 2 * BORDER_INSET;
493 minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
494 minHeight += fBottomControlHeight;
495 return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
500 MediaControlView::_LayoutControl(BView* view, BRect frame,
501 bool resizeWidth, bool resizeHeight) const
505 frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
507 //center horizontally
508 frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
509 view->MoveTo(frame.LeftTop());
510 float width = resizeWidth ? frame.Width() : view->Bounds().Width();
511 float height = resizeHeight ? frame.Height() : view->Bounds().Height();
512 if (resizeWidth || resizeHeight)
513 view->ResizeTo(width, height);
518 /*****************************************************************************
520 *****************************************************************************/
521 SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
522 int32 minValue, int32 maxValue)
523 : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
524 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
530 BFont font(be_plain_font);
535 SeekSlider::~SeekSlider()
540 /*****************************************************************************
541 * VolumeSlider::AttachedToWindow
542 *****************************************************************************/
544 SeekSlider::AttachedToWindow()
546 BControl::AttachedToWindow();
547 SetViewColor(B_TRANSPARENT_32_BIT);
550 /*****************************************************************************
552 *****************************************************************************/
554 SeekSlider::Draw(BRect updateRect)
557 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
558 float sliderStart = (r.left + knobWidth2);
559 float sliderEnd = (r.right - knobWidth2);
560 float knobPos = sliderStart
561 + floorf((sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
562 / (fMaxValue - fMinValue) + 0.5);
563 // draw both sides (the original from Be doesn't seem
564 // to make a difference for enabled/disabled state)
565 // DrawBitmapAsync(fLeftSideBits, r.LeftTop());
566 // DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
567 // colors for the slider area between the two bitmaps
568 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
569 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
570 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
571 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
572 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
573 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
574 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
575 rgb_color green = kSeekGreen;
576 rgb_color greenShadow = kSeekGreenShadow;
577 rgb_color black = kBlack;
578 rgb_color dotGrey = midShadow;
579 rgb_color dotGreen = greenShadow;
581 _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
583 _StrokeFrame(r, black, black, light, light);
588 _StrokeFrame(r, greenShadow, greenShadow, green, green);
591 _StrokeFrame(r, greenShadow, greenShadow, green, green);
597 int32 dotCount = (int32)(r.Width() / 6.0);
599 dotPos.y = r.top + 2.0;
600 SetHighColor(dotGreen);
601 for (int32 i = 0; i < dotCount; i++)
603 dotPos.x = sliderStart + i * 6.0 + 5.0;
604 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
609 r.left = knobPos - knobWidth2;
610 r.right = knobPos + knobWidth2;
612 float handleBottomSize = 2.0;
613 float handleArrowSize = 6.0;
616 AddLine(BPoint(r.left, r.top + handleBottomSize),
617 BPoint(r.left, r.top), black);
618 AddLine(BPoint(r.left + 1.0, r.top),
619 BPoint(r.right, r.top), black);
620 AddLine(BPoint(r.right, r.top + 1.0),
621 BPoint(r.right, r.top + handleBottomSize), black);
622 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
623 BPoint(knobPos, r.top + handleArrowSize), black);
624 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
625 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
627 AddLine(BPoint(r.left, r.bottom),
628 BPoint(r.left, r.bottom - handleBottomSize), black);
629 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
630 BPoint(knobPos, r.bottom - handleArrowSize), black);
631 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
632 BPoint(r.right, r.bottom - handleBottomSize), black);
633 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
634 BPoint(r.right, r.bottom), black);
635 AddLine(BPoint(r.right - 1.0, r.bottom),
636 BPoint(r.left + 1.0, r.bottom), black);
638 // inner red light and shadow lines
641 handleArrowSize -= 2.0;
644 AddLine(BPoint(r.left, r.top + handleBottomSize),
645 BPoint(r.left, r.top), kSeekRedLight);
646 AddLine(BPoint(r.left + 1.0, r.top),
647 BPoint(r.right, r.top), kSeekRedLight);
648 AddLine(BPoint(r.right, r.top + 1.0),
649 BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
650 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
651 BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
652 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
653 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
655 AddLine(BPoint(r.left, r.bottom),
656 BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
657 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
658 BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
659 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
660 BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
661 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
662 BPoint(r.right, r.bottom), kSeekRedShadow);
663 AddLine(BPoint(r.right - 1.0, r.bottom),
664 BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
666 // fill rest of handles with red
667 SetHighColor(kSeekRed);
669 handleArrowSize -= 2.0;
671 // upper handle arrow
674 arrow[1].x = r.right;
676 arrow[2].x = knobPos;
677 arrow[2].y = r.top + handleArrowSize;
678 FillPolygon(arrow, 3);
679 // lower handle arrow
681 arrow[0].y = r.bottom;
682 arrow[1].x = r.right;
683 arrow[1].y = r.bottom;
684 arrow[2].x = knobPos;
685 arrow[2].y = r.bottom - handleArrowSize;
686 FillPolygon(arrow, 3);
691 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
693 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
695 SetHighColor(darkShadow);
698 float width = floorf(StringWidth(kDisabledSeekMessage));
699 float textPos = r.left + r.Width() / 2.0 - width / 2.0;
700 pattern stripes = {{ 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 }};
701 BRect stripesRect(r);
702 stripesRect.right = textPos - 5.0;
703 FillRect(stripesRect, stripes);
704 stripesRect.left = textPos + width + 3.0;
705 stripesRect.right = r.right;
706 FillRect(stripesRect, stripes);
708 r.left = textPos - 4.0;
709 r.right = textPos + width + 2.0;
711 SetHighColor(shadow);
712 SetLowColor(darkShadow);
715 DrawString(kDisabledSeekMessage, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
719 /*****************************************************************************
720 * SeekSlider::MouseDown
721 *****************************************************************************/
723 SeekSlider::MouseDown(BPoint where)
725 if (IsEnabled() && Bounds().Contains(where))
727 SetValue(_ValueFor(where.x));
729 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
734 /*****************************************************************************
735 * SeekSlider::MouseMoved
736 *****************************************************************************/
738 SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
742 SetValue(_ValueFor(where.x));
747 /*****************************************************************************
748 * SeekSlider::MouseUp
749 *****************************************************************************/
751 SeekSlider::MouseUp(BPoint where)
760 /*****************************************************************************
761 * SeekSlider::ResizeToPreferred
762 *****************************************************************************/
764 SeekSlider::ResizeToPreferred()
766 float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
767 ResizeTo(width, 17.0);
770 /*****************************************************************************
771 * SeekSlider::SetPosition
772 *****************************************************************************/
774 SeekSlider::SetPosition(float position)
777 SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
781 /*****************************************************************************
782 * SeekSlider::_ValueFor
783 *****************************************************************************/
785 SeekSlider::_ValueFor(float xPos) const
788 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
789 float sliderStart = (r.left + knobWidth2);
790 float sliderEnd = (r.right - knobWidth2);
791 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
792 / (sliderEnd - sliderStart - 1.0));
793 if (value < fMinValue)
795 if (value > fMaxValue)
800 /*****************************************************************************
801 * SeekSlider::_StrokeFrame
802 *****************************************************************************/
804 SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
805 rgb_color right, rgb_color bottom)
808 AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
809 AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
810 AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
811 AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
815 /*****************************************************************************
816 * SeekSlider::_BeginSeek
817 *****************************************************************************/
819 SeekSlider::_BeginSeek()
821 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
822 if (fOwner->fScrubSem >= B_OK)
823 release_sem(fOwner->fScrubSem);
826 /*****************************************************************************
828 *****************************************************************************/
832 if (fOwner->fScrubSem >= B_OK)
833 delete_sem(fOwner->fScrubSem);
834 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
835 if (fOwner->fScrubSem >= B_OK)
836 release_sem(fOwner->fScrubSem);
839 /*****************************************************************************
840 * SeekSlider::_EndSeek
841 *****************************************************************************/
843 SeekSlider::_EndSeek()
845 if (fOwner->fScrubSem >= B_OK)
846 delete_sem(fOwner->fScrubSem);
847 fOwner->fScrubSem = B_ERROR;
851 /*****************************************************************************
853 *****************************************************************************/
854 VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
855 BMessage* message, BHandler* target)
856 : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
857 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
859 fRightSideBits(NULL),
869 BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
870 fLeftSideBits = new BBitmap(r, B_CMAP8);
871 fRightSideBits = new BBitmap(r, B_CMAP8);
872 r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
873 fKnobBits = new BBitmap(r, B_CMAP8);
878 /*****************************************************************************
879 * VolumeSlider destructor
880 *****************************************************************************/
881 VolumeSlider::~VolumeSlider()
883 delete fLeftSideBits;
884 delete fRightSideBits;
888 /*****************************************************************************
889 * VolumeSlider::AttachedToWindow
890 *****************************************************************************/
892 VolumeSlider::AttachedToWindow()
894 BControl::AttachedToWindow();
895 SetViewColor(B_TRANSPARENT_32_BIT);
898 /*****************************************************************************
899 * VolumeSlider::SetValue
900 *****************************************************************************/
902 VolumeSlider::SetValue(int32 value)
904 if (value != Value())
906 BControl::SetValue(value);
911 /*****************************************************************************
912 * VolumeSlider::SetEnabled
913 *****************************************************************************/
915 VolumeSlider::SetEnabled(bool enable)
917 if (enable != IsEnabled())
919 BControl::SetEnabled(enable);
925 /*****************************************************************************
927 *****************************************************************************/
929 VolumeSlider::Draw(BRect updateRect)
934 float sliderSideWidth = kVolumeSliderBitmapWidth;
935 float sliderStart = (r.left + sliderSideWidth);
936 float sliderEnd = (r.right - sliderSideWidth);
937 float knobPos = sliderStart
938 + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
939 / (fMaxValue - fMinValue);
940 // draw both sides (the original from Be doesn't seem
941 // to make a difference for enabled/disabled state)
942 DrawBitmapAsync(fLeftSideBits, r.LeftTop());
943 DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
944 // colors for the slider area between the two bitmaps
945 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
946 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
947 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
948 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
949 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
950 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
951 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
952 rgb_color green = kGreen;
953 rgb_color greenShadow = kGreenShadow;
954 rgb_color black = kBlack;
955 rgb_color dotGrey = midShadow;
956 rgb_color dotGreen = greenShadow;
957 // make dimmed version of colors if we're disabled
960 shadow = (rgb_color){ 200, 200, 200, 255 };
961 softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
962 darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
964 light = dimmed_color_cmap8(light, background, DIM_LEVEL);
965 softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
966 green = dimmed_color_cmap8(green, background, DIM_LEVEL);
967 greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
968 black = dimmed_color_cmap8(black, background, DIM_LEVEL);
973 green = tint_color(kBackground, B_DARKEN_3_TINT);
974 greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
975 dotGreen = greenShadow;
977 // draw slider edges between bitmaps
979 AddLine(BPoint(sliderStart, r.top),
980 BPoint(sliderEnd, r.top), softShadow);
981 AddLine(BPoint(sliderStart, r.bottom),
982 BPoint(sliderEnd, r.bottom), softLight);
984 AddLine(BPoint(sliderStart, r.top),
985 BPoint(sliderEnd, r.top), black);
986 AddLine(BPoint(sliderStart, r.bottom),
987 BPoint(sliderEnd, r.bottom), light);
989 AddLine(BPoint(sliderStart, r.top),
990 BPoint(knobPos, r.top), greenShadow);
991 AddLine(BPoint(knobPos, r.top),
992 BPoint(sliderEnd, r.top), midShadow);
994 AddLine(BPoint(sliderStart, r.top),
995 BPoint(knobPos, r.top), greenShadow);
997 // fill rest inside of slider
999 r.left = sliderStart;
1001 SetHighColor(green);
1002 FillRect(r, B_SOLID_HIGH);
1003 r.left = knobPos + 1.0;
1004 r.right = sliderEnd;
1006 SetHighColor(shadow);
1007 FillRect(r, B_SOLID_HIGH);
1008 // draw little dots inside
1009 int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
1011 dotPos.y = r.top + 4.0;
1012 for (int32 i = 0; i < dotCount; i++)
1014 dotPos.x = sliderStart + i * 5.0 + 4.0;
1015 SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
1016 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
1020 SetDrawingMode(B_OP_OVER); // part of knob is transparent
1021 DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
1025 /*****************************************************************************
1026 * VolumeSlider::MouseDown
1027 *****************************************************************************/
1029 VolumeSlider::MouseDown(BPoint where)
1031 if (Bounds().Contains(where) && IsEnabled())
1034 SetValue(_ValueFor(where.x));
1035 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
1039 /*****************************************************************************
1040 * VolumeSlider::MouseMoved
1041 *****************************************************************************/
1043 VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
1046 SetValue(_ValueFor(where.x));
1049 /*****************************************************************************
1050 * VolumeSlider::MouseUp
1051 *****************************************************************************/
1053 VolumeSlider::MouseUp(BPoint where)
1059 /*****************************************************************************
1060 * VolumeSlider::IsValid
1061 *****************************************************************************/
1063 VolumeSlider::IsValid() const
1065 return (fLeftSideBits && fLeftSideBits->IsValid()
1066 && fRightSideBits && fRightSideBits->IsValid()
1067 && fKnobBits && fKnobBits->IsValid());
1070 /*****************************************************************************
1071 * VolumeSlider::SetMuted
1072 *****************************************************************************/
1074 VolumeSlider::SetMuted(bool mute)
1084 /*****************************************************************************
1085 * VolumeSlider::_MakeBitmaps
1086 *****************************************************************************/
1088 VolumeSlider::_MakeBitmaps()
1092 // left side of slider
1093 memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
1094 fLeftSideBits->BitsLength());
1095 // right side of slider
1096 memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
1097 fRightSideBits->BitsLength());
1099 int32 length = fKnobBits->BitsLength();
1100 memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
1101 uint8* bits = (uint8*)fKnobBits->Bits();
1102 // black was used in the knob to represent transparency
1103 // use screen to get index for the "transarent" color used in the bitmap
1104 BScreen screen(B_MAIN_SCREEN_ID);
1105 uint8 blackIndex = screen.IndexForColor(kBlack);
1106 // replace black index with transparent index
1107 for (int32 i = 0; i < length; i++)
1108 if (bits[i] == blackIndex)
1109 bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
1113 // make ghosted versions of the bitmaps
1114 dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
1115 dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
1116 dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
1120 // replace green color (and shadow) in left slider side
1121 bits = (uint8*)fLeftSideBits->Bits();
1122 length = fLeftSideBits->BitsLength();
1123 uint8 greenIndex = screen.IndexForColor(kGreen);
1124 uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
1125 rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
1126 rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
1127 uint8 replaceIndex = screen.IndexForColor(shadow);
1128 uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
1129 for (int32 i = 0; i < length; i++)
1131 if (bits[i] == greenIndex)
1132 bits[i] = replaceIndex;
1133 else if (bits[i] == greenShadowIndex)
1134 bits[i] = replaceShadowIndex;
1140 /*****************************************************************************
1141 * VolumeSlider::_ValueFor
1142 *****************************************************************************/
1144 VolumeSlider::_ValueFor(float xPos) const
1147 float sliderStart = (r.left + kVolumeSliderBitmapWidth);
1148 float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
1149 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
1150 / (sliderEnd - sliderStart - 1.0));
1151 if (value < fMinValue)
1153 if (value > fMaxValue)
1158 /*****************************************************************************
1159 * PositionInfoView::PositionInfoView
1160 *****************************************************************************/
1161 PositionInfoView::PositionInfoView( BRect frame, const char* name,
1162 intf_thread_t * p_interface )
1163 : BView( frame, name, B_FOLLOW_NONE,
1164 B_WILL_DRAW | B_PULSE_NEEDED | B_FULL_UPDATE_ON_RESIZE ),
1165 fMode( MODE_SMALL ),
1166 fCurrentFileIndex( -1 ),
1167 fCurrentFileSize( -1 ),
1168 fCurrentTitleIndex( -1 ),
1169 fCurrentTitleSize( -1 ),
1170 fCurrentChapterIndex( -1 ),
1171 fCurrentChapterSize( -1 ),
1173 fTimeString( "-:--:--" ),
1174 fLastPulseUpdate( system_time() ),
1175 fStackedWidthCache( 0.0 ),
1176 fStackedHeightCache( 0.0 )
1178 p_intf = p_interface;
1180 SetViewColor( B_TRANSPARENT_32_BIT );
1181 SetLowColor( kBlack );
1182 SetHighColor( 0, 255, 0, 255 );
1183 SetFontSize( 11.0 );
1186 /*****************************************************************************
1187 * PositionInfoView::~PositionInfoView
1188 *****************************************************************************/
1189 PositionInfoView::~PositionInfoView()
1193 /*****************************************************************************
1194 * PositionInfoView::Draw
1195 *****************************************************************************/
1197 PositionInfoView::Draw( BRect updateRect )
1199 rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
1200 rgb_color shadow = tint_color( background, B_DARKEN_1_TINT );
1201 rgb_color darkShadow = tint_color( background, B_DARKEN_4_TINT );
1202 rgb_color light = tint_color( background, B_LIGHTEN_MAX_TINT );
1203 rgb_color softLight = tint_color( background, B_LIGHTEN_1_TINT );
1205 BRect r( Bounds() );
1206 BeginLineArray( 8 );
1207 AddLine( BPoint( r.left, r.bottom ),
1208 BPoint( r.left, r.top ), shadow );
1209 AddLine( BPoint( r.left + 1.0, r.top ),
1210 BPoint( r.right, r.top ), shadow );
1211 AddLine( BPoint( r.right, r.top + 1.0 ),
1212 BPoint( r.right, r.bottom ), softLight );
1213 AddLine( BPoint( r.right - 1.0, r.bottom ),
1214 BPoint( r.left + 1.0, r.bottom ), softLight );
1215 r.InsetBy( 1.0, 1.0 );
1216 AddLine( BPoint( r.left, r.bottom ),
1217 BPoint( r.left, r.top ), darkShadow );
1218 AddLine( BPoint( r.left + 1.0, r.top ),
1219 BPoint( r.right, r.top ), darkShadow );
1220 AddLine( BPoint( r.right, r.top + 1.0 ),
1221 BPoint( r.right, r.bottom ), light );
1222 AddLine( BPoint( r.right - 1.0, r.bottom ),
1223 BPoint( r.left + 1.0, r.bottom ), light );
1226 r.InsetBy( 1.0, 1.0 );
1227 FillRect( r, B_SOLID_LOW );
1230 GetFontHeight( &fh );
1235 float width = StringWidth( fTimeString.String() );
1236 DrawString( fTimeString.String(),
1237 BPoint( r.left + r.Width() / 2.0 - width / 2.0,
1238 r.top + r.Height() / 2.0 + fh.ascent / 2.0 - 1.0 ) );
1245 BFont smallFont = font;
1246 BFont bigFont = font;
1247 BFont tinyFont = font;
1248 smallFont.SetSize( r.Height() / 5.0 );
1249 bigFont.SetSize( r.Height() / 3.0 );
1250 tinyFont.SetSize( r.Height() / 7.0 );
1251 float timeHeight = r.Height() / 2.5;
1252 float height = ( r.Height() - timeHeight ) / 3.0;
1253 SetFont( &tinyFont );
1254 SetHighColor( 0, 180, 0, 255 );
1255 DrawString( "File", BPoint( r.left + 3.0, r.top + height ) );
1256 DrawString( "Title", BPoint( r.left + 3.0, r.top + 2.0 * height ) );
1257 DrawString( "Chapter", BPoint( r.left + 3.0, r.top + 3.0 * height ) );
1258 SetFont( &smallFont );
1260 SetHighColor( 0, 255, 0, 255 );
1262 _MakeString( helper, fCurrentFileIndex, fCurrentFileSize );
1263 float width = StringWidth( helper.String() );
1264 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + height ) );
1266 _MakeString( helper, fCurrentTitleIndex, fCurrentTitleSize );
1267 width = StringWidth( helper.String() );
1268 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 2.0 * height ) );
1270 _MakeString( helper, fCurrentChapterIndex, fCurrentChapterSize );
1271 width = StringWidth( helper.String() );
1272 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 3.0 * height ) );
1274 SetFont( &bigFont );
1275 width = StringWidth( fTimeString.String() );
1276 DrawString( fTimeString.String(),
1277 BPoint( r.left + r.Width() / 2.0 - width / 2.0,
1284 /*****************************************************************************
1285 * PositionInfoView::ResizeToPreferred
1286 *****************************************************************************/
1288 PositionInfoView::ResizeToPreferred()
1290 float width, height;
1291 GetPreferredSize( &width, &height );
1292 ResizeTo( width, height );
1295 /*****************************************************************************
1296 * PositionInfoView::GetPreferredSize
1297 *****************************************************************************/
1299 PositionInfoView::GetPreferredSize( float* width, float* height )
1301 if ( width && height )
1303 *width = 5.0 + ceilf( StringWidth( "0:00:00" ) ) + 5.0;
1305 GetFontHeight( &fh );
1306 *height = 3.0 + ceilf( fh.ascent ) + 3.0;
1307 fStackedWidthCache = *width * 1.2;
1308 fStackedHeightCache = *height * 2.7;
1312 /*****************************************************************************
1313 * PositionInfoView::Pulse
1314 *****************************************************************************/
1316 PositionInfoView::Pulse()
1318 // allow for Pulse frequency to be higher, MediaControlView needs it
1319 bigtime_t now = system_time();
1320 if ( now - fLastPulseUpdate > 900000 )
1323 p_intf->p_sys->p_wrapper->GetPlaylistInfo( index, size );
1324 SetFile( index, size );
1325 p_intf->p_sys->p_wrapper->TitleInfo( index, size );
1326 SetTitle( index, size );
1327 p_intf->p_sys->p_wrapper->ChapterInfo( index, size );
1328 SetChapter( index, size );
1329 SetTime( p_intf->p_sys->p_wrapper->GetTimeAsString() );
1330 fLastPulseUpdate = now;
1334 /*****************************************************************************
1335 * PositionInfoView::GetBigPreferredSize
1336 *****************************************************************************/
1338 PositionInfoView::GetBigPreferredSize( float* width, float* height )
1340 if ( width && height )
1342 *width = fStackedWidthCache;
1343 *height = fStackedHeightCache;
1347 /*****************************************************************************
1348 * PositionInfoView::SetMode
1349 *****************************************************************************/
1351 PositionInfoView::SetMode( uint32 mode )
1353 if ( fMode != mode )
1356 _InvalidateContents();
1360 /*****************************************************************************
1361 * PositionInfoView::SetFile
1362 *****************************************************************************/
1364 PositionInfoView::SetFile( int32 index, int32 size )
1366 if ( fCurrentFileIndex != index || fCurrentFileSize != size )
1368 fCurrentFileIndex = index;
1369 fCurrentFileSize = size;
1370 _InvalidateContents();
1374 /*****************************************************************************
1375 * PositionInfoView::SetTitle
1376 *****************************************************************************/
1378 PositionInfoView::SetTitle( int32 index, int32 size )
1380 if ( fCurrentTitleIndex != index || fCurrentFileSize != size )
1382 fCurrentTitleIndex = index;
1383 fCurrentTitleSize = size;
1384 _InvalidateContents();
1388 /*****************************************************************************
1389 * PositionInfoView::SetChapter
1390 *****************************************************************************/
1392 PositionInfoView::SetChapter( int32 index, int32 size )
1394 if ( fCurrentChapterIndex != index || fCurrentFileSize != size )
1396 fCurrentChapterIndex = index;
1397 fCurrentChapterSize = size;
1398 _InvalidateContents();
1402 /*****************************************************************************
1403 * PositionInfoView::SetTime
1404 *****************************************************************************/
1406 PositionInfoView::SetTime( int32 seconds )
1408 if ( fSeconds != seconds )
1412 int32 minutes = seconds / 60;
1413 int32 hours = minutes / 60;
1414 seconds -= minutes * 60 - hours * 60 * 60;
1415 minutes -= hours * 60;
1416 fTimeString.SetTo( "" );
1417 fTimeString << hours << ":" << minutes << ":" << seconds;
1420 fTimeString.SetTo( "-:--:--" );
1423 _InvalidateContents();
1427 /*****************************************************************************
1428 * PositionInfoView::SetTime
1429 *****************************************************************************/
1431 PositionInfoView::SetTime( const char* string )
1433 fTimeString.SetTo( string );
1434 _InvalidateContents();
1437 /*****************************************************************************
1438 * PositionInfoView::_InvalidateContents
1439 *****************************************************************************/
1441 PositionInfoView::_InvalidateContents( uint32 which )
1443 BRect r( Bounds() );
1444 r.InsetBy( 2.0, 2.0 );
1448 /*****************************************************************************
1449 * PositionInfoView::_InvalidateContents
1450 *****************************************************************************/
1452 PositionInfoView::_MakeString( BString& into, int32 index, int32 maxIndex ) const