/*****************************************************************************
* MediaControlView.cpp: beos interface
*****************************************************************************
- * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: MediaControlView.cpp,v 1.2 2002/09/18 11:50:47 tcastley Exp $
+ * Copyright (C) 1999, 2000, 2001 the VideoLAN team
+ * $Id$
*
* Authors: Tony Castley <tony@castley.net>
+ * Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/* System headers */
#include <InterfaceKit.h>
#include <AppKit.h>
-#include <string.h>
+#include <String.h>
/* VLC headers */
#include <vlc/vlc.h>
-#include <vlc/intf.h>
+#include <vlc_interface.h>
+extern "C"
+{
+ #include <audio_output.h>
+}
/* BeOS interface headers */
-#include "MsgVals.h"
#include "Bitmaps.h"
+#include "DrawingTidbits.h"
+#include "InterfaceWindow.h"
+#include "MsgVals.h"
#include "TransportButton.h"
+#include "ListViews.h"
#include "MediaControlView.h"
+#define BORDER_INSET 6.0
+#define MIN_SPACE 4.0
+#define SPEAKER_SLIDER_DIST 6.0
+#define VOLUME_MIN_WIDTH 70.0
+#define DIM_LEVEL 0.4
+#define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0
+#define SEEK_SLIDER_KNOB_WIDTH 8.0
+
+// slider colors are hardcoded here, because that's just
+// what they currently are within those bitmaps
+const rgb_color kGreen = (rgb_color){ 152, 203, 152, 255 };
+const rgb_color kGreenShadow = (rgb_color){ 102, 152, 102, 255 };
+const rgb_color kBackground = (rgb_color){ 216, 216, 216, 255 };
+const rgb_color kSeekGreen = (rgb_color){ 171, 221, 161, 255 };
+const rgb_color kSeekGreenShadow = (rgb_color){ 144, 186, 136, 255 };
+const rgb_color kSeekRed = (rgb_color){ 255, 0, 0, 255 };
+const rgb_color kSeekRedLight = (rgb_color){ 255, 152, 152, 255 };
+const rgb_color kSeekRedShadow = (rgb_color){ 178, 0, 0, 255 };
+
+#define DISABLED_SEEK_MESSAGE _("Drop files to play")
+#define SEEKSLIDER_RANGE 2048
+
+enum
+{
+ MSG_REWIND = 'rwnd',
+ MSG_FORWARD = 'frwd',
+ MSG_SKIP_BACKWARDS = 'skpb',
+ MSG_SKIP_FORWARD = 'skpf',
+};
+
+// constructor
+MediaControlView::MediaControlView( intf_thread_t * _p_intf, BRect frame)
+ : BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
+ B_PLAIN_BORDER),
+ p_intf( _p_intf ),
+ fCurrentRate(INPUT_RATE_DEFAULT),
+ fCurrentStatus(-1),
+ fBottomControlHeight(0.0),
+ fIsEnabled( true )
+{
+ BRect frame(0.0, 0.0, 10.0, 10.0);
+
+ // Seek Slider
+ fSeekSlider = new SeekSlider( p_intf, frame, "seek slider", this );
+ fSeekSlider->SetValue(0);
+ fSeekSlider->ResizeToPreferred();
+ AddChild( fSeekSlider );
+
+ // Buttons
+ // Skip Back
+ frame.SetRightBottom(kSkipButtonSize);
+ fBottomControlHeight = kRewindBitmapHeight - 1.0;
+ fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
+ kSkipBackBitmapBits,
+ kPressedSkipBackBitmapBits,
+ kDisabledSkipBackBitmapBits,
+ new BMessage(MSG_SKIP_BACKWARDS));
+ AddChild( fSkipBack );
+
+ // Play Pause
+ frame.SetRightBottom(kPlayButtonSize);
+ if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
+ fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
+ fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
+ kPlayButtonBitmapBits,
+ kPressedPlayButtonBitmapBits,
+ kDisabledPlayButtonBitmapBits,
+ kPlayingPlayButtonBitmapBits,
+ kPressedPlayingPlayButtonBitmapBits,
+ kPausedPlayButtonBitmapBits,
+ kPressedPausedPlayButtonBitmapBits,
+ new BMessage(START_PLAYBACK));
+
+ AddChild( fPlayPause );
+
+ // Skip Foward
+ frame.SetRightBottom(kSkipButtonSize);
+ fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
+ kSkipForwardBitmapBits,
+ kPressedSkipForwardBitmapBits,
+ kDisabledSkipForwardBitmapBits,
+ new BMessage(MSG_SKIP_FORWARD));
+ AddChild( fSkipForward );
+
+ // Forward
+ fForward = new TransportButton(frame, B_EMPTY_STRING,
+ kForwardBitmapBits,
+ kPressedForwardBitmapBits,
+ kDisabledForwardBitmapBits,
+ new BMessage(MSG_FORWARD));
+// AddChild( fForward );
+
+ // Rewind
+ fRewind = new TransportButton(frame, B_EMPTY_STRING,
+ kRewindBitmapBits,
+ kPressedRewindBitmapBits,
+ kDisabledRewindBitmapBits,
+ new BMessage(MSG_REWIND));
+// AddChild( fRewind );
+
+ // Stop
+ frame.SetRightBottom(kStopButtonSize);
+ if (fBottomControlHeight < kStopBitmapHeight - 1.0)
+ fBottomControlHeight = kStopBitmapHeight - 1.0;
+ fStop = new TransportButton(frame, B_EMPTY_STRING,
+ kStopButtonBitmapBits,
+ kPressedStopButtonBitmapBits,
+ kDisabledStopButtonBitmapBits,
+ new BMessage(STOP_PLAYBACK));
+ AddChild( fStop );
+
+ // Mute
+ frame.SetRightBottom(kSpeakerButtonSize);
+ if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
+ fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
+ fMute = new TransportButton(frame, B_EMPTY_STRING,
+ kSpeakerIconBits,
+ kPressedSpeakerIconBits,
+ kSpeakerIconBits,
+ new BMessage(VOLUME_MUTE));
-MediaControlView::MediaControlView( BRect frame )
- : BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER )
-{
- float xStart = HORZ_SPACE;
- float yStart = VERT_SPACE;
- fScrubSem = B_ERROR;
-
- BRect controlRect = BRect(xStart,yStart,
- frame.Width() - (HORZ_SPACE * 2), 15);
-
- /* Seek Status */
- rgb_color fill_color = {0,255,0};
- p_seek = new SeekSlider(controlRect, this, 0, 100, B_TRIANGLE_THUMB);
- p_seek->SetValue(0);
- p_seek->UseFillColor(true, &fill_color);
- AddChild( p_seek );
- yStart += 15 + VERT_SPACE;
-
-
- /* Buttons */
- /* Slow play */
- controlRect.SetLeftTop(BPoint(xStart, yStart));
- controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
- xStart += kRewindBitmapWidth;
- p_slow = new TransportButton(controlRect, B_EMPTY_STRING,
- kSkipBackBitmapBits,
- kPressedSkipBackBitmapBits,
- kDisabledSkipBackBitmapBits,
- new BMessage(SLOWER_PLAY));
- AddChild( p_slow );
-
- /* Play Pause */
- controlRect.SetLeftTop(BPoint(xStart, yStart));
- controlRect.SetRightBottom(controlRect.LeftTop() + kPlayButtonSize);
- xStart += kPlayPauseBitmapWidth + 1.0;
- p_play = new PlayPauseButton(controlRect, B_EMPTY_STRING,
- kPlayButtonBitmapBits,
- kPressedPlayButtonBitmapBits,
- kDisabledPlayButtonBitmapBits,
- kPlayingPlayButtonBitmapBits,
- kPressedPlayingPlayButtonBitmapBits,
- kPausedPlayButtonBitmapBits,
- kPressedPausedPlayButtonBitmapBits,
- new BMessage(START_PLAYBACK));
-
- AddChild( p_play );
-
- /* Fast Foward */
- controlRect.SetLeftTop(BPoint(xStart, yStart));
- controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
- xStart += kRewindBitmapWidth;
- p_fast = new TransportButton(controlRect, B_EMPTY_STRING,
- kSkipForwardBitmapBits,
- kPressedSkipForwardBitmapBits,
- kDisabledSkipForwardBitmapBits,
- new BMessage(FASTER_PLAY));
- AddChild( p_fast );
-
- /* Stop */
- controlRect.SetLeftTop(BPoint(xStart, yStart));
- controlRect.SetRightBottom(controlRect.LeftTop() + kStopButtonSize);
- xStart += kStopBitmapWidth;
- p_stop = new TransportButton(controlRect, B_EMPTY_STRING,
- kStopButtonBitmapBits,
- kPressedStopButtonBitmapBits,
- kDisabledStopButtonBitmapBits,
- new BMessage(STOP_PLAYBACK));
- AddChild( p_stop );
-
- controlRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
- controlRect.SetRightBottom(controlRect.LeftTop() + kSpeakerButtonSize);
- xStart += kSpeakerIconBitmapWidth;
-
- p_mute = new TransportButton(controlRect, B_EMPTY_STRING,
- kSpeakerIconBits,
- kPressedSpeakerIconBits,
- kSpeakerIconBits,
- new BMessage(VOLUME_MUTE));
-
- AddChild( p_mute );
-
- /* Volume Slider */
- p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
- AOUT_VOLUME_MIN, AOUT_VOLUME_MAX);
- p_vol->SetValue(AOUT_VOLUME_DEFAULT);
- p_vol->UseFillColor(true, &fill_color);
- AddChild( p_vol );
+ AddChild( fMute );
+ // Volume Slider
+ fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
+ kVolumeSliderBitmapHeight - 1.0),
+ "volume slider", 1, AOUT_VOLUME_MAX,
+ new BMessage(VOLUME_CHG));
+ fVolumeSlider->SetValue( config_GetInt( p_intf, "volume" ) );
+ AddChild( fVolumeSlider );
+
+ // Position Info View
+ fPositionInfo = new PositionInfoView(BRect(0.0, 0.0, 10.0, 10.0), "led",
+ p_intf);
+ fPositionInfo->ResizeToPreferred();
+ AddChild( fPositionInfo );
}
+// destructor
MediaControlView::~MediaControlView()
{
}
-void MediaControlView::MessageReceived(BMessage *message)
+// AttachedToWindow
+void
+MediaControlView::AttachedToWindow()
+{
+ // we are now a valid BHandler
+ fRewind->SetTarget(this);
+ fForward->SetTarget(this);
+ fSkipBack->SetTarget(this);
+ fSkipForward->SetTarget(this);
+ fVolumeSlider->SetTarget(Window());
+
+ BRect r(_MinFrame());
+ if (BMenuBar* menuBar = Window()->KeyMenuBar()) {
+ float width, height;
+ menuBar->GetPreferredSize(&width, &height);
+// r.bottom += menuBar->Bounds().Height();
+ r.bottom += height;
+ // see that our calculated minimal width is not smaller than what
+ // the menubar can be
+ width -= r.Width();
+ if (width > 0.0)
+ r.right += width;
+ }
+
+ Window()->SetSizeLimits(r.Width(), r.Width() * 1.8, r.Height(), r.Height() * 1.3);
+ if (!Window()->Bounds().Contains(r))
+ Window()->ResizeTo(r.Width(), r.Height());
+ else
+ FrameResized(Bounds().Width(), Bounds().Height());
+
+ // get pulse message every two frames
+ Window()->SetPulseRate(80000);
+}
+
+// FrameResized
+void
+MediaControlView::FrameResized(float width, float height)
+{
+ BRect r(Bounds());
+ // make sure we don't leave dirty pixels
+ // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
+ if (fOldBounds.Width() < r.Width())
+ Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
+ fOldBounds.right, fOldBounds.bottom - 1.0));
+ else
+ Invalidate(BRect(r.right, r.top + 1.0,
+ r.right, r.bottom - 1.0));
+ if (fOldBounds.Height() < r.Height())
+ Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
+ fOldBounds.right - 1.0, fOldBounds.bottom));
+ else
+ Invalidate(BRect(r.left + 1.0, r.bottom,
+ r.right - 1.0, r.bottom));
+ // remember for next time
+ fOldBounds = r;
+ // layout controls
+ r.InsetBy(BORDER_INSET, BORDER_INSET);
+ _LayoutControls(r);
+}
+
+// GetPreferredSize
+void
+MediaControlView::GetPreferredSize(float* width, float* height)
+{
+ if (width && height)
+ {
+ BRect r(_MinFrame());
+ *width = r.Width();
+ *height = r.Height();
+ }
+}
+
+// MessageReceived
+void
+MediaControlView::MessageReceived(BMessage* message)
+{
+ switch (message->what)
+ {
+ case MSG_REWIND:
+ break;
+ case MSG_FORWARD:
+ break;
+ case MSG_SKIP_BACKWARDS:
+ Window()->PostMessage(NAVIGATE_PREV);
+ break;
+ case MSG_SKIP_FORWARD:
+ Window()->PostMessage(NAVIGATE_NEXT);
+ break;
+ default:
+ BBox::MessageReceived(message);
+ break;
+ }
+}
+
+// Pulse
+void
+MediaControlView::Pulse()
{
+ InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
+ if (window && window->IsStopped())
+ fPlayPause->SetStopped();
+
+ unsigned short i_volume;
+ aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
+ fVolumeSlider->SetValue( i_volume );
}
-void MediaControlView::SetProgress(uint64 seek, uint64 size)
+// SetProgress
+void
+MediaControlView::SetProgress( float position )
{
- p_seek->SetPosition((float)seek/size);
+ fSeekSlider->SetPosition( position );
}
-void MediaControlView::SetStatus(int status, int rate)
+// SetStatus
+void
+MediaControlView::SetStatus(int status, int rate)
{
+ // we need to set the button status periodically
+ // (even if it is the same) to get a blinking button
+ fCurrentStatus = status;
switch( status )
{
case PLAYING_S:
- case FORWARD_S:
- case BACKWARD_S:
- case START_S:
- p_play->SetPlaying();
+ case OPENNING_S:
+ case BUFFERING_S:
+ fPlayPause->SetPlaying();
break;
case PAUSE_S:
- p_play->SetPaused();
+ fPlayPause->SetPaused();
break;
- case UNDEF_S:
- case NOT_STARTED_S:
default:
- p_play->SetStopped();
+ fPlayPause->SetStopped();
break;
}
- if ( rate < DEFAULT_RATE )
+ if (rate != fCurrentRate)
+ {
+ fCurrentRate = rate;
+ if ( rate < INPUT_RATE_DEFAULT )
+ {
+ // TODO: ...
+ }
+ }
+}
+
+// SetEnabled
+void
+MediaControlView::SetEnabled(bool enabled)
+{
+ if( ( enabled && fIsEnabled ) ||
+ ( !enabled && !fIsEnabled ) )
+ {
+ /* do not redraw if it is not necessary */
+ return;
+ }
+
+ if( LockLooper() )
{
+ fSkipBack->SetEnabled( enabled );
+ fPlayPause->SetEnabled( enabled );
+ fSkipForward->SetEnabled( enabled );
+ fStop->SetEnabled( enabled );
+ fMute->SetEnabled( enabled );
+ fVolumeSlider->SetEnabled( enabled );
+ fSeekSlider->SetEnabled( enabled );
+ fRewind->SetEnabled( enabled );
+ fForward->SetEnabled( enabled );
+ UnlockLooper();
+ fIsEnabled = enabled;
}
}
-void MediaControlView::SetEnabled(bool enabled)
+// SetAudioEnabled
+void
+MediaControlView::SetAudioEnabled(bool enabled)
+{
+ fMute->SetEnabled(enabled);
+ fVolumeSlider->SetEnabled(enabled);
+}
+
+// GetVolume
+uint32
+MediaControlView::GetVolume() const
{
- p_slow->SetEnabled(enabled);
- p_play->SetEnabled(enabled);
- p_fast->SetEnabled(enabled);
- p_stop->SetEnabled(enabled);
- p_mute->SetEnabled(enabled);
- p_vol->SetEnabled(enabled);
- p_seek->SetEnabled(enabled);
+ return fVolumeSlider->Value();
}
-uint32 MediaControlView::GetSeekTo()
+// SetSkippable
+void
+MediaControlView::SetSkippable(bool backward, bool forward)
{
- return p_seek->seekTo;
+ fSkipBack->SetEnabled(backward);
+ fSkipForward->SetEnabled(forward);
}
-uint32 MediaControlView::GetVolume()
+// SetMuted
+void
+MediaControlView::SetMuted(bool mute)
{
- return p_vol->Value();
+ fVolumeSlider->SetMuted(mute);
+}
+
+// _LayoutControls
+void
+MediaControlView::_LayoutControls(BRect frame) const
+{
+ // seek slider
+ BRect r(frame);
+ // calculate absolutly minimal width
+ float minWidth = fSkipBack->Bounds().Width();
+// minWidth += fRewind->Bounds().Width();
+ minWidth += fStop->Bounds().Width();
+ minWidth += fPlayPause->Bounds().Width();
+// minWidth += fForward->Bounds().Width();
+ minWidth += fSkipForward->Bounds().Width();
+ minWidth += fMute->Bounds().Width();
+ minWidth += VOLUME_MIN_WIDTH;
+
+ // layout time slider and info view
+ float width, height;
+ fPositionInfo->GetBigPreferredSize( &width, &height );
+ float ratio = width / height;
+ width = r.Height() * ratio;
+ if (frame.Width() - minWidth - MIN_SPACE >= width
+ && frame.Height() >= height)
+ {
+ r.right = r.left + width;
+ fPositionInfo->SetMode(PositionInfoView::MODE_BIG);
+ _LayoutControl(fPositionInfo, r, true, true);
+ frame.left = r.right + MIN_SPACE;
+ r.left = frame.left;
+ r.right = frame.right;
+ // r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
+ r.bottom = r.top + fSeekSlider->Bounds().Height();
+ _LayoutControl(fSeekSlider, r, true);
+ }
+ else
+ {
+ fPositionInfo->GetPreferredSize( &width, &height );
+ fPositionInfo->SetMode(PositionInfoView::MODE_SMALL);
+ fPositionInfo->ResizeTo(width, height);
+ r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
+ r.right = r.left + fPositionInfo->Bounds().Width();
+ _LayoutControl(fPositionInfo, r, true );
+ r.left = r.right + MIN_SPACE;
+ r.right = frame.right;
+ _LayoutControl(fSeekSlider, r, true);
+ }
+ float currentWidth = frame.Width();
+ float space = (currentWidth - minWidth) / 6.0;//8.0;
+ // apply weighting
+ space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
+ // layout controls with "space" inbetween
+ r.left = frame.left;
+ r.top = r.bottom + MIN_SPACE + 1.0;
+ r.bottom = frame.bottom;
+ // skip back
+ r.right = r.left + fSkipBack->Bounds().Width();
+ _LayoutControl(fSkipBack, r);
+ // rewind
+// r.left = r.right + space;
+// r.right = r.left + fRewind->Bounds().Width();
+// _LayoutControl(fRewind, r);
+ // stop
+ r.left = r.right + space;
+ r.right = r.left + fStop->Bounds().Width();
+ _LayoutControl(fStop, r);
+ // play/pause
+ r.left = r.right + space;
+ r.right = r.left + fPlayPause->Bounds().Width();
+ _LayoutControl(fPlayPause, r);
+ // forward
+// r.left = r.right + space;
+// r.right = r.left + fForward->Bounds().Width();
+// _LayoutControl(fForward, r);
+ // skip forward
+ r.left = r.right + space;
+ r.right = r.left + fSkipForward->Bounds().Width();
+ _LayoutControl(fSkipForward, r);
+ // speaker icon
+ r.left = r.right + space + space;
+ r.right = r.left + fMute->Bounds().Width();
+ _LayoutControl(fMute, r);
+ // volume slider
+ r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
+ r.right = frame.right;
+ _LayoutControl(fVolumeSlider, r, true);
}
+// _MinFrame
+BRect
+MediaControlView::_MinFrame() const
+{
+ // add up width of controls along bottom (seek slider will likely adopt)
+ float minWidth = 2 * BORDER_INSET;
+ minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
+// minWidth += fRewind->Bounds().Width() + MIN_SPACE;
+ minWidth += fStop->Bounds().Width() + MIN_SPACE;
+ minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
+// minWidth += fForward->Bounds().Width() + MIN_SPACE;
+ minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
+ minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
+ minWidth += VOLUME_MIN_WIDTH;
+
+ // add up height of seek slider and heighest control on bottom
+ float minHeight = 2 * BORDER_INSET;
+ minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
+ minHeight += fBottomControlHeight;
+ return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
+}
+
+// _LayoutControl
+void
+MediaControlView::_LayoutControl(BView* view, BRect frame,
+ bool resizeWidth, bool resizeHeight) const
+{
+ if (!resizeHeight)
+ // center vertically
+ frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
+ if (!resizeWidth)
+ //center horizontally
+ frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
+ view->MoveTo(frame.LeftTop());
+ float width = resizeWidth ? frame.Width() : view->Bounds().Width();
+ float height = resizeHeight ? frame.Height() : view->Bounds().Height();
+ if (resizeWidth || resizeHeight)
+ view->ResizeTo(width, height);
+}
+
+
/*****************************************************************************
- * MediaSlider
+ * SeekSlider
*****************************************************************************/
-MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
- int32 i_min, int32 i_max )
- :BSlider(frame, NULL, NULL, p_message, i_min, i_max )
+SeekSlider::SeekSlider( intf_thread_t * _p_intf,
+ BRect frame, const char* name, MediaControlView *owner )
+ : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+ p_intf(_p_intf),
+ fOwner(owner),
+ fTracking(false)
{
+ BFont font(be_plain_font);
+ font.SetSize(9.0);
+ SetFont(&font);
+}
+SeekSlider::~SeekSlider()
+{
}
-MediaSlider::~MediaSlider()
+/*****************************************************************************
+ * VolumeSlider::AttachedToWindow
+ *****************************************************************************/
+void
+SeekSlider::AttachedToWindow()
{
+ BControl::AttachedToWindow();
+ SetViewColor(B_TRANSPARENT_32_BIT);
+}
+/*****************************************************************************
+ * VolumeSlider::Draw
+ *****************************************************************************/
+void
+SeekSlider::Draw(BRect updateRect)
+{
+ BRect r(Bounds());
+ float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
+ float sliderStart = (r.left + knobWidth2);
+ float sliderEnd = (r.right - knobWidth2);
+ float knobPos = sliderStart
+ + floorf((sliderEnd - sliderStart - 1.0) * Value()
+ / SEEKSLIDER_RANGE);
+ // draw both sides (the original from Be doesn't seem
+ // to make a difference for enabled/disabled state)
+// DrawBitmapAsync(fLeftSideBits, r.LeftTop());
+// DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
+ // colors for the slider area between the two bitmaps
+ rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
+ rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
+ rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
+ rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
+ rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
+ rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
+ rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
+ rgb_color green = kSeekGreen;
+ rgb_color greenShadow = kSeekGreenShadow;
+ rgb_color black = kBlack;
+ rgb_color dotGrey = midShadow;
+ rgb_color dotGreen = greenShadow;
+ // draw frame
+ _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
+ r.InsetBy(1.0, 1.0);
+ _StrokeFrame(r, black, black, light, light);
+ if (IsEnabled())
+ {
+ r.InsetBy(1.0, 1.0);
+ // inner shadow
+ _StrokeFrame(r, greenShadow, greenShadow, green, green);
+ r.top++;
+ r.left++;
+ _StrokeFrame(r, greenShadow, greenShadow, green, green);
+ // inside area
+ r.InsetBy(1.0, 1.0);
+ SetHighColor(green);
+ FillRect(r);
+ // dots
+ int32 dotCount = (int32)(r.Width() / 6.0);
+ BPoint dotPos;
+ dotPos.y = r.top + 2.0;
+ SetHighColor(dotGreen);
+ for (int32 i = 0; i < dotCount; i++)
+ {
+ dotPos.x = sliderStart + i * 6.0 + 5.0;
+ StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
+ }
+ // slider handle
+ r.top -= 4.0;
+ r.bottom += 3.0;
+ r.left = knobPos - knobWidth2;
+ r.right = knobPos + knobWidth2;
+ // black outline
+ float handleBottomSize = 2.0;
+ float handleArrowSize = 6.0;
+ BeginLineArray(10);
+ // upper handle
+ AddLine(BPoint(r.left, r.top + handleBottomSize),
+ BPoint(r.left, r.top), black);
+ AddLine(BPoint(r.left + 1.0, r.top),
+ BPoint(r.right, r.top), black);
+ AddLine(BPoint(r.right, r.top + 1.0),
+ BPoint(r.right, r.top + handleBottomSize), black);
+ AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
+ BPoint(knobPos, r.top + handleArrowSize), black);
+ AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
+ BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
+ // lower handle
+ AddLine(BPoint(r.left, r.bottom),
+ BPoint(r.left, r.bottom - handleBottomSize), black);
+ AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
+ BPoint(knobPos, r.bottom - handleArrowSize), black);
+ AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
+ BPoint(r.right, r.bottom - handleBottomSize), black);
+ AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
+ BPoint(r.right, r.bottom), black);
+ AddLine(BPoint(r.right - 1.0, r.bottom),
+ BPoint(r.left + 1.0, r.bottom), black);
+ EndLineArray();
+ // inner red light and shadow lines
+ r.InsetBy(1.0, 1.0);
+ handleBottomSize--;
+ handleArrowSize -= 2.0;
+ BeginLineArray(10);
+ // upper handle
+ AddLine(BPoint(r.left, r.top + handleBottomSize),
+ BPoint(r.left, r.top), kSeekRedLight);
+ AddLine(BPoint(r.left + 1.0, r.top),
+ BPoint(r.right, r.top), kSeekRedLight);
+ AddLine(BPoint(r.right, r.top + 1.0),
+ BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
+ AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
+ BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
+ AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
+ BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
+ // lower handle
+ AddLine(BPoint(r.left, r.bottom),
+ BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
+ AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
+ BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
+ AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
+ BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
+ AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
+ BPoint(r.right, r.bottom), kSeekRedShadow);
+ AddLine(BPoint(r.right - 1.0, r.bottom),
+ BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
+ EndLineArray();
+ // fill rest of handles with red
+ SetHighColor(kSeekRed);
+ r.InsetBy(1.0, 1.0);
+ handleArrowSize -= 2.0;
+ BPoint arrow[3];
+ // upper handle arrow
+ arrow[0].x = r.left;
+ arrow[0].y = r.top;
+ arrow[1].x = r.right;
+ arrow[1].y = r.top;
+ arrow[2].x = knobPos;
+ arrow[2].y = r.top + handleArrowSize;
+ FillPolygon(arrow, 3);
+ // lower handle arrow
+ arrow[0].x = r.left;
+ arrow[0].y = r.bottom;
+ arrow[1].x = r.right;
+ arrow[1].y = r.bottom;
+ arrow[2].x = knobPos;
+ arrow[2].y = r.bottom - handleArrowSize;
+ FillPolygon(arrow, 3);
+ }
+ else
+ {
+ r.InsetBy(1.0, 1.0);
+ _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
+ r.InsetBy(1.0, 1.0);
+ _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
+ r.InsetBy(1.0, 1.0);
+ SetHighColor(darkShadow);
+ SetLowColor(shadow);
+ // stripes
+ float width = floorf(StringWidth(DISABLED_SEEK_MESSAGE));
+ float textPos = r.left + r.Width() / 2.0 - width / 2.0;
+ pattern stripes = {{ 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 }};
+ BRect stripesRect(r);
+ stripesRect.right = textPos - 5.0;
+ FillRect(stripesRect, stripes);
+ stripesRect.left = textPos + width + 3.0;
+ stripesRect.right = r.right;
+ FillRect(stripesRect, stripes);
+ // info text
+ r.left = textPos - 4.0;
+ r.right = textPos + width + 2.0;
+ FillRect(r);
+ SetHighColor(shadow);
+ SetLowColor(darkShadow);
+ font_height fh;
+ GetFontHeight(&fh);
+ DrawString(DISABLED_SEEK_MESSAGE, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
+ }
}
-void MediaSlider::DrawThumb(void)
+/*****************************************************************************
+ * SeekSlider::MouseDown
+ *****************************************************************************/
+void
+SeekSlider::MouseDown(BPoint where)
{
- BRect r;
- BView *v;
+ if (IsEnabled() && Bounds().Contains(where))
+ {
+ SetValue(_ValueFor(where.x));
+ fTracking = true;
+ SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+ }
+}
- rgb_color black = {0,0,0};
- r = ThumbFrame();
- v = OffscreenView();
+/*****************************************************************************
+ * SeekSlider::MouseMoved
+ *****************************************************************************/
+void
+SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
+{
+ if (fTracking)
+ {
+ SetValue(_ValueFor(where.x));
+ }
+}
- if(IsEnabled())
+/*****************************************************************************
+ * SeekSlider::MouseUp
+ *****************************************************************************/
+void
+SeekSlider::MouseUp(BPoint where)
+{
+ if (fTracking)
{
- v->SetHighColor(black);
+ fTracking = false;
+ input_thread_t * p_input;
+ p_input = (input_thread_t *)
+ vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
+
+ if( p_input )
+ {
+ var_SetFloat( p_input, "position",
+ (float) Value() / SEEKSLIDER_RANGE );
+ vlc_object_release( p_input );
+ }
}
- else
+}
+
+/*****************************************************************************
+ * SeekSlider::ResizeToPreferred
+ *****************************************************************************/
+void
+SeekSlider::ResizeToPreferred()
+{
+ float width = 15.0 + StringWidth(DISABLED_SEEK_MESSAGE) + 15.0;
+ ResizeTo(width, 17.0);
+}
+
+/*****************************************************************************
+ * SeekSlider::SetPosition
+ *****************************************************************************/
+void
+SeekSlider::SetPosition(float position)
+{
+ if ( LockLooper() )
{
- v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
+ if( !fTracking )
+ {
+ SetValue( SEEKSLIDER_RANGE * position );
+ }
+ UnlockLooper();
}
+}
- r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
- v->StrokeEllipse(r);
+/*****************************************************************************
+ * SeekSlider::_ValueFor
+ *****************************************************************************/
+int32
+SeekSlider::_ValueFor(float xPos) const
+{
+ BRect r(Bounds());
+ float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
+ float sliderStart = (r.left + knobWidth2);
+ float sliderEnd = (r.right - knobWidth2);
+ int32 value = (int32)(((xPos - sliderStart) * SEEKSLIDER_RANGE)
+ / (sliderEnd - sliderStart - 1.0));
+ if (value < 0)
+ value = 0;
+ if (value > SEEKSLIDER_RANGE)
+ value = SEEKSLIDER_RANGE;
+ return value;
+}
- if(IsEnabled())
+/*****************************************************************************
+ * SeekSlider::_StrokeFrame
+ *****************************************************************************/
+void
+SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
+ rgb_color right, rgb_color bottom)
+{
+ BeginLineArray(4);
+ AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
+ AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
+ AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
+ AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
+ EndLineArray();
+}
+
+/*****************************************************************************
+ * VolumeSlider
+ *****************************************************************************/
+VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
+ BMessage* message, BHandler* target)
+ : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
+ B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+ fLeftSideBits(NULL),
+ fRightSideBits(NULL),
+ fKnobBits(NULL),
+ fTracking(false),
+ fMuted(false),
+ fMinValue(minValue),
+ fMaxValue(maxValue)
+{
+ SetTarget(target);
+
+ // create bitmaps
+ BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
+ fLeftSideBits = new BBitmap(r, B_CMAP8);
+ fRightSideBits = new BBitmap(r, B_CMAP8);
+ r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
+ fKnobBits = new BBitmap(r, B_CMAP8);
+
+ _MakeBitmaps();
+}
+
+/*****************************************************************************
+ * VolumeSlider destructor
+ *****************************************************************************/
+VolumeSlider::~VolumeSlider()
+{
+ delete fLeftSideBits;
+ delete fRightSideBits;
+ delete fKnobBits;
+}
+
+/*****************************************************************************
+ * VolumeSlider::AttachedToWindow
+ *****************************************************************************/
+void
+VolumeSlider::AttachedToWindow()
+{
+ BControl::AttachedToWindow();
+ SetViewColor(B_TRANSPARENT_32_BIT);
+}
+
+/*****************************************************************************
+ * VolumeSlider::SetValue
+ *****************************************************************************/
+void
+VolumeSlider::SetValue(int32 value)
+{
+ if (value != Value())
{
- v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
+ BControl::SetValue(value);
+ Invoke();
}
- else
+}
+
+/*****************************************************************************
+ * VolumeSlider::SetEnabled
+ *****************************************************************************/
+void
+VolumeSlider::SetEnabled(bool enable)
+{
+ if (enable != IsEnabled())
{
- v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
+ BControl::SetEnabled(enable);
+ _MakeBitmaps();
+ Invalidate();
}
+}
- r.InsetBy(1,1);
- v->FillEllipse(r);
+/*****************************************************************************
+ * VolumeSlider::Draw
+ *****************************************************************************/
+void
+VolumeSlider::Draw(BRect updateRect)
+{
+ if (IsValid())
+ {
+ BRect r(Bounds());
+ float sliderSideWidth = kVolumeSliderBitmapWidth;
+ float sliderStart = (r.left + sliderSideWidth);
+ float sliderEnd = (r.right - sliderSideWidth);
+ float knobPos = sliderStart
+ + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
+ / (fMaxValue - fMinValue);
+ // draw both sides (the original from Be doesn't seem
+ // to make a difference for enabled/disabled state)
+ DrawBitmapAsync(fLeftSideBits, r.LeftTop());
+ DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
+ // colors for the slider area between the two bitmaps
+ rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
+ rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
+ rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
+ rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
+ rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
+ rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
+ rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
+ rgb_color green = kGreen;
+ rgb_color greenShadow = kGreenShadow;
+ rgb_color black = kBlack;
+ rgb_color dotGrey = midShadow;
+ rgb_color dotGreen = greenShadow;
+ // make dimmed version of colors if we're disabled
+ if (!IsEnabled())
+ {
+ shadow = (rgb_color){ 200, 200, 200, 255 };
+ softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
+ darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
+ midShadow = shadow;
+ light = dimmed_color_cmap8(light, background, DIM_LEVEL);
+ softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
+ green = dimmed_color_cmap8(green, background, DIM_LEVEL);
+ greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
+ black = dimmed_color_cmap8(black, background, DIM_LEVEL);
+ dotGreen = dotGrey;
+ }
+ else if (fMuted)
+ {
+ green = tint_color(kBackground, B_DARKEN_3_TINT);
+ greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
+ dotGreen = greenShadow;
+ }
+ // draw slider edges between bitmaps
+ BeginLineArray(7);
+ AddLine(BPoint(sliderStart, r.top),
+ BPoint(sliderEnd, r.top), softShadow);
+ AddLine(BPoint(sliderStart, r.bottom),
+ BPoint(sliderEnd, r.bottom), softLight);
+ r.InsetBy(0.0, 1.0);
+ AddLine(BPoint(sliderStart, r.top),
+ BPoint(sliderEnd, r.top), black);
+ AddLine(BPoint(sliderStart, r.bottom),
+ BPoint(sliderEnd, r.bottom), light);
+ r.top++;
+ AddLine(BPoint(sliderStart, r.top),
+ BPoint(knobPos, r.top), greenShadow);
+ AddLine(BPoint(knobPos, r.top),
+ BPoint(sliderEnd, r.top), midShadow);
+ r.top++;
+ AddLine(BPoint(sliderStart, r.top),
+ BPoint(knobPos, r.top), greenShadow);
+ EndLineArray();
+ // fill rest inside of slider
+ r.InsetBy(0.0, 1.0);
+ r.left = sliderStart;
+ r.right = knobPos;
+ SetHighColor(green);
+ FillRect(r, B_SOLID_HIGH);
+ r.left = knobPos + 1.0;
+ r.right = sliderEnd;
+ r.top -= 1.0;
+ SetHighColor(shadow);
+ FillRect(r, B_SOLID_HIGH);
+ // draw little dots inside
+ int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
+ BPoint dotPos;
+ dotPos.y = r.top + 4.0;
+ for (int32 i = 0; i < dotCount; i++)
+ {
+ dotPos.x = sliderStart + i * 5.0 + 4.0;
+ SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
+ StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
+ }
+ // draw knob
+ r.top -= 1.0;
+ SetDrawingMode(B_OP_OVER); // part of knob is transparent
+ DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
+ }
}
/*****************************************************************************
- * SeekSlider
+ * VolumeSlider::MouseDown
*****************************************************************************/
-SeekSlider::SeekSlider( BRect frame, MediaControlView *p_owner, int32 i_min,
- int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
- :MediaSlider( frame, NULL, i_min, i_max )
+void
+VolumeSlider::MouseDown(BPoint where)
{
- fOwner = p_owner;
- fMouseDown = false;
+ if (Bounds().Contains(where) && IsEnabled())
+ {
+ fTracking = true;
+ SetValue(_ValueFor(where.x));
+ SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+ }
}
-SeekSlider::~SeekSlider()
+/*****************************************************************************
+ * VolumeSlider::MouseMoved
+ *****************************************************************************/
+void
+VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
+ if (fTracking)
+ SetValue(_ValueFor(where.x));
}
/*****************************************************************************
- * SeekSlider::MouseDown
+ * VolumeSlider::MouseUp
*****************************************************************************/
-void SeekSlider::MouseDown(BPoint where)
+void
+VolumeSlider::MouseUp(BPoint where)
{
- BSlider::MouseDown(where);
- seekTo = ValueForPoint(where);
- fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
- release_sem(fOwner->fScrubSem);
- fMouseDown = true;
+ fTracking = false;
}
+
/*****************************************************************************
- * SeekSlider::MouseUp
+ * VolumeSlider::IsValid
*****************************************************************************/
-void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
+bool
+VolumeSlider::IsValid() const
{
- BSlider::MouseMoved(where, code, message);
- if (!fMouseDown)
- return;
- seekTo = ValueForPoint(where);
- release_sem(fOwner->fScrubSem);
+ return (fLeftSideBits && fLeftSideBits->IsValid()
+ && fRightSideBits && fRightSideBits->IsValid()
+ && fKnobBits && fKnobBits->IsValid());
}
/*****************************************************************************
- * SeekSlider::MouseUp
+ * VolumeSlider::SetMuted
+ *****************************************************************************/
+void
+VolumeSlider::SetMuted(bool mute)
+{
+ if (mute != fMuted)
+ {
+ fMuted = mute;
+ _MakeBitmaps();
+ Invalidate();
+ }
+}
+
+/*****************************************************************************
+ * VolumeSlider::_MakeBitmaps
+ *****************************************************************************/
+void
+VolumeSlider::_MakeBitmaps()
+{
+ if (IsValid())
+ {
+ // left side of slider
+ memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
+ fLeftSideBits->BitsLength());
+ // right side of slider
+ memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
+ fRightSideBits->BitsLength());
+ // slider knob
+ int32 length = fKnobBits->BitsLength();
+ memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
+ uint8* bits = (uint8*)fKnobBits->Bits();
+ // black was used in the knob to represent transparency
+ // use screen to get index for the "transarent" color used in the bitmap
+ BScreen screen(B_MAIN_SCREEN_ID);
+ uint8 blackIndex = screen.IndexForColor(kBlack);
+ // replace black index with transparent index
+ for (int32 i = 0; i < length; i++)
+ if (bits[i] == blackIndex)
+ bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
+
+ if (!IsEnabled())
+ {
+ // make ghosted versions of the bitmaps
+ dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
+ dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
+ dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
+ }
+ else if (fMuted)
+ {
+ // replace green color (and shadow) in left slider side
+ bits = (uint8*)fLeftSideBits->Bits();
+ length = fLeftSideBits->BitsLength();
+ uint8 greenIndex = screen.IndexForColor(kGreen);
+ uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
+ rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
+ rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
+ uint8 replaceIndex = screen.IndexForColor(shadow);
+ uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
+ for (int32 i = 0; i < length; i++)
+ {
+ if (bits[i] == greenIndex)
+ bits[i] = replaceIndex;
+ else if (bits[i] == greenShadowIndex)
+ bits[i] = replaceShadowIndex;
+ }
+ }
+ }
+}
+
+/*****************************************************************************
+ * VolumeSlider::_ValueFor
+ *****************************************************************************/
+int32
+VolumeSlider::_ValueFor(float xPos) const
+{
+ BRect r(Bounds());
+ float sliderStart = (r.left + kVolumeSliderBitmapWidth);
+ float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
+ int32 value = fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
+ / (sliderEnd - sliderStart - 1.0));
+ if (value < fMinValue)
+ value = fMinValue;
+ if (value > fMaxValue)
+ value = fMaxValue;
+ return value;
+}
+
+/*****************************************************************************
+ * PositionInfoView::PositionInfoView
+ *****************************************************************************/
+PositionInfoView::PositionInfoView( BRect frame, const char* name,
+ intf_thread_t * p_interface )
+ : BView( frame, name, B_FOLLOW_NONE,
+ B_WILL_DRAW | B_PULSE_NEEDED | B_FULL_UPDATE_ON_RESIZE ),
+ fMode( MODE_SMALL ),
+ fCurrentFileIndex( -1 ),
+ fCurrentFileSize( -1 ),
+ fCurrentTitleIndex( -1 ),
+ fCurrentTitleSize( -1 ),
+ fCurrentChapterIndex( -1 ),
+ fCurrentChapterSize( -1 ),
+ fSeconds( -1 ),
+ fTimeString( "-:--:--" ),
+ fLastPulseUpdate( system_time() ),
+ fStackedWidthCache( 0.0 ),
+ fStackedHeightCache( 0.0 )
+{
+ p_intf = p_interface;
+
+ SetViewColor( B_TRANSPARENT_32_BIT );
+ SetLowColor( kBlack );
+ SetHighColor( 0, 255, 0, 255 );
+ SetFontSize( 11.0 );
+}
+
+/*****************************************************************************
+ * PositionInfoView::~PositionInfoView
+ *****************************************************************************/
+PositionInfoView::~PositionInfoView()
+{
+}
+
+/*****************************************************************************
+ * PositionInfoView::Draw
+ *****************************************************************************/
+void
+PositionInfoView::Draw( BRect updateRect )
+{
+ rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
+ rgb_color shadow = tint_color( background, B_DARKEN_1_TINT );
+ rgb_color darkShadow = tint_color( background, B_DARKEN_4_TINT );
+ rgb_color light = tint_color( background, B_LIGHTEN_MAX_TINT );
+ rgb_color softLight = tint_color( background, B_LIGHTEN_1_TINT );
+ // frame
+ BRect r( Bounds() );
+ BeginLineArray( 8 );
+ AddLine( BPoint( r.left, r.bottom ),
+ BPoint( r.left, r.top ), shadow );
+ AddLine( BPoint( r.left + 1.0, r.top ),
+ BPoint( r.right, r.top ), shadow );
+ AddLine( BPoint( r.right, r.top + 1.0 ),
+ BPoint( r.right, r.bottom ), softLight );
+ AddLine( BPoint( r.right - 1.0, r.bottom ),
+ BPoint( r.left + 1.0, r.bottom ), softLight );
+ r.InsetBy( 1.0, 1.0 );
+ AddLine( BPoint( r.left, r.bottom ),
+ BPoint( r.left, r.top ), darkShadow );
+ AddLine( BPoint( r.left + 1.0, r.top ),
+ BPoint( r.right, r.top ), darkShadow );
+ AddLine( BPoint( r.right, r.top + 1.0 ),
+ BPoint( r.right, r.bottom ), light );
+ AddLine( BPoint( r.right - 1.0, r.bottom ),
+ BPoint( r.left + 1.0, r.bottom ), light );
+ EndLineArray();
+ // background
+ r.InsetBy( 1.0, 1.0 );
+ FillRect( r, B_SOLID_LOW );
+ // contents
+ font_height fh;
+ GetFontHeight( &fh );
+ switch ( fMode )
+ {
+ case MODE_SMALL:
+ {
+ float width = StringWidth( fTimeString.String() );
+ DrawString( fTimeString.String(),
+ BPoint( r.left + r.Width() / 2.0 - width / 2.0,
+ r.top + r.Height() / 2.0 + fh.ascent / 2.0 - 1.0 ) );
+ break;
+ }
+ case MODE_BIG:
+ {
+ BFont font;
+ GetFont( &font );
+ BFont smallFont = font;
+ BFont bigFont = font;
+ BFont tinyFont = font;
+ smallFont.SetSize( r.Height() / 5.0 );
+ bigFont.SetSize( r.Height() / 3.0 );
+ tinyFont.SetSize( r.Height() / 7.0 );
+ float timeHeight = r.Height() / 2.5;
+ float height = ( r.Height() - timeHeight ) / 3.0;
+ SetFont( &tinyFont );
+ SetHighColor( 0, 180, 0, 255 );
+ DrawString( _("File"), BPoint( r.left + 3.0, r.top + height ) );
+ DrawString( _("Title"), BPoint( r.left + 3.0, r.top + 2.0 * height ) );
+ DrawString( _("Chapter"), BPoint( r.left + 3.0, r.top + 3.0 * height ) );
+ SetFont( &smallFont );
+ BString helper;
+ SetHighColor( 0, 255, 0, 255 );
+ // file
+ _MakeString( helper, fCurrentFileIndex, fCurrentFileSize );
+ float width = StringWidth( helper.String() );
+ DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + height ) );
+ // title
+ _MakeString( helper, fCurrentTitleIndex, fCurrentTitleSize );
+ width = StringWidth( helper.String() );
+ DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 2.0 * height ) );
+ // chapter
+ _MakeString( helper, fCurrentChapterIndex, fCurrentChapterSize );
+ width = StringWidth( helper.String() );
+ DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 3.0 * height ) );
+ // time
+ SetFont( &bigFont );
+ width = StringWidth( fTimeString.String() );
+ DrawString( fTimeString.String(),
+ BPoint( r.left + r.Width() / 2.0 - width / 2.0,
+ r.bottom - 3.0 ) );
+ break;
+ }
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::ResizeToPreferred
+ *****************************************************************************/
+void
+PositionInfoView::ResizeToPreferred()
+{
+ float width, height;
+ GetPreferredSize( &width, &height );
+ ResizeTo( width, height );
+}
+
+/*****************************************************************************
+ * PositionInfoView::GetPreferredSize
+ *****************************************************************************/
+void
+PositionInfoView::GetPreferredSize( float* width, float* height )
+{
+ if ( width && height )
+ {
+ *width = 5.0 + ceilf( StringWidth( "0:00:00" ) ) + 5.0;
+ font_height fh;
+ GetFontHeight( &fh );
+ *height = 3.0 + ceilf( fh.ascent ) + 3.0;
+ fStackedWidthCache = *width * 1.2;
+ fStackedHeightCache = *height * 2.7;
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::Pulse
+ *****************************************************************************/
+void
+PositionInfoView::Pulse()
+{
+ // allow for Pulse frequency to be higher, MediaControlView needs it
+ bigtime_t now = system_time();
+ if ( now - fLastPulseUpdate > 900000 )
+ {
+#if 0
+ int32 index, size;
+ p_intf->p_sys->p_wrapper->GetPlaylistInfo( index, size );
+ SetFile( index + 1, size );
+ p_intf->p_sys->p_wrapper->TitleInfo( index, size );
+ SetTitle( index, size );
+ p_intf->p_sys->p_wrapper->ChapterInfo( index, size );
+ SetChapter( index, size );
+ SetTime( p_intf->p_sys->p_wrapper->GetTimeAsString() );
+ fLastPulseUpdate = now;
+#endif
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::GetBigPreferredSize
+ *****************************************************************************/
+void
+PositionInfoView::GetBigPreferredSize( float* width, float* height )
+{
+ if ( width && height )
+ {
+ *width = fStackedWidthCache;
+ *height = fStackedHeightCache;
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetMode
+ *****************************************************************************/
+void
+PositionInfoView::SetMode( uint32 mode )
+{
+ if ( fMode != mode )
+ {
+ fMode = mode;
+ _InvalidateContents();
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetFile
*****************************************************************************/
-void SeekSlider::MouseUp(BPoint where)
+void
+PositionInfoView::SetFile( int32 index, int32 size )
{
- BSlider::MouseUp(where);
- seekTo = ValueForPoint(where);
- delete_sem(fOwner->fScrubSem);
- fOwner->fScrubSem = B_ERROR;
- fMouseDown = false;
+ if ( fCurrentFileIndex != index || fCurrentFileSize != size )
+ {
+ fCurrentFileIndex = index;
+ fCurrentFileSize = size;
+ _InvalidateContents();
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetTitle
+ *****************************************************************************/
+void
+PositionInfoView::SetTitle( int32 index, int32 size )
+{
+ if ( fCurrentTitleIndex != index || fCurrentFileSize != size )
+ {
+ fCurrentTitleIndex = index;
+ fCurrentTitleSize = size;
+ _InvalidateContents();
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetChapter
+ *****************************************************************************/
+void
+PositionInfoView::SetChapter( int32 index, int32 size )
+{
+ if ( fCurrentChapterIndex != index || fCurrentFileSize != size )
+ {
+ fCurrentChapterIndex = index;
+ fCurrentChapterSize = size;
+ _InvalidateContents();
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetTime
+ *****************************************************************************/
+void
+PositionInfoView::SetTime( int32 seconds )
+{
+ if ( fSeconds != seconds )
+ {
+ if ( seconds >= 0 )
+ {
+ int32 minutes = seconds / 60;
+ int32 hours = minutes / 60;
+ seconds -= minutes * 60 - hours * 60 * 60;
+ minutes -= hours * 60;
+ fTimeString.SetTo( "" );
+ fTimeString << hours << ":" << minutes << ":" << seconds;
+ }
+ else
+ fTimeString.SetTo( "-:--:--" );
+
+ fSeconds = seconds;
+ _InvalidateContents();
+ }
+}
+
+/*****************************************************************************
+ * PositionInfoView::SetTime
+ *****************************************************************************/
+void
+PositionInfoView::SetTime( const char* string )
+{
+ fTimeString.SetTo( string );
+ _InvalidateContents();
+}
+
+/*****************************************************************************
+ * PositionInfoView::_InvalidateContents
+ *****************************************************************************/
+void
+PositionInfoView::_InvalidateContents( uint32 which )
+{
+ BRect r( Bounds() );
+ r.InsetBy( 2.0, 2.0 );
+ Invalidate( r );
+}
+
+/*****************************************************************************
+ * PositionInfoView::_InvalidateContents
+ *****************************************************************************/
+void
+PositionInfoView::_MakeString( BString& into, int32 index, int32 maxIndex ) const
+{
+ into = "";
+ if ( index >= 0 && maxIndex >= 0 )
+ into << index;
+ else
+ into << "-";
+ into << "/";
+ if ( maxIndex >= 0 )
+ into << maxIndex;
+ else
+ into << "-";
}