Commit 4a9a8422 authored by Tony Castley's avatar Tony Castley

src/misc/beos_specific.cpp:

- Implemented VlcApplication::RefsReceived()
- this added ability to open a file by dropping its icon onto the vlc icon
- this makes Open With... work as well
plugins/beos/intf_beos.cpp
- A message is sent to be_app when the interface is created
	(needed to support BApplication::RefsReceived())
plugins/beos/vout_beos.cpp
- reacts on Escape and Tab key to switch fullscreen/window mode
- blanks cursor when no activity
- Fixed a memory leak in VideoWindow::ScreenChanged()
- Fixed the ugly scrambled video content before any decoding actually begins
- Added selectable aspect ratio correction
- Added better error handling when setting the drawing mode
plugins/beos/InterfaceWindow.h/.cpp
- Implemented dynamic view layout
- Fixed crashes in MessageReceived() when no file was loaded
- Implemented disabling of menus when no file is loaded
- Added "Speed" menu
- Added ability to enable navigation menu items according to features of current stream
- Cleaned up code somewhat
- Changed parts of LanguageMenu::GetChannels() to show more user friendly and no invalid entries
- better support for muting and volume info
- better support for scrubbing and detection of stopped stream
plugins/beos/MediaControlView.h/.cpp
- Added dynamic layout of elements
- Exchanged rewind/fastforward buttons for skip buttons that skip to the next chapter if stream supports it.
- made nicer looking SeekSlider similar to BeOS MediaPlayer
- made VolumeSlider similar to BeOS MediaPlayer, plus additional features that one doesn't have (muted state)
- got rid of MediaSlider (no need for it anymore)
- detection of stopped stream
plugins/beos/Bitmaps.h
- Added bitmaps for VolumeSlider
plugins/beos/intf_vlc_wrapper.h/.cpp
- added set_volume() and is_muted() functions
- fixed a bug in toggle_muted()
parent a25aaff5
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* DrawingTidbits.cpp * DrawingTidbits.cpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: DrawingTidbits.cpp,v 1.2 2001/03/21 13:42:33 sam Exp $ * $Id: DrawingTidbits.cpp,v 1.2.4.1 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Tony Castley <tcastley@mail.powerup.com.au> * Authors: Tony Castley <tcastley@mail.powerup.com.au>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include "DrawingTidbits.h" #include "DrawingTidbits.h"
// ShiftComponent
inline uchar inline uchar
ShiftComponent(uchar component, float percent) ShiftComponent(uchar component, float percent)
{ {
...@@ -38,6 +40,7 @@ ShiftComponent(uchar component, float percent) ...@@ -38,6 +40,7 @@ ShiftComponent(uchar component, float percent)
return (uchar)(255 - percent * (255 - component)); return (uchar)(255 - percent * (255 - component));
} }
// ShiftColor
rgb_color rgb_color
ShiftColor(rgb_color color, float percent) ShiftColor(rgb_color color, float percent)
{ {
...@@ -51,6 +54,7 @@ ShiftColor(rgb_color color, float percent) ...@@ -51,6 +54,7 @@ ShiftColor(rgb_color color, float percent)
return result; return result;
} }
// CompareColors
static bool static bool
CompareColors(const rgb_color a, const rgb_color b) CompareColors(const rgb_color a, const rgb_color b)
{ {
...@@ -60,18 +64,21 @@ CompareColors(const rgb_color a, const rgb_color b) ...@@ -60,18 +64,21 @@ CompareColors(const rgb_color a, const rgb_color b)
&& a.alpha == b.alpha; && a.alpha == b.alpha;
} }
bool // ==
bool
operator==(const rgb_color &a, const rgb_color &b) operator==(const rgb_color &a, const rgb_color &b)
{ {
return CompareColors(a, b); return CompareColors(a, b);
} }
bool // !=
bool
operator!=(const rgb_color &a, const rgb_color &b) operator!=(const rgb_color &a, const rgb_color &b)
{ {
return !CompareColors(a, b); return !CompareColors(a, b);
} }
// ReplaceColor
void void
ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to) ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
{ {
...@@ -88,6 +95,7 @@ ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to) ...@@ -88,6 +95,7 @@ ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
bits[index] = toIndex; bits[index] = toIndex;
} }
// ReplaceTransparentColor
void void
ReplaceTransparentColor(BBitmap *bitmap, rgb_color with) ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
{ {
...@@ -103,3 +111,180 @@ ReplaceTransparentColor(BBitmap *bitmap, rgb_color with) ...@@ -103,3 +111,180 @@ ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
bits[index] = withIndex; bits[index] = withIndex;
} }
// convert_bitmap
status_t
convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap)
{
status_t status = B_BAD_VALUE;
/* // see that we got valid bitmaps
if (inBitmap && inBitmap->IsValid()
&& outBitmap && outBitmap->IsValid())
{
status = B_MISMATCHED_VALUES;
// see that bitmaps are compatible and that we support the conversion
if (inBitmap->Bounds().Width() == outBitmap->Bounds().Width()
&& inBitmap->Bounds().Height() == outBitmap->Bounds().Height()
&& (outBitmap->ColorSpace() == B_RGB32
|| outBitmap->ColorSpace() == B_RGBA32))
{
int32 width = inBitmap->Bounds().IntegerWidth() + 1;
int32 height = inBitmap->Bounds().IntegerHeight() + 1;
int32 srcBpr = inBitmap->BytesPerRow();
int32 dstBpr = outBitmap->BytesPerRow();
uint8* srcbits = (uint8*)inbitmap->bits();
uint8* dstbits = (uint8*)outbitmap->bits();
switch (inBitmap->ColorSpace())
{
case B_YCbCr422:
for (int32 y = 0; y < height; y ++)
{
for (int32 x = 0; x < width; x += 2)
{
uint8 y =
uint8 cb =
uint8 cr =
}
srcbits += srcBpr;
dstbits += dstBpr;
}
status = B_OK;
break;
case B_YCbCr420:
status = B_OK;
break;
case B_YUV422:
status = B_OK;
break;
case B_RGB32:
memcpy(dstBits, srcBits, inBitmap->BitsLength());
status = B_OK;
break;
default:
status = B_MISMATCHED_VALUES;
break;
}
}
}*/
return status;
}
// clip_float
inline uint8
clip_float(float value)
{
if (value < 0)
value = 0;
if (value > 255)
value = 255;
return (uint8)value;
}
// dim_bitmap
status_t
dim_bitmap(BBitmap* bitmap, rgb_color center, float dimLevel)
{
status_t status = B_BAD_VALUE;
if (bitmap && bitmap->IsValid())
{
switch (bitmap->ColorSpace())
{
case B_CMAP8:
{
BScreen screen(B_MAIN_SCREEN_ID);
if (screen.IsValid())
{
// iterate over each pixel, get the respective
// color from the screen object, find the distance
// to the "center" color and shorten the distance
// by "dimLevel"
int32 length = bitmap->BitsLength();
uint8* bits = (uint8*)bitmap->Bits();
for (int32 i = 0; i < length; i++)
{
// preserve transparent pixels
if (bits[i] != B_TRANSPARENT_MAGIC_CMAP8)
{
// get color for this index
rgb_color c = screen.ColorForIndex(bits[i]);
// red
float dist = (c.red - center.red) * dimLevel;
c.red = clip_float(center.red + dist);
// green
dist = (c.green - center.green) * dimLevel;
c.green = clip_float(center.green + dist);
// blue
dist = (c.blue - center.blue) * dimLevel;
c.blue = clip_float(center.blue + dist);
// write correct index of the dimmed color
// back into bitmap (and hope the match is close...)
bits[i] = screen.IndexForColor(c);
}
}
status = B_OK;
}
break;
}
case B_RGB32:
case B_RGBA32:
{
// iterate over each color component, find the distance
// to the "center" color and shorten the distance
// by "dimLevel"
uint8* bits = (uint8*)bitmap->Bits();
int32 bpr = bitmap->BytesPerRow();
int32 pixels = bitmap->Bounds().IntegerWidth() + 1;
int32 lines = bitmap->Bounds().IntegerHeight() + 1;
// iterate over color components
for (int32 y = 0; y < lines; y++) {
for (int32 x = 0; x < pixels; x++) {
int32 offset = 4 * x; // four bytes per pixel
// blue
float dist = (bits[offset + 0] - center.blue) * dimLevel;
bits[offset + 0] = clip_float(center.blue + dist);
// green
dist = (bits[offset + 1] - center.green) * dimLevel;
bits[offset + 1] = clip_float(center.green + dist);
// red
dist = (bits[offset + 2] - center.red) * dimLevel;
bits[offset + 2] = clip_float(center.red + dist);
// ignore alpha channel
}
// next line
bits += bpr;
}
status = B_OK;
break;
}
default:
status = B_ERROR;
break;
}
}
return status;
}
// dimmed_color_cmap8
rgb_color
dimmed_color_cmap8(rgb_color color, rgb_color center, float dimLevel)
{
BScreen screen(B_MAIN_SCREEN_ID);
if (screen.IsValid())
{
// red
float dist = (color.red - center.red) * dimLevel;
color.red = clip_float(center.red + dist);
// green
dist = (color.green - center.green) * dimLevel;
color.green = clip_float(center.green + dist);
// blue
dist = (color.blue - center.blue) * dimLevel;
color.blue = clip_float(center.blue + dist);
// get color index for dimmed color
int32 index = screen.IndexForColor(color);
// put color at index (closest match in palette
// to dimmed result) into returned color
color = screen.ColorForIndex(index);
}
return color;
}
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* DrawingTidbits.h * DrawingTidbits.h
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: DrawingTidbits.h,v 1.2 2001/03/21 13:42:33 sam Exp $ * $Id: DrawingTidbits.h,v 1.2.4.1 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Tony Castley <tcastley@mail.powerup.com.au> * Authors: Tony Castley <tcastley@mail.powerup.com.au>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -51,5 +52,28 @@ const float kDimLevel = 0.6; ...@@ -51,5 +52,28 @@ const float kDimLevel = 0.6;
void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to); void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with); void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
// bitmaps need to be the same size, or this function will fail
// currently supported conversions:
// B_YCbCr422 -> B_RGB32
// B_YCbCr420 -> B_RGB32
// B_YUV422 -> B_RGB32
// B_RGB32 -> B_RGB32
//status_t convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap);
#endif // dims bitmap (in place) by finding the distance of
// the color at each pixel to the provided "center" color
// and shortens that distance by dimLevel
// (dimLevel < 1 -> less contrast)
// (dimLevel > 1 -> more contrast)
// (dimLevel < 0 -> inverted colors)
// currently supported colorspaces:
// B_RGB32
// B_RGBA32
// B_CMAP8
status_t dim_bitmap(BBitmap* bitmap, rgb_color center,
float dimLevel);
rgb_color dimmed_color_cmap8(rgb_color color, rgb_color center,
float dimLevel);
#endif // __DRAWING_TIBITS__
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
* InterfaceWindow.cpp: beos interface * InterfaceWindow.cpp: beos interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: InterfaceWindow.cpp,v 1.16.2.2 2002/07/13 11:33:11 tcastley Exp $ * $Id: InterfaceWindow.cpp,v 1.16.2.3 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
* Tony Castley <tony@castley.net> * Tony Castley <tony@castley.net>
* Richard Shepherd <richard@rshepherd.demon.co.uk> * Richard Shepherd <richard@rshepherd.demon.co.uk>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -58,6 +59,8 @@ extern "C" ...@@ -58,6 +59,8 @@ extern "C"
#include "intf_vlc_wrapper.h" #include "intf_vlc_wrapper.h"
#include "InterfaceWindow.h" #include "InterfaceWindow.h"
#define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps
/***************************************************************************** /*****************************************************************************
* InterfaceWindow * InterfaceWindow
...@@ -65,90 +68,112 @@ extern "C" ...@@ -65,90 +68,112 @@ extern "C"
InterfaceWindow::InterfaceWindow( BRect frame, const char *name, InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
intf_thread_t *p_interface ) intf_thread_t *p_interface )
: BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
| B_ASYNCHRONOUS_CONTROLS ) p_intf(p_interface),
b_empty_playlist(p_main->p_playlist->i_size < 0),
file_panel(NULL),
playlist_window(NULL),
fLastUpdateTime(system_time())
{ {
file_panel = NULL; // set the title bar
playlist_window = NULL; SetName( "interface" );
p_intf = p_interface; SetTitle(VOUT_TITLE);
BRect controlRect(0,0,0,0);
b_empty_playlist = (p_main->p_playlist->i_size < 0); // the media control view
p_mediaControl = new MediaControlView( BRect(0.0, 0.0, 250.0, 50.0) );
/* set the title bar */ p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
SetName( "interface" ); b_empty_playlist = true;
SetTitle(VOUT_TITLE); p_mediaControl->SetEnabled( !b_empty_playlist );
/* set up the main menu */ float width, height;
BMenuBar *menu_bar; p_mediaControl->GetPreferredSize(&width, &height);
menu_bar = new BMenuBar(controlRect, "main menu");
AddChild( menu_bar ); // set up the main menu
fMenuBar = new BMenuBar( BRect(0.0, 0.0, width, 15.0), "main menu",
BMenu *mFile; B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
BMenu *mAudio;
CDMenu *cd_menu; // make menu bar resize to correct height
BMenu *mNavigation; float menuWidth, menuHeight;
BMenu *mConfig; fMenuBar->GetPreferredSize(&menuWidth, &menuHeight);
fMenuBar->ResizeTo(width, menuHeight); // don't change! it's a workarround!
// take care of proper size for ourself
height += fMenuBar->Bounds().Height();
ResizeTo(width, height);
p_mediaControl->MoveTo( fMenuBar->Bounds().LeftBottom() + BPoint(0.0, 1.0) );
AddChild( fMenuBar );
AddChild( p_mediaControl );
BMenu *fileMenu;
// BMenu *configMenu;
/* Add the file Menu */ // Add the file Menu
BMenuItem *mItem; BMenuItem *mItem;
menu_bar->AddItem( mFile = new BMenu( "File" ) ); fMenuBar->AddItem( fileMenu = new BMenu( "File" ) );
menu_bar->ResizeToPreferred(); fileMenu->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
new BMessage(OPEN_FILE), 'O') ); new BMessage(OPEN_FILE), 'O') );
cd_menu = new CDMenu( "Open Disc" ); fileMenu->AddItem( new CDMenu( "Open Disc" ) );
mFile->AddItem( cd_menu );
mFile->AddSeparatorItem(); fileMenu->AddSeparatorItem();
mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS, fileMenu->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
new BMessage(OPEN_PLAYLIST), 'P') ); new BMessage(OPEN_PLAYLIST), 'P') );
mFile->AddSeparatorItem(); fileMenu->AddSeparatorItem();
mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS, fileMenu->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
new BMessage(B_ABOUT_REQUESTED), 'A') ); new BMessage(B_ABOUT_REQUESTED), 'A') );
mItem->SetTarget( be_app ); mItem->SetTarget( be_app );
mFile->AddItem(mItem = new BMenuItem( "Quit", fileMenu->AddItem(mItem = new BMenuItem( "Quit",
new BMessage(B_QUIT_REQUESTED), 'Q') ); new BMessage(B_QUIT_REQUESTED), 'Q') );
fLanguageMenu = new LanguageMenu("Language", AUDIO_ES, p_intf);
fSubtitlesMenu = new LanguageMenu("Subtitles", SPU_ES, p_intf);
/* Add the Audio menu */ /* Add the Audio menu */
menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) ); fAudioMenu = new BMenu( "Audio" );
menu_bar->ResizeToPreferred(); fMenuBar->AddItem ( fAudioMenu );
mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) ); fAudioMenu->AddItem( fLanguageMenu );
mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) ); fAudioMenu->AddItem( fSubtitlesMenu );
fPrevTitleMI = new BMenuItem("Prev Title", new BMessage(PREV_TITLE));
fNextTitleMI = new BMenuItem("Next Title", new BMessage(NEXT_TITLE));
fPrevChapterMI = new BMenuItem("Prev Chapter", new BMessage(PREV_CHAPTER));
fNextChapterMI = new BMenuItem("Next Chapter", new BMessage(NEXT_CHAPTER));
/* Add the Navigation menu */ /* Add the Navigation menu */
menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) ); fNavigationMenu = new BMenu( "Navigation" );
menu_bar->ResizeToPreferred(); fMenuBar->AddItem( fNavigationMenu );
mNavigation->AddItem( new BMenuItem( "Prev Title", fNavigationMenu->AddItem(fPrevTitleMI);
new BMessage(PREV_TITLE)) ); fNavigationMenu->AddItem(fNextTitleMI);
mNavigation->AddItem( new BMenuItem( "Next Title", fNavigationMenu->AddItem(fPrevChapterMI);
new BMessage(NEXT_TITLE)) ); fNavigationMenu->AddItem(fNextChapterMI);
mNavigation->AddItem( new BMenuItem( "Prev Chapter",
new BMessage(PREV_CHAPTER)) ); /* Add the Speed menu */
mNavigation->AddItem( new BMenuItem( "Next Chapter", fSpeedMenu = new BMenu("Speed");
new BMessage(NEXT_CHAPTER)) ); fSpeedMenu->SetRadioMode(true);
fSpeedMenu->AddItem( new BMenuItem( "Slow",
new BMessage(SLOWER_PLAY)) );
BMenuItem* normalSpeedItem = new BMenuItem( "Normal",
new BMessage(NORMAL_PLAY));
normalSpeedItem->SetMarked(true); // default to normal speed
fSpeedMenu->AddItem( normalSpeedItem );
fSpeedMenu->AddItem( new BMenuItem( "Fast",
new BMessage(FASTER_PLAY)) );
fSpeedMenu->SetTargetForItems(this);
fMenuBar->AddItem(fSpeedMenu);
/* Add the Config menu */ /* Add the Config menu */
// menu_bar->AddItem( mConfig = new BMenu( "Config" ) ); // menu_bar->AddItem( configMenu = new BMenu( "Config" ) );
// menu_bar->ResizeToPreferred(); // menu_bar->ResizeToPreferred();
// mConfig->AddItem( miOnTop = new BMenuItem( "Always on Top", // configMenu->AddItem( miOnTop = new BMenuItem( "Always on Top",
// new BMessage(TOGGLE_ON_TOP)) ); // new BMessage(TOGGLE_ON_TOP)) );
// miOnTop->SetMarked(false); // miOnTop->SetMarked(false);
ResizeTo(260,50 + menu_bar->Bounds().IntegerHeight()+1);
controlRect = Bounds();
controlRect.top += menu_bar->Bounds().IntegerHeight() + 1;
p_mediaControl = new MediaControlView( controlRect );
p_mediaControl->SetViewColor( ui_color(B_PANEL_BACKGROUND_COLOR) );
b_empty_playlist = true;
p_mediaControl->SetEnabled( !b_empty_playlist );
/* Show */ /* Show */
AddChild( p_mediaControl ); _SetMenusEnabled(false);
Show(); Show();
} }
InterfaceWindow::~InterfaceWindow() InterfaceWindow::~InterfaceWindow()
...@@ -156,6 +181,20 @@ InterfaceWindow::~InterfaceWindow() ...@@ -156,6 +181,20 @@ InterfaceWindow::~InterfaceWindow()
if (playlist_window) playlist_window->ReallyQuit(); if (playlist_window) playlist_window->ReallyQuit();
} }
/*****************************************************************************
* InterfaceWindow::FrameResized
*****************************************************************************/
void
InterfaceWindow::FrameResized(float width, float height)
{
BRect r(Bounds());
fMenuBar->MoveTo(r.LeftTop());
fMenuBar->ResizeTo(r.Width(), fMenuBar->Bounds().Height());
r.top += fMenuBar->Bounds().Height() + 1.0;
p_mediaControl->MoveTo(r.LeftTop());
p_mediaControl->ResizeTo(r.Width(), r.Height());
}
/***************************************************************************** /*****************************************************************************
* InterfaceWindow::MessageReceived * InterfaceWindow::MessageReceived
*****************************************************************************/ *****************************************************************************/
...@@ -166,7 +205,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -166,7 +205,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
int i_index; int i_index;
BAlert *alert; BAlert *alert;
Activate(); // Activate(); // why ?!?
if (p_input_bank->pp_input[0]) if (p_input_bank->pp_input[0])
{ {
playback_status = p_input_bank->pp_input[0]->stream.control.i_status; playback_status = p_input_bank->pp_input[0]->stream.control.i_status;
...@@ -211,7 +250,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -211,7 +250,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
{ {
const char *psz_device; const char *psz_device;
BString type("dvd"); BString type("dvd");
if( p_message->FindString("device", &psz_device) != B_ERROR ) if( p_message->FindString("device", &psz_device) == B_OK )
{ {
BString device(psz_device); BString device(psz_device);
Intf_VLCWrapper::openDisc(type, device, 0,0); Intf_VLCWrapper::openDisc(type, device, 0,0);
...@@ -223,10 +262,13 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -223,10 +262,13 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case STOP_PLAYBACK: case STOP_PLAYBACK:
// this currently stops playback not nicely // this currently stops playback not nicely
Intf_VLCWrapper::volume_mute(); if (playback_status > UNDEF_S)
snooze( 400000 ); {
Intf_VLCWrapper::playlistStop(); Intf_VLCWrapper::volume_mute();
p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE); snooze( 400000 );
Intf_VLCWrapper::playlistStop();
p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
}
break; break;
case START_PLAYBACK: case START_PLAYBACK:
...@@ -234,7 +276,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -234,7 +276,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case PAUSE_PLAYBACK: case PAUSE_PLAYBACK:
/* toggle between pause and play */ /* toggle between pause and play */
if( p_input_bank->pp_input[0] != NULL ) if (playback_status > UNDEF_S)
{ {
/* pause if currently playing */ /* pause if currently playing */
if ( playback_status == PLAYING_S ) if ( playback_status == PLAYING_S )
...@@ -258,16 +300,31 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -258,16 +300,31 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case FASTER_PLAY: case FASTER_PLAY:
/* cycle the fast playback modes */ /* cycle the fast playback modes */
Intf_VLCWrapper::volume_mute(); if (playback_status > UNDEF_S)
snooze( 400000 ); {
Intf_VLCWrapper::playFaster(); Intf_VLCWrapper::volume_mute();
snooze( 400000 );
Intf_VLCWrapper::playFaster();
}
break; break;
case SLOWER_PLAY: case SLOWER_PLAY:
/* cycle the slow playback modes */ /* cycle the slow playback modes */
Intf_VLCWrapper::volume_mute(); if (playback_status > UNDEF_S)
snooze( 400000 ); {
Intf_VLCWrapper::playSlower(); Intf_VLCWrapper::volume_mute();
snooze( 400000 );
Intf_VLCWrapper::playSlower();
}
break;
case NORMAL_PLAY:
/* restore speed to normal if already playing */
if (playback_status > UNDEF_S)
{
Intf_VLCWrapper::volume_restore();
Intf_VLCWrapper::playlistPlay();
}
break; break;
case SEEK_PLAYBACK: case SEEK_PLAYBACK:
...@@ -276,27 +333,34 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -276,27 +333,34 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case VOLUME_CHG: case VOLUME_CHG:
/* adjust the volume */ /* adjust the volume */
vlc_mutex_lock( &p_aout_bank->lock ); if (playback_status > UNDEF_S)
for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
{ {
if( p_aout_bank->pp_aout[i_index]->i_savedvolume ) /* vlc_mutex_lock( &p_aout_bank->lock );
{ for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val; {
} if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
else {
{ p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
p_aout_bank->pp_aout[i_index]->i_volume = vol_val; }
} else
{
p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
}
}
vlc_mutex_unlock( &p_aout_bank->lock );*/
Intf_VLCWrapper::set_volume( vol_val );
p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
} }
vlc_mutex_unlock( &p_aout_bank->lock );
break; break;
case VOLUME_MUTE: case VOLUME_MUTE:
/* toggle muting */ /* toggle muting */
Intf_VLCWrapper::toggle_mute(); Intf_VLCWrapper::toggle_mute();
p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
break; break;
case SELECT_CHANNEL: case SELECT_CHANNEL:
if (playback_status > UNDEF_S)
{ {
int32 i = p_message->FindInt32( "channel" ); int32 i = p_message->FindInt32( "channel" );
if ( i == -1 ) if ( i == -1 )
...@@ -312,6 +376,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -312,6 +376,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
break; break;
case SELECT_SUBTITLE: case SELECT_SUBTITLE:
if (playback_status > UNDEF_S)
{ {
int32 i = p_message->FindInt32( "subtitle" ); int32 i = p_message->FindInt32( "subtitle" );
if ( i == -1 ) if ( i == -1 )
...@@ -326,6 +391,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -326,6 +391,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
} }
break; break;
case PREV_TITLE: case PREV_TITLE:
if (playback_status > UNDEF_S)
{ {
int i_id; int i_id;
i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1; i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1;
...@@ -338,6 +404,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -338,6 +404,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
break; break;
} }
case NEXT_TITLE: case NEXT_TITLE:
if (playback_status > UNDEF_S)
{ {
int i_id; int i_id;
...@@ -350,6 +417,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -350,6 +417,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
} }
break; break;
case PREV_CHAPTER: case PREV_CHAPTER:
if (playback_status > UNDEF_S)
{ {
int i_id; int i_id;
...@@ -362,6 +430,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -362,6 +430,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
} }
break; break;
case NEXT_CHAPTER: case NEXT_CHAPTER:
if (playback_status > UNDEF_S)
{ {
int i_id; int i_id;
...@@ -397,6 +466,24 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) ...@@ -397,6 +466,24 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
} }
/*****************************************************************************
* InterfaceWindow::QuitRequested
*****************************************************************************/
bool InterfaceWindow::QuitRequested()
{
if (p_input_bank->pp_input[0])
{
Intf_VLCWrapper::volume_mute();
snooze( 400000 );
Intf_VLCWrapper::playlistStop();
p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
}
p_intf->b_die = 1;
return( true );
}
/***************************************************************************** /*****************************************************************************
* InterfaceWindow::updateInterface * InterfaceWindow::updateInterface
*****************************************************************************/ *****************************************************************************/
...@@ -407,18 +494,34 @@ void InterfaceWindow::updateInterface() ...@@ -407,18 +494,34 @@ void InterfaceWindow::updateInterface()
if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK ) if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
{ {
uint64 seekTo = (p_mediaControl->GetSeekTo() * uint64 seekTo = (p_mediaControl->GetSeekTo() *
p_input_bank->pp_input[0]->stream.p_selected_area->i_size) / 100; p_input_bank->pp_input[0]->stream.p_selected_area->i_size) / 2048;
input_Seek( p_input_bank->pp_input[0], seekTo); input_Seek( p_input_bank->pp_input[0], seekTo);
} }
else if( Lock() ) else if( Lock() )
{ {
bool hasTitles = p_input_bank->pp_input[0]->stream.i_area_nb > 1;
bool hasChapters = p_input_bank->pp_input[0]->stream.p_selected_area->i_part_nb > 1;
p_mediaControl->SetStatus(p_input_bank->pp_input[0]->stream.control.i_status, p_mediaControl->SetStatus(p_input_bank->pp_input[0]->stream.control.i_status,
p_input_bank->pp_input[0]->stream.control.i_rate); p_input_bank->pp_input[0]->stream.control.i_rate);
p_mediaControl->SetProgress(p_input_bank->pp_input[0]->stream.p_selected_area->i_tell, p_mediaControl->SetProgress(p_input_bank->pp_input[0]->stream.p_selected_area->i_tell,
p_input_bank->pp_input[0]->stream.p_selected_area->i_size); p_input_bank->pp_input[0]->stream.p_selected_area->i_size);
_SetMenusEnabled(true, hasChapters, hasTitles);
bool canSkipBack = false;
bool canSkipForward = false;
if (hasChapters)
{
canSkipBack = p_input_bank->pp_input[0]->stream.p_selected_area->i_part > 0;
canSkipForward = p_input_bank->pp_input[0]->stream.p_selected_area->i_part <
p_input_bank->pp_input[0]->stream.p_selected_area->i_part_nb - 1;
}
p_mediaControl->SetSkippable(canSkipBack, canSkipForward);
p_mediaControl->SetMuted(Intf_VLCWrapper::is_muted());
Unlock(); Unlock();
} }
} }
else
_SetMenusEnabled(false);
if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) ) if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) )
{ {
if (Lock()) if (Lock())
...@@ -428,16 +531,51 @@ void InterfaceWindow::updateInterface() ...@@ -428,16 +531,51 @@ void InterfaceWindow::updateInterface()
Unlock(); Unlock();
} }
} }
fLastUpdateTime = system_time();
} }
/***************************************************************************** /*****************************************************************************
* InterfaceWindow::QuitRequested * InterfaceWindow::IsStopped
*****************************************************************************/ *****************************************************************************/
bool InterfaceWindow::QuitRequested() bool
InterfaceWindow::IsStopped() const
{ {
p_intf->b_die = 1; return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
}
return( true ); /*****************************************************************************
* InterfaceWindow::_SetMenusEnabled
*****************************************************************************/
void
InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles)
{
if (!hasFile)
{
hasChapters = false;
hasTitles = false;
}
if (Lock())
{
if (fNextChapterMI->IsEnabled() != hasChapters)
fNextChapterMI->SetEnabled(hasChapters);
if (fPrevChapterMI->IsEnabled() != hasChapters)
fPrevChapterMI->SetEnabled(hasChapters);
if (fNextTitleMI->IsEnabled() != hasTitles)
fNextTitleMI->SetEnabled(hasTitles);
if (fPrevTitleMI->IsEnabled() != hasTitles)
fPrevTitleMI->SetEnabled(hasTitles);
if (fAudioMenu->IsEnabled() != hasFile)
fAudioMenu->SetEnabled(hasFile);
if (fNavigationMenu->IsEnabled() != hasFile)
fNavigationMenu->SetEnabled(hasFile);
if (fLanguageMenu->IsEnabled() != hasFile)
fLanguageMenu->SetEnabled(hasFile);
if (fSubtitlesMenu->IsEnabled() != hasFile)
fSubtitlesMenu->SetEnabled(hasFile);
if (fSpeedMenu->IsEnabled() != hasFile)
fSpeedMenu->SetEnabled(hasFile);
Unlock();
}
} }
/***************************************************************************** /*****************************************************************************
...@@ -460,7 +598,9 @@ CDMenu::~CDMenu() ...@@ -460,7 +598,9 @@ CDMenu::~CDMenu()
*****************************************************************************/ *****************************************************************************/
void CDMenu::AttachedToWindow(void) void CDMenu::AttachedToWindow(void)
{ {
while (RemoveItem((long int)0) != NULL); // remove all items // remove all items
while (BMenuItem* item = RemoveItem(0L))
delete item;
GetCD("/dev/disk"); GetCD("/dev/disk");
BMenu::AttachedToWindow(); BMenu::AttachedToWindow();
} }
...@@ -542,10 +682,9 @@ LanguageMenu::~LanguageMenu() ...@@ -542,10 +682,9 @@ LanguageMenu::~LanguageMenu()
*****************************************************************************/ *****************************************************************************/
void LanguageMenu::AttachedToWindow(void) void LanguageMenu::AttachedToWindow(void)
{ {
while( RemoveItem((long int)0) != NULL ) // remove all items
{ while (BMenuItem* item = RemoveItem(0L))
; // remove all items delete item;
}
SetRadioMode(true); SetRadioMode(true);
GetChannels(); GetChannels();
...@@ -560,30 +699,26 @@ int LanguageMenu::GetChannels() ...@@ -560,30 +699,26 @@ int LanguageMenu::GetChannels()
char *psz_name; char *psz_name;
bool b_active; bool b_active;
BMessage *msg; BMessage *msg;
BMenuItem *menu_item;
int i; int i;
es_descriptor_t *p_es = NULL; es_descriptor_t *p_es = NULL;
/* Insert the null */ /* Insert the null */
if( kind == AUDIO_ES ) //audio if( kind != AUDIO_ES ) //subtitle
{
msg = new BMessage(SELECT_CHANNEL);
msg->AddInt32("channel", -1);
}
else
{ {
msg = new BMessage(SELECT_SUBTITLE); msg = new BMessage(SELECT_SUBTITLE);
msg->AddInt32("subtitle", -1); msg->AddInt32("subtitle", -1);
menu_item = new BMenuItem("None", msg);
AddItem(menu_item);
menu_item->SetMarked(true);
} }
BMenuItem *menu_item;
menu_item = new BMenuItem("None", msg);
AddItem(menu_item);
menu_item->SetMarked(TRUE);
if( p_input_bank->pp_input[0] == NULL ) if( p_input_bank->pp_input[0] == NULL )
{ {
return 1; return 1;
} }
int32 addedItems = 0;
vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock ); vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
for( i = 0; i < p_input_bank->pp_input[0]->stream.i_selected_es_number; i++ ) for( i = 0; i < p_input_bank->pp_input[0]->stream.i_selected_es_number; i++ )
...@@ -598,6 +733,7 @@ int LanguageMenu::GetChannels() ...@@ -598,6 +733,7 @@ int LanguageMenu::GetChannels()
{ {
if( kind == p_input_bank->pp_input[0]->stream.pp_es[i]->i_cat ) if( kind == p_input_bank->pp_input[0]->stream.pp_es[i]->i_cat )
{ {
addedItems++;
psz_name = p_input_bank->pp_input[0]->stream.pp_es[i]->psz_desc; psz_name = p_input_bank->pp_input[0]->stream.pp_es[i]->psz_desc;
if( kind == AUDIO_ES ) //audio if( kind == AUDIO_ES ) //audio
{ {
...@@ -610,6 +746,9 @@ int LanguageMenu::GetChannels() ...@@ -610,6 +746,9 @@ int LanguageMenu::GetChannels()
msg->AddInt32("subtitle", i); msg->AddInt32("subtitle", i);
} }
BMenuItem *menu_item; BMenuItem *menu_item;
// workarround for irritating empty strings
if (strcmp(psz_name, "") == 0)
psz_name = "Default";
menu_item = new BMenuItem(psz_name, msg); menu_item = new BMenuItem(psz_name, msg);
AddItem(menu_item); AddItem(menu_item);
b_active = (p_es == p_input_bank->pp_input[0]->stream.pp_es[i]); b_active = (p_es == p_input_bank->pp_input[0]->stream.pp_es[i]);
...@@ -618,6 +757,9 @@ int LanguageMenu::GetChannels() ...@@ -618,6 +757,9 @@ int LanguageMenu::GetChannels()
} }
vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock ); vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
// enhance readability and separate first item from rest
if (addedItems > 1)
AddItem(new BSeparatorItem(), 1);
} }
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
* InterfaceWindow.h: BeOS interface window class prototype * InterfaceWindow.h: BeOS interface window class prototype
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: InterfaceWindow.h,v 1.12.2.2 2002/07/13 11:33:11 tcastley Exp $ * $Id: InterfaceWindow.h,v 1.12.2.3 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au> * Tony Castley <tcastley@mail.powerup.com.au>
* Richard Shepherd <richard@rshepherd.demon.co.uk> * Richard Shepherd <richard@rshepherd.demon.co.uk>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -22,55 +23,88 @@ ...@@ -22,55 +23,88 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef BEOS_INTERFACE_WINDOW_H
#define BEOS_INTERFACE_WINDOW_H
#include <Menu.h>
#include <Window.h>
class BMenuBar;
class MediaControlView; class MediaControlView;
class PlayListWindow; class PlayListWindow;
class BFilePanel;
class CDMenu : public BMenu class CDMenu : public BMenu
{ {
public: public:
CDMenu(const char *name); CDMenu(const char* name);
~CDMenu(); virtual ~CDMenu();
void AttachedToWindow(void);
private: virtual void AttachedToWindow(void);
int GetCD(const char *directory);
private:
int GetCD(const char* directory);
}; };
class LanguageMenu : public BMenu class LanguageMenu : public BMenu
{ {
public: public:
LanguageMenu(const char *name, int menu_kind, LanguageMenu(const char* name,
intf_thread_t *p_interface); int menu_kind,
~LanguageMenu(); intf_thread_t* p_interface);
void AttachedToWindow(void); virtual ~LanguageMenu();
private:
intf_thread_t *p_intf; virtual void AttachedToWindow(void);
int kind;
int GetChannels(); private:
intf_thread_t* p_intf;
int kind;
int GetChannels();
}; };
class InterfaceWindow : public BWindow class InterfaceWindow : public BWindow
{ {
public: public:
InterfaceWindow( BRect frame, const char *name, InterfaceWindow(BRect frame,
intf_thread_t *p_interface ); const char* name,
~InterfaceWindow(); intf_thread_t* p_interface);
virtual ~InterfaceWindow();
// standard window member
virtual void FrameResized(float width, float height);
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
// standard window member // InterfaceWindow
virtual bool QuitRequested(); void updateInterface();
virtual void MessageReceived(BMessage *message); bool IsStopped() const;
void updateInterface();
MediaControlView *p_mediaControl; MediaControlView* p_mediaControl;
private: private:
intf_thread_t *p_intf; void _SetMenusEnabled(bool hasFile,
bool b_empty_playlist; bool hasChapters = false,
BFilePanel *file_panel; bool hasTitles = false);
PlayListWindow* playlist_window;
BMenuItem *miOnTop;
es_descriptor_t * p_audio_es;
es_descriptor_t * p_spu_es;
intf_thread_t* p_intf;
bool b_empty_playlist;
BFilePanel* file_panel;
PlayListWindow* playlist_window;
BMenuItem* miOnTop;
es_descriptor_t* p_audio_es;
es_descriptor_t* p_spu_es;
BMenuBar* fMenuBar;
BMenuItem* fNextTitleMI;
BMenuItem* fPrevTitleMI;
BMenuItem* fNextChapterMI;
BMenuItem* fPrevChapterMI;
BMenu* fAudioMenu;
BMenu* fNavigationMenu;
BMenu* fLanguageMenu;
BMenu* fSubtitlesMenu;
BMenu* fSpeedMenu;
bigtime_t fLastUpdateTime;
}; };
#endif // BEOS_INTERFACE_WINDOW_H
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* MediaControlView.cpp: beos interface * MediaControlView.cpp: beos interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: MediaControlView.cpp,v 1.7.2.1 2002/07/13 11:33:11 tcastley Exp $ * $Id: MediaControlView.cpp,v 1.7.2.2 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Tony Castley <tony@castley.net> * Authors: Tony Castley <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -39,258 +40,1063 @@ extern "C" ...@@ -39,258 +40,1063 @@ extern "C"
} }
/* BeOS interface headers */ /* BeOS interface headers */
#include "MsgVals.h"
#include "Bitmaps.h" #include "Bitmaps.h"
#include "DrawingTidbits.h"
#include "InterfaceWindow.h"
#include "MsgVals.h"
#include "TransportButton.h" #include "TransportButton.h"
#include "MediaControlView.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
MediaControlView::MediaControlView( BRect frame ) // slider colors are hardcoded here, because that's just
: BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER ) // 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 };
const char* kDisabledSeekMessage = "Drop files to play";
enum
{ {
float xStart = HORZ_SPACE; MSG_REWIND = 'rwnd',
float yStart = VERT_SPACE; MSG_FORWARD = 'frwd',
fScrubSem = B_ERROR; MSG_SKIP_BACKWARDS = 'skpb',
MSG_SKIP_FORWARD = 'skpf',
BRect controlRect = BRect(xStart,yStart, };
frame.Width() - (HORZ_SPACE * 2), 15);
// 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 */ // Seek Slider
rgb_color fill_color = {0,255,0}; fSeekSlider = new SeekSlider(frame, "seek slider", this, 0, 2047);
p_seek = new SeekSlider(controlRect, this, 0, 100, B_TRIANGLE_THUMB); fSeekSlider->SetValue(0);
p_seek->SetValue(0); fSeekSlider->ResizeToPreferred();
p_seek->UseFillColor(true, &fill_color); AddChild( fSeekSlider );
AddChild( p_seek );
yStart += 15 + VERT_SPACE; // Buttons
// Skip Back
frame.SetRightBottom(kSkipButtonSize);
/* Buttons */ fBottomControlHeight = kRewindBitmapHeight - 1.0;
/* Slow play */ fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
controlRect.SetLeftTop(BPoint(xStart, yStart)); kSkipBackBitmapBits,
controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize); kPressedSkipBackBitmapBits,
xStart += kRewindBitmapWidth; kDisabledSkipBackBitmapBits,
p_slow = new TransportButton(controlRect, B_EMPTY_STRING, new BMessage(MSG_SKIP_BACKWARDS));
kSkipBackBitmapBits, AddChild( fSkipBack );
kPressedSkipBackBitmapBits,
kDisabledSkipBackBitmapBits, // Play Pause
new BMessage(SLOWER_PLAY)); frame.SetRightBottom(kPlayButtonSize);
AddChild( p_slow ); if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
/* Play Pause */ fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
controlRect.SetLeftTop(BPoint(xStart, yStart)); kPlayButtonBitmapBits,
controlRect.SetRightBottom(controlRect.LeftTop() + kPlayButtonSize); kPressedPlayButtonBitmapBits,
xStart += kPlayPauseBitmapWidth + 1.0; kDisabledPlayButtonBitmapBits,
p_play = new PlayPauseButton(controlRect, B_EMPTY_STRING, kPlayingPlayButtonBitmapBits,
kPlayButtonBitmapBits, kPressedPlayingPlayButtonBitmapBits,
kPressedPlayButtonBitmapBits, kPausedPlayButtonBitmapBits,
kDisabledPlayButtonBitmapBits, kPressedPausedPlayButtonBitmapBits,
kPlayingPlayButtonBitmapBits, new BMessage(START_PLAYBACK));
kPressedPlayingPlayButtonBitmapBits,
kPausedPlayButtonBitmapBits, AddChild( fPlayPause );
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),
0, VOLUME_MAX);
p_vol->SetValue(VOLUME_DEFAULT);
p_vol->UseFillColor(true, &fill_color);
AddChild( p_vol );
// 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", 0, VOLUME_MAX,
new BMessage(VOLUME_CHG));
fVolumeSlider->SetValue(VOLUME_DEFAULT);
AddChild( fVolumeSlider );
} }
// destructor
MediaControlView::~MediaControlView() MediaControlView::~MediaControlView()
{ {
} }
void MediaControlView::MessageReceived(BMessage *message) // AttachedToWindow
void
MediaControlView::AttachedToWindow()
{ {
BView::MessageReceived(message); // 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);
} }
void MediaControlView::SetProgress(uint64 seek, uint64 size) // FrameResized
void
MediaControlView::FrameResized(float width, float height)
{ {
p_seek->SetPosition((float)seek/size); 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::SetStatus(int status, int rate) // GetPreferredSize
void
MediaControlView::GetPreferredSize(float* width, float* height)
{ {
if (width && height)
{
BRect r(_MinFrame());
*width = r.Width();
*height = r.Height();
}
}
// MessageReceived
void
MediaControlView::MessageReceived(BMessage* message)
{
switch (message->what)
{
case MSG_REWIND:
break;
case MSG_FORWARD:
break;
case MSG_SKIP_BACKWARDS:
Window()->PostMessage(PREV_CHAPTER);
break;
case MSG_SKIP_FORWARD:
Window()->PostMessage(NEXT_CHAPTER);
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 ) switch( status )
{ {
case PLAYING_S: case PLAYING_S:
case FORWARD_S: case FORWARD_S:
case BACKWARD_S: case BACKWARD_S:
case START_S: case START_S:
p_play->SetPlaying(); fPlayPause->SetPlaying();
break; break;
case PAUSE_S: case PAUSE_S:
p_play->SetPaused(); fPlayPause->SetPaused();
break; break;
case UNDEF_S: case UNDEF_S:
case NOT_STARTED_S: case NOT_STARTED_S:
default: default:
p_play->SetStopped(); fPlayPause->SetStopped();
break; 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);
}
// GetSeekTo
uint32
MediaControlView::GetSeekTo() const
{
return fSeekSlider->Value();
} }
void MediaControlView::SetEnabled(bool enabled) // GetVolume
uint32
MediaControlView::GetVolume() const
{ {
p_slow->SetEnabled(enabled); return fVolumeSlider->Value();
p_play->SetEnabled(enabled);
p_fast->SetEnabled(enabled);
p_stop->SetEnabled(enabled);
p_mute->SetEnabled(enabled);
p_vol->SetEnabled(enabled);
p_seek->SetEnabled(enabled);
} }
uint32 MediaControlView::GetSeekTo() // SetSkippable
void
MediaControlView::SetSkippable(bool backward, bool forward)
{ {
return p_seek->seekTo; fSkipBack->SetEnabled(backward);
fSkipForward->SetEnabled(forward);
} }
uint32 MediaControlView::GetVolume() // SetMuted
void
MediaControlView::SetMuted(bool mute)
{ {
return p_vol->Value(); fVolumeSlider->SetMuted(mute);
} }
// _LayoutControls
void
MediaControlView::_LayoutControls(BRect frame) const
{
// seek slider
BRect r(frame);
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, SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
int32 i_min, int32 i_max ) int32 minValue, int32 maxValue)
:BSlider(frame, NULL, NULL, p_message, i_min, i_max ) : 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; if (IsEnabled() && Bounds().Contains(where))
BView *v; {
SetValue(_ValueFor(where.x));
fTracking = true;
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
_BeginSeek();
}
}
rgb_color black = {0,0,0}; /*****************************************************************************
r = ThumbFrame(); * SeekSlider::MouseMoved
v = OffscreenView(); *****************************************************************************/
void
SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
{
if (fTracking)
{
SetValue(_ValueFor(where.x));
_Seek();
}
}
if(IsEnabled()) /*****************************************************************************
{ * SeekSlider::MouseUp
v->SetHighColor(black); *****************************************************************************/
} void
else SeekSlider::MouseUp(BPoint where)
{ {
v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT)); 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()) /*****************************************************************************
{ * SeekSlider::SetPosition
v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); *****************************************************************************/
} void
else SeekSlider::SetPosition(float position)
{ {
v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT)); 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, void
int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB ) SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
:MediaSlider( frame, NULL, i_min, i_max ) rgb_color right, rgb_color bottom)
{ {
fOwner = p_owner; BeginLineArray(4);
fMouseDown = false; 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); if (fOwner->fScrubSem >= B_OK)
seekTo = ValueForPoint(where); delete_sem(fOwner->fScrubSem);
fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem"); fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
release_sem(fOwner->fScrubSem); if (fOwner->fScrubSem >= B_OK)
fMouseDown = true; 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 (fOwner->fScrubSem >= B_OK)
if (!fMouseDown) delete_sem(fOwner->fScrubSem);
return; fOwner->fScrubSem = B_ERROR;
seekTo = ValueForPoint(where);
release_sem(fOwner->fScrubSem);
} }
/***************************************************************************** /*****************************************************************************
* 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 SeekSlider::MouseUp(BPoint where) void
VolumeSlider::Draw(BRect updateRect)
{ {
BSlider::MouseUp(where); if (IsValid())
seekTo = ValueForPoint(where); {
delete_sem(fOwner->fScrubSem); BRect r(Bounds());
fOwner->fScrubSem = B_ERROR; float sliderSideWidth = kVolumeSliderBitmapWidth;
fMouseDown = false; 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
*****************************************************************************/
bool
VolumeSlider::IsValid() const
{
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;
}
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* MediaControlView.h: beos interface * MediaControlView.h: beos interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: MediaControlView.h,v 1.2 2001/09/12 01:31:37 tcastley Exp $ * $Id: MediaControlView.h,v 1.2.4.1 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Tony Castley <tony@castley.net> * Authors: Tony Castley <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -20,73 +21,147 @@ ...@@ -20,73 +21,147 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#define HORZ_SPACE 5.0
#define VERT_SPACE 5.0
#ifndef BEOS_MEDIA_CONTROL_VIEW_H
#define BEOS_MEDIA_CONTROL_VIEW_H
class TransportButton; #include <Box.h>
#include <Control.h>
class BBitmap;
class PlayPauseButton; class PlayPauseButton;
class MediaSlider;
class SeekSlider; class SeekSlider;
class TransportButton;
class VolumeSlider;
class MediaControlView : public BBox class MediaControlView : public BBox
{ {
public: public:
MediaControlView( BRect frame ); MediaControlView( BRect frame );
~MediaControlView(); virtual ~MediaControlView();
virtual void MessageReceived(BMessage *message); // BBox
void SetProgress(uint64 seek, uint64 size); virtual void AttachedToWindow();
virtual void FrameResized(float width, float height);
void SetStatus(int status, int rate); virtual void GetPreferredSize(float* width, float* height);
void SetEnabled(bool); virtual void MessageReceived(BMessage* message);
uint32 GetSeekTo(); virtual void Pulse(); // detect stopped stream
uint32 GetVolume();
sem_id fScrubSem; // MediaControlView
bool fSeeking; void SetProgress(uint64 seek, uint64 size);
void SetStatus(int status, int rate);
void SetEnabled(bool enable);
uint32 GetSeekTo() const;
uint32 GetVolume() const;
void SetSkippable(bool backward,
bool forward);
void SetMuted(bool mute);
sem_id fScrubSem;
private: private:
MediaSlider * p_vol; void _LayoutControls(BRect frame) const;
SeekSlider * p_seek; BRect _MinFrame() const;
TransportButton* p_slow; void _LayoutControl(BView* view,
PlayPauseButton* p_play; BRect frame,
TransportButton* p_fast; bool resize = false) const;
TransportButton* p_stop;
TransportButton* p_mute;
int current_rate;
int current_status;
};
class MediaSlider : public BSlider
{ VolumeSlider* fVolumeSlider;
public: SeekSlider* fSeekSlider;
MediaSlider(BRect frame, TransportButton* fSkipBack;
BMessage *message, TransportButton* fSkipForward;
int32 minValue, TransportButton* fRewind;
int32 maxValue); TransportButton* fForward;
~MediaSlider(); PlayPauseButton* fPlayPause;
virtual void DrawThumb(void); TransportButton* fStop;
TransportButton* fMute;
int fCurrentRate;
int fCurrentStatus;
float fBottomControlHeight;
BRect fOldBounds;
}; };
class SeekSlider : public MediaSlider class SeekSlider : public BControl
{ {
public: public:
SeekSlider(BRect frame, SeekSlider(BRect frame,
MediaControlView *owner, const char* name,
int32 minValue, MediaControlView* owner,
int32 maxValue, int32 minValue,
thumb_style thumbType = B_TRIANGLE_THUMB); int32 maxValue);
~SeekSlider(); virtual ~SeekSlider();
uint32 seekTo;
virtual void MouseDown(BPoint); // BControl
virtual void MouseUp(BPoint pt); virtual void AttachedToWindow();
virtual void MouseMoved(BPoint pt, uint32 c, const BMessage *m); virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MouseUp(BPoint where);
virtual void ResizeToPreferred();
// SeekSlider
void SetPosition(float position);
private: private:
MediaControlView* fOwner; int32 _ValueFor(float x) const;
bool fMouseDown; void _StrokeFrame(BRect frame,
rgb_color left,
rgb_color top,
rgb_color right,
rgb_color bottom);
void _BeginSeek();
void _Seek();
void _EndSeek();
MediaControlView* fOwner;
bool fTracking;
int32 fMinValue;
int32 fMaxValue;
}; };
class VolumeSlider : public BControl
{
public:
VolumeSlider(BRect frame,
const char* name,
int32 minValue,
int32 maxValue,
BMessage* message = NULL,
BHandler* target = NULL);
virtual ~VolumeSlider();
// BControl
virtual void AttachedToWindow();
virtual void SetValue(int32 value);
virtual void SetEnabled(bool enable);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void MouseUp(BPoint where);
// VolumeSlider
bool IsValid() const;
void SetMuted(bool mute);
private:
void _MakeBitmaps();
void _DimBitmap(BBitmap* bitmap);
int32 _ValueFor(float xPos) const;
BBitmap* fLeftSideBits;
BBitmap* fRightSideBits;
BBitmap* fKnobBits;
bool fTracking;
bool fMuted;
int32 fMinValue;
int32 fMaxValue;
};
#endif // BEOS_MEDIA_CONTROL_VIEW_H
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* MsgVals.h * MsgVals.h
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: MsgVals.h,v 1.9.2.2 2002/07/13 11:33:11 tcastley Exp $ * $Id: MsgVals.h,v 1.9.2.3 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Tony Castley <tcastley@mail.powerup.com.au> * Authors: Tony Castley <tcastley@mail.powerup.com.au>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -21,32 +22,39 @@ ...@@ -21,32 +22,39 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
/* MsgVals.h */ #ifndef BEOS_MESSAGE_VALUES_H
#define BEOS_MESSAGE_VALUES_H
#define PLAYING 0 #define PLAYING 0
#define PAUSED 1 #define PAUSED 1
const uint32 OPEN_FILE = 'OPFL'; const uint32 OPEN_FILE = 'opfl';
const uint32 OPEN_DVD = 'OPDV'; const uint32 OPEN_DVD = 'opdv';
const uint32 OPEN_PLAYLIST = 'OPPL'; const uint32 OPEN_PLAYLIST = 'oppl';
const uint32 STOP_PLAYBACK = 'STPL'; const uint32 STOP_PLAYBACK = 'stpl';
const uint32 START_PLAYBACK = 'PLAY'; const uint32 START_PLAYBACK = 'play';
const uint32 PAUSE_PLAYBACK = 'PAPL'; const uint32 PAUSE_PLAYBACK = 'papl';
const uint32 FASTER_PLAY = 'FAPL'; const uint32 FASTER_PLAY = 'fapl';
const uint32 SLOWER_PLAY = 'SLPL'; const uint32 SLOWER_PLAY = 'slpl';
const uint32 SEEK_PLAYBACK = 'SEEK'; const uint32 NORMAL_PLAY = 'nrpl';
const uint32 VOLUME_CHG = 'VOCH'; const uint32 SEEK_PLAYBACK = 'seek';
const uint32 VOLUME_MUTE = 'MUTE'; const uint32 VOLUME_CHG = 'voch';
const uint32 SELECT_CHANNEL = 'CHAN'; const uint32 VOLUME_MUTE = 'mute';
const uint32 SELECT_SUBTITLE = 'SUBT'; const uint32 SELECT_CHANNEL = 'chan';
const uint32 PREV_TITLE = 'PRTI'; const uint32 SELECT_SUBTITLE = 'subt';
const uint32 NEXT_TITLE = 'NXTI'; const uint32 PREV_TITLE = 'prti';
const uint32 PREV_CHAPTER = 'PRCH'; const uint32 NEXT_TITLE = 'nxti';
const uint32 NEXT_CHAPTER = 'NXCH'; const uint32 PREV_CHAPTER = 'prch';
const uint32 TOGGLE_ON_TOP = 'ONTP'; const uint32 NEXT_CHAPTER = 'nxch';
const uint32 TOGGLE_FULL_SCREEN = 'TGFS'; const uint32 TOGGLE_ON_TOP = 'ontp';
const uint32 RESIZE_100 = 'RSOR'; const uint32 TOGGLE_FULL_SCREEN = 'tgfs';
const uint32 RESIZE_200 = 'RSDB'; const uint32 RESIZE_100 = 'rsor';
const uint32 ASPECT_CORRECT = 'ASCO'; const uint32 RESIZE_200 = 'rsdb';
const uint32 VERT_SYNC = 'VSYN'; const uint32 RESIZE_TRUE = 'rstr';
const uint32 WINDOW_FEEL = 'WFEL'; const uint32 ASPECT_CORRECT = 'asco';
const uint32 VERT_SYNC = 'vsyn';
const uint32 WINDOW_FEEL = 'wfel';
const uint32 INTERFACE_CREATED = 'ifcr'; /* see VlcApplication::MessageReceived()
* in src/misc/beos_specific.cpp */
#endif // BEOS_MESSAGE_VALUES_H
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* PlayListWindow.h: BeOS interface window class prototype * PlayListWindow.h: BeOS interface window class prototype
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: PlayListWindow.h,v 1.1.4.1 2002/06/01 10:12:10 tcastley Exp $ * $Id: PlayListWindow.h,v 1.1.4.2 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au> * Tony Castley <tcastley@mail.powerup.com.au>
...@@ -22,7 +22,16 @@ ...@@ -22,7 +22,16 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef BEOS_PLAY_LIST_WINDOW_H
#define BEOS_PLAY_LIST_WINDOW_H
#include <Window.h>
class BFilePanel;
class BListView;
class CDMenu; class CDMenu;
class PlayListWindow : public BWindow class PlayListWindow : public BWindow
{ {
public: public:
...@@ -42,4 +51,5 @@ private: ...@@ -42,4 +51,5 @@ private:
BFilePanel *file_panel; BFilePanel *file_panel;
}; };
#endif // BEOS_PLAY_LIST_WINDOW_H
...@@ -2,9 +2,10 @@ ...@@ -2,9 +2,10 @@
* TransportButton.cpp * TransportButton.cpp
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: TransportButton.cpp,v 1.3 2001/03/21 13:42:33 sam Exp $ * $Id: TransportButton.cpp,v 1.3.4.1 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Tony Castley <tcastley@mail.powerup.com.au> * Authors: Tony Castley <tcastley@mail.powerup.com.au>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -246,10 +247,8 @@ TransportButton::AttachedToWindow() ...@@ -246,10 +247,8 @@ TransportButton::AttachedToWindow()
void void
TransportButton::DetachedFromWindow() TransportButton::DetachedFromWindow()
{ {
if (keyPressFilter) { if (keyPressFilter)
Window()->RemoveCommonFilter(keyPressFilter); Window()->RemoveCommonFilter(keyPressFilter);
delete keyPressFilter;
}
_inherited::DetachedFromWindow(); _inherited::DetachedFromWindow();
} }
...@@ -260,6 +259,7 @@ TransportButton::~TransportButton() ...@@ -260,6 +259,7 @@ TransportButton::~TransportButton()
delete pressingMessage; delete pressingMessage;
delete donePressingMessage; delete donePressingMessage;
delete bitmaps; delete bitmaps;
delete keyPressFilter;
} }
void void
...@@ -274,9 +274,11 @@ TransportButton::WindowActivated(bool state) ...@@ -274,9 +274,11 @@ TransportButton::WindowActivated(bool state)
void void
TransportButton::SetEnabled(bool on) TransportButton::SetEnabled(bool on)
{ {
_inherited::SetEnabled(on); if (on != IsEnabled()) {
if (!on) _inherited::SetEnabled(on);
ShortcutKeyUp(); if (!on)
ShortcutKeyUp();
}
} }
const unsigned char * const unsigned char *
...@@ -300,11 +302,31 @@ TransportButton::BitsForMask(uint32 mask) const ...@@ -300,11 +302,31 @@ TransportButton::BitsForMask(uint32 mask) const
BBitmap * BBitmap *
TransportButton::MakeBitmap(uint32 mask) TransportButton::MakeBitmap(uint32 mask)
{ {
BBitmap *result = new BBitmap(Bounds(), B_COLOR_8_BIT); BRect r(Bounds());
result->SetBits(BitsForMask(mask), (Bounds().Width() + 1) * (Bounds().Height() + 1), BBitmap *result = new BBitmap(r, B_CMAP8);
0, B_COLOR_8_BIT);
uint8* src = (uint8*)BitsForMask(mask);
ReplaceTransparentColor(result, Parent()->ViewColor());
if (src && result && result->IsValid()) {
int32 width = r.IntegerWidth() + 1;
int32 height = r.IntegerHeight() + 1;
int32 bpr = result->BytesPerRow();
uint8* dst = (uint8*)result->Bits();
// copy source bits into bitmap line by line,
// taking possible alignment into account
// since the source data has been generated
// by QuickRes, it still contains aligment too
// (hence skipping bpr and not width bytes)
for (int32 y = 0; y < height; y++) {
memcpy(dst, src, bpr);
src += bpr;
dst += bpr;
}
ReplaceTransparentColor(result, Parent()->ViewColor());
} else {
delete result;
result = NULL;
}
return result; return result;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* TransportButton.h * TransportButton.h
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: TransportButton.h,v 1.3 2001/03/21 13:42:33 sam Exp $ * $Id: TransportButton.h,v 1.3.4.1 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Tony Castley <tcastley@mail.powerup.com.au> * Authors: Tony Castley <tcastley@mail.powerup.com.au>
* *
...@@ -180,4 +180,4 @@ private: ...@@ -180,4 +180,4 @@ private:
typedef TransportButton _inherited; typedef TransportButton _inherited;
}; };
#endif #endif // __MEDIA_BUTTON__
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
* VideoWindow.h: BeOS video window class prototype * VideoWindow.h: BeOS video window class prototype
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: VideoWindow.h,v 1.19.2.4 2002/07/11 12:24:45 tcastley Exp $ * $Id: VideoWindow.h,v 1.19.2.5 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au> * Tony Castley <tcastley@mail.powerup.com.au>
* Richard Shepherd <richard@rshepherd.demon.co.uk> * Richard Shepherd <richard@rshepherd.demon.co.uk>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -22,6 +23,13 @@ ...@@ -22,6 +23,13 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ *****************************************************************************/
#ifndef BEOS_VIDEO_WINDOW_H
#define BEOS_VIDEO_WINDOW_H
#include <View.h>
#include <Window.h>
#define BITMAP 0 #define BITMAP 0
#define OVERLAY 1 #define OVERLAY 1
#define OPENGL 2 #define OPENGL 2
...@@ -50,35 +58,58 @@ colorcombo colspace[]= ...@@ -50,35 +58,58 @@ colorcombo colspace[]=
class VLCView : public BView class VLCView : public BView
{ {
public: public:
VLCView( BRect bounds); VLCView( BRect bounds);
~VLCView(); virtual ~VLCView();
void MouseDown(BPoint point); virtual void AttachedToWindow();
void Draw(BRect updateRect); virtual void MouseDown(BPoint where);
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage);
virtual void Pulse();
virtual void Draw(BRect updateRect);
virtual void KeyDown(const char* bytes, int32 numBytes);
private:
bigtime_t fLastMouseMovedTime;
bool fCursorHidden;
bool fCursorInside;
}; };
class VideoWindow : public BWindow class VideoWindow : public BWindow
{ {
public: public:
// standard constructor and destructor VideoWindow(int v_width,
VideoWindow( int v_width, int v_height, int v_height,
BRect frame); BRect frame);
~VideoWindow(); virtual ~VideoWindow();
void Zoom(BPoint origin, float width, float height); // BWindow
void FrameResized(float width, float height); virtual void MessageReceived(BMessage* message);
void FrameMoved(BPoint origin); virtual void Zoom(BPoint origin,
void ScreenChanged(BRect frame, color_space mode); float width, float height);
void drawBuffer(int bufferIndex); virtual void FrameResized(float width, float height);
void WindowActivated(bool active); virtual void FrameMoved(BPoint origin);
int SelectDrawingMode(int width, int height); virtual void ScreenChanged(BRect frame,
virtual void MessageReceived(BMessage *message); color_space mode);
virtual void WindowActivated(bool active);
// VideoWindow
void drawBuffer(int bufferIndex);
void ToggleInterfaceShowing();
void SetInterfaceShowing(bool showIt);
void SetCorrectAspectRatio(bool doIt);
inline bool CorrectAspectRatio() const
{ return fCorrectAspect; }
inline status_t InitCheck() const
{ return fInitStatus; }
// this is the hook controling direct screen connection // this is the hook controling direct screen connection
int32 i_width; // incomming bitmap size int32 i_width; // aspect corrected bitmap size
int32 i_height; int32 i_height;
BRect winSize; // current window size BRect winSize; // current window size
bool is_zoomed, vsync; bool is_zoomed, vsync;
...@@ -86,14 +117,28 @@ public: ...@@ -86,14 +117,28 @@ public:
BBitmap *overlaybitmap; BBitmap *overlaybitmap;
VLCView *view; VLCView *view;
int i_buffer; int i_buffer;
bool teardownwindow; volatile bool teardownwindow;
thread_id fDrawThreadID; thread_id fDrawThreadID;
int mode; int mode;
int colspace_index; int colspace_index;
private: private:
status_t _AllocateBuffers(int width,
int height,
int* mode);
void _FreeBuffers();
void _BlankBitmap(BBitmap* bitmap) const;
void _SetVideoSize(uint32 mode);
struct vout_thread_s *p_vout; struct vout_thread_s *p_vout;
int32 fTrueWidth; // incomming bitmap size
int32 fTrueHeight;
bool fCorrectAspect;
window_feel fCachedFeel;
bool fInterfaceShowing;
status_t fInitStatus;
}; };
#endif // BEOS_VIDEO_WINDOW_H
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
* intf_beos.cpp: beos interface * intf_beos.cpp: beos interface
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: intf_beos.cpp,v 1.38.2.1 2002/07/13 11:33:11 tcastley Exp $ * $Id: intf_beos.cpp,v 1.38.2.2 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
* Tony Castley <tony@castley.net> * Tony Castley <tony@castley.net>
* Richard Shepherd <richard@rshepherd.demon.co.uk> * Richard Shepherd <richard@rshepherd.demon.co.uk>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -30,6 +31,8 @@ ...@@ -30,6 +31,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> /* malloc(), free() */ #include <stdlib.h> /* malloc(), free() */
#include <InterfaceKit.h> #include <InterfaceKit.h>
#include <Application.h>
#include <Message.h>
#include <string.h> #include <string.h>
extern "C" extern "C"
...@@ -44,6 +47,7 @@ extern "C" ...@@ -44,6 +47,7 @@ extern "C"
#include "InterfaceWindow.h" #include "InterfaceWindow.h"
#include "intf_vlc_wrapper.h" #include "intf_vlc_wrapper.h"
#include "MsgVals.h"
extern "C" extern "C"
{ {
...@@ -98,6 +102,10 @@ static int intf_Open( intf_thread_t *p_intf ) ...@@ -98,6 +102,10 @@ static int intf_Open( intf_thread_t *p_intf )
free( p_intf->p_sys ); free( p_intf->p_sys );
intf_ErrMsg( "error: cannot allocate memory for InterfaceWindow" ); intf_ErrMsg( "error: cannot allocate memory for InterfaceWindow" );
return( 1 ); return( 1 );
} else {
BMessage message(INTERFACE_CREATED);
message.AddPointer("window", p_intf->p_sys->p_window);
be_app->PostMessage(&message);
} }
p_intf->p_sys->b_disabled_menus = 0; p_intf->p_sys->b_disabled_menus = 0;
p_intf->p_sys->i_saved_volume = VOLUME_DEFAULT; p_intf->p_sys->i_saved_volume = VOLUME_DEFAULT;
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
* intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port ) * intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: intf_vlc_wrapper.cpp,v 1.1.2.1 2002/07/13 11:33:11 tcastley Exp $ * $Id: intf_vlc_wrapper.cpp,v 1.1.2.2 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Florian G. Pflug <fgp@phlo.org> * Authors: Florian G. Pflug <fgp@phlo.org>
* Jon Lech Johansen <jon-vl@nanocrew.net> * Jon Lech Johansen <jon-vl@nanocrew.net>
* Tony Casltey <tony@castley.net> * Tony Casltey <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software{} you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -263,9 +264,38 @@ void Intf_VLCWrapper::volume_restore() ...@@ -263,9 +264,38 @@ void Intf_VLCWrapper::volume_restore()
p_aout_bank->pp_aout[0]->i_volume = p_aout_bank->pp_aout[0]->i_volume =
p_main->p_intf->p_sys->i_saved_volume; p_main->p_intf->p_sys->i_saved_volume;
p_main->p_intf->p_sys->i_saved_volume = 0;
p_main->p_intf->p_sys->b_mute = 0; p_main->p_intf->p_sys->b_mute = 0;
} }
void Intf_VLCWrapper::set_volume(int value)
{
if( p_aout_bank->pp_aout[0] == NULL ) return;
//printf("Intf_VLCWrapper::set_volume(%ld)\n", value);
// make sure value is within bounds
if (value < 0)
value = 0;
if (value > VOLUME_MAX)
value = VOLUME_MAX;
vlc_mutex_lock( &p_aout_bank->lock );
// unmute volume if muted
if (p_main->p_intf->p_sys->b_mute)
{
p_main->p_intf->p_sys->b_mute = 0;
// p_main->p_intf->p_sys->i_saved_volume = 0;
}
// set every stream to the given value
for(int i = 0 ; i < p_aout_bank->i_count ; i++ )
{
if (p_aout_bank->pp_aout[i])
{
// p_aout_bank->pp_aout[i]->i_savedvolume = 0;
p_aout_bank->pp_aout[i]->i_volume = value;
}
}
vlc_mutex_unlock( &p_aout_bank->lock );
}
void Intf_VLCWrapper::toggle_mute() void Intf_VLCWrapper::toggle_mute()
{ {
if( p_aout_bank->pp_aout[0] == NULL ) return; if( p_aout_bank->pp_aout[0] == NULL ) return;
...@@ -277,7 +307,13 @@ void Intf_VLCWrapper::toggle_mute() ...@@ -277,7 +307,13 @@ void Intf_VLCWrapper::toggle_mute()
{ {
Intf_VLCWrapper::volume_mute(); Intf_VLCWrapper::volume_mute();
} }
p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute; // p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
}
bool Intf_VLCWrapper::is_muted()
{
if( p_aout_bank->pp_aout[0] == NULL ) return false;
return p_main->p_intf->p_sys->b_mute;
} }
void Intf_VLCWrapper::maxvolume() void Intf_VLCWrapper::maxvolume()
......
...@@ -2,11 +2,12 @@ ...@@ -2,11 +2,12 @@
* intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port ) * intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: intf_vlc_wrapper.h,v 1.1.2.1 2002/07/13 11:33:11 tcastley Exp $ * $Id: intf_vlc_wrapper.h,v 1.1.2.2 2002/09/03 12:00:25 tcastley Exp $
* *
* Authors: Florian G. Pflug <fgp@phlo.org> * Authors: Florian G. Pflug <fgp@phlo.org>
* Jon Lech Johansen <jon-vl@nanocrew.net> * Jon Lech Johansen <jon-vl@nanocrew.net>
* Tony Casltey <tony@castley.net> * Tony Casltey <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -61,7 +62,9 @@ public: ...@@ -61,7 +62,9 @@ public:
static void playFaster(); static void playFaster();
static void volume_mute(); static void volume_mute();
static void volume_restore(); static void volume_restore();
static void set_volume(int value);
static void toggle_mute(); static void toggle_mute();
static bool is_muted();
static void maxvolume(); static void maxvolume();
// static void fullscreen(); // static void fullscreen();
static void eject(); static void eject();
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
* vout_beos.cpp: beos video output display method * vout_beos.cpp: beos video output display method
***************************************************************************** *****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN * Copyright (C) 2000, 2001 VideoLAN
* $Id: vout_beos.cpp,v 1.58.2.4 2002/07/13 11:33:11 tcastley Exp $ * $Id: vout_beos.cpp,v 1.58.2.5 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
* Tony Castley <tcastley@mail.powerup.com.au> * Tony Castley <tcastley@mail.powerup.com.au>
* Richard Shepherd <richard@rshepherd.demon.co.uk> * Richard Shepherd <richard@rshepherd.demon.co.uk>
* Stephan Aßmus <stippi@yellowbites.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -70,10 +71,14 @@ typedef struct vout_sys_s ...@@ -70,10 +71,14 @@ typedef struct vout_sys_s
} vout_sys_t; } vout_sys_t;
#define MOUSE_IDLE_TIMEOUT 2000000 // two seconds
#define MIN_AUTO_VSYNC_REFRESH 61 // Hz
/***************************************************************************** /*****************************************************************************
* beos_GetAppWindow : retrieve a BWindow pointer from the window name * beos_GetAppWindow : retrieve a BWindow pointer from the window name
*****************************************************************************/ *****************************************************************************/
BWindow *beos_GetAppWindow(char *name) BWindow*
beos_GetAppWindow(char *name)
{ {
int32 index; int32 index;
BWindow *window; BWindow *window;
...@@ -96,57 +101,96 @@ BWindow *beos_GetAppWindow(char *name) ...@@ -96,57 +101,96 @@ BWindow *beos_GetAppWindow(char *name)
return window; return window;
} }
/*****************************************************************************
* get_interface_window
*****************************************************************************/
BWindow*
get_interface_window()
{
return beos_GetAppWindow(VOUT_TITLE);
}
class BackgroundView : public BView
{
public:
BackgroundView(BRect frame, VLCView* view)
: BView(frame, "background",
B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE),
fVideoView(view)
{
SetViewColor(kBlack);
}
virtual ~BackgroundView() {}
virtual void MouseDown(BPoint where)
{
// convert coordinates
where = fVideoView->ConvertFromParent(where);
// let him handle it
fVideoView->MouseDown(where);
}
virtual void MouseMoved(BPoint where, uint32 transit,
const BMessage* dragMessage)
{
// convert coordinates
where = fVideoView->ConvertFromParent(where);
// let him handle it
fVideoView->MouseMoved(where, transit, dragMessage);
// notice: It might look like transit should be
// B_OUTSIDE_VIEW regardless, but leave it like this,
// otherwise, unwanted things will happen!
}
private:
VLCView* fVideoView;
};
/***************************************************************************** /*****************************************************************************
* VideoWindow constructor and destructor * VideoWindow constructor and destructor
*****************************************************************************/ *****************************************************************************/
VideoWindow::VideoWindow( int v_width, int v_height, VideoWindow::VideoWindow(int v_width, int v_height, BRect frame)
BRect frame ) : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
: BWindow( frame, NULL, B_TITLED_WINDOW, i_width(frame.IntegerWidth()),
B_NOT_CLOSABLE | B_NOT_MINIMIZABLE ) i_height(frame.IntegerHeight()),
is_zoomed(false),
vsync(false),
i_buffer(0),
teardownwindow(false),
fTrueWidth(v_width),
fTrueHeight(v_height),
fCorrectAspect(true),
fCachedFeel(B_NORMAL_WINDOW_FEEL),
fInterfaceShowing(false),
fInitStatus(B_ERROR)
{ {
BView *mainView = new BView( Bounds(), "mainView", // create the view to do the display
B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE);
AddChild(mainView);
mainView->SetViewColor(kBlack);
/* create the view to do the display */
view = new VLCView( Bounds() ); view = new VLCView( Bounds() );
mainView->AddChild(view);
/* set the VideoWindow variables */ // create background view
teardownwindow = false; BView *mainView = new BackgroundView( Bounds(), view );
is_zoomed = false; AddChild(mainView);
i_buffer = 0; mainView->AddChild(view);
/* call ScreenChanged to set vsync correctly */ // figure out if we should use vertical sync by default
BScreen *screen; BScreen screen(this);
display_mode disp_mode; if (screen.IsValid())
float refresh; {
display_mode mode;
screen.GetMode(&mode);
float refresh = (mode.timing.pixel_clock * 1000)
/ ((mode.timing.h_total)* (mode.timing.v_total));
vsync = (refresh < MIN_AUTO_VSYNC_REFRESH);
}
screen = new BScreen(this); // allocate bitmap buffers
for (int32 i = 0; i < 3; i++)
screen-> GetMode(&disp_mode); bitmap[i] = NULL;
refresh = fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
(disp_mode.timing.v_total));
if (refresh < 61)
{
vsync = true;
}
else
{
vsync = false;
}
delete screen;
mode = SelectDrawingMode(v_width, v_height);
// remember current settings // make sure we layout the view correctly
i_width = frame.IntegerWidth();
i_height = frame.IntegerHeight();
FrameResized(i_width, i_height); FrameResized(i_width, i_height);
if (mode == OVERLAY) if (fInitStatus >= B_OK && mode == OVERLAY)
{ {
overlay_restrictions r; overlay_restrictions r;
...@@ -154,7 +198,6 @@ VideoWindow::VideoWindow( int v_width, int v_height, ...@@ -154,7 +198,6 @@ VideoWindow::VideoWindow( int v_width, int v_height,
SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale, SetSizeLimits((i_width * r.min_width_scale), i_width * r.max_width_scale,
(i_height * r.min_height_scale), i_height * r.max_height_scale); (i_height * r.min_height_scale), i_height * r.max_height_scale);
} }
Show();
} }
VideoWindow::~VideoWindow() VideoWindow::~VideoWindow()
...@@ -163,63 +206,156 @@ VideoWindow::~VideoWindow() ...@@ -163,63 +206,156 @@ VideoWindow::~VideoWindow()
teardownwindow = true; teardownwindow = true;
wait_for_thread(fDrawThreadID, &result); wait_for_thread(fDrawThreadID, &result);
delete bitmap[0]; _FreeBuffers();
delete bitmap[1];
delete bitmap[2];
} }
void VideoWindow::MessageReceived( BMessage *p_message ) /*****************************************************************************
* VideoWindow::MessageReceived
*****************************************************************************/
void
VideoWindow::MessageReceived( BMessage *p_message )
{
switch( p_message->what )
{
case TOGGLE_FULL_SCREEN:
BWindow::Zoom();
break;
case RESIZE_100:
case RESIZE_200:
if (is_zoomed)
BWindow::Zoom();
_SetVideoSize(p_message->what);
break;
case VERT_SYNC:
vsync = !vsync;
break;
case WINDOW_FEEL:
{
window_feel winFeel;
if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
{
SetFeel(winFeel);
fCachedFeel = winFeel;
}
}
break;
case ASPECT_CORRECT:
SetCorrectAspectRatio(!fCorrectAspect);
break;
default:
BWindow::MessageReceived( p_message );
break;
}
}
/*****************************************************************************
* VideoWindow::Zoom
*****************************************************************************/
void
VideoWindow::Zoom(BPoint origin, float width, float height )
{
if(is_zoomed)
{
MoveTo(winSize.left, winSize.top);
ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
be_app->ShowCursor();
fInterfaceShowing = true;
}
else
{
BScreen screen(this);
BRect rect = screen.Frame();
Activate();
MoveTo(0.0, 0.0);
ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
be_app->ObscureCursor();
fInterfaceShowing = false;
}
is_zoomed = !is_zoomed;
}
/*****************************************************************************
* VideoWindow::FrameMoved
*****************************************************************************/
void
VideoWindow::FrameMoved(BPoint origin)
{
if (is_zoomed) return ;
winSize = Frame();
}
/*****************************************************************************
* VideoWindow::FrameResized
*****************************************************************************/
void
VideoWindow::FrameResized( float width, float height )
{ {
switch( p_message->what ) int32 useWidth = fCorrectAspect ? i_width : fTrueWidth;
int32 useHeight = fCorrectAspect ? i_height : fTrueHeight;
float out_width, out_height;
float out_left, out_top;
float width_scale = width / useWidth;
float height_scale = height / useHeight;
if (width_scale <= height_scale)
{ {
case TOGGLE_FULL_SCREEN: out_width = (useWidth * width_scale);
((BWindow *)this)->Zoom(); out_height = (useHeight * width_scale);
break; out_left = 0;
case RESIZE_100: out_top = (height - out_height) / 2;
if (is_zoomed)
{
((BWindow *)this)->Zoom();
}
ResizeTo(i_width, i_height);
break;
case RESIZE_200:
if (is_zoomed)
{
((BWindow *)this)->Zoom();
}
ResizeTo(i_width * 2, i_height * 2);
break;
case VERT_SYNC:
vsync = !vsync;
break;
case WINDOW_FEEL:
{
int16 winFeel;
if (p_message->FindInt16("WinFeel", &winFeel) == B_OK)
{
SetFeel((window_feel)winFeel);
}
}
break;
default:
BWindow::MessageReceived( p_message );
break;
} }
else /* if the height is proportionally smaller */
{
out_width = (useWidth * height_scale);
out_height = (useHeight * height_scale);
out_top = 0;
out_left = (width - out_width) / 2;
}
view->MoveTo(out_left,out_top);
view->ResizeTo(out_width, out_height);
if (!is_zoomed)
winSize = Frame();
}
/*****************************************************************************
* VideoWindow::ScreenChanged
*****************************************************************************/
void
VideoWindow::ScreenChanged(BRect frame, color_space format)
{
BScreen screen(this);
display_mode mode;
screen.GetMode(&mode);
float refresh = (mode.timing.pixel_clock * 1000)
/ ((mode.timing.h_total) * (mode.timing.v_total));
if (refresh < MIN_AUTO_VSYNC_REFRESH)
vsync = true;
}
/*****************************************************************************
* VideoWindow::Activate
*****************************************************************************/
void
VideoWindow::WindowActivated(bool active)
{
} }
void VideoWindow::drawBuffer(int bufferIndex) /*****************************************************************************
* VideoWindow::drawBuffer
*****************************************************************************/
void
VideoWindow::drawBuffer(int bufferIndex)
{ {
i_buffer = bufferIndex; i_buffer = bufferIndex;
// sync to the screen if required // sync to the screen if required
if (vsync) if (vsync)
{ {
BScreen *screen; BScreen screen(this);
screen = new BScreen(this); screen.WaitForRetrace(22000);
screen-> WaitForRetrace(22000);
delete screen;
} }
if (LockLooper()) if (fInitStatus >= B_OK && LockLooper())
{ {
// switch the overlay bitmap // switch the overlay bitmap
if (mode == OVERLAY) if (mode == OVERLAY)
...@@ -229,107 +365,86 @@ void VideoWindow::drawBuffer(int bufferIndex) ...@@ -229,107 +365,86 @@ void VideoWindow::drawBuffer(int bufferIndex)
bitmap[i_buffer]->Bounds() , bitmap[i_buffer]->Bounds() ,
view->Bounds(), view->Bounds(),
&key, B_FOLLOW_ALL, &key, B_FOLLOW_ALL,
B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL| B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
B_OVERLAY_TRANSFER_CHANNEL); B_OVERLAY_TRANSFER_CHANNEL);
view->SetViewColor(key); view->SetViewColor(key);
} }
else else
{ {
// switch the bitmap // switch the bitmap
view-> DrawBitmap(bitmap[i_buffer], view->Bounds() ); view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
} }
UnlockLooper(); UnlockLooper();
} }
} }
void VideoWindow::Zoom(BPoint origin, float width, float height ) /*****************************************************************************
{ * VideoWindow::SetInterfaceShowing
if(is_zoomed) *****************************************************************************/
{ void
is_zoomed = !is_zoomed; VideoWindow::ToggleInterfaceShowing()
MoveTo(winSize.left, winSize.top);
ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
be_app->ShowCursor();
}
else
{
is_zoomed = !is_zoomed;
BScreen *screen;
screen = new BScreen(this);
BRect rect = screen->Frame();
delete screen;
MoveTo(0,0);
ResizeTo(rect.IntegerWidth(), rect.IntegerHeight());
be_app->ObscureCursor();
}
}
void VideoWindow::FrameMoved(BPoint origin)
{ {
if (is_zoomed) return ; SetInterfaceShowing(!fInterfaceShowing);
winSize = Frame();
} }
void VideoWindow::FrameResized( float width, float height ) /*****************************************************************************
* VideoWindow::SetInterfaceShowing
*****************************************************************************/
void
VideoWindow::SetInterfaceShowing(bool showIt)
{ {
float out_width, out_height; BWindow* window = get_interface_window();
float out_left, out_top; if (window)
float width_scale = width / i_width;
float height_scale = height / i_height;
if (width_scale <= height_scale)
{
out_width = (i_width * width_scale);
out_height = (i_height * width_scale);
out_left = 0;
out_top = (height - out_height) / 2;
}
else /* if the height is proportionally smaller */
{
out_width = (i_width * height_scale);
out_height = (i_height * height_scale);
out_top = 0;
out_left = (width - out_width) /2;
}
view->MoveTo(out_left,out_top);
view->ResizeTo(out_width, out_height);
if (!is_zoomed)
{ {
winSize = Frame(); if (showIt)
} {
} if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
SetFeel(B_NORMAL_WINDOW_FEEL);
void VideoWindow::ScreenChanged(BRect frame, color_space mode) window->Activate(true);
{ SendBehind(window);
BScreen *screen; }
float refresh; else
{
screen = new BScreen(this); SetFeel(fCachedFeel);
display_mode disp_mode; Activate(true);
window->SendBehind(this);
screen-> GetMode(&disp_mode); }
refresh = fInterfaceShowing = showIt;
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)* }
(disp_mode.timing.v_total));
if (refresh < 61)
{
vsync = true;
}
} }
void VideoWindow::WindowActivated(bool active) /*****************************************************************************
* VideoWindow::SetCorrectAspectRatio
*****************************************************************************/
void
VideoWindow::SetCorrectAspectRatio(bool doIt)
{ {
if (fCorrectAspect != doIt)
{
fCorrectAspect = doIt;
FrameResized(Bounds().Width(), Bounds().Height());
}
} }
int VideoWindow::SelectDrawingMode(int width, int height) /*****************************************************************************
* VideoWindow::_AllocateBuffers
*****************************************************************************/
status_t
VideoWindow::_AllocateBuffers(int width, int height, int* mode)
{ {
int drawingMode = BITMAP; // clear any old buffers
_FreeBuffers();
// set default mode
*mode = BITMAP;
BRect bitmapFrame( 0, 0, width, height );
// read from config, if we are supposed to use overlay at all
int noOverlay = !config_GetIntVariable( "overlay" ); int noOverlay = !config_GetIntVariable( "overlay" );
// test for overlay capability
for (int i = 0; i < COLOR_COUNT; i++) for (int i = 0; i < COLOR_COUNT; i++)
{ {
if (noOverlay) break; if (noOverlay) break;
bitmap[0] = new BBitmap ( BRect( 0, 0, width, height ), bitmap[0] = new BBitmap ( bitmapFrame,
B_BITMAP_WILL_OVERLAY, B_BITMAP_WILL_OVERLAY,
colspace[i].colspace); colspace[i].colspace);
...@@ -337,13 +452,13 @@ int VideoWindow::SelectDrawingMode(int width, int height) ...@@ -337,13 +452,13 @@ int VideoWindow::SelectDrawingMode(int width, int height)
{ {
colspace_index = i; colspace_index = i;
bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY, bitmap[1] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
colspace[colspace_index].colspace); colspace[colspace_index].colspace);
bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), B_BITMAP_WILL_OVERLAY, bitmap[2] = new BBitmap( bitmapFrame, B_BITMAP_WILL_OVERLAY,
colspace[colspace_index].colspace); colspace[colspace_index].colspace);
if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) ) if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
{ {
drawingMode = OVERLAY; *mode = OVERLAY;
rgb_color key; rgb_color key;
view->SetViewOverlay(bitmap[0], view->SetViewOverlay(bitmap[0],
bitmap[0]->Bounds() , bitmap[0]->Bounds() ,
...@@ -356,35 +471,166 @@ int VideoWindow::SelectDrawingMode(int width, int height) ...@@ -356,35 +471,166 @@ int VideoWindow::SelectDrawingMode(int width, int height)
} }
else else
{ {
delete bitmap[0]; _FreeBuffers();
delete bitmap[1]; *mode = BITMAP; // might want to try again with normal bitmaps
delete bitmap[2];
} }
} }
else else
{
delete bitmap[0]; delete bitmap[0];
}
} }
if (drawingMode == BITMAP) if (*mode == BITMAP)
{ {
// fallback to RGB32 // fallback to RGB32
colspace_index = DEFAULT_COL; colspace_index = DEFAULT_COL;
SetTitle(VOUT_TITLE " (Bitmap)"); SetTitle(VOUT_TITLE " (Bitmap)");
bitmap[0] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace); bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace);
bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace); bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace);
bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace); bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace);
} }
return drawingMode; // see if everything went well
status_t status = B_ERROR;
for (int32 i = 0; i < 3; i++)
{
if (bitmap[i])
status = bitmap[i]->InitCheck();
if (status < B_OK)
break;
}
if (status >= B_OK)
{
// clear bitmaps to black
for (int32 i = 0; i < 3; i++)
_BlankBitmap(bitmap[i]);
}
return status;
} }
/***************************************************************************** /*****************************************************************************
* VLCView::VLCView * VideoWindow::_FreeBuffers
*****************************************************************************/ *****************************************************************************/
VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_NONE, void
B_WILL_DRAW) VideoWindow::_FreeBuffers()
{
delete bitmap[0];
bitmap[0] = NULL;
delete bitmap[1];
bitmap[1] = NULL;
delete bitmap[2];
bitmap[2] = NULL;
fInitStatus = B_ERROR;
}
/*****************************************************************************
* VideoWindow::_BlankBitmap
*****************************************************************************/
void
VideoWindow::_BlankBitmap(BBitmap* bitmap) const
{
// no error checking (we do that earlier on and since it's a private function...
// YCbCr:
// Loss/Saturation points are Y 16-235 (absoulte); Cb/Cr 16-240 (center 128)
// YUV:
// Extrema points are Y 0 - 207 (absolute) U -91 - 91 (offset 128) V -127 - 127 (offset 128)
// we only handle weird colorspaces with special care
switch (bitmap->ColorSpace()) {
case B_YCbCr422: {
// Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0] Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
int32 height = bitmap->Bounds().IntegerHeight() + 1;
uint8* bits = (uint8*)bitmap->Bits();
int32 bpr = bitmap->BytesPerRow();
for (int32 y = 0; y < height; y++) {
// handle 2 bytes at a time
for (int32 i = 0; i < bpr; i += 2) {
// offset into line
bits[i] = 16;
bits[i + 1] = 128;
}
// next line
bits += bpr;
}
break;
}
case B_YCbCr420: {
// TODO: untested!!
// Non-interlaced only, Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
// Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
int32 height = bitmap->Bounds().IntegerHeight() + 1;
uint8* bits = (uint8*)bitmap->Bits();
int32 bpr = bitmap->BytesPerRow();
for (int32 y = 0; y < height; y += 1) {
// handle 3 bytes at a time
for (int32 i = 0; i < bpr; i += 3) {
// offset into line
bits[i] = 128;
bits[i + 1] = 16;
bits[i + 2] = 16;
}
// next line
bits += bpr;
}
break;
}
case B_YUV422: {
// TODO: untested!!
// U0[7:0] Y0[7:0] V0[7:0] Y1[7:0] U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
int32 height = bitmap->Bounds().IntegerHeight() + 1;
uint8* bits = (uint8*)bitmap->Bits();
int32 bpr = bitmap->BytesPerRow();
for (int32 y = 0; y < height; y += 1) {
// handle 2 bytes at a time
for (int32 i = 0; i < bpr; i += 2) {
// offset into line
bits[i] = 128;
bits[i + 1] = 0;
}
// next line
bits += bpr;
}
break;
}
default:
memset(bitmap->Bits(), 0, bitmap->BitsLength());
break;
}
}
/*****************************************************************************
* VideoWindow::_SetVideoSize
*****************************************************************************/
void
VideoWindow::_SetVideoSize(uint32 mode)
{
// let size depend on aspect correction
int32 width = fCorrectAspect ? i_width : fTrueWidth;
int32 height = fCorrectAspect ? i_height : fTrueHeight;
switch (mode)
{
case RESIZE_200:
width *= 2;
height *= 2;
break;
case RESIZE_100:
default:
break;
}
ResizeTo(width, height);
is_zoomed = false;
}
/*****************************************************************************
* VLCView::VLCView
*****************************************************************************/
VLCView::VLCView(BRect bounds)
: BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
fLastMouseMovedTime(system_time()),
fCursorHidden(false),
fCursorInside(false)
{ {
SetViewColor(B_TRANSPARENT_32_BIT); SetViewColor(B_TRANSPARENT_32_BIT);
} }
...@@ -396,77 +642,198 @@ VLCView::~VLCView() ...@@ -396,77 +642,198 @@ VLCView::~VLCView()
{ {
} }
/*****************************************************************************
* VLCVIew::AttachedToWindow
*****************************************************************************/
void
VLCView::AttachedToWindow()
{
// in order to get keyboard events
MakeFocus(true);
// periodically check if we want to hide the pointer
Window()->SetPulseRate(1000000);
}
/***************************************************************************** /*****************************************************************************
* VLCVIew::MouseDown * VLCVIew::MouseDown
*****************************************************************************/ *****************************************************************************/
void VLCView::MouseDown(BPoint point) void
VLCView::MouseDown(BPoint where)
{ {
BMessage* msg = Window()->CurrentMessage(); VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
int32 clicks = msg->FindInt32("clicks"); BMessage* msg = Window()->CurrentMessage();
int32 clicks;
uint32 buttons;
msg->FindInt32("clicks", &clicks);
msg->FindInt32("buttons", (int32*)&buttons);
if (videoWindow)
{
if (buttons & B_PRIMARY_MOUSE_BUTTON)
{
if (clicks == 2)
Window()->Zoom();
else
videoWindow->ToggleInterfaceShowing();
}
else
{
if (buttons & B_SECONDARY_MOUSE_BUTTON)
{
BPopUpMenu *menu = new BPopUpMenu("context menu");
menu->SetRadioMode(false);
// Toggle FullScreen
BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
zoomItem->SetMarked(videoWindow->is_zoomed);
menu->AddItem(zoomItem);
// Resize to 100%
BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100));
menu->AddItem(origItem);
// Resize to 200%
BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200));
menu->AddItem(doubleItem);
menu->AddSeparatorItem();
// Toggle vSync
BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
vsyncItem->SetMarked(videoWindow->vsync);
menu->AddItem(vsyncItem);
// Correct Aspect Ratio
BMenuItem *aspectItem = new BMenuItem("Correct Aspect Ratio", new BMessage(ASPECT_CORRECT));
aspectItem->SetMarked(videoWindow->CorrectAspectRatio());
menu->AddItem(aspectItem);
menu->AddSeparatorItem();
// Windwo Feel Items
BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
winNormFeel->AddInt32("WinFeel", (int32)B_NORMAL_WINDOW_FEEL);
BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
menu->AddItem(normWindItem);
BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
winFloatFeel->AddInt32("WinFeel", (int32)B_FLOATING_APP_WINDOW_FEEL);
BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
menu->AddItem(onTopWindItem);
BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
winAllFeel->AddInt32("WinFeel", (int32)B_FLOATING_ALL_WINDOW_FEEL);
BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
menu->AddItem(allSpacesWindItem);
menu->SetTargetForItems(this);
ConvertToScreen(&where);
menu->Go(where, true, false, true);
}
}
}
fLastMouseMovedTime = system_time();
fCursorHidden = false;
}
VideoWindow *vWindow = (VideoWindow *)Window(); /*****************************************************************************
uint32 mouseButtons; * VLCVIew::MouseMoved
BPoint where; *****************************************************************************/
GetMouse(&where, &mouseButtons, true); void
VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
{
fLastMouseMovedTime = system_time();
fCursorHidden = false;
fCursorInside = (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW);
}
if ((mouseButtons & B_PRIMARY_MOUSE_BUTTON) && (clicks == 2)) /*****************************************************************************
{ * VLCVIew::Pulse
Window()->Zoom(); *****************************************************************************/
return; void
} VLCView::Pulse()
else {
{ // We are getting the pulse messages no matter if the mouse is over
if (mouseButtons & B_SECONDARY_MOUSE_BUTTON) // this view. If we are in full screen mode, we want to hide the cursor
{ // even if it is not.
BPopUpMenu *menu = new BPopUpMenu("context menu"); if (!fCursorHidden) {
menu->SetRadioMode(false); VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
// Toggle FullScreen if (fCursorInside
BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN)); && system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT) {
zoomItem->SetMarked(vWindow->is_zoomed); be_app->ObscureCursor();
menu->AddItem(zoomItem); fCursorHidden = true;
// Resize to 100% // hide the interface window as well
BMenuItem *origItem = new BMenuItem("100%", new BMessage(RESIZE_100)); videoWindow->SetInterfaceShowing(false);
menu->AddItem(origItem); }
// Resize to 200% }
BMenuItem *doubleItem = new BMenuItem("200%", new BMessage(RESIZE_200)); }
menu->AddItem(doubleItem);
menu->AddSeparatorItem(); /*****************************************************************************
// Toggle vSync * VLCVIew::KeyDown
BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC)); *****************************************************************************/
vsyncItem->SetMarked(vWindow->vsync); void
menu->AddItem(vsyncItem); VLCView::KeyDown(const char *bytes, int32 numBytes)
menu->AddSeparatorItem(); {
VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
// Windwo Feel Items BWindow* interfaceWindow = get_interface_window();
BMessage *winNormFeel = new BMessage(WINDOW_FEEL); if (videoWindow && numBytes > 0) {
winNormFeel->AddInt16("WinFeel", (int16)B_NORMAL_WINDOW_FEEL); uint32 mods = modifiers();
BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel); switch (*bytes) {
normWindItem->SetMarked(vWindow->Feel() == B_NORMAL_WINDOW_FEEL); case B_TAB:
menu->AddItem(normWindItem); // toggle window and full screen mode
// not passing on the tab key to the default KeyDown()
BMessage *winFloatFeel = new BMessage(WINDOW_FEEL); // implementation also avoids loosing the keyboard focus
winFloatFeel->AddInt16("WinFeel", (int16)B_FLOATING_APP_WINDOW_FEEL); videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel); break;
onTopWindItem->SetMarked(vWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL); case B_ESCAPE:
menu->AddItem(onTopWindItem); // go back to window mode
if (videoWindow->is_zoomed)
BMessage *winAllFeel = new BMessage(WINDOW_FEEL); videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
winAllFeel->AddInt16("WinFeel", (int16)B_FLOATING_ALL_WINDOW_FEEL); break;
BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel); case B_SPACE:
allSpacesWindItem->SetMarked(vWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL); // toggle playback
menu->AddItem(allSpacesWindItem); if (interfaceWindow)
interfaceWindow->PostMessage(PAUSE_PLAYBACK);
menu->SetTargetForItems(this); break;
ConvertToScreen(&where); case B_RIGHT_ARROW:
menu->Go(where, true, false, true); if (interfaceWindow)
} {
} if (mods & B_SHIFT_KEY)
// next title
interfaceWindow->PostMessage(NEXT_CHAPTER);
else
// next chapter
interfaceWindow->PostMessage(NEXT_TITLE);
}
break;
case B_LEFT_ARROW:
if (interfaceWindow)
{
if (mods & B_SHIFT_KEY)
// previous title
interfaceWindow->PostMessage(PREV_CHAPTER);
else
// previous chapter
interfaceWindow->PostMessage(PREV_TITLE);
}
break;
case B_UP_ARROW:
// previous file in playlist?
break;
case B_DOWN_ARROW:
// next file in playlist?
break;
default:
BView::KeyDown(bytes, numBytes);
break;
}
}
} }
/***************************************************************************** /*****************************************************************************
* VLCVIew::Draw * VLCVIew::Draw
*****************************************************************************/ *****************************************************************************/
void VLCView::Draw(BRect updateRect) void
VLCView::Draw(BRect updateRect)
{ {
VideoWindow *win = (VideoWindow *) Window(); VideoWindow *win = (VideoWindow *) Window();
if (win->mode == BITMAP) if (win->mode == BITMAP)
...@@ -679,11 +1046,14 @@ static int BeosOpenDisplay( vout_thread_t *p_vout ) ...@@ -679,11 +1046,14 @@ static int BeosOpenDisplay( vout_thread_t *p_vout )
20 + p_vout->i_window_width - 1, 20 + p_vout->i_window_width - 1,
50 + p_vout->i_window_height - 1 )); 50 + p_vout->i_window_height - 1 ));
if( p_vout->p_sys->p_window == NULL ) if( p_vout->p_sys->p_window->InitCheck() < B_OK)
{ {
delete p_vout->p_sys->p_window;
p_vout->p_sys->p_window = NULL;
intf_ErrMsg( "error: cannot allocate memory for VideoWindow" ); intf_ErrMsg( "error: cannot allocate memory for VideoWindow" );
return( 1 ); return( 1 );
} } else
p_vout->p_sys->p_window->Show();
return( 0 ); return( 0 );
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* beos_init.cpp: Initialization for BeOS specific features * beos_init.cpp: Initialization for BeOS specific features
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: beos_specific.cpp,v 1.18 2002/04/26 05:43:37 sam Exp $ * $Id: beos_specific.cpp,v 1.18.2.1 2002/09/03 12:00:24 tcastley Exp $
* *
* Authors: Jean-Marc Dressler <polux@via.ecp.fr> * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* *
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <Roster.h> #include <Roster.h>
#include <Path.h> #include <Path.h>
#include <Alert.h> #include <Alert.h>
#include <Message.h>
#include <Window.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> /* strdup() */ #include <string.h> /* strdup() */
#include <malloc.h> /* free() */ #include <malloc.h> /* free() */
...@@ -44,6 +46,12 @@ public: ...@@ -44,6 +46,12 @@ public:
virtual void ReadyToRun(); virtual void ReadyToRun();
virtual void AboutRequested(); virtual void AboutRequested();
virtual void RefsReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
private:
BWindow* fInterfaceWindow;
BMessage* fRefsMessage;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -54,6 +62,9 @@ static vlc_mutex_t app_lock; ...@@ -54,6 +62,9 @@ static vlc_mutex_t app_lock;
static vlc_cond_t app_wait; static vlc_cond_t app_wait;
static char *psz_program_path; static char *psz_program_path;
//const uint32 INTERFACE_CREATED = 'ifcr'; /* message sent from interface */
#include "../../plugins/beos/MsgVals.h"
extern "C" extern "C"
{ {
...@@ -131,7 +142,9 @@ static void system_AppThread( void * args ) ...@@ -131,7 +142,9 @@ static void system_AppThread( void * args )
* VlcApplication: application constructor * VlcApplication: application constructor
*****************************************************************************/ *****************************************************************************/
VlcApplication::VlcApplication( char * psz_mimetype ) VlcApplication::VlcApplication( char * psz_mimetype )
:BApplication( psz_mimetype ) :BApplication( psz_mimetype ),
fInterfaceWindow( NULL ),
fRefsMessage( NULL )
{ {
/* Nothing to do, we use the default constructor */ /* Nothing to do, we use the default constructor */
} }
...@@ -142,6 +155,7 @@ VlcApplication::VlcApplication( char * psz_mimetype ) ...@@ -142,6 +155,7 @@ VlcApplication::VlcApplication( char * psz_mimetype )
VlcApplication::~VlcApplication( ) VlcApplication::~VlcApplication( )
{ {
/* Nothing to do, we use the default destructor */ /* Nothing to do, we use the default destructor */
delete fRefsMessage;
} }
/***************************************************************************** /*****************************************************************************
...@@ -177,3 +191,47 @@ void VlcApplication::ReadyToRun( ) ...@@ -177,3 +191,47 @@ void VlcApplication::ReadyToRun( )
vlc_mutex_unlock( &app_lock ); vlc_mutex_unlock( &app_lock );
} }
/*****************************************************************************
* RefsReceived: called when files are sent to our application
* (for example when the user drops fils onto our icon)
*****************************************************************************/
void VlcApplication::RefsReceived(BMessage* message)
{
if (fInterfaceWindow)
fInterfaceWindow->PostMessage(message);
else {
delete fRefsMessage;
fRefsMessage = new BMessage(*message);
}
}
/*****************************************************************************
* MessageReceived: a BeOS applications main message loop
* Since VlcApplication and interface are separated
* in the vlc binary and the interface plugin,
* we use this method to "stick" them together.
* The interface will post a message to the global
* "be_app" pointer when the interface is created
* containing a pointer to the interface window.
* In this way, we can keep a B_REFS_RECEIVED message
* in store for the interface window to handle later.
*****************************************************************************/
void VlcApplication::MessageReceived(BMessage* message)
{
switch (message->what) {
case INTERFACE_CREATED: {
BWindow* interfaceWindow;
if (message->FindPointer("window", (void**)&interfaceWindow) == B_OK) {
fInterfaceWindow = interfaceWindow;
if (fRefsMessage) {
fInterfaceWindow->PostMessage(fRefsMessage);
delete fRefsMessage;
fRefsMessage = NULL;
}
}
break;
}
default:
BApplication::MessageReceived(message);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment