]> git.sesse.net Git - vlc/blobdiff - modules/gui/beos/MediaControlView.cpp
Attempt to port new BeOS features from the stable branch.
[vlc] / modules / gui / beos / MediaControlView.cpp
index 8b0b3aa2401966e593c4335f0e5f592feb3320f5..a7ad72662497995565711bec6ba31ab8314428f4 100644 (file)
@@ -2,9 +2,10 @@
  * MediaControlView.cpp: beos interface
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: MediaControlView.cpp,v 1.2 2002/09/18 11:50:47 tcastley Exp $
+ * $Id: MediaControlView.cpp,v 1.3 2002/09/30 18:30:27 titer Exp $
  *
  * 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
 #include <vlc/intf.h>
 
 /* BeOS interface headers */
-#include "MsgVals.h"
+#include "VlcWrapper.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 };
 
-MediaControlView::MediaControlView( BRect frame )
-    : BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER )
+const char* kDisabledSeekMessage = "Drop files to play";
+
+enum
 {
-       float xStart = HORZ_SPACE;
-       float yStart = VERT_SPACE;
-       fScrubSem = B_ERROR;
-       
-       BRect controlRect = BRect(xStart,yStart, 
-                                 frame.Width() - (HORZ_SPACE * 2), 15);
+       MSG_REWIND                              = 'rwnd',
+       MSG_FORWARD                             = 'frwd',
+       MSG_SKIP_BACKWARDS              = 'skpb',
+       MSG_SKIP_FORWARD                = 'skpf',
+};
+
+// constructor
+MediaControlView::MediaControlView(BRect frame)
+       : BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
+                  B_PLAIN_BORDER),
+      fScrubSem(B_ERROR),
+      fCurrentRate(DEFAULT_RATE),
+      fCurrentStatus(UNDEF_S),
+      fBottomControlHeight(0.0)
+{
+       BRect frame(0.0, 0.0, 10.0, 10.0);
        
-    /* 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 );
+    // Seek Slider
+    fSeekSlider = new SeekSlider(frame, "seek slider", this, 0, 2047);
+    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));
+
+       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(AOUT_VOLUME_DEFAULT);
+       AddChild( fVolumeSlider );
 }
 
+// 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())
+               r.bottom += menuBar->Bounds().Height();
+
+       Window()->SetSizeLimits(r.Width(), r.Width() * 2.0, r.Height(), r.Height() * 2.0);
+       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);
 }
 
-void MediaControlView::SetProgress(uint64 seek, uint64 size)
+// GetPreferredSize
+void
+MediaControlView::GetPreferredSize(float* width, float* height)
 {
-       p_seek->SetPosition((float)seek/size);
+       if (width && height)
+       {
+               BRect r(_MinFrame());
+               *width = r.Width();
+               *height = r.Height();
+       }
 }
 
-void MediaControlView::SetStatus(int status, int rate)
+// 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();
+}
+
+// SetProgress
+void
+MediaControlView::SetProgress(uint64 seek, uint64 size)
+{
+       fSeekSlider->SetPosition((float)seek / (float)size);
+}
+
+// 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();
+            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 < DEFAULT_RATE )
+           {
+               // TODO: ...
+           }
+       }
+}
+
+// SetEnabled
+void
+MediaControlView::SetEnabled(bool enabled)
+{
+       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);
+}
+
+// SetAudioEnabled
+void
+MediaControlView::SetAudioEnabled(bool enabled)
+{
+       fMute->SetEnabled(enabled);
+       fVolumeSlider->SetEnabled(enabled);
+}
+
+// GetSeekTo
+uint32
+MediaControlView::GetSeekTo() const
+{
+       return fSeekSlider->Value();
+}
+
+// GetVolume
+uint32
+MediaControlView::GetVolume() const
+{
+       return fVolumeSlider->Value();
 }
 
-void MediaControlView::SetEnabled(bool enabled)
+// SetSkippable
+void
+MediaControlView::SetSkippable(bool backward, bool forward)
 {
-       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);
+       fSkipBack->SetEnabled(backward);
+       fSkipForward->SetEnabled(forward);
 }
 
-uint32 MediaControlView::GetSeekTo()
+// SetMuted
+void
+MediaControlView::SetMuted(bool mute)
 {
-       return p_seek->seekTo;
+       fVolumeSlider->SetMuted(mute);
 }
 
-uint32 MediaControlView::GetVolume()
+// _LayoutControls
+void
+MediaControlView::_LayoutControls(BRect frame) const
 {
-       return p_vol->Value();
+       // seek slider
+       BRect r(frame);
+       r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
+       _LayoutControl(fSeekSlider, r, true);
+       // 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;
+       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.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 resize) const
+{
+       // center vertically
+       frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
+       if (!resize)
+               frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
+       view->MoveTo(frame.LeftTop());
+       if (resize)
+               view->ResizeTo(frame.Width(), view->Bounds().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(BRect frame, const char* name, MediaControlView *owner,
+                                          int32 minValue, int32 maxValue)
+       : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
+                          B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
+         fOwner(owner),
+         fTracking(false),
+         fMinValue(minValue),
+         fMaxValue(maxValue)
 {
+       BFont font(be_plain_font);
+       font.SetSize(9.0);
+       SetFont(&font);
+}
 
+SeekSlider::~SeekSlider()
+{
+       _EndSeek();
 }
 
-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() - fMinValue)
+                                       / (fMaxValue - fMinValue) + 0.5);
+       // 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(kDisabledSeekMessage));
+               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(kDisabledSeekMessage, 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);
+               _BeginSeek();
+       }
+}
 
-    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));
+               _Seek();
+       }
+}
 
-    if(IsEnabled())
-    {
-        v->SetHighColor(black);
-    }
-    else
-    {
-        v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
-    }
+/*****************************************************************************
+ * SeekSlider::MouseUp
+ *****************************************************************************/
+void
+SeekSlider::MouseUp(BPoint where)
+{
+       if (fTracking)
+       {
+               fTracking = false;
+               _EndSeek();
+       }
+}
 
-    r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
-    v->StrokeEllipse(r);
+/*****************************************************************************
+ * SeekSlider::ResizeToPreferred
+ *****************************************************************************/
+void
+SeekSlider::ResizeToPreferred()
+{
+       float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
+       ResizeTo(width, 17.0);
+}
 
-    if(IsEnabled())
-    {
-        v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
-    }
-    else
-    {
-        v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
-    }
+/*****************************************************************************
+ * SeekSlider::SetPosition
+ *****************************************************************************/
+void
+SeekSlider::SetPosition(float position)
+{
+       SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
+}
 
-    r.InsetBy(1,1);
-    v->FillEllipse(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 =  fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
+                                 / (sliderEnd - sliderStart - 1.0));
+       if (value < fMinValue)
+               value = fMinValue;
+       if (value > fMaxValue)
+               value = fMaxValue;
+       return value;
 }
 
 /*****************************************************************************
- * SeekSlider
+ * SeekSlider::_StrokeFrame
  *****************************************************************************/
