MediaControlView.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:50k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * MediaControlView.cpp: beos interface
  3.  *****************************************************************************
  4.  * Copyright (C) 1999, 2000, 2001 the VideoLAN team
  5.  * $Id: b3cdf450ee04045c1d5f4364769c2513596f3fee $
  6.  *
  7.  * Authors: Tony Castley <tony@castley.net>
  8.  *          Stephan Aßmus <stippi@yellowbites.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /* System headers */
  25. #include <InterfaceKit.h>
  26. #include <AppKit.h>
  27. #include <String.h>
  28. /* VLC headers */
  29. #ifdef HAVE_CONFIG_H
  30. # include "config.h"
  31. #endif
  32. #include <vlc_common.h>
  33. #include <vlc_interface.h>
  34. extern "C"
  35. {
  36.   #include <audio_output.h>
  37. }
  38. /* BeOS interface headers */
  39. #include "Bitmaps.h"
  40. #include "DrawingTidbits.h"
  41. #include "InterfaceWindow.h"
  42. #include "MsgVals.h"
  43. #include "TransportButton.h"
  44. #include "ListViews.h"
  45. #include "MediaControlView.h"
  46. #define BORDER_INSET 6.0
  47. #define MIN_SPACE 4.0
  48. #define SPEAKER_SLIDER_DIST 6.0
  49. #define VOLUME_MIN_WIDTH 70.0
  50. #define DIM_LEVEL 0.4
  51. #define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0
  52. #define SEEK_SLIDER_KNOB_WIDTH 8.0
  53. // slider colors are hardcoded here, because that's just
  54. // what they currently are within those bitmaps
  55. const rgb_color kGreen = (rgb_color){ 152, 203, 152, 255 };
  56. const rgb_color kGreenShadow = (rgb_color){ 102, 152, 102, 255 };
  57. const rgb_color kBackground = (rgb_color){ 216, 216, 216, 255 };
  58. const rgb_color kSeekGreen = (rgb_color){ 171, 221, 161, 255 };
  59. const rgb_color kSeekGreenShadow = (rgb_color){ 144, 186, 136, 255 };
  60. const rgb_color kSeekRed = (rgb_color){ 255, 0, 0, 255 };
  61. const rgb_color kSeekRedLight = (rgb_color){ 255, 152, 152, 255 };
  62. const rgb_color kSeekRedShadow = (rgb_color){ 178, 0, 0, 255 };
  63. #define DISABLED_SEEK_MESSAGE _("Drop files to play")
  64. #define SEEKSLIDER_RANGE 2048
  65. enum
  66. {
  67.     MSG_REWIND                = 'rwnd',
  68.     MSG_FORWARD                = 'frwd',
  69.     MSG_SKIP_BACKWARDS        = 'skpb',
  70.     MSG_SKIP_FORWARD        = 'skpf',
  71. };
  72. // constructor
  73. MediaControlView::MediaControlView( intf_thread_t * _p_intf, BRect frame)
  74.     : BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
  75.            B_PLAIN_BORDER),
  76.       p_intf( _p_intf ),
  77.       fCurrentRate(INPUT_RATE_DEFAULT),
  78.       fCurrentStatus(-1),
  79.       fBottomControlHeight(0.0),
  80.       fIsEnabled( true )
  81. {
  82.     BRect frame(0.0, 0.0, 10.0, 10.0);
  83.     
  84.     // Seek Slider
  85.     fSeekSlider = new SeekSlider( p_intf, frame, "seek slider", this );
  86.     fSeekSlider->SetValue(0);
  87.     fSeekSlider->ResizeToPreferred();
  88.     AddChild( fSeekSlider );
  89.     // Buttons
  90.     // Skip Back
  91.     frame.SetRightBottom(kSkipButtonSize);
  92.     fBottomControlHeight = kRewindBitmapHeight - 1.0;
  93.     fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
  94.                                     kSkipBackBitmapBits,
  95.                                     kPressedSkipBackBitmapBits,
  96.                                     kDisabledSkipBackBitmapBits,
  97.                                     new BMessage(MSG_SKIP_BACKWARDS));
  98.     AddChild( fSkipBack );
  99.     // Play Pause
  100.     frame.SetRightBottom(kPlayButtonSize);
  101.     if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
  102.         fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
  103.     fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
  104.                                      kPlayButtonBitmapBits,
  105.                                      kPressedPlayButtonBitmapBits,
  106.                                      kDisabledPlayButtonBitmapBits,
  107.                                      kPlayingPlayButtonBitmapBits,
  108.                                      kPressedPlayingPlayButtonBitmapBits,
  109.                                      kPausedPlayButtonBitmapBits,
  110.                                      kPressedPausedPlayButtonBitmapBits,
  111.                                      new BMessage(START_PLAYBACK));
  112.     AddChild( fPlayPause );
  113.     // Skip Foward
  114.     frame.SetRightBottom(kSkipButtonSize);
  115.     fSkipForward = new TransportButton(frame, B_EMPTY_STRING,
  116.                                        kSkipForwardBitmapBits,
  117.                                        kPressedSkipForwardBitmapBits,
  118.                                        kDisabledSkipForwardBitmapBits,
  119.                                        new BMessage(MSG_SKIP_FORWARD));
  120.     AddChild( fSkipForward );
  121.     // Forward
  122.     fForward = new TransportButton(frame, B_EMPTY_STRING,
  123.                                    kForwardBitmapBits,
  124.                                    kPressedForwardBitmapBits,
  125.                                    kDisabledForwardBitmapBits,
  126.                                    new BMessage(MSG_FORWARD));
  127. //    AddChild( fForward );
  128.     // Rewind
  129.     fRewind = new TransportButton(frame, B_EMPTY_STRING,
  130.                                   kRewindBitmapBits,
  131.                                   kPressedRewindBitmapBits,
  132.                                   kDisabledRewindBitmapBits,
  133.                                   new BMessage(MSG_REWIND));
  134. //    AddChild( fRewind );
  135.     // Stop
  136.     frame.SetRightBottom(kStopButtonSize);
  137.     if (fBottomControlHeight < kStopBitmapHeight - 1.0)
  138.         fBottomControlHeight = kStopBitmapHeight - 1.0;
  139.     fStop = new TransportButton(frame, B_EMPTY_STRING,
  140.                                 kStopButtonBitmapBits,
  141.                                 kPressedStopButtonBitmapBits,
  142.                                 kDisabledStopButtonBitmapBits,
  143.                                 new BMessage(STOP_PLAYBACK));
  144.     AddChild( fStop );
  145.     // Mute
  146.     frame.SetRightBottom(kSpeakerButtonSize);
  147.     if (fBottomControlHeight < kSpeakerIconBitmapHeight - 1.0)
  148.         fBottomControlHeight = kSpeakerIconBitmapHeight - 1.0;
  149.     fMute = new TransportButton(frame, B_EMPTY_STRING,
  150.                                 kSpeakerIconBits,
  151.                                 kPressedSpeakerIconBits,
  152.                                 kSpeakerIconBits,
  153.                                 new BMessage(VOLUME_MUTE));
  154.     AddChild( fMute );
  155.     // Volume Slider
  156.     fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
  157.                                            kVolumeSliderBitmapHeight - 1.0),
  158.                                      "volume slider", 1, AOUT_VOLUME_MAX,
  159.                                      new BMessage(VOLUME_CHG));
  160.     fVolumeSlider->SetValue( config_GetInt( p_intf, "volume" ) );
  161.     AddChild( fVolumeSlider );
  162.     
  163.     // Position Info View
  164.     fPositionInfo = new PositionInfoView(BRect(0.0, 0.0, 10.0, 10.0), "led",
  165.                                          p_intf);
  166.     fPositionInfo->ResizeToPreferred();
  167.     AddChild( fPositionInfo );
  168. }
  169. // destructor
  170. MediaControlView::~MediaControlView()
  171. {
  172. }
  173. // AttachedToWindow
  174. void
  175. MediaControlView::AttachedToWindow()
  176. {
  177.     // we are now a valid BHandler
  178.     fRewind->SetTarget(this);
  179.     fForward->SetTarget(this);
  180.     fSkipBack->SetTarget(this);
  181.     fSkipForward->SetTarget(this);
  182.     fVolumeSlider->SetTarget(Window());
  183.     BRect r(_MinFrame());
  184.     if (BMenuBar* menuBar = Window()->KeyMenuBar()) {
  185.         float width, height;
  186.         menuBar->GetPreferredSize(&width, &height);
  187. //        r.bottom += menuBar->Bounds().Height();
  188.         r.bottom += height;
  189.         // see that our calculated minimal width is not smaller than what
  190.         // the menubar can be
  191.         width -= r.Width();
  192.         if (width > 0.0)
  193.             r.right += width;
  194.     }
  195.     Window()->SetSizeLimits(r.Width(), r.Width() * 1.8, r.Height(), r.Height() * 1.3);
  196.     if (!Window()->Bounds().Contains(r))
  197.         Window()->ResizeTo(r.Width(), r.Height());
  198.     else
  199.         FrameResized(Bounds().Width(), Bounds().Height());
  200.     // get pulse message every two frames
  201.     Window()->SetPulseRate(80000);
  202. }
  203. // FrameResized
  204. void
  205. MediaControlView::FrameResized(float width, float height)
  206. {
  207.     BRect r(Bounds());
  208.     // make sure we don't leave dirty pixels
  209.     // (B_FULL_UPDATE_ON_RESIZE == annoying flicker -> this is smarter)
  210.     if (fOldBounds.Width() < r.Width())
  211.         Invalidate(BRect(fOldBounds.right, fOldBounds.top + 1.0,
  212.                          fOldBounds.right, fOldBounds.bottom - 1.0));
  213.     else
  214.         Invalidate(BRect(r.right, r.top + 1.0,
  215.                          r.right, r.bottom - 1.0));
  216.     if (fOldBounds.Height() < r.Height())
  217.         Invalidate(BRect(fOldBounds.left + 1.0, fOldBounds.bottom,
  218.                          fOldBounds.right - 1.0, fOldBounds.bottom));
  219.     else
  220.         Invalidate(BRect(r.left + 1.0, r.bottom,
  221.                          r.right - 1.0, r.bottom));
  222.     // remember for next time
  223.     fOldBounds = r;
  224.     // layout controls
  225.     r.InsetBy(BORDER_INSET, BORDER_INSET);
  226.     _LayoutControls(r);
  227. }
  228. // GetPreferredSize
  229. void
  230. MediaControlView::GetPreferredSize(float* width, float* height)
  231. {
  232.     if (width && height)
  233.     {
  234.         BRect r(_MinFrame());
  235.         *width = r.Width();
  236.         *height = r.Height();
  237.     }
  238. }
  239. // MessageReceived
  240. void
  241. MediaControlView::MessageReceived(BMessage* message)
  242. {
  243.     switch (message->what)
  244.     {
  245.         case MSG_REWIND:
  246.             break;
  247.         case MSG_FORWARD:
  248.             break;
  249.         case MSG_SKIP_BACKWARDS:
  250.             Window()->PostMessage(NAVIGATE_PREV);
  251.             break;
  252.         case MSG_SKIP_FORWARD:
  253.             Window()->PostMessage(NAVIGATE_NEXT);
  254.             break;
  255.         default:
  256.             BBox::MessageReceived(message);
  257.             break;
  258.     }
  259. }
  260. // Pulse
  261. void
  262. MediaControlView::Pulse()
  263. {
  264.     InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
  265.     if (window && window->IsStopped())
  266.             fPlayPause->SetStopped();
  267.     unsigned short i_volume;
  268.     aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
  269.     fVolumeSlider->SetValue( i_volume );
  270. }
  271. // SetProgress
  272. void
  273. MediaControlView::SetProgress( float position )
  274. {
  275.     fSeekSlider->SetPosition( position );
  276. }
  277. // SetStatus
  278. void
  279. MediaControlView::SetStatus(int status, int rate)
  280. {
  281.     // we need to set the button status periodically
  282.     // (even if it is the same) to get a blinking button
  283.     fCurrentStatus = status;
  284.     switch( status )
  285.     {
  286.         case PLAYING_S:
  287.         case OPENNING_S:
  288.             fPlayPause->SetPlaying();
  289.             break;
  290.         case PAUSE_S:
  291.             fPlayPause->SetPaused();
  292.             break;
  293.         default:
  294.             fPlayPause->SetStopped();
  295.             break;
  296.     }
  297.     if (rate != fCurrentRate)
  298.     {
  299.         fCurrentRate = rate;
  300.         if ( rate < INPUT_RATE_DEFAULT )
  301.         {
  302.             // TODO: ...
  303.         }
  304.     }
  305. }
  306. // SetEnabled
  307. void
  308. MediaControlView::SetEnabled(bool enabled)
  309. {
  310.     if( ( enabled && fIsEnabled ) ||
  311.         ( !enabled && !fIsEnabled ) )
  312.     {
  313.         /* do not redraw if it is not necessary */
  314.         return;
  315.     }
  316.  
  317.     if( LockLooper() )
  318.     {
  319.         fSkipBack->SetEnabled( enabled );
  320.         fPlayPause->SetEnabled( enabled );
  321.         fSkipForward->SetEnabled( enabled );
  322.         fStop->SetEnabled( enabled );
  323.         fMute->SetEnabled( enabled );
  324.         fVolumeSlider->SetEnabled( enabled );
  325.         fSeekSlider->SetEnabled( enabled );
  326.         fRewind->SetEnabled( enabled );
  327.         fForward->SetEnabled( enabled );
  328.         UnlockLooper();
  329.         fIsEnabled = enabled;
  330.     }
  331. }
  332. // SetAudioEnabled
  333. void
  334. MediaControlView::SetAudioEnabled(bool enabled)
  335. {
  336.     fMute->SetEnabled(enabled);
  337.     fVolumeSlider->SetEnabled(enabled);
  338. }
  339. // GetVolume
  340. uint32
  341. MediaControlView::GetVolume() const
  342. {
  343.     return fVolumeSlider->Value();
  344. }
  345. // SetSkippable
  346. void
  347. MediaControlView::SetSkippable(bool backward, bool forward)
  348. {
  349.     fSkipBack->SetEnabled(backward);
  350.     fSkipForward->SetEnabled(forward);
  351. }
  352. // SetMuted
  353. void
  354. MediaControlView::SetMuted(bool mute)
  355. {
  356.     fVolumeSlider->SetMuted(mute);
  357. }
  358. // _LayoutControls
  359. void
  360. MediaControlView::_LayoutControls(BRect frame) const
  361. {
  362.     // seek slider
  363.     BRect r(frame);
  364.     // calculate absolutly minimal width
  365.     float minWidth = fSkipBack->Bounds().Width();
  366. //    minWidth += fRewind->Bounds().Width();
  367.     minWidth += fStop->Bounds().Width();
  368.     minWidth += fPlayPause->Bounds().Width();
  369. //    minWidth += fForward->Bounds().Width();
  370.     minWidth += fSkipForward->Bounds().Width();
  371.     minWidth += fMute->Bounds().Width();
  372.     minWidth += VOLUME_MIN_WIDTH;
  373.     
  374.     // layout time slider and info view
  375.     float width, height;
  376.     fPositionInfo->GetBigPreferredSize( &width, &height );
  377.     float ratio = width / height;
  378.     width = r.Height() * ratio;
  379.     if (frame.Width() - minWidth - MIN_SPACE >= width
  380.               && frame.Height() >= height)
  381.     {
  382.         r.right = r.left + width;
  383.         fPositionInfo->SetMode(PositionInfoView::MODE_BIG);
  384.         _LayoutControl(fPositionInfo, r, true, true);
  385.         frame.left = r.right + MIN_SPACE;
  386.         r.left = frame.left;
  387.         r.right = frame.right;
  388.     //    r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
  389.         r.bottom = r.top + fSeekSlider->Bounds().Height();
  390.         _LayoutControl(fSeekSlider, r, true);
  391.     }
  392.     else
  393.     {
  394.         fPositionInfo->GetPreferredSize( &width, &height );
  395.         fPositionInfo->SetMode(PositionInfoView::MODE_SMALL);
  396.         fPositionInfo->ResizeTo(width, height);
  397.         r.bottom = r.top + r.Height() / 2.0 - MIN_SPACE / 2.0;
  398.         r.right = r.left + fPositionInfo->Bounds().Width();
  399.         _LayoutControl(fPositionInfo, r, true );
  400.         r.left = r.right + MIN_SPACE;
  401.         r.right = frame.right;
  402.         _LayoutControl(fSeekSlider, r, true);
  403.     }
  404.     float currentWidth = frame.Width();
  405.     float space = (currentWidth - minWidth) / 6.0;//8.0;
  406.     // apply weighting
  407.     space = MIN_SPACE + (space - MIN_SPACE) / VOLUME_SLIDER_LAYOUT_WEIGHT;
  408.     // layout controls with "space" inbetween
  409.     r.left = frame.left;
  410.     r.top = r.bottom + MIN_SPACE + 1.0;
  411.     r.bottom = frame.bottom;
  412.     // skip back
  413.     r.right = r.left + fSkipBack->Bounds().Width();
  414.     _LayoutControl(fSkipBack, r);
  415.     // rewind
  416. //    r.left = r.right + space;
  417. //    r.right = r.left + fRewind->Bounds().Width();
  418. //    _LayoutControl(fRewind, r);
  419.     // stop
  420.     r.left = r.right + space;
  421.     r.right = r.left + fStop->Bounds().Width();
  422.     _LayoutControl(fStop, r);
  423.     // play/pause
  424.     r.left = r.right + space;
  425.     r.right = r.left + fPlayPause->Bounds().Width();
  426.     _LayoutControl(fPlayPause, r);
  427.     // forward
  428. //    r.left = r.right + space;
  429. //    r.right = r.left + fForward->Bounds().Width();
  430. //    _LayoutControl(fForward, r);
  431.     // skip forward
  432.     r.left = r.right + space;
  433.     r.right = r.left + fSkipForward->Bounds().Width();
  434.     _LayoutControl(fSkipForward, r);
  435.     // speaker icon
  436.     r.left = r.right + space + space;
  437.     r.right = r.left + fMute->Bounds().Width();
  438.     _LayoutControl(fMute, r);
  439.     // volume slider
  440.     r.left = r.right + SPEAKER_SLIDER_DIST; // keep speaker icon and volume slider attached
  441.     r.right = frame.right;
  442.     _LayoutControl(fVolumeSlider, r, true);
  443. }
  444. // _MinFrame
  445. BRect
  446. MediaControlView::_MinFrame() const
  447. {
  448.     // add up width of controls along bottom (seek slider will likely adopt)
  449.     float minWidth = 2 * BORDER_INSET;
  450.     minWidth += fSkipBack->Bounds().Width() + MIN_SPACE;
  451. //    minWidth += fRewind->Bounds().Width() + MIN_SPACE;
  452.     minWidth += fStop->Bounds().Width() + MIN_SPACE;
  453.     minWidth += fPlayPause->Bounds().Width() + MIN_SPACE;
  454. //    minWidth += fForward->Bounds().Width() + MIN_SPACE;
  455.     minWidth += fSkipForward->Bounds().Width() + MIN_SPACE + MIN_SPACE;
  456.     minWidth += fMute->Bounds().Width() + SPEAKER_SLIDER_DIST;
  457.     minWidth += VOLUME_MIN_WIDTH;
  458.     // add up height of seek slider and heighest control on bottom
  459.     float minHeight = 2 * BORDER_INSET;
  460.     minHeight += fSeekSlider->Bounds().Height() + MIN_SPACE + MIN_SPACE / 2.0;
  461.     minHeight += fBottomControlHeight;
  462.     return BRect(0.0, 0.0, minWidth - 1.0, minHeight - 1.0);
  463. }
  464. // _LayoutControl
  465. void
  466. MediaControlView::_LayoutControl(BView* view, BRect frame,
  467.                                  bool resizeWidth, bool resizeHeight) const
  468. {
  469.     if (!resizeHeight)
  470.         // center vertically
  471.         frame.top = (frame.top + frame.bottom) / 2.0 - view->Bounds().Height() / 2.0;
  472.     if (!resizeWidth)
  473.         //center horizontally
  474.         frame.left = (frame.left + frame.right) / 2.0 - view->Bounds().Width() / 2.0;
  475.     view->MoveTo(frame.LeftTop());
  476.     float width = resizeWidth ? frame.Width() : view->Bounds().Width();
  477.     float height = resizeHeight ? frame.Height() : view->Bounds().Height();
  478.     if (resizeWidth || resizeHeight)
  479.         view->ResizeTo(width, height);
  480. }
  481. /*****************************************************************************
  482.  * SeekSlider
  483.  *****************************************************************************/
  484. SeekSlider::SeekSlider( intf_thread_t * _p_intf,
  485.                         BRect frame, const char* name, MediaControlView *owner )
  486.     : BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
  487.                B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
  488.       p_intf(_p_intf),
  489.       fOwner(owner),
  490.       fTracking(false)
  491. {
  492.     BFont font(be_plain_font);
  493.     font.SetSize(9.0);
  494.     SetFont(&font);
  495. }
  496. SeekSlider::~SeekSlider()
  497. {
  498. }
  499. /*****************************************************************************
  500.  * VolumeSlider::AttachedToWindow
  501.  *****************************************************************************/
  502. void
  503. SeekSlider::AttachedToWindow()
  504. {
  505.     BControl::AttachedToWindow();
  506.     SetViewColor(B_TRANSPARENT_32_BIT);
  507. }
  508. /*****************************************************************************
  509.  * VolumeSlider::Draw
  510.  *****************************************************************************/
  511. void
  512. SeekSlider::Draw(BRect updateRect)
  513. {
  514.     BRect r(Bounds());
  515.     float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
  516.     float sliderStart = (r.left + knobWidth2);
  517.     float sliderEnd = (r.right - knobWidth2);
  518.     float knobPos = sliderStart
  519.                     + floorf((sliderEnd - sliderStart - 1.0) * Value()
  520.                     / SEEKSLIDER_RANGE);
  521.     // draw both sides (the original from Be doesn't seem
  522.     // to make a difference for enabled/disabled state)
  523. //    DrawBitmapAsync(fLeftSideBits, r.LeftTop());
  524. //    DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
  525.     // colors for the slider area between the two bitmaps
  526.     rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
  527.     rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
  528.     rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
  529.     rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
  530.     rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
  531.     rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
  532.     rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
  533.     rgb_color green = kSeekGreen;
  534.     rgb_color greenShadow = kSeekGreenShadow;
  535.     rgb_color black = kBlack;
  536.     rgb_color dotGrey = midShadow;
  537.     rgb_color dotGreen = greenShadow;
  538.     // draw frame
  539.     _StrokeFrame(r, softShadow, softShadow, softLight, softLight);
  540.     r.InsetBy(1.0, 1.0);
  541.     _StrokeFrame(r, black, black, light, light);
  542.     if (IsEnabled())
  543.     {
  544.         r.InsetBy(1.0, 1.0);
  545.         // inner shadow
  546.         _StrokeFrame(r, greenShadow, greenShadow, green, green);
  547.         r.top++;
  548.         r.left++;
  549.         _StrokeFrame(r, greenShadow, greenShadow, green, green);
  550.         // inside area
  551.         r.InsetBy(1.0, 1.0);
  552.         SetHighColor(green);
  553.         FillRect(r);
  554.         // dots
  555.         int32 dotCount = (int32)(r.Width() / 6.0);
  556.         BPoint dotPos;
  557.         dotPos.y = r.top + 2.0;
  558.         SetHighColor(dotGreen);
  559.         for (int32 i = 0; i < dotCount; i++)
  560.         {
  561.             dotPos.x = sliderStart + i * 6.0 + 5.0;
  562.             StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 6.0));
  563.         }
  564.         // slider handle
  565.         r.top -= 4.0;
  566.         r.bottom += 3.0;
  567.         r.left = knobPos - knobWidth2;
  568.         r.right = knobPos + knobWidth2;
  569.         // black outline
  570.         float handleBottomSize = 2.0;
  571.         float handleArrowSize = 6.0;
  572.         BeginLineArray(10);
  573.             // upper handle
  574.             AddLine(BPoint(r.left, r.top + handleBottomSize),
  575.                     BPoint(r.left, r.top), black);
  576.             AddLine(BPoint(r.left + 1.0, r.top),
  577.                     BPoint(r.right, r.top), black);
  578.             AddLine(BPoint(r.right, r.top + 1.0),
  579.                     BPoint(r.right, r.top + handleBottomSize), black);
  580.             AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
  581.                     BPoint(knobPos, r.top + handleArrowSize), black);
  582.             AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
  583.                     BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), black);
  584.             // lower handle
  585.             AddLine(BPoint(r.left, r.bottom),
  586.                     BPoint(r.left, r.bottom - handleBottomSize), black);
  587.             AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
  588.                     BPoint(knobPos, r.bottom - handleArrowSize), black);
  589.             AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
  590.                     BPoint(r.right, r.bottom - handleBottomSize), black);
  591.             AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
  592.                     BPoint(r.right, r.bottom), black);
  593.             AddLine(BPoint(r.right - 1.0, r.bottom),
  594.                     BPoint(r.left + 1.0, r.bottom), black);
  595.         EndLineArray();
  596.         // inner red light and shadow lines
  597.         r.InsetBy(1.0, 1.0);
  598.         handleBottomSize--;
  599.         handleArrowSize -= 2.0;
  600.         BeginLineArray(10);
  601.             // upper handle
  602.             AddLine(BPoint(r.left, r.top + handleBottomSize),
  603.                     BPoint(r.left, r.top), kSeekRedLight);
  604.             AddLine(BPoint(r.left + 1.0, r.top),
  605.                     BPoint(r.right, r.top), kSeekRedLight);
  606.             AddLine(BPoint(r.right, r.top + 1.0),
  607.                     BPoint(r.right, r.top + handleBottomSize), kSeekRedShadow);
  608.             AddLine(BPoint(r.right - 1.0, r.top + handleBottomSize + 1.0),
  609.                     BPoint(knobPos, r.top + handleArrowSize), kSeekRedShadow);
  610.             AddLine(BPoint(knobPos - 1.0, r.top + handleArrowSize - 1.0),
  611.                     BPoint(r.left + 1.0, r.top + handleBottomSize + 1.0), kSeekRedLight);
  612.             // lower handle
  613.             AddLine(BPoint(r.left, r.bottom),
  614.                     BPoint(r.left, r.bottom - handleBottomSize), kSeekRedLight);
  615.             AddLine(BPoint(r.left + 1.0, r.bottom - handleBottomSize - 1.0),
  616.                     BPoint(knobPos, r.bottom - handleArrowSize), kSeekRedLight);
  617.             AddLine(BPoint(knobPos + 1.0, r.bottom - handleArrowSize + 1.0),
  618.                     BPoint(r.right, r.bottom - handleBottomSize), kSeekRedShadow);
  619.             AddLine(BPoint(r.right, r.bottom - handleBottomSize + 1.0),
  620.                     BPoint(r.right, r.bottom), kSeekRedShadow);
  621.             AddLine(BPoint(r.right - 1.0, r.bottom),
  622.                     BPoint(r.left + 1.0, r.bottom), kSeekRedShadow);
  623.         EndLineArray();
  624.         // fill rest of handles with red
  625.         SetHighColor(kSeekRed);
  626.         r.InsetBy(1.0, 1.0);
  627.         handleArrowSize -= 2.0;
  628.         BPoint arrow[3];
  629.         // upper handle arrow
  630.         arrow[0].x = r.left;
  631.         arrow[0].y = r.top;
  632.         arrow[1].x = r.right;
  633.         arrow[1].y = r.top;
  634.         arrow[2].x = knobPos;
  635.         arrow[2].y = r.top + handleArrowSize;
  636.         FillPolygon(arrow, 3);
  637.         // lower handle arrow
  638.         arrow[0].x = r.left;
  639.         arrow[0].y = r.bottom;
  640.         arrow[1].x = r.right;
  641.         arrow[1].y = r.bottom;
  642.         arrow[2].x = knobPos;
  643.         arrow[2].y = r.bottom - handleArrowSize;
  644.         FillPolygon(arrow, 3);
  645.     }
  646.     else
  647.     {
  648.         r.InsetBy(1.0, 1.0);
  649.         _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
  650.         r.InsetBy(1.0, 1.0);
  651.         _StrokeFrame(r, darkShadow, darkShadow, darkShadow, darkShadow);
  652.         r.InsetBy(1.0, 1.0);
  653.         SetHighColor(darkShadow);
  654.         SetLowColor(shadow);
  655.         // stripes
  656.         float width = floorf(StringWidth(DISABLED_SEEK_MESSAGE));
  657.         float textPos = r.left + r.Width() / 2.0 - width / 2.0;
  658.         pattern stripes = {{ 0xc7, 0x8f, 0x1f, 0x3e, 0x7c, 0xf8, 0xf1, 0xe3 }};
  659.         BRect stripesRect(r);
  660.         stripesRect.right = textPos - 5.0;
  661.         FillRect(stripesRect, stripes);
  662.         stripesRect.left = textPos + width + 3.0;
  663.         stripesRect.right = r.right;
  664.         FillRect(stripesRect, stripes);
  665.         // info text
  666.         r.left = textPos - 4.0;
  667.         r.right = textPos + width + 2.0;
  668.         FillRect(r);
  669.         SetHighColor(shadow);
  670.         SetLowColor(darkShadow);
  671.         font_height fh;
  672.         GetFontHeight(&fh);
  673.         DrawString(DISABLED_SEEK_MESSAGE, BPoint(textPos, r.top + ceilf(fh.ascent) - 1.0));
  674.     }
  675. }
  676. /*****************************************************************************
  677.  * SeekSlider::MouseDown
  678.  *****************************************************************************/
  679. void
  680. SeekSlider::MouseDown(BPoint where)
  681. {
  682.     if (IsEnabled() && Bounds().Contains(where))
  683.     {
  684.         SetValue(_ValueFor(where.x));
  685.         fTracking = true;
  686.         SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
  687.     }
  688. }
  689. /*****************************************************************************
  690.  * SeekSlider::MouseMoved
  691.  *****************************************************************************/
  692. void
  693. SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
  694. {
  695.     if (fTracking)
  696.     {
  697.         SetValue(_ValueFor(where.x));
  698.     }
  699. }
  700. /*****************************************************************************
  701.  * SeekSlider::MouseUp
  702.  *****************************************************************************/
  703. void
  704. SeekSlider::MouseUp(BPoint where)
  705. {
  706.     if (fTracking)
  707.     {
  708.         fTracking = false;
  709.         input_thread_t * p_input;
  710.         p_input = (input_thread_t *)
  711.             vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE );
  712.         if( p_input )
  713.         {
  714.             var_SetFloat( p_input, "position",
  715.                           (float) Value() / SEEKSLIDER_RANGE );
  716.             vlc_object_release( p_input );
  717.         }
  718.     }
  719. }
  720. /*****************************************************************************
  721.  * SeekSlider::ResizeToPreferred
  722.  *****************************************************************************/
  723. void
  724. SeekSlider::ResizeToPreferred()
  725. {
  726.     float width = 15.0 + StringWidth(DISABLED_SEEK_MESSAGE) + 15.0;
  727.     ResizeTo(width, 17.0);
  728. }
  729. /*****************************************************************************
  730.  * SeekSlider::SetPosition
  731.  *****************************************************************************/
  732. void
  733. SeekSlider::SetPosition(float position)
  734. {
  735.     if ( LockLooper() )
  736.     {
  737.         if( !fTracking )
  738.         {
  739.             SetValue( SEEKSLIDER_RANGE * position );
  740.         }
  741.         UnlockLooper();
  742.     }
  743. }
  744. /*****************************************************************************
  745.  * SeekSlider::_ValueFor
  746.  *****************************************************************************/
  747. int32
  748. SeekSlider::_ValueFor(float xPos) const
  749. {
  750.     BRect r(Bounds());
  751.     float knobWidth2 = SEEK_SLIDER_KNOB_WIDTH / 2.0;
  752.     float sliderStart = (r.left + knobWidth2);
  753.     float sliderEnd = (r.right - knobWidth2);
  754.     int32 value =  (int32)(((xPos - sliderStart) * SEEKSLIDER_RANGE)
  755.                   / (sliderEnd - sliderStart - 1.0));
  756.     if (value < 0)
  757.         value = 0;
  758.     if (value > SEEKSLIDER_RANGE)
  759.         value = SEEKSLIDER_RANGE;
  760.     return value;
  761. }
  762. /*****************************************************************************
  763.  * SeekSlider::_StrokeFrame
  764.  *****************************************************************************/
  765. void
  766. SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
  767.                          rgb_color right, rgb_color bottom)
  768. {
  769.     BeginLineArray(4);
  770.         AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
  771.         AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
  772.         AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
  773.         AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
  774.     EndLineArray();
  775. }
  776. /*****************************************************************************
  777.  * VolumeSlider
  778.  *****************************************************************************/
  779. VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
  780.                            BMessage* message, BHandler* target)
  781.     : BControl(frame, name, NULL, message, B_FOLLOW_NONE,
  782.                B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
  783.       fLeftSideBits(NULL),
  784.       fRightSideBits(NULL),
  785.       fKnobBits(NULL),
  786.       fTracking(false),
  787.       fMuted(false),
  788.       fMinValue(minValue),
  789.       fMaxValue(maxValue)
  790. {
  791.     SetTarget(target);
  792.     // create bitmaps
  793.     BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
  794.     fLeftSideBits = new BBitmap(r, B_CMAP8);
  795.     fRightSideBits = new BBitmap(r, B_CMAP8);
  796.     r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
  797.     fKnobBits = new BBitmap(r, B_CMAP8);
  798.     _MakeBitmaps();
  799. }
  800. /*****************************************************************************
  801.  * VolumeSlider destructor
  802.  *****************************************************************************/
  803. VolumeSlider::~VolumeSlider()
  804. {
  805.     delete fLeftSideBits;
  806.     delete fRightSideBits;
  807.     delete fKnobBits;
  808. }
  809. /*****************************************************************************
  810.  * VolumeSlider::AttachedToWindow
  811.  *****************************************************************************/
  812. void
  813. VolumeSlider::AttachedToWindow()
  814. {
  815.     BControl::AttachedToWindow();
  816.     SetViewColor(B_TRANSPARENT_32_BIT);
  817. }
  818. /*****************************************************************************
  819.  * VolumeSlider::SetValue
  820.  *****************************************************************************/
  821. void
  822. VolumeSlider::SetValue(int32 value)
  823. {
  824.     if (value != Value())
  825.     {
  826.         BControl::SetValue(value);
  827.         Invoke();
  828.     }
  829. }
  830. /*****************************************************************************
  831.  * VolumeSlider::SetEnabled
  832.  *****************************************************************************/
  833. void
  834. VolumeSlider::SetEnabled(bool enable)
  835. {
  836.     if (enable != IsEnabled())
  837.     {
  838.         BControl::SetEnabled(enable);
  839.         _MakeBitmaps();
  840.         Invalidate();
  841.     }
  842. }
  843. /*****************************************************************************
  844.  * VolumeSlider::Draw
  845.  *****************************************************************************/
  846. void
  847. VolumeSlider::Draw(BRect updateRect)
  848. {
  849.     if (IsValid())
  850.     {
  851.         BRect r(Bounds());
  852.         float sliderSideWidth = kVolumeSliderBitmapWidth;
  853.         float sliderStart = (r.left + sliderSideWidth);
  854.         float sliderEnd = (r.right - sliderSideWidth);
  855.         float knobPos = sliderStart
  856.                         + (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
  857.                         / (fMaxValue - fMinValue);
  858.         // draw both sides (the original from Be doesn't seem
  859.         // to make a difference for enabled/disabled state)
  860.         DrawBitmapAsync(fLeftSideBits, r.LeftTop());
  861.         DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
  862.         // colors for the slider area between the two bitmaps
  863.         rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
  864.         rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
  865.         rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
  866.         rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
  867.         rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
  868.         rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
  869.         rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
  870.         rgb_color green = kGreen;
  871.         rgb_color greenShadow = kGreenShadow;
  872.         rgb_color black = kBlack;
  873.         rgb_color dotGrey = midShadow;
  874.         rgb_color dotGreen = greenShadow;
  875.         // make dimmed version of colors if we're disabled
  876.         if (!IsEnabled())
  877.         {
  878.             shadow = (rgb_color){ 200, 200, 200, 255 };
  879.             softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
  880.             darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
  881.             midShadow = shadow;
  882.             light = dimmed_color_cmap8(light, background, DIM_LEVEL);
  883.             softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
  884.             green = dimmed_color_cmap8(green, background, DIM_LEVEL);
  885.             greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
  886.             black = dimmed_color_cmap8(black, background, DIM_LEVEL);
  887.             dotGreen = dotGrey;
  888.         }
  889.         else if (fMuted)
  890.         {
  891.             green = tint_color(kBackground, B_DARKEN_3_TINT);
  892.             greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
  893.             dotGreen = greenShadow;
  894.         }
  895.         // draw slider edges between bitmaps
  896.         BeginLineArray(7);
  897.             AddLine(BPoint(sliderStart, r.top),
  898.                     BPoint(sliderEnd, r.top), softShadow);
  899.             AddLine(BPoint(sliderStart, r.bottom),
  900.                     BPoint(sliderEnd, r.bottom), softLight);
  901.             r.InsetBy(0.0, 1.0);
  902.             AddLine(BPoint(sliderStart, r.top),
  903.                     BPoint(sliderEnd, r.top), black);
  904.             AddLine(BPoint(sliderStart, r.bottom),
  905.                     BPoint(sliderEnd, r.bottom), light);
  906.             r.top++;
  907.             AddLine(BPoint(sliderStart, r.top),
  908.                     BPoint(knobPos, r.top), greenShadow);
  909.             AddLine(BPoint(knobPos, r.top),
  910.                     BPoint(sliderEnd, r.top), midShadow);
  911.             r.top++;
  912.             AddLine(BPoint(sliderStart, r.top),
  913.                     BPoint(knobPos, r.top), greenShadow);
  914.         EndLineArray();
  915.         // fill rest inside of slider
  916.         r.InsetBy(0.0, 1.0);
  917.         r.left = sliderStart;
  918.         r.right = knobPos;
  919.         SetHighColor(green);
  920.         FillRect(r, B_SOLID_HIGH);
  921.         r.left = knobPos + 1.0;
  922.         r.right = sliderEnd;
  923.         r.top -= 1.0;
  924.         SetHighColor(shadow);
  925.         FillRect(r, B_SOLID_HIGH);
  926.         // draw little dots inside
  927.         int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
  928.         BPoint dotPos;
  929.         dotPos.y = r.top + 4.0;
  930.         for (int32 i = 0; i < dotCount; i++)
  931.         {
  932.             dotPos.x = sliderStart + i * 5.0 + 4.0;
  933.             SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
  934.             StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
  935.         }
  936.         // draw knob
  937.         r.top -= 1.0;
  938.         SetDrawingMode(B_OP_OVER); // part of knob is transparent
  939.         DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
  940.     }
  941. }
  942. /*****************************************************************************
  943.  * VolumeSlider::MouseDown
  944.  *****************************************************************************/
  945. void
  946. VolumeSlider::MouseDown(BPoint where)
  947. {
  948.     if (Bounds().Contains(where) && IsEnabled())
  949.     {
  950.         fTracking = true;
  951.         SetValue(_ValueFor(where.x));
  952.         SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
  953.     }
  954. }
  955. /*****************************************************************************
  956.  * VolumeSlider::MouseMoved
  957.  *****************************************************************************/
  958. void
  959. VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
  960. {
  961.     if (fTracking)
  962.         SetValue(_ValueFor(where.x));
  963. }
  964. /*****************************************************************************
  965.  * VolumeSlider::MouseUp
  966.  *****************************************************************************/
  967. void
  968. VolumeSlider::MouseUp(BPoint where)
  969. {
  970.     fTracking = false;
  971. }
  972. /*****************************************************************************
  973.  * VolumeSlider::IsValid
  974.  *****************************************************************************/
  975. bool
  976. VolumeSlider::IsValid() const
  977. {
  978.     return (fLeftSideBits && fLeftSideBits->IsValid()
  979.             && fRightSideBits && fRightSideBits->IsValid()
  980.             && fKnobBits && fKnobBits->IsValid());
  981. }
  982. /*****************************************************************************
  983.  * VolumeSlider::SetMuted
  984.  *****************************************************************************/
  985. void
  986. VolumeSlider::SetMuted(bool mute)
  987. {
  988.     if (mute != fMuted)
  989.     {
  990.         fMuted = mute;
  991.         _MakeBitmaps();
  992.         Invalidate();
  993.     }
  994. }
  995. /*****************************************************************************
  996.  * VolumeSlider::_MakeBitmaps
  997.  *****************************************************************************/
  998. void
  999. VolumeSlider::_MakeBitmaps()
  1000. {
  1001.     if (IsValid())
  1002.     {
  1003.         // left side of slider
  1004.         memcpy(fLeftSideBits->Bits(), kVolumeSliderLeftBitmapBits,
  1005.                fLeftSideBits->BitsLength());
  1006.         // right side of slider
  1007.         memcpy(fRightSideBits->Bits(), kVolumeSliderRightBits,
  1008.                fRightSideBits->BitsLength());
  1009.         // slider knob
  1010.         int32 length = fKnobBits->BitsLength();
  1011.         memcpy(fKnobBits->Bits(), kVolumeSliderKnobBits, length);
  1012.         uint8* bits = (uint8*)fKnobBits->Bits();
  1013.         // black was used in the knob to represent transparency
  1014.         // use screen to get index for the "transarent" color used in the bitmap
  1015.         BScreen screen(B_MAIN_SCREEN_ID);
  1016.         uint8 blackIndex = screen.IndexForColor(kBlack);
  1017.         // replace black index with transparent index
  1018.         for (int32 i = 0; i < length; i++)
  1019.             if (bits[i] == blackIndex)
  1020.                 bits[i] = B_TRANSPARENT_MAGIC_CMAP8;
  1021.         if (!IsEnabled())
  1022.         {
  1023.             // make ghosted versions of the bitmaps
  1024.             dim_bitmap(fLeftSideBits, kBackground, DIM_LEVEL);
  1025.             dim_bitmap(fRightSideBits, kBackground, DIM_LEVEL);
  1026.             dim_bitmap(fKnobBits, kBackground, DIM_LEVEL);
  1027.         }
  1028.         else if (fMuted)
  1029.         {
  1030.             // replace green color (and shadow) in left slider side
  1031.             bits = (uint8*)fLeftSideBits->Bits();
  1032.             length = fLeftSideBits->BitsLength();
  1033.             uint8 greenIndex = screen.IndexForColor(kGreen);
  1034.             uint8 greenShadowIndex = screen.IndexForColor(kGreenShadow);
  1035.             rgb_color shadow = tint_color(kBackground, B_DARKEN_3_TINT);
  1036.             rgb_color midShadow = tint_color(kBackground, B_DARKEN_4_TINT);
  1037.             uint8 replaceIndex = screen.IndexForColor(shadow);
  1038.             uint8 replaceShadowIndex = screen.IndexForColor(midShadow);
  1039.             for (int32 i = 0; i < length; i++)
  1040.             {
  1041.                 if (bits[i] == greenIndex)
  1042.                     bits[i] = replaceIndex;
  1043.                 else if (bits[i] == greenShadowIndex)
  1044.                     bits[i] = replaceShadowIndex;
  1045.             }
  1046.         }
  1047.     }
  1048. }
  1049. /*****************************************************************************
  1050.  * VolumeSlider::_ValueFor
  1051.  *****************************************************************************/
  1052. int32
  1053. VolumeSlider::_ValueFor(float xPos) const
  1054. {
  1055.     BRect r(Bounds());
  1056.     float sliderStart = (r.left + kVolumeSliderBitmapWidth);
  1057.     float sliderEnd = (r.right - kVolumeSliderBitmapWidth);
  1058.     int32 value =  fMinValue + (int32)(((xPos - sliderStart) * (fMaxValue - fMinValue))
  1059.                   / (sliderEnd - sliderStart - 1.0));
  1060.     if (value < fMinValue)
  1061.         value = fMinValue;
  1062.     if (value > fMaxValue)
  1063.         value = fMaxValue;
  1064.     return value;
  1065. }
  1066. /*****************************************************************************
  1067.  * PositionInfoView::PositionInfoView
  1068.  *****************************************************************************/
  1069. PositionInfoView::PositionInfoView( BRect frame, const char* name,
  1070.                                     intf_thread_t * p_interface )
  1071.     : BView( frame, name, B_FOLLOW_NONE,
  1072.              B_WILL_DRAW | B_PULSE_NEEDED | B_FULL_UPDATE_ON_RESIZE ),
  1073.       fMode( MODE_SMALL ),
  1074.       fCurrentFileIndex( -1 ),
  1075.       fCurrentFileSize( -1 ),
  1076.       fCurrentTitleIndex( -1 ),
  1077.       fCurrentTitleSize( -1 ),
  1078.       fCurrentChapterIndex( -1 ),
  1079.       fCurrentChapterSize( -1 ),
  1080.       fSeconds( -1 ),
  1081.       fTimeString( "-:--:--" ),
  1082.       fLastPulseUpdate( system_time() ),
  1083.       fStackedWidthCache( 0.0 ),
  1084.       fStackedHeightCache( 0.0 )
  1085. {
  1086.     p_intf = p_interface;
  1087.     SetViewColor( B_TRANSPARENT_32_BIT );
  1088.     SetLowColor( kBlack );
  1089.     SetHighColor( 0, 255, 0, 255 );
  1090.     SetFontSize( 11.0 );
  1091. }
  1092. /*****************************************************************************
  1093.  * PositionInfoView::~PositionInfoView
  1094.  *****************************************************************************/
  1095. PositionInfoView::~PositionInfoView()
  1096. {
  1097. }
  1098. /*****************************************************************************
  1099.  * PositionInfoView::Draw
  1100.  *****************************************************************************/
  1101. void
  1102. PositionInfoView::Draw( BRect updateRect )
  1103. {
  1104.     rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
  1105.     rgb_color shadow = tint_color( background, B_DARKEN_1_TINT );
  1106.     rgb_color darkShadow = tint_color( background, B_DARKEN_4_TINT );
  1107.     rgb_color light = tint_color( background, B_LIGHTEN_MAX_TINT );
  1108.     rgb_color softLight = tint_color( background, B_LIGHTEN_1_TINT );
  1109.     // frame
  1110.     BRect r( Bounds() );
  1111.     BeginLineArray( 8 );
  1112.         AddLine( BPoint( r.left, r.bottom ),
  1113.                  BPoint( r.left, r.top ), shadow );
  1114.         AddLine( BPoint( r.left + 1.0, r.top ),
  1115.                  BPoint( r.right, r.top ), shadow );
  1116.         AddLine( BPoint( r.right, r.top + 1.0 ),
  1117.                  BPoint( r.right, r.bottom ), softLight );
  1118.         AddLine( BPoint( r.right - 1.0, r.bottom ),
  1119.                  BPoint( r.left + 1.0, r.bottom ), softLight );
  1120.         r.InsetBy( 1.0, 1.0 );
  1121.         AddLine( BPoint( r.left, r.bottom ),
  1122.                  BPoint( r.left, r.top ), darkShadow );
  1123.         AddLine( BPoint( r.left + 1.0, r.top ),
  1124.                  BPoint( r.right, r.top ), darkShadow );
  1125.         AddLine( BPoint( r.right, r.top + 1.0 ),
  1126.                  BPoint( r.right, r.bottom ), light );
  1127.         AddLine( BPoint( r.right - 1.0, r.bottom ),
  1128.                  BPoint( r.left + 1.0, r.bottom ), light );
  1129.     EndLineArray();
  1130.     // background
  1131.     r.InsetBy( 1.0, 1.0 );
  1132.     FillRect( r, B_SOLID_LOW );
  1133.     // contents
  1134.     font_height fh;
  1135.     GetFontHeight( &fh );
  1136.     switch ( fMode )
  1137.     {
  1138.         case MODE_SMALL:
  1139.         {
  1140.             float width = StringWidth( fTimeString.String() );
  1141.             DrawString( fTimeString.String(),
  1142.                         BPoint( r.left + r.Width() / 2.0 - width / 2.0,
  1143.                                 r.top + r.Height() / 2.0 + fh.ascent / 2.0 - 1.0 ) );
  1144.             break;
  1145.         }
  1146.         case MODE_BIG:
  1147.         {
  1148.             BFont font;
  1149.             GetFont( &font );
  1150.             BFont smallFont = font;
  1151.             BFont bigFont = font;
  1152.             BFont tinyFont = font;
  1153.             smallFont.SetSize( r.Height() / 5.0 );
  1154.             bigFont.SetSize( r.Height() / 3.0 );
  1155.             tinyFont.SetSize( r.Height() / 7.0 );
  1156.             float timeHeight = r.Height() / 2.5;
  1157.             float height = ( r.Height() - timeHeight ) / 3.0;
  1158.             SetFont( &tinyFont );
  1159.             SetHighColor( 0, 180, 0, 255 );
  1160.             DrawString( _("File"), BPoint( r.left + 3.0, r.top + height ) );
  1161.             DrawString( _("Title"), BPoint( r.left + 3.0, r.top + 2.0 * height ) );
  1162.             DrawString( _("Chapter"), BPoint( r.left + 3.0, r.top + 3.0 * height ) );
  1163.             SetFont( &smallFont );
  1164.             BString helper;
  1165.             SetHighColor( 0, 255, 0, 255 );
  1166.             // file
  1167.             _MakeString( helper, fCurrentFileIndex, fCurrentFileSize );
  1168.             float width = StringWidth( helper.String() );
  1169.             DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + height ) );
  1170.             // title
  1171.             _MakeString( helper, fCurrentTitleIndex, fCurrentTitleSize );
  1172.             width = StringWidth( helper.String() );
  1173.             DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 2.0 * height ) );
  1174.             // chapter
  1175.             _MakeString( helper, fCurrentChapterIndex, fCurrentChapterSize );
  1176.             width = StringWidth( helper.String() );
  1177.             DrawString( helper.String(), BPoint( r.right - 3.0 - width, r.top + 3.0 * height ) );
  1178.             // time
  1179.             SetFont( &bigFont );
  1180.             width = StringWidth( fTimeString.String() );
  1181.             DrawString( fTimeString.String(),
  1182.                         BPoint( r.left + r.Width() / 2.0 - width / 2.0,
  1183.                                 r.bottom - 3.0 ) );
  1184.             break;
  1185.         }
  1186.     }
  1187. }
  1188. /*****************************************************************************
  1189.  * PositionInfoView::ResizeToPreferred
  1190.  *****************************************************************************/
  1191. void
  1192. PositionInfoView::ResizeToPreferred()
  1193. {
  1194.     float width, height;
  1195.     GetPreferredSize( &width, &height );
  1196.     ResizeTo( width, height );
  1197. }
  1198. /*****************************************************************************
  1199.  * PositionInfoView::GetPreferredSize
  1200.  *****************************************************************************/
  1201. void
  1202. PositionInfoView::GetPreferredSize( float* width, float* height )
  1203. {
  1204.     if ( width && height )
  1205.     {
  1206.         *width = 5.0 + ceilf( StringWidth( "0:00:00" ) ) + 5.0;
  1207.         font_height fh;
  1208.         GetFontHeight( &fh );
  1209.         *height = 3.0 + ceilf( fh.ascent ) + 3.0;
  1210.         fStackedWidthCache = *width * 1.2;
  1211.         fStackedHeightCache = *height * 2.7;
  1212.     }
  1213. }
  1214. /*****************************************************************************
  1215.  * PositionInfoView::Pulse
  1216.  *****************************************************************************/
  1217. void
  1218. PositionInfoView::Pulse()
  1219. {
  1220.     // allow for Pulse frequency to be higher, MediaControlView needs it
  1221.     bigtime_t now = system_time();
  1222.     if ( now - fLastPulseUpdate > 900000 )
  1223.     {
  1224. #if 0
  1225.         int32 index, size;
  1226.         p_intf->p_sys->p_wrapper->GetPlaylistInfo( index, size );
  1227.         SetFile( index + 1, size );
  1228.         p_intf->p_sys->p_wrapper->TitleInfo( index, size );
  1229.         SetTitle( index, size );
  1230.         p_intf->p_sys->p_wrapper->ChapterInfo( index, size );
  1231.         SetChapter( index, size );
  1232.         SetTime( p_intf->p_sys->p_wrapper->GetTimeAsString() );
  1233.         fLastPulseUpdate = now;
  1234. #endif
  1235.     }
  1236. }
  1237. /*****************************************************************************
  1238.  * PositionInfoView::GetBigPreferredSize
  1239.  *****************************************************************************/
  1240. void
  1241. PositionInfoView::GetBigPreferredSize( float* width, float* height )
  1242. {
  1243.     if ( width && height )
  1244.     {
  1245.         *width = fStackedWidthCache;
  1246.         *height = fStackedHeightCache;
  1247.     }
  1248. }
  1249. /*****************************************************************************
  1250.  * PositionInfoView::SetMode
  1251.  *****************************************************************************/
  1252. void
  1253. PositionInfoView::SetMode( uint32 mode )
  1254. {
  1255.     if ( fMode != mode )
  1256.     {
  1257.         fMode = mode;
  1258.         _InvalidateContents();
  1259.     }
  1260. }
  1261. /*****************************************************************************
  1262.  * PositionInfoView::SetFile
  1263.  *****************************************************************************/
  1264. void
  1265. PositionInfoView::SetFile( int32 index, int32 size )
  1266. {
  1267.     if ( fCurrentFileIndex != index || fCurrentFileSize != size )
  1268.     {
  1269.         fCurrentFileIndex = index;
  1270.         fCurrentFileSize = size;
  1271.         _InvalidateContents();
  1272.     }
  1273. }
  1274. /*****************************************************************************
  1275.  * PositionInfoView::SetTitle
  1276.  *****************************************************************************/
  1277. void
  1278. PositionInfoView::SetTitle( int32 index, int32 size )
  1279. {
  1280.     if ( fCurrentTitleIndex != index || fCurrentFileSize != size )
  1281.     {
  1282.         fCurrentTitleIndex = index;
  1283.         fCurrentTitleSize = size;
  1284.         _InvalidateContents();
  1285.     }
  1286. }
  1287. /*****************************************************************************
  1288.  * PositionInfoView::SetChapter
  1289.  *****************************************************************************/
  1290. void
  1291. PositionInfoView::SetChapter( int32 index, int32 size )
  1292. {
  1293.     if ( fCurrentChapterIndex != index || fCurrentFileSize != size )
  1294.     {
  1295.         fCurrentChapterIndex = index;
  1296.         fCurrentChapterSize = size;
  1297.         _InvalidateContents();
  1298.     }
  1299. }
  1300. /*****************************************************************************
  1301.  * PositionInfoView::SetTime
  1302.  *****************************************************************************/
  1303. void
  1304. PositionInfoView::SetTime( int32 seconds )
  1305. {
  1306.     if ( fSeconds != seconds )
  1307.     {
  1308.         if ( seconds >= 0 )
  1309.         {
  1310.             int32 minutes = seconds / 60;
  1311.             int32 hours = minutes / 60;
  1312.             seconds -= minutes * 60 - hours * 60 * 60;
  1313.             minutes -= hours * 60;
  1314.             fTimeString.SetTo( "" );
  1315.             fTimeString << hours << ":" << minutes << ":" << seconds;
  1316.         }
  1317.         else
  1318.             fTimeString.SetTo( "-:--:--" );
  1319.         fSeconds = seconds;
  1320.         _InvalidateContents();
  1321.     }
  1322. }
  1323. /*****************************************************************************
  1324.  * PositionInfoView::SetTime
  1325.  *****************************************************************************/
  1326. void
  1327. PositionInfoView::SetTime( const char* string )
  1328. {
  1329.     fTimeString.SetTo( string );
  1330.     _InvalidateContents();
  1331. }
  1332. /*****************************************************************************
  1333.  * PositionInfoView::_InvalidateContents
  1334.  *****************************************************************************/
  1335. void
  1336. PositionInfoView::_InvalidateContents( uint32 which )
  1337. {
  1338.     BRect r( Bounds() );
  1339.     r.InsetBy( 2.0, 2.0 );
  1340.     Invalidate( r );
  1341. }
  1342. /*****************************************************************************
  1343.  * PositionInfoView::_InvalidateContents
  1344.  *****************************************************************************/
  1345. void
  1346. PositionInfoView::_MakeString( BString& into, int32 index, int32 maxIndex ) const
  1347. {
  1348.     into = "";
  1349.     if ( index >= 0 && maxIndex >= 0 )
  1350.         into << index;
  1351.     else
  1352.         into << "-";
  1353.     into << "/";
  1354.     if ( maxIndex >= 0 )
  1355.         into << maxIndex;
  1356.     else
  1357.         into << "-";
  1358. }