1 /*****************************************************************************
2 * MediaControlView.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: MediaControlView.cpp,v 1.10 2003/01/12 02:08:38 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)
85 BRect frame(0.0, 0.0, 10.0, 10.0);
88 fSeekSlider = new SeekSlider(frame, "seek slider", this,
89 0, SEEKSLIDER_RANGE - 1);
90 fSeekSlider->SetValue(0);
91 fSeekSlider->ResizeToPreferred();
92 AddChild( fSeekSlider );
96 frame.SetRightBottom(kSkipButtonSize);
97 fBottomControlHeight = kRewindBitmapHeight - 1.0;
98 fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
100 kPressedSkipBackBitmapBits,
101 kDisabledSkipBackBitmapBits,
102 new BMessage(MSG_SKIP_BACKWARDS));
103 AddChild( fSkipBack );
106 frame.SetRightBottom(kPlayButtonSize);
107 if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
108 fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
109 fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
110 kPlayButtonBitmapBits,
111 kPressedPlayButtonBitmapBits,
112 kDisabledPlayButtonBitmapBits,
113 kPlayingPlayButtonBitmapBits,
114 kPressedPlayingPlayButtonBitmapBits,
115 kPausedPlayButtonBitmapBits,
116 kPressedPausedPlayButtonBitmapBits,
117 new BMessage(START_PLAYBACK));
119 AddChild( fPlayPause );
122 frame.SetRightBottom(kSkipButtonSize);
123 fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
124 kSkipForwardBitmapBits,
125 kPressedSkipForwardBitmapBits,
126 kDisabledSkipForwardBitmapBits,
127 new BMessage(MSG_SKIP_FORWARD));
128 AddChild( fSkipForward );
131 fForward = new TransportButton(frame, B_EMPTY_STRING,
133 kPressedForwardBitmapBits,
134 kDisabledForwardBitmapBits,
135 new BMessage(MSG_FORWARD));
136 // AddChild( fForward );
139 fRewind = new TransportButton(frame, B_EMPTY_STRING,
141 kPressedRewindBitmapBits,
142 kDisabledRewindBitmapBits,
143 new BMessage(MSG_REWIND));
144 // AddChild( fRewind );
147 frame.SetRightBottom(kStopButtonSize);
148 if (fBottomControlHeight < kStopBitmapHeight - 1.0)
149 fBottomControlHeight = kStopBitmapHeight - 1.0;
150 fStop = new TransportButton(frame, B_EMPTY_STRING,
151 kStopButtonBitmapBits,
152 kPressedStopButtonBitmapBits,
153 kDisabledStopButtonBitmapBits,
154 new BMessage(STOP_PLAYBACK));
158 frame.SetRightBottom(kSpeakerButtonSize);
159 if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
160 fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
161 fMute = new TransportButton(frame, B_EMPTY_STRING,
163 kPressedSpeakerIconBits,
165 new BMessage(VOLUME_MUTE));
170 fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
171 kVolumeSliderBitmapHeight - 1.0),
172 "volume slider", 1, AOUT_VOLUME_MAX,
173 new BMessage(VOLUME_CHG));
174 fVolumeSlider->SetValue(AOUT_VOLUME_DEFAULT);
175 AddChild( fVolumeSlider );
177 // Position Info View
178 fPositionInfo = new PositionInfoView(BRect(0.0, 0.0, 10.0, 10.0), "led",
180 fPositionInfo->ResizeToPreferred();
181 AddChild( fPositionInfo );
185 MediaControlView::~MediaControlView()
191 MediaControlView::AttachedToWindow()
193 // we are now a valid BHandler
194 fRewind->SetTarget(this);
195 fForward->SetTarget(this);
196 fSkipBack->SetTarget(this);
197 fSkipForward->SetTarget(this);
198 fVolumeSlider->SetTarget(Window());
200 BRect r(_MinFrame());
201 if (BMenuBar* menuBar = Window()->KeyMenuBar())
202 r.bottom += menuBar->Bounds().Height();
204 Window()->SetSizeLimits(r.Width(), r.Width() * 1.8, r.Height(), r.Height() * 1.3);
205 if (!Window()->Bounds().Contains(r))
206 Window()->ResizeTo(r.Width(), r.Height());
208 FrameResized(Bounds().Width(), Bounds().Height());
210 // get pulse message every two frames
211 Window()->SetPulseRate(80000);
216 MediaControlView::FrameResized(float width, float height)
219 // make sure we don't leave dirty pixels
220 // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
221 if (fOldBounds.Width() < r.Width())
222 Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
223 fOldBounds.right, fOldBounds.bottom - 1.0));
225 Invalidate(BRect(r.right, r.top + 1.0,
226 r.right, r.bottom - 1.0));
227 if (fOldBounds.Height() < r.Height())
228 Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
229 fOldBounds.right - 1.0, fOldBounds.bottom));
231 Invalidate(BRect(r.left + 1.0, r.bottom,
232 r.right - 1.0, r.bottom));
233 // remember for next time
236 r.InsetBy(BORDER_INSET, BORDER_INSET);
242 MediaControlView::GetPreferredSize(float* width, float* height)
246 BRect r(_MinFrame());
248 *height = r.Height();
254 MediaControlView::MessageReceived(BMessage* message)
256 switch (message->what)
262 case MSG_SKIP_BACKWARDS:
263 Window()->PostMessage(NAVIGATE_PREV);
265 case MSG_SKIP_FORWARD:
266 Window()->PostMessage(NAVIGATE_NEXT);
269 BBox::MessageReceived(message);
276 MediaControlView::Pulse()
278 InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
279 if (window && window->IsStopped())
280 fPlayPause->SetStopped();
285 MediaControlView::SetProgress( float position )
287 fSeekSlider->SetPosition( position );
292 MediaControlView::SetStatus(int status, int rate)
294 // we need to set the button status periodically
295 // (even if it is the same) to get a blinking button
296 fCurrentStatus = status;
303 fPlayPause->SetPlaying();
306 fPlayPause->SetPaused();
311 fPlayPause->SetStopped();
314 if (rate != fCurrentRate)
317 if ( rate < DEFAULT_RATE )
326 MediaControlView::SetEnabled(bool enabled)
330 fSkipBack->SetEnabled( enabled );
331 fPlayPause->SetEnabled( enabled );
332 fSkipForward->SetEnabled( enabled );
333 fStop->SetEnabled( enabled );
334 fMute->SetEnabled( enabled );
335 fVolumeSlider->SetEnabled( enabled );
336 fSeekSlider->SetEnabled( enabled );
337 fRewind->SetEnabled( enabled );
338 fForward->SetEnabled( enabled );
345 MediaControlView::SetAudioEnabled(bool enabled)
347 fMute->SetEnabled(enabled);
348 fVolumeSlider->SetEnabled(enabled);
353 MediaControlView::GetSeekTo() const
355 return fSeekSlider->Value();
360 MediaControlView::GetVolume() const
362 return fVolumeSlider->Value();
367 MediaControlView::SetSkippable(bool backward, bool forward)
369 fSkipBack->SetEnabled(backward);
370 fSkipForward->SetEnabled(forward);
375 MediaControlView::SetMuted(bool mute)
377 fVolumeSlider->SetMuted(mute);
382 MediaControlView::_LayoutControls(BRect frame) const
386 // calculate absolutly minimal width
387 float minWidth = fSkipBack->Bounds().Width();
388 // minWidth += fRewind->Bounds().Width();
389 minWidth += fStop->Bounds().Width();
390 minWidth += fPlayPause->Bounds().Width();
391 // minWidth += fForward->Bounds().Width();
392 minWidth += fSkipForward->Bounds().Width();
393 minWidth += fMute->Bounds().Width();
394 minWidth += VOLUME_MIN_WIDTH;
396 // layout time slider and info view
398 fPositionInfo->GetBigPreferredSize( &width, &height );
399 float ratio = width / height;
400 width = r.Height() * ratio;
401 if (frame.Width() - minWidth - MIN_SPACE >= width
402 && frame.Height() >= height)
404 r.right = r.left + width;
405 fPositionInfo->SetMode(PositionInfoView::MODE_BIG);
406 _LayoutControl(fPositionInfo, r, true, true);
407 frame.left = r.right + MIN_SPACE;
409 r.right = frame.right;
410 // r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
411 r.bottom = r.top + fSeekSlider->Bounds().Height();
412 _LayoutControl(fSeekSlider, r, true);
416 fPositionInfo->GetPreferredSize( &width, &height );
417 fPositionInfo->SetMode(PositionInfoView::MODE_SMALL);
418 fPositionInfo->ResizeTo(width, height);
419 r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
420 r.right = r.left + fPositionInfo->Bounds().Width();
421 _LayoutControl(fPositionInfo, r, true );
422 r.left = r.right + MIN_SPACE;
423 r.right = frame.right;
424 _LayoutControl(fSeekSlider, r, true);
426 float currentWidth = frame.Width();
427 float space = (currentWidth - minWidth) / 6.0;//8.0;
429 space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
430 // layout controls with "space" inbetween
432 r.top = r.bottom + MIN_SPACE + 1.0;
433 r.bottom = frame.bottom;
435 r.right = r.left + fSkipBack->Bounds().Width();
436 _LayoutControl(fSkipBack, r);
438 // r.left = r.right + space;
439 // r.right = r.left + fRewind->Bounds().Width();
440 // _LayoutControl(fRewind, r);
442 r.left = r.right + space;
443 r.right = r.left + fStop->Bounds().Width();
444 _LayoutControl(fStop, r);
446 r.left = r.right + space;
447 r.right = r.left + fPlayPause->Bounds().Width();
448 _LayoutControl(fPlayPause, r);
450 // r.left = r.right + space;
451 // r.right = r.left + fForward->Bounds().Width();
452 // _LayoutControl(fForward, r);
454 r.left = r.right + space;
455 r.right = r.left + fSkipForward->Bounds().Width();
456 _LayoutControl(fSkipForward, r);
458 r.left = r.right + space + space;
459 r.right = r.left + fMute->Bounds().Width();
460 _LayoutControl(fMute, r);
462 r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
463 r.right = frame.right;
464 _LayoutControl(fVolumeSlider, r, true);
469 MediaControlView::_MinFrame() const
471 // add up width of controls along bottom (seek slider will likely adopt)
472 float minWidth = 2 * BORDER_INSET;
473 minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
474 // minWidth += fRewind->Bounds().Width() + MIN_SPACE;
475 minWidth += fStop->Bounds().Width() + MIN_SPACE;
476 minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
477 // minWidth += fForward->Bounds().Width() + MIN_SPACE;
478 minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
479 minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
480 minWidth += VOLUME_MIN_WIDTH;
482 // add up height of seek slider and heighest control on bottom
483 float minHeight = 2 * BORDER_INSET;
484 minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
485 minHeight += fBottomControlHeight;
486 return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
491 MediaControlView::_LayoutControl(BView* view, BRect frame,
492 bool resizeWidth, bool resizeHeight) const
496 frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
498 //center horizontally
499 frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
500 view->MoveTo(frame.LeftTop());
501 float width = resizeWidth ? frame.Width() : view->Bounds().Width();
502 float height = resizeHeight ? frame.Height() : view->Bounds().Height();
503 if (resizeWidth || resizeHeight)
504 view->ResizeTo(width, height);
509 /*****************************************************************************
511 *****************************************************************************/
512 SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
513 int32 minValue, int32 maxValue)
514 : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
515 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
521 BFont font(be_plain_font);
526 SeekSlider::~SeekSlider()
531 /*****************************************************************************
532 * VolumeSlider::AttachedToWindow
533 *****************************************************************************/
535 SeekSlider::AttachedToWindow()
537 BControl::AttachedToWindow();
538 SetViewColor(B_TRANSPARENT_32_BIT);
541 /*****************************************************************************
543 *****************************************************************************/
545 SeekSlider::Draw(BRect updateRect)
548 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
549 float sliderStart = (r.left + knobWidth2);
550 float sliderEnd = (r.right - knobWidth2);
551 float knobPos = sliderStart
552 + floorf((sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
553 / (fMaxValue - fMinValue) + 0.5);
554 // draw both sides (the original from Be doesn't seem
555 // to make a difference for enabled/disabled state)
556 // DrawBitmapAsync(fLeftSideBits, r.LeftTop());
557 // DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
558 // colors for the slider area between the two bitmaps
559 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
560 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
561 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
562 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
563 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
564 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
565 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
566 rgb_color green = kSeekGreen;
567 rgb_color greenShadow = kSeekGreenShadow;
568 rgb_color black = kBlack;
569 rgb_color dotGrey = midShadow;
570 rgb_color dotGreen = greenShadow;
572 _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
574 _StrokeFrame(r, black, black, light, light);
579 _StrokeFrame(r, greenShadow, greenShadow, green, green);
582 _StrokeFrame(r, greenShadow, greenShadow, green, green);
588 int32 dotCount = (int32)(r.Width() / 6.0);
590 dotPos.y = r.top + 2.0;
591 SetHighColor(dotGreen);
592 for (int32 i = 0; i < dotCount; i++)
594 dotPos.x = sliderStart + i * 6.0 + 5.0;
595 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
600 r.left = knobPos - knobWidth2;
601 r.right = knobPos + knobWidth2;
603 float handleBottomSize = 2.0;
604 float handleArrowSize = 6.0;
607 AddLine(BPoint(r.left, r.top + handleBottomSize),
608 BPoint(r.left, r.top), black);
609 AddLine(BPoint(r.left + 1.0, r.top),
610 BPoint(r.right, r.top), black);
611 AddLine(BPoint(r.right, r.top + 1.0),
612 BPoint(r.right, r.top + handleBottomSize), black);
613 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
614 BPoint(knobPos, r.top + handleArrowSize), black);
615 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
616 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
618 AddLine(BPoint(r.left, r.bottom),
619 BPoint(r.left, r.bottom - handleBottomSize), black);
620 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
621 BPoint(knobPos, r.bottom - handleArrowSize), black);
622 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
623 BPoint(r.right, r.bottom - handleBottomSize), black);
624 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
625 BPoint(r.right, r.bottom), black);
626 AddLine(BPoint(r.right - 1.0, r.bottom),
627 BPoint(r.left + 1.0, r.bottom), black);
629 // inner red light and shadow lines
632 handleArrowSize -= 2.0;
635 AddLine(BPoint(r.left, r.top + handleBottomSize),
636 BPoint(r.left, r.top), kSeekRedLight);
637 AddLine(BPoint(r.left + 1.0, r.top),
638 BPoint(r.right, r.top), kSeekRedLight);
639 AddLine(BPoint(r.right, r.top + 1.0),
640 BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
641 AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
642 BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
643 AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
644 BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
646 AddLine(BPoint(r.left, r.bottom),
647 BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
648 AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
649 BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
650 AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
651 BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
652 AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
653 BPoint(r.right, r.bottom), kSeekRedShadow);
654 AddLine(BPoint(r.right - 1.0, r.bottom),
655 BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
657 // fill rest of handles with red
658 SetHighColor(kSeekRed);
660 handleArrowSize -= 2.0;
662 // upper handle arrow
665 arrow[1].x = r.right;
667 arrow[2].x = knobPos;
668 arrow[2].y = r.top + handleArrowSize;
669 FillPolygon(arrow, 3);
670 // lower handle arrow
672 arrow[0].y = r.bottom;
673 arrow[1].x = r.right;
674 arrow[1].y = r.bottom;
675 arrow[2].x = knobPos;
676 arrow[2].y = r.bottom - handleArrowSize;
677 FillPolygon(arrow, 3);
682 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
684 _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
686 SetHighColor(darkShadow);
689 float width = floorf(StringWidth(kDisabledSeekMessage));
690 float textPos = r.left + r.Width() / 2.0 - width / 2.0;
691 pattern stripes = {{ 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 }};
692 BRect stripesRect(r);
693 stripesRect.right = textPos - 5.0;
694 FillRect(stripesRect, stripes);
695 stripesRect.left = textPos + width + 3.0;
696 stripesRect.right = r.right;
697 FillRect(stripesRect, stripes);
699 r.left = textPos - 4.0;
700 r.right = textPos + width + 2.0;
702 SetHighColor(shadow);
703 SetLowColor(darkShadow);
706 DrawString(kDisabledSeekMessage, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
710 /*****************************************************************************
711 * SeekSlider::MouseDown
712 *****************************************************************************/
714 SeekSlider::MouseDown(BPoint where)
716 if (IsEnabled() && Bounds().Contains(where))
718 SetValue(_ValueFor(where.x));
720 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
725 /*****************************************************************************
726 * SeekSlider::MouseMoved
727 *****************************************************************************/
729 SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
733 SetValue(_ValueFor(where.x));
738 /*****************************************************************************
739 * SeekSlider::MouseUp
740 *****************************************************************************/
742 SeekSlider::MouseUp(BPoint where)
751 /*****************************************************************************
752 * SeekSlider::ResizeToPreferred
753 *****************************************************************************/
755 SeekSlider::ResizeToPreferred()
757 float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
758 ResizeTo(width, 17.0);
761 /*****************************************************************************
762 * SeekSlider::SetPosition
763 *****************************************************************************/
765 SeekSlider::SetPosition(float position)
767 SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
770 /*****************************************************************************
771 * SeekSlider::_ValueFor
772 *****************************************************************************/
774 SeekSlider::_ValueFor(float xPos) const
777 float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
778 float sliderStart = (r.left + knobWidth2);
779 float sliderEnd = (r.right - knobWidth2);
780 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
781 / (sliderEnd - sliderStart - 1.0));
782 if (value < fMinValue)
784 if (value > fMaxValue)
789 /*****************************************************************************
790 * SeekSlider::_StrokeFrame
791 *****************************************************************************/
793 SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
794 rgb_color right, rgb_color bottom)
797 AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
798 AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
799 AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
800 AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
804 /*****************************************************************************
805 * SeekSlider::_BeginSeek
806 *****************************************************************************/
808 SeekSlider::_BeginSeek()
810 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
811 if (fOwner->fScrubSem >= B_OK)
812 release_sem(fOwner->fScrubSem);
815 /*****************************************************************************
817 *****************************************************************************/
821 if (fOwner->fScrubSem >= B_OK)
822 delete_sem(fOwner->fScrubSem);
823 fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
824 if (fOwner->fScrubSem >= B_OK)
825 release_sem(fOwner->fScrubSem);
828 /*****************************************************************************
829 * SeekSlider::_EndSeek
830 *****************************************************************************/
832 SeekSlider::_EndSeek()
834 if (fOwner->fScrubSem >= B_OK)
835 delete_sem(fOwner->fScrubSem);
836 fOwner->fScrubSem = B_ERROR;
840 /*****************************************************************************
842 *****************************************************************************/
843 VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
844 BMessage* message, BHandler* target)
845 : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
846 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
848 fRightSideBits(NULL),
858 BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
859 fLeftSideBits = new BBitmap(r, B_CMAP8);
860 fRightSideBits = new BBitmap(r, B_CMAP8);
861 r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
862 fKnobBits = new BBitmap(r, B_CMAP8);
867 /*****************************************************************************
868 * VolumeSlider destructor
869 *****************************************************************************/
870 VolumeSlider::~VolumeSlider()
872 delete fLeftSideBits;
873 delete fRightSideBits;
877 /*****************************************************************************
878 * VolumeSlider::AttachedToWindow
879 *****************************************************************************/
881 VolumeSlider::AttachedToWindow()
883 BControl::AttachedToWindow();
884 SetViewColor(B_TRANSPARENT_32_BIT);
887 /*****************************************************************************
888 * VolumeSlider::SetValue
889 *****************************************************************************/
891 VolumeSlider::SetValue(int32 value)
893 if (value != Value())
895 BControl::SetValue(value);
900 /*****************************************************************************
901 * VolumeSlider::SetEnabled
902 *****************************************************************************/
904 VolumeSlider::SetEnabled(bool enable)
906 if (enable != IsEnabled())
908 BControl::SetEnabled(enable);
914 /*****************************************************************************
916 *****************************************************************************/
918 VolumeSlider::Draw(BRect updateRect)
923 float sliderSideWidth = kVolumeSliderBitmapWidth;
924 float sliderStart = (r.left + sliderSideWidth);
925 float sliderEnd = (r.right - sliderSideWidth);
926 float knobPos = sliderStart
927 + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
928 / (fMaxValue - fMinValue);
929 // draw both sides (the original from Be doesn't seem
930 // to make a difference for enabled/disabled state)
931 DrawBitmapAsync(fLeftSideBits, r.LeftTop());
932 DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
933 // colors for the slider area between the two bitmaps
934 rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
935 rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
936 rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
937 rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
938 rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
939 rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
940 rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
941 rgb_color green = kGreen;
942 rgb_color greenShadow = kGreenShadow;
943 rgb_color black = kBlack;
944 rgb_color dotGrey = midShadow;
945 rgb_color dotGreen = greenShadow;
946 // make dimmed version of colors if we're disabled
949 shadow = (rgb_color){ 200, 200, 200, 255 };
950 softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
951 darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
953 light = dimmed_color_cmap8(light, background, DIM_LEVEL);
954 softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
955 green = dimmed_color_cmap8(green, background, DIM_LEVEL);
956 greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
957 black = dimmed_color_cmap8(black, background, DIM_LEVEL);
962 green = tint_color(kBackground, B_DARKEN_3_TINT);
963 greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
964 dotGreen = greenShadow;
966 // draw slider edges between bitmaps
968 AddLine(BPoint(sliderStart, r.top),
969 BPoint(sliderEnd, r.top), softShadow);
970 AddLine(BPoint(sliderStart, r.bottom),
971 BPoint(sliderEnd, r.bottom), softLight);
973 AddLine(BPoint(sliderStart, r.top),
974 BPoint(sliderEnd, r.top), black);
975 AddLine(BPoint(sliderStart, r.bottom),
976 BPoint(sliderEnd, r.bottom), light);
978 AddLine(BPoint(sliderStart, r.top),
979 BPoint(knobPos, r.top), greenShadow);
980 AddLine(BPoint(knobPos, r.top),
981 BPoint(sliderEnd, r.top), midShadow);
983 AddLine(BPoint(sliderStart, r.top),
984 BPoint(knobPos, r.top), greenShadow);
986 // fill rest inside of slider
988 r.left = sliderStart;
991 FillRect(r, B_SOLID_HIGH);
992 r.left = knobPos + 1.0;
995 SetHighColor(shadow);
996 FillRect(r, B_SOLID_HIGH);
997 // draw little dots inside
998 int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
1000 dotPos.y = r.top + 4.0;
1001 for (int32 i = 0; i < dotCount; i++)
1003 dotPos.x = sliderStart + i * 5.0 + 4.0;
1004 SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
1005 StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
1009 SetDrawingMode(B_OP_OVER); // part of knob is transparent
1010 DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
1013 fprintf(stderr, "VolumeSlider::Draw() - Error: no valid bitmaps!");
1016 /*****************************************************************************
1017 * VolumeSlider::MouseDown
1018 *****************************************************************************/
1020 VolumeSlider::MouseDown(BPoint where)
1022 if (Bounds().Contains(where) && IsEnabled())
1025 SetValue(_ValueFor(where.x));
1026 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
1030 /*****************************************************************************
1031 * VolumeSlider::MouseMoved
1032 *****************************************************************************/
1034 VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
1037 SetValue(_ValueFor(where.x));
1040 /*****************************************************************************
1041 * VolumeSlider::MouseUp
1042 *****************************************************************************/
1044 VolumeSlider::MouseUp(BPoint where)
1050 /*****************************************************************************
1051 * VolumeSlider::IsValid
1052 *****************************************************************************/
1054 VolumeSlider::IsValid() const
1056 return (fLeftSideBits && fLeftSideBits->IsValid()
1057 && fRightSideBits && fRightSideBits->IsValid()
1058 && fKnobBits && fKnobBits->IsValid());
1061 /*****************************************************************************
1062 * VolumeSlider::SetMuted
1063 *****************************************************************************/
1065 VolumeSlider::SetMuted(bool mute)
1075 /*****************************************************************************
1076 * VolumeSlider::_MakeBitmaps
1077 *****************************************************************************/
1079 VolumeSlider::_MakeBitmaps()
1083 // left side of slider
1084 memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
1085 fLeftSideBits->BitsLength());
1086 // right side of slider
1087 memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
1088 fRightSideBits->BitsLength());
1090 int32 length = fKnobBits->BitsLength();
1091 memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
1092 uint8* bits = (uint8*)fKnobBits->Bits();
1093 // black was used in the knob to represent transparency
1094 // use screen to get index for the "transarent" color used in the bitmap
1095 BScreen screen(B_MAIN_SCREEN_ID);
1096 uint8 blackIndex = screen.IndexForColor(kBlack);
1097 // replace black index with transparent index
1098 for (int32 i = 0; i < length; i++)
1099 if (bits[i] == blackIndex)
1100 bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
1104 // make ghosted versions of the bitmaps
1105 dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
1106 dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
1107 dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
1111 // replace green color (and shadow) in left slider side
1112 bits = (uint8*)fLeftSideBits->Bits();
1113 length = fLeftSideBits->BitsLength();
1114 uint8 greenIndex = screen.IndexForColor(kGreen);
1115 uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
1116 rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
1117 rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
1118 uint8 replaceIndex = screen.IndexForColor(shadow);
1119 uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
1120 for (int32 i = 0; i < length; i++)
1122 if (bits[i] == greenIndex)
1123 bits[i] = replaceIndex;
1124 else if (bits[i] == greenShadowIndex)
1125 bits[i] = replaceShadowIndex;
1131 /*****************************************************************************
1132 * VolumeSlider::_ValueFor
1133 *****************************************************************************/
1135 VolumeSlider::_ValueFor(float xPos) const
1138 float sliderStart = (r.left + kVolumeSliderBitmapWidth);
1139 float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
1140 int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
1141 / (sliderEnd - sliderStart - 1.0));
1142 if (value < fMinValue)
1144 if (value > fMaxValue)
1149 /*****************************************************************************
1150 * PositionInfoView::PositionInfoView
1151 *****************************************************************************/
1152 PositionInfoView::PositionInfoView( BRect frame, const char* name,
1153 intf_thread_t * p_interface )
1154 : BView( frame, name, B_FOLLOW_NONE,
1155 B_WILL_DRAW | B_PULSE_NEEDED | B_FULL_UPDATE_ON_RESIZE ),
1156 fMode( MODE_SMALL ),
1157 fCurrentFileIndex( -1 ),
1158 fCurrentFileSize( -1 ),
1159 fCurrentTitleIndex( -1 ),
1160 fCurrentTitleSize( -1 ),
1161 fCurrentChapterIndex( -1 ),
1162 fCurrentChapterSize( -1 ),
1164 fTimeString( "-:--:--" ),
1165 fLastPulseUpdate( system_time() ),
1166 fStackedWidthCache( 0.0 ),
1167 fStackedHeightCache( 0.0 )
1169 p_intf = p_interface;
1171 SetViewColor( B_TRANSPARENT_32_BIT );
1172 SetLowColor( kBlack );
1173 SetHighColor( 0, 255, 0, 255 );
1174 SetFontSize( 11.0 );
1177 /*****************************************************************************
1178 * PositionInfoView::~PositionInfoView
1179 *****************************************************************************/
1180 PositionInfoView::~PositionInfoView()
1184 /*****************************************************************************
1185 * PositionInfoView::Draw
1186 *****************************************************************************/
1188 PositionInfoView::Draw( BRect updateRect )
1190 rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
1191 rgb_color shadow = tint_color( background, B_DARKEN_1_TINT );
1192 rgb_color darkShadow = tint_color( background, B_DARKEN_4_TINT );
1193 rgb_color light = tint_color( background, B_LIGHTEN_MAX_TINT );
1194 rgb_color softLight = tint_color( background, B_LIGHTEN_1_TINT );
1196 BRect r( Bounds() );
1197 BeginLineArray( 8 );
1198 AddLine( BPoint( r.left, r.bottom ),
1199 BPoint( r.left, r.top ), shadow );
1200 AddLine( BPoint( r.left + 1.0, r.top ),
1201 BPoint( r.right, r.top ), shadow );
1202 AddLine( BPoint( r.right, r.top + 1.0 ),
1203 BPoint( r.right, r.bottom ), softLight );
1204 AddLine( BPoint( r.right - 1.0, r.bottom ),
1205 BPoint( r.left + 1.0, r.bottom ), softLight );
1206 r.InsetBy( 1.0, 1.0 );
1207 AddLine( BPoint( r.left, r.bottom ),
1208 BPoint( r.left, r.top ), darkShadow );
1209 AddLine( BPoint( r.left + 1.0, r.top ),
1210 BPoint( r.right, r.top ), darkShadow );
1211 AddLine( BPoint( r.right, r.top + 1.0 ),
1212 BPoint( r.right, r.bottom ), light );
1213 AddLine( BPoint( r.right - 1.0, r.bottom ),
1214 BPoint( r.left + 1.0, r.bottom ), light );
1217 r.InsetBy( 1.0, 1.0 );
1218 FillRect( r, B_SOLID_LOW );
1221 GetFontHeight( &fh );
1226 float width = StringWidth( fTimeString.String() );
1227 DrawString( fTimeString.String(),
1228 BPoint( r.left + r.Width() / 2.0 - width / 2.0,
1229 r.top + r.Height() / 2.0 + fh.ascent / 2.0 - 1.0 ) );
1236 BFont smallFont = font;
1237 BFont bigFont = font;
1238 BFont tinyFont = font;
1239 smallFont.SetSize( r.Height() / 5.0 );
1240 bigFont.SetSize( r.Height() / 3.0 );
1241 tinyFont.SetSize( r.Height() / 7.0 );
1242 float timeHeight = r.Height() / 2.5;
1243 float height = ( r.Height() - timeHeight ) / 3.0;
1244 SetFont( &tinyFont );
1245 SetHighColor( 0, 180, 0, 255 );
1246 DrawString( "File", BPoint( r.left + 3.0, r.top + height ) );
1247 DrawString( "Title", BPoint( r.left + 3.0, r.top + 2.0 * height ) );
1248 DrawString( "Chapter", BPoint( r.left + 3.0, r.top + 3.0 * height ) );
1249 SetFont( &smallFont );
1251 SetHighColor( 0, 255, 0, 255 );
1253 _MakeString( helper, fCurrentFileIndex, fCurrentFileSize );
1254 float width = StringWidth( helper.String() );
1255 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + height ) );
1257 _MakeString( helper, fCurrentTitleIndex, fCurrentTitleSize );
1258 width = StringWidth( helper.String() );
1259 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 2.0 * height ) );
1261 _MakeString( helper, fCurrentChapterIndex, fCurrentChapterSize );
1262 width = StringWidth( helper.String() );
1263 DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 3.0 * height ) );
1265 SetFont( &bigFont );
1266 width = StringWidth( fTimeString.String() );
1267 DrawString( fTimeString.String(),
1268 BPoint( r.left + r.Width() / 2.0 - width / 2.0,
1275 /*****************************************************************************
1276 * PositionInfoView::ResizeToPreferred
1277 *****************************************************************************/
1279 PositionInfoView::ResizeToPreferred()
1281 float width, height;
1282 GetPreferredSize( &width, &height );
1283 ResizeTo( width, height );
1286 /*****************************************************************************
1287 * PositionInfoView::GetPreferredSize
1288 *****************************************************************************/
1290 PositionInfoView::GetPreferredSize( float* width, float* height )
1292 if ( width && height )
1294 *width = 5.0 + ceilf( StringWidth( "0:00:00" ) ) + 5.0;
1296 GetFontHeight( &fh );
1297 *height = 3.0 + ceilf( fh.ascent ) + 3.0;
1298 fStackedWidthCache = *width * 1.2;
1299 fStackedHeightCache = *height * 2.7;
1303 /*****************************************************************************
1304 * PositionInfoView::Pulse
1305 *****************************************************************************/
1307 PositionInfoView::Pulse()
1309 // allow for Pulse frequency to be higher, MediaControlView needs it
1310 bigtime_t now = system_time();
1311 if ( now - fLastPulseUpdate > 900000 )
1314 p_intf->p_sys->p_wrapper->getPlaylistInfo( index, size );
1315 SetFile( index, size );
1316 p_intf->p_sys->p_wrapper->TitleInfo( index, size );
1317 SetTitle( index, size );
1318 p_intf->p_sys->p_wrapper->ChapterInfo( index, size );
1319 SetChapter( index, size );
1320 SetTime( p_intf->p_sys->p_wrapper->getTimeAsString() );
1321 fLastPulseUpdate = now;
1325 /*****************************************************************************
1326 * PositionInfoView::GetBigPreferredSize
1327 *****************************************************************************/
1329 PositionInfoView::GetBigPreferredSize( float* width, float* height )
1331 if ( width && height )
1333 *width = fStackedWidthCache;
1334 *height = fStackedHeightCache;
1338 /*****************************************************************************
1339 * PositionInfoView::SetMode
1340 *****************************************************************************/
1342 PositionInfoView::SetMode( uint32 mode )
1344 if ( fMode != mode )
1347 _InvalidateContents();
1351 /*****************************************************************************
1352 * PositionInfoView::SetFile
1353 *****************************************************************************/
1355 PositionInfoView::SetFile( int32 index, int32 size )
1357 if ( fCurrentFileIndex != index || fCurrentFileSize != size )
1359 fCurrentFileIndex = index;
1360 fCurrentFileSize = size;
1361 _InvalidateContents();
1365 /*****************************************************************************
1366 * PositionInfoView::SetTitle
1367 *****************************************************************************/
1369 PositionInfoView::SetTitle( int32 index, int32 size )
1371 if ( fCurrentTitleIndex != index || fCurrentFileSize != size )
1373 fCurrentTitleIndex = index;
1374 fCurrentTitleSize = size;
1375 _InvalidateContents();
1379 /*****************************************************************************
1380 * PositionInfoView::SetChapter
1381 *****************************************************************************/
1383 PositionInfoView::SetChapter( int32 index, int32 size )
1385 if ( fCurrentChapterIndex != index || fCurrentFileSize != size )
1387 fCurrentChapterIndex = index;
1388 fCurrentChapterSize = size;
1389 _InvalidateContents();
1393 /*****************************************************************************
1394 * PositionInfoView::SetTime
1395 *****************************************************************************/
1397 PositionInfoView::SetTime( int32 seconds )
1399 if ( fSeconds != seconds )
1403 int32 minutes = seconds / 60;
1404 int32 hours = minutes / 60;
1405 seconds -= minutes * 60 - hours * 60 * 60;
1406 minutes -= hours * 60;
1407 fTimeString.SetTo( "" );
1408 fTimeString << hours << ":" << minutes << ":" << seconds;
1411 fTimeString.SetTo( "-:--:--" );
1414 _InvalidateContents();
1418 /*****************************************************************************
1419 * PositionInfoView::SetTime
1420 *****************************************************************************/
1422 PositionInfoView::SetTime( const char* string )
1424 fTimeString.SetTo( string );
1425 _InvalidateContents();
1428 /*****************************************************************************
1429 * PositionInfoView::_InvalidateContents
1430 *****************************************************************************/
1432 PositionInfoView::_InvalidateContents( uint32 which )
1434 BRect r( Bounds() );
1435 r.InsetBy( 2.0, 2.0 );
1439 /*****************************************************************************
1440 * PositionInfoView::_InvalidateContents
1441 *****************************************************************************/
1443 PositionInfoView::_MakeString( BString& into, int32 index, int32 maxIndex ) const