-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
+SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
+                                                rgb_color right, rgb_color bottom)
 {
-    fOwner = p_owner;
-    fMouseDown = false;
+       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();
 }
 
-SeekSlider::~SeekSlider()
+/*****************************************************************************
+ * SeekSlider::_BeginSeek
+ *****************************************************************************/
+void
+SeekSlider::_BeginSeek()
 {
+       fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
+       if (fOwner->fScrubSem >= B_OK)
+               release_sem(fOwner->fScrubSem);
 }
 
 /*****************************************************************************
- * SeekSlider::MouseDown
+ * SeekSlider::_Seek
  *****************************************************************************/
-void SeekSlider::MouseDown(BPoint where)
+void
+SeekSlider::_Seek()
 {
-    BSlider::MouseDown(where);
-    seekTo = ValueForPoint(where);
-    fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
-    release_sem(fOwner->fScrubSem);
-    fMouseDown = true;
+       if (fOwner->fScrubSem >= B_OK)
+               delete_sem(fOwner->fScrubSem);
+       fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
+       if (fOwner->fScrubSem >= B_OK)
+               release_sem(fOwner->fScrubSem);
 }
 
 /*****************************************************************************
- * SeekSlider::MouseUp
+ * SeekSlider::_EndSeek
  *****************************************************************************/
-void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
+void
+SeekSlider::_EndSeek()
 {
-    BSlider::MouseMoved(where, code, message);
-    if (!fMouseDown)
-        return;
-    seekTo = ValueForPoint(where);
-    release_sem(fOwner->fScrubSem);
+       if (fOwner->fScrubSem >= B_OK)
+               delete_sem(fOwner->fScrubSem);
+       fOwner->fScrubSem = B_ERROR;
 }
 
+
 /*****************************************************************************
- * SeekSlider::MouseUp
+ * 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())
+       {
+               BControl::SetValue(value);
+               Invoke();
+       }
+}
+
+/*****************************************************************************
+ * VolumeSlider::SetEnabled
+ *****************************************************************************/
+void
+VolumeSlider::SetEnabled(bool enable)
+{
+       if (enable != IsEnabled())
+       {
+               BControl::SetEnabled(enable);
+               _MakeBitmaps();
+               Invalidate();
+       }
+}
+
+/*****************************************************************************
+ * 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));
+       }
+       else
+               fprintf(stderr, "VolumeSlider::Draw() - Error: no valid bitmaps!");
+}
+
+/*****************************************************************************
+ * VolumeSlider::MouseDown
+ *****************************************************************************/
+void
+VolumeSlider::MouseDown(BPoint where)
+{
+       if (Bounds().Contains(where) && IsEnabled())
+       {
+               fTracking = true;
+               SetValue(_ValueFor(where.x));
+               SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+       }
+}
+
+/*****************************************************************************
+ * VolumeSlider::MouseMoved
+ *****************************************************************************/
+void
+VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
+{
+       if (fTracking)
+               SetValue(_ValueFor(where.x));
+}
+
+/*****************************************************************************
+ * VolumeSlider::MouseUp
+ *****************************************************************************/
+void
+VolumeSlider::MouseUp(BPoint where)
+{
+       fTracking = false;
+}
+
+
+/*****************************************************************************
+ * VolumeSlider::IsValid
  *****************************************************************************/
-void SeekSlider::MouseUp(BPoint where)
+bool
+VolumeSlider::IsValid() const
 {
-    BSlider::MouseUp(where);
-    seekTo = ValueForPoint(where);
-    delete_sem(fOwner->fScrubSem);
-    fOwner->fScrubSem = B_ERROR;
-    fMouseDown = false;
+       return (fLeftSideBits && fLeftSideBits->IsValid()
+                       && fRightSideBits && fRightSideBits->IsValid()
+                       && fKnobBits && fKnobBits->IsValid());
 }
+
+/*****************************************************************************
+ * 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;
+}
+
+
+
+
+