Commit bf2f5b00 authored by Eric Petit's avatar Eric Petit

Attempt to port new BeOS features from the stable branch.

Playlist is yet broken (maybe others things too)
parent 370ab2b0
......@@ -128,7 +128,7 @@ case "x${target_os}" in
CXXFLAGS_save="${CXXFLAGS_save} -Wno-multichar -Wno-ctor-dtor-privacy -Woverloaded-virtual"; CXXFLAGS="${CXXFLAGS_save}"
LDFLAGS_vlc="${LDFLAGS_vlc} -lbe"
LDFLAGS_plugins="${LDFLAGS_plugins} -nostart"
LDFLAGS_beos="${LDFLAGS_beos} -lbe -lgame -lroot -ltracker -lstdc++.r4"
LDFLAGS_beos="${LDFLAGS_beos} -lbe -lgame -lroot -ltracker -lstdc++.r4 -ltranslation"
LDFLAGS_ipv4="${LDFLAGS_ipv4} -lbind"
;;
x*)
......
......@@ -2,7 +2,7 @@
* render.c : SPU renderer
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: render.c,v 1.1 2002/08/16 03:07:56 sam Exp $
* $Id: render.c,v 1.2 2002/09/30 18:30:26 titer Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
......@@ -356,12 +356,12 @@ void E_(RenderSPU)( vout_thread_t *p_vout, picture_t *p_pic,
case VLC_FOURCC('Y','U','Y','2'):
p_dest = p_pic->p->p_pixels +
(p_spu->i_x + p_spu->i_width +
p_vout->output.i_width * ( p_spu->i_y + p_spu->i_height )) * 2;
+ ( p_spu->i_y + p_spu->i_height ) * p_pic->p->i_pitch // * bytes per line
+ ( p_spu->i_x + p_spu->i_width ) * 2; // * bytes per pixel
/* Draw until we reach the bottom of the subtitle */
for( i_y = p_spu->i_height * p_vout->output.i_width;
for( i_y = p_spu->i_height * p_pic->p->i_pitch / 2;
i_y ;
i_y -= p_vout->output.i_width )
i_y -= p_pic->p->i_pitch / 2 )
{
/* Draw until we reach the end of the line */
for( i_x = p_spu->i_width ; i_x ; )
......
......@@ -2,7 +2,7 @@
* beos.cpp : BeOS plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: BeOS.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: BeOS.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -57,4 +57,3 @@ vlc_module_begin();
set_capability( "audio output", 100 );
set_callbacks( E_(OpenAudio), E_(CloseAudio) );
vlc_module_end();
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2,9 +2,10 @@
* DrawingTidbits.cpp
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: DrawingTidbits.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: DrawingTidbits.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* 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
* it under the terms of the GNU General Public License as published by
......@@ -21,12 +22,15 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <math.h>
#include <Bitmap.h>
#include <Debug.h>
#include <Screen.h>
#include "DrawingTidbits.h"
// ShiftComponent
inline uchar
ShiftComponent(uchar component, float percent)
{
......@@ -38,6 +42,7 @@ ShiftComponent(uchar component, float percent)
return (uchar)(255 - percent * (255 - component));
}
// ShiftColor
rgb_color
ShiftColor(rgb_color color, float percent)
{
......@@ -51,6 +56,7 @@ ShiftColor(rgb_color color, float percent)
return result;
}
// CompareColors
static bool
CompareColors(const rgb_color a, const rgb_color b)
{
......@@ -60,18 +66,21 @@ CompareColors(const rgb_color a, const rgb_color b)
&& a.alpha == b.alpha;
}
// ==
bool
operator==(const rgb_color &a, const rgb_color &b)
{
return CompareColors(a, b);
}
// !=
bool
operator!=(const rgb_color &a, const rgb_color &b)
{
return !CompareColors(a, b);
}
// ReplaceColor
void
ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
{
......@@ -88,6 +97,7 @@ ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to)
bits[index] = toIndex;
}
// ReplaceTransparentColor
void
ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
{
......@@ -103,3 +113,366 @@ ReplaceTransparentColor(BBitmap *bitmap, rgb_color with)
bits[index] = withIndex;
}
// ycrcb_to_rgb
inline void
ycbcr_to_rgb( uint8 y, uint8 cb, uint8 cr,
uint8& r, uint8& g, uint8& b)
{
r = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) + 1.596 * ( cr - 128 ) ) );
g = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) - 0.813 * ( cr - 128 )
- 0.391 * ( cb - 128 ) ) );
b = (uint8)max_c( 0, min_c( 255, 1.164 * ( y - 16 ) + 2.018 * ( cb - 128 ) ) );
}
// this function will not produce visually pleasing results!
// we'd have to convert to Lab colorspace, do the mixing
// and convert back to RGB - in an ideal world...
//
// mix_colors
inline void
mix_colors( uint8 ra, uint8 ga, uint8 ba,
uint8 rb, uint8 gb, uint8 bb,
uint8& r, uint8& g, uint8& b, float mixLevel )
{
float mixA = ( 1.0 - mixLevel );
float mixB = mixLevel;
r = (uint8)(mixA * ra + mixB * rb);
g = (uint8)(mixA * ga + mixB * gb);
b = (uint8)(mixA * ba + mixB * bb);
}
// the algorithm used is probably pretty slow, but it should be easy
// to understand what's going on...
//
// scale_bitmap
status_t
scale_bitmap( BBitmap* bitmap, uint32 fromWidth, uint32 fromHeight )
{
status_t status = B_BAD_VALUE;
if ( bitmap && bitmap->IsValid()
&& ( bitmap->ColorSpace() == B_RGB32 || bitmap->ColorSpace() == B_RGBA32 ) )
{
status = B_MISMATCHED_VALUES;
// we only support upscaling as of now
uint32 destWidth = bitmap->Bounds().IntegerWidth() + 1;
uint32 destHeight = bitmap->Bounds().IntegerHeight() + 1;
if ( fromWidth <= destWidth && fromHeight <= destHeight )
{
status = B_OK;
uint32 bpr = bitmap->BytesPerRow();
if ( fromWidth < destWidth )
{
// scale horizontally
uint8* src = (uint8*)bitmap->Bits();
uint8* p = new uint8[fromWidth * 4]; // temp buffer
for ( uint32 y = 0; y < fromHeight; y++ )
{
// copy valid pixels into temp buffer
memcpy( p, src, fromWidth * 4 );
for ( uint32 x = 0; x < destWidth; x++ )
{
// mix colors of left and right pixels and write it back
// into the bitmap
float xPos = ( (float)x / (float)destWidth ) * (float)fromWidth;
uint32 leftIndex = (uint32)floorf( xPos ) * 4;
uint32 rightIndex = (uint32)ceilf( xPos ) * 4;
rgb_color left;
left.red = p[leftIndex + 2];
left.green = p[leftIndex + 1];
left.blue = p[leftIndex + 0];
rgb_color right;
right.red = p[rightIndex + 2];
right.green = p[rightIndex + 1];
right.blue = p[rightIndex + 0];
rgb_color mix;
mix_colors( left.red, left.green, left.blue,
right.red, right.green, right.blue,
mix.red, mix.green, mix.blue, xPos - floorf( xPos ) );
uint32 destIndex = x * 4;
src[destIndex + 2] = mix.red;
src[destIndex + 1] = mix.green;
src[destIndex + 0] = mix.blue;
}
src += bpr;
}
delete[] p;
}
if ( fromHeight < destHeight )
{
// scale vertically
uint8* src = (uint8*)bitmap->Bits();
uint8* p = new uint8[fromHeight * 3]; // temp buffer
for ( uint32 x = 0; x < destWidth; x++ )
{
// copy valid pixels into temp buffer
for ( uint32 y = 0; y < fromHeight; y++ )
{
uint32 destIndex = y * 3;
uint32 srcIndex = x * 4 + y * bpr;
p[destIndex + 0] = src[srcIndex + 0];
p[destIndex + 1] = src[srcIndex + 1];
p[destIndex + 2] = src[srcIndex + 2];
}
// do the scaling
for ( uint32 y = 0; y < destHeight; y++ )
{
// mix colors of upper and lower pixels and write it back
// into the bitmap
float yPos = ( (float)y / (float)destHeight ) * (float)fromHeight;
uint32 upperIndex = (uint32)floorf( yPos ) * 3;
uint32 lowerIndex = (uint32)ceilf( yPos ) * 3;
rgb_color upper;
upper.red = p[upperIndex + 2];
upper.green = p[upperIndex + 1];
upper.blue = p[upperIndex + 0];
rgb_color lower;
lower.red = p[lowerIndex + 2];
lower.green = p[lowerIndex + 1];
lower.blue = p[lowerIndex + 0];
rgb_color mix;
mix_colors( upper.red, upper.green, upper.blue,
lower.red, lower.green, lower.blue,
mix.red, mix.green, mix.blue, yPos - floorf( yPos ) );
uint32 destIndex = x * 4 + y * bpr;
src[destIndex + 2] = mix.red;
src[destIndex + 1] = mix.green;
src[destIndex + 0] = mix.blue;
}
}
delete[] p;
}
}
}
return status;
}
// 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:
// Y0[7:0] Cb0[7:0] Y1[7:0] Cr0[7:0]
// Y2[7:0] Cb2[7:0] Y3[7:0] Cr2[7:0]
for ( int32 y = 0; y < height; y++ )
{
for ( int32 x = 0; x < width; x += 2 )
{
int32 srcOffset = x * 2;
int32 dstOffset = x * 4;
ycbcr_to_rgb( srcBits[srcOffset + 0],
srcBits[srcOffset + 1],
srcBits[srcOffset + 3],
dstBits[dstOffset + 2],
dstBits[dstOffset + 1],
dstBits[dstOffset + 0] );
ycbcr_to_rgb( srcBits[srcOffset + 2],
srcBits[srcOffset + 1],
srcBits[srcOffset + 3],
dstBits[dstOffset + 6],
dstBits[dstOffset + 5],
dstBits[dstOffset + 4] );
// take care of alpha
dstBits[x * 4 + 3] = 255;
dstBits[x * 4 + 7] = 255;
}
srcBits += srcBpr;
dstBits += dstBpr;
}
status = B_OK;
break;
case B_YCbCr420:
// Non-interlaced only!
// Cb0 Y0 Y1 Cb2 Y2 Y3 on even scan lines ...
// Cr0 Y0 Y1 Cr2 Y2 Y3 on odd scan lines
status = B_ERROR;
break;
case B_YUV422:
// U0[7:0] Y0[7:0] V0[7:0] Y1[7:0]
// U2[7:0] Y2[7:0] V2[7:0] Y3[7:0]
status = B_ERROR;
break;
case B_RGB32:
case B_RGBA32:
memcpy( dstBits, srcBits, inBitmap->BitsLength() );
status = B_OK;
break;
case B_RGB16:
// G[2:0],B[4:0] R[4:0],G[5:3]
for ( int32 y = 0; y < height; y ++ )
{
for ( int32 x = 0; x < width; x++ )
{
int32 srcOffset = x * 2;
int32 dstOffset = x * 4;
uint8 blue = srcBits[srcOffset + 0] & 0x1f;
uint8 green = ( srcBits[srcOffset + 0] >> 5 )
| ( ( srcBits[srcOffset + 1] & 0x07 ) << 3 );
uint8 red = srcBits[srcOffset + 1] & 0xf8;
// homogeneously scale each component to 8 bit
dstBits[dstOffset + 0] = (blue << 3) | (blue >> 2);
dstBits[dstOffset + 1] = (green << 2) | (green >> 4);
dstBits[dstOffset + 2] = red | (red >> 5);
}
srcBits += srcBpr;
dstBits += dstBpr;
}
status = B_OK;
break;
default:
//printf("unkown colorspace: %ld\n", inBitmap->ColorSpace());
status = B_MISMATCHED_VALUES;
break;
}
if ( status == B_OK )
{
if ( width < outBitmap->Bounds().IntegerWidth() + 1
|| height < outBitmap->Bounds().IntegerHeight() + 1 )
{
scale_bitmap( outBitmap, width, height );
}
}
}
}
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 @@
* DrawingTidbits.h
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: DrawingTidbits.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: DrawingTidbits.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* 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
* it under the terms of the GNU General Public License as published by
......@@ -52,4 +53,37 @@ const float kDimLevel = 0.6;
void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
#endif
// function can be used to scale the upper left part of
// a bitmap to fill the entire bitmap, ie fromWidth
// and fromHeight must be smaller or equal to the bitmaps size!
// only supported colorspaces are B_RGB32 and B_RGBA32
status_t scale_bitmap( BBitmap* bitmap,
uint32 fromWidth, uint32 fromHeight );
// bitmaps need to be the same size, or this function will fail
// currently supported conversions:
// B_YCbCr422 -> B_RGB32
// B_RGB32 -> B_RGB32
// B_RGB16 -> B_RGB32
// not yet implemented conversions:
// B_YCbCr420 -> B_RGB32
// B_YUV422 -> B_RGB32
status_t convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap);
// 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__
/*****************************************************************************
* intf.cpp: beos interface
* intf_beos.cpp: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: Interface.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: Interface.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Tony Castley <tony@castley.net>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -30,6 +31,8 @@
#include <stdio.h>
#include <stdlib.h> /* malloc(), free() */
#include <InterfaceKit.h>
#include <Application.h>
#include <Message.h>
#include <string.h>
#include <vlc/vlc.h>
......@@ -37,6 +40,7 @@
#include "VlcWrapper.h"
#include "InterfaceWindow.h"
#include "MsgVals.h"
/*****************************************************************************
* Local prototype
......@@ -44,7 +48,7 @@
static void Run ( intf_thread_t *p_intf );
/*****************************************************************************
* OpenIntf: initialize interface
* intf_Open: initialize interface
*****************************************************************************/
int E_(OpenIntf) ( vlc_object_t *p_this )
{
......@@ -65,7 +69,7 @@ int E_(OpenIntf) ( vlc_object_t *p_this )
msg_Err( p_intf, "out of memory" );
return( 1 );
}
// p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
p_intf->p_sys->p_input = NULL;
p_intf->pf_run = Run;
......@@ -79,13 +83,21 @@ int E_(OpenIntf) ( vlc_object_t *p_this )
free( p_intf->p_sys );
msg_Err( p_intf, "cannot allocate InterfaceWindow" );
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->i_saved_volume = AOUT_VOLUME_DEFAULT;
p_intf->p_sys->b_loop = 0;
p_intf->p_sys->b_mute = 0;
return( 0 );
}
/*****************************************************************************
* CloseIntf: destroy interface
* intf_Close: destroy dummy interface
*****************************************************************************/
void E_(CloseIntf) ( vlc_object_t *p_this )
{
......@@ -96,8 +108,6 @@ void E_(CloseIntf) ( vlc_object_t *p_this )
vlc_object_release( p_intf->p_sys->p_input );
}
// msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
/* Destroy the interface window */
p_intf->p_sys->p_window->Lock();
p_intf->p_sys->p_window->Quit();
......@@ -108,7 +118,7 @@ void E_(CloseIntf) ( vlc_object_t *p_this )
/*****************************************************************************
* Run: event loop
* intf_Run: event loop
*****************************************************************************/
static void Run( intf_thread_t *p_intf )
{
......@@ -133,11 +143,7 @@ static void Run( intf_thread_t *p_intf )
FIND_ANYWHERE );
}
/* Wait a bit */
msleep( INTF_IDLE_SLEEP );
}
}
......@@ -2,12 +2,13 @@
* InterfaceWindow.cpp: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: InterfaceWindow.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: InterfaceWindow.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Tony Castley <tony@castley.net>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -36,7 +37,6 @@
#include <fs_info.h>
#include <string.h>
/* VLC headers */
#include <vlc/vlc.h>
#include <vlc/aout.h>
......@@ -49,6 +49,8 @@
#include "VlcWrapper.h"
#include "InterfaceWindow.h"
#define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps
/*****************************************************************************
* InterfaceWindow
......@@ -56,92 +58,139 @@
InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
intf_thread_t *p_interface )
: BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK
| B_ASYNCHRONOUS_CONTROLS )
: BWindow( frame, name, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_NOT_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
p_intf( p_interface ),
fInputThread( NULL ),
fFilePanel( NULL ),
fLastUpdateTime( system_time() ),
fSettings( new BMessage( 'sett' ) )
{
file_panel = NULL;
playlist_window = NULL;
p_intf = p_interface;
p_vlc_wrapper = Intf_VLCWrapper::getVLCWrapper(p_intf);
BRect controlRect(0,0,0,0);
p_vlc_wrapper = p_vlc_wrapper->getVLCWrapper(p_intf);
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
b_empty_playlist = (p_playlist->i_size < 0);
b_mute = false;
fPlaylistIsEmpty = (p_playlist->i_size < 0);
/* set the title bar */
// set the title bar
SetName( "interface" );
SetTitle(VOUT_TITLE);
/* set up the main menu */
BMenuBar *menu_bar;
menu_bar = new BMenuBar(controlRect, "main menu");
AddChild( menu_bar );
BMenu *mFile;
BMenu *mAudio;
CDMenu *cd_menu;
BMenu *mNavigation;
/* Add the file Menu */
BMenuItem *mItem;
menu_bar->AddItem( mFile = new BMenu( "File" ) );
menu_bar->ResizeToPreferred();
mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
new BMessage(OPEN_FILE), 'O') );
cd_menu = new CDMenu( "Open Disc" );
mFile->AddItem( cd_menu );
mFile->AddSeparatorItem();
mFile->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
new BMessage(OPEN_PLAYLIST), 'P') );
mFile->AddSeparatorItem();
mFile->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
new BMessage(B_ABOUT_REQUESTED), 'A') );
mItem->SetTarget( be_app );
mFile->AddItem(mItem = new BMenuItem( "Quit",
new BMessage(B_QUIT_REQUESTED), 'Q') );
SetTitle( VOUT_TITLE );
// the media control view
p_mediaControl = new MediaControlView( BRect( 0.0, 0.0, 250.0, 50.0 ) );
p_mediaControl->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
float width, height;
p_mediaControl->GetPreferredSize( &width, &height );
// set up the main menu
fMenuBar = new BMenuBar( BRect(0.0, 0.0, width, 15.0), "main menu",
B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
// make menu bar resize to correct height
float menuWidth, menuHeight;
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 );
// Add the file Menu
BMenu* fileMenu = new BMenu( "File" );
fMenuBar->AddItem( fileMenu );
fileMenu->AddItem( new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
new BMessage( OPEN_FILE ), 'O') );
fileMenu->AddItem( new CDMenu( "Open Disc" ) );
fileMenu->AddSeparatorItem();
fileMenu->AddItem( new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
new BMessage( OPEN_PLAYLIST ), 'P') );
fileMenu->AddSeparatorItem();
BMenuItem* item = new BMenuItem( "About" B_UTF8_ELLIPSIS,
new BMessage( B_ABOUT_REQUESTED ), 'A');
item->SetTarget( be_app );
fileMenu->AddItem( item );
fileMenu->AddItem( new BMenuItem( "Quit", 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 */
menu_bar->AddItem ( mAudio = new BMenu( "Audio" ) );
menu_bar->ResizeToPreferred();
mAudio->AddItem( new LanguageMenu( "Language", AUDIO_ES, p_intf ) );
mAudio->AddItem( new LanguageMenu( "Subtitles", SPU_ES, p_intf ) );
fAudioMenu = new BMenu( "Audio" );
fMenuBar->AddItem ( fAudioMenu );
fAudioMenu->AddItem( fLanguageMenu );
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 */
menu_bar->AddItem( mNavigation = new BMenu( "Navigation" ) );
menu_bar->ResizeToPreferred();
mNavigation->AddItem( new BMenuItem( "Prev Title",
new BMessage(PREV_TITLE)) );
mNavigation->AddItem( new BMenuItem( "Next Title",
new BMessage(NEXT_TITLE)) );
mNavigation->AddItem( new BMenuItem( "Prev Chapter",
new BMessage(PREV_CHAPTER)) );
mNavigation->AddItem( new BMenuItem( "Next Chapter",
new BMessage(NEXT_CHAPTER)) );
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 */
AddChild( p_mediaControl );
Show();
fNavigationMenu = new BMenu( "Navigation" );
fMenuBar->AddItem( fNavigationMenu );
fNavigationMenu->AddItem( fPrevTitleMI );
fNavigationMenu->AddItem( fNextTitleMI );
fNavigationMenu->AddItem( fTitleMenu = new TitleMenu( "Go to Title", p_intf ) );
fNavigationMenu->AddSeparatorItem();
fNavigationMenu->AddItem( fPrevChapterMI );
fNavigationMenu->AddItem( fNextChapterMI );
fNavigationMenu->AddItem( fChapterMenu = new ChapterMenu( "Go to Chapter", p_intf ) );
/* Add the Speed menu */
fSpeedMenu = new BMenu( "Speed" );
fSpeedMenu->SetRadioMode( true );
fSpeedMenu->AddItem( fSlowerMI = new BMenuItem( "Slower", new BMessage( SLOWER_PLAY ) ) );
fNormalMI = new BMenuItem( "Normal", new BMessage( NORMAL_PLAY ) );
fNormalMI->SetMarked(true); // default to normal speed
fSpeedMenu->AddItem( fNormalMI );
fSpeedMenu->AddItem( fFasterMI = new BMenuItem( "Faster", new BMessage( FASTER_PLAY) ) );
fSpeedMenu->SetTargetForItems( this );
fMenuBar->AddItem( fSpeedMenu );
/* Add the Config menu */
// BMenu* configMenu = new BMenu( "Config" );
// menu_bar->AddItem( configMenu );
// fOnTopMI = new BMenuItem( "Always on Top",
// new BMessage( TOGGLE_ON_TOP ) )
// configMenu->AddItem( );
// fOnTopMI->SetMarked(false);
// prepare fow showing
_SetMenusEnabled(false);
_RestoreSettings();
Show();
}
InterfaceWindow::~InterfaceWindow()
{
if (playlist_window) playlist_window->ReallyQuit();
if (fPlaylistWindow)
fPlaylistWindow->ReallyQuit();
delete fSettings;
}
/*****************************************************************************
* 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());
}
/*****************************************************************************
......@@ -149,66 +198,64 @@ InterfaceWindow::~InterfaceWindow()
*****************************************************************************/
void InterfaceWindow::MessageReceived( BMessage * p_message )
{
int vol_val = p_mediaControl->GetVolume(); // remember the current volume
int playback_status; // remember playback state
int i_index;
BAlert *alert;
Activate();
playback_status = p_vlc_wrapper->inputGetStatus();
switch( p_message->what )
{
case B_ABOUT_REQUESTED:
alert = new BAlert(VOUT_TITLE, "BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
{
BAlert* alert = new BAlert( VOUT_TITLE,
"BeOS " VOUT_TITLE "\n\n<www.videolan.org>", "Ok");
alert->Go();
break;
}
case TOGGLE_ON_TOP:
break;
case OPEN_FILE:
if( file_panel )
if( fFilePanel )
{
file_panel->Show();
fFilePanel->Show();
break;
}
file_panel = new BFilePanel();
file_panel->SetTarget( this );
file_panel->Show();
b_empty_playlist = false;
p_mediaControl->SetEnabled( !b_empty_playlist );
fFilePanel = new BFilePanel();
fFilePanel->SetTarget( this );
fFilePanel->Show();
break;
case OPEN_PLAYLIST:
if (fPlaylistWindow->Lock())
{
BRect rect(20,20,320,420);
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
playlist_window = PlayListWindow::getPlayList(rect,
"Playlist", p_playlist);
playlist_window->Show();
if (fPlaylistWindow->IsHidden())
fPlaylistWindow->Show();
else
fPlaylistWindow->Activate();
fPlaylistWindow->Unlock();
}
break;
case OPEN_DVD:
{
const char *psz_device;
BString type("dvd");
if( p_message->FindString("device", &psz_device) != B_ERROR )
BString type( "dvd" );
if( p_message->FindString( "device", &psz_device ) == B_OK )
{
BString device(psz_device);
p_vlc_wrapper->openDisc(type, device, 0,0);
BString device( psz_device );
p_vlc_wrapper->openDisc( type, device, 0, 0 );
}
_UpdatePlaylist();
}
break;
case STOP_PLAYBACK:
// this currently stops playback not nicely
//p_vlc_wrapper->volume_mute();
//snooze( 400000 );
if (playback_status > UNDEF_S)
{
p_vlc_wrapper->volume_mute();
snooze( 400000 );
p_vlc_wrapper->playlistStop();
p_mediaControl->SetStatus(NOT_STARTED_S,DEFAULT_RATE);
p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
}
break;
case START_PLAYBACK:
......@@ -216,18 +263,18 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case PAUSE_PLAYBACK:
/* toggle between pause and play */
if( p_intf->p_sys->p_input != NULL )
if (playback_status > UNDEF_S)
{
/* pause if currently playing */
if ( playback_status == PLAYING_S )
{
//p_vlc_wrapper->volume_mute();
//snooze( 400000 );
p_vlc_wrapper->volume_mute();
snooze( 400000 );
p_vlc_wrapper->playlistPause();
}
else
{
//p_vlc_wrapper->volume_restore();
p_vlc_wrapper->volume_restore();
p_vlc_wrapper->playlistPlay();
}
}
......@@ -240,57 +287,80 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
case FASTER_PLAY:
/* cycle the fast playback modes */
//p_vlc_wrapper->volume_mute();
//snooze( 400000 );
if (playback_status > UNDEF_S)
{
p_vlc_wrapper->volume_mute();
snooze( 400000 );
p_vlc_wrapper->playFaster();
}
break;
case SLOWER_PLAY:
/* cycle the slow playback modes */
//p_vlc_wrapper->volume_mute();
//snooze( 400000 );
if (playback_status > UNDEF_S)
{
p_vlc_wrapper->volume_mute();
snooze( 400000 );
p_vlc_wrapper->playSlower();
}
break;
case NORMAL_PLAY:
/* restore speed to normal if already playing */
if (playback_status > UNDEF_S)
{
p_vlc_wrapper->volume_restore();
p_vlc_wrapper->playlistPlay();
}
break;
case SEEK_PLAYBACK:
/* handled by semaphores */
break;
// volume related messages
case VOLUME_CHG:
/* adjust the volume */
// vlc_mutex_lock( &p_intf->p_sys->p_input->lock );
// for( i_index = 0 ; i_index < p_aout_bank->i_count ; i_index++ )
// {
// if( p_aout_bank->pp_aout[i_index]->i_savedvolume )
// {
// p_aout_bank->pp_aout[i_index]->i_savedvolume = vol_val;
// }
// else
// {
// p_aout_bank->pp_aout[i_index]->i_volume = vol_val;
// }
// }
// vlc_mutex_unlock( &p_aout_bank->lock );
if (playback_status > UNDEF_S)
{
p_vlc_wrapper->set_volume( p_mediaControl->GetVolume() );
p_mediaControl->SetMuted( p_vlc_wrapper->is_muted() );
}
break;
case VOLUME_MUTE:
/* toggle muting */
p_vlc_wrapper->toggleMute( );
// toggle muting
p_vlc_wrapper->toggle_mute();
p_mediaControl->SetMuted( p_vlc_wrapper->is_muted() );
break;
case SELECT_AUDIO:
case SELECT_CHANNEL:
if ( playback_status > UNDEF_S )
{
int32 i = p_message->FindInt32( "audio" );
p_vlc_wrapper->toggleLanguage( i );
int32 channel;
if ( p_message->FindInt32( "channel", &channel ) == B_OK )
{
p_vlc_wrapper->toggleLanguage( channel );
// vlc seems to remember the volume for every channel,
// but I would assume that to be somewhat annoying to the user
// the next call will also unmute the volume, which is probably
// desired as well, because if the user selects another language,
// he probably wants to hear the change as well
snooze( 400000 ); // we have to wait a bit, or the change will be reverted
p_vlc_wrapper->set_volume( p_mediaControl->GetVolume() );
}
}
break;
case SELECT_SUBTITLE:
if ( playback_status > UNDEF_S )
{
int32 i = p_message->FindInt32( "subtitle" );
p_vlc_wrapper->toggleSubtitle( i );
int32 subtitle;
if ( p_message->FindInt32( "subtitle", &subtitle ) == B_OK )
p_vlc_wrapper->toggleSubtitle( subtitle );
}
break;
// specific navigation messages
case PREV_TITLE:
{
int i_id;
......@@ -313,6 +383,14 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
{
p_vlc_wrapper->toggleTitle(i_id);
}
break;
}
case TOGGLE_TITLE:
if ( playback_status > UNDEF_S )
{
int32 index;
if ( p_message->FindInt32( "index", &index ) == B_OK )
p_vlc_wrapper->toggleTitle( index );
}
break;
case PREV_CHAPTER:
......@@ -325,8 +403,8 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
{
p_vlc_wrapper->toggleChapter(i_id);
}
}
break;
}
case NEXT_CHAPTER:
{
int i_id;
......@@ -337,24 +415,51 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
{
p_vlc_wrapper->toggleChapter(i_id);
}
break;
}
case TOGGLE_CHAPTER:
if ( playback_status > UNDEF_S )
{
int32 index;
if ( p_message->FindInt32( "index", &index ) == B_OK )
p_vlc_wrapper->toggleChapter( index );
}
break;
case PREV_FILE:
p_vlc_wrapper->playlistPrev();
break;
case NEXT_FILE:
p_vlc_wrapper->playlistNext();
break;
// general next/prev functionality (skips to whatever makes most sense)
case NAVIGATE_PREV:
p_vlc_wrapper->navigatePrev();
break;
case NAVIGATE_NEXT:
p_vlc_wrapper->navigateNext();
break;
// drag'n'drop and system messages
case B_REFS_RECEIVED:
case B_SIMPLE_DATA:
{
// figure out if user wants files replaced or added
bool replace = false;
if ( p_message->WasDropped() )
replace = !( modifiers() & B_SHIFT_KEY );
// build list of files to be played from message contents
entry_ref ref;
BList* files = new BList();
int i = 0;
while( p_message->FindRef( "refs", i, &ref ) == B_OK )
BList files;
for ( int i = 0; p_message->FindRef( "refs", i, &ref ) == B_OK; i++ )
{
BPath path( &ref );
files->AddItem(new BString((char*)path.Path()) );
i++;
if ( path.InitCheck() == B_OK )
// the BString objects will be deleted
// by the wrapper function further down
files.AddItem( new BString( (char*)path.Path() ) );
}
p_vlc_wrapper->openFiles(files);
delete files;
// give the list to VLC
p_vlc_wrapper->openFiles(&files, replace);
_UpdatePlaylist();
}
break;
......@@ -365,50 +470,378 @@ void InterfaceWindow::MessageReceived( BMessage * p_message )
}
/*****************************************************************************
* InterfaceWindow::QuitRequested
*****************************************************************************/
bool InterfaceWindow::QuitRequested()
{
if (p_intf->p_sys->p_input)
{
p_vlc_wrapper->volume_mute();
snooze( 400000 );
p_vlc_wrapper->playlistStop();
p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
}
p_intf->b_die = 1;
_StoreSettings();
return( true );
}
/*****************************************************************************
* InterfaceWindow::updateInterface
*****************************************************************************/
void InterfaceWindow::updateInterface()
{
if ( p_intf->p_sys->p_input != NULL )
input_thread_t* input = p_intf->p_sys->p_input;
if ( input )
{
if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
if ( acquire_sem( p_mediaControl->fScrubSem ) == B_OK )
{
p_vlc_wrapper->setTimeAsFloat(p_mediaControl->GetSeekTo());
}
else if( Lock() )
else if ( Lock() )
{
bool hasTitles = input->stream.i_area_nb > 1;
bool hasChapters = input->stream.p_selected_area->i_part_nb > 1;
p_mediaControl->SetStatus( input->stream.control.i_status,
input->stream.control.i_rate );
p_mediaControl->SetProgress( input->stream.p_selected_area->i_tell,
input->stream.p_selected_area->i_size );
_SetMenusEnabled( true, hasChapters, hasTitles );
_UpdateSpeedMenu( input->stream.control.i_rate );
// enable/disable skip buttons
bool canSkipPrev;
bool canSkipNext;
p_vlc_wrapper->getNavCapabilities( &canSkipPrev, &canSkipNext );
p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
if ( p_vlc_wrapper->has_audio() )
{
p_mediaControl->SetAudioEnabled( true );
p_mediaControl->SetMuted( p_vlc_wrapper->is_muted() );
} else
p_mediaControl->SetAudioEnabled( false );
if ( input != fInputThread )
{
fInputThread = input;
_InputStreamChanged();
}
Unlock();
}
// update playlist as well
if ( fPlaylistWindow->Lock() )
{
fPlaylistWindow->UpdatePlaylist();
fPlaylistWindow->Unlock();
}
}
else
_SetMenusEnabled(false);
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
if ( fPlaylistIsEmpty != ( p_playlist->i_size < 0) )
{
if ( Lock() )
{
p_mediaControl->SetStatus(p_intf->p_sys->p_input->stream.control.i_status,
p_intf->p_sys->p_input->stream.control.i_rate);
p_mediaControl->SetProgress(p_intf->p_sys->p_input->stream.p_selected_area->i_tell,
p_intf->p_sys->p_input->stream.p_selected_area->i_size);
fPlaylistIsEmpty = !fPlaylistIsEmpty;
p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
Unlock();
}
}
if ( input != fInputThread )
fInputThread = input;
fLastUpdateTime = system_time();
}
/*****************************************************************************
* InterfaceWindow::IsStopped
*****************************************************************************/
bool
InterfaceWindow::IsStopped() const
{
return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
}
/*****************************************************************************
* InterfaceWindow::_UpdatePlaylist
*****************************************************************************/
void
InterfaceWindow::_UpdatePlaylist()
{
if ( fPlaylistWindow->Lock() )
{
fPlaylistWindow->UpdatePlaylist( true );
fPlaylistWindow->Unlock();
playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
fPlaylistIsEmpty = p_playlist->i_size < 1;
p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
}
}
if ( b_empty_playlist != (p_playlist->i_size < 1) )
/*****************************************************************************
* InterfaceWindow::_SetMenusEnabled
*****************************************************************************/
void
InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles)
{
if (!hasFile)
{
hasChapters = false;
hasTitles = false;
}
if (Lock())
{
b_empty_playlist = !b_empty_playlist;
p_mediaControl->SetEnabled( !b_empty_playlist );
if (fNextChapterMI->IsEnabled() != hasChapters)
fNextChapterMI->SetEnabled(hasChapters);
if (fPrevChapterMI->IsEnabled() != hasChapters)
fPrevChapterMI->SetEnabled(hasChapters);
if (fChapterMenu->IsEnabled() != hasChapters)
fChapterMenu->SetEnabled(hasChapters);
if (fNextTitleMI->IsEnabled() != hasTitles)
fNextTitleMI->SetEnabled(hasTitles);
if (fPrevTitleMI->IsEnabled() != hasTitles)
fPrevTitleMI->SetEnabled(hasTitles);
if (fTitleMenu->IsEnabled() != hasTitles)
fTitleMenu->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();
}
}
/*****************************************************************************
* InterfaceWindow::_UpdateSpeedMenu
*****************************************************************************/
void
InterfaceWindow::_UpdateSpeedMenu( int rate )
{
if ( rate == DEFAULT_RATE )
{
if ( !fNormalMI->IsMarked() )
fNormalMI->SetMarked( true );
}
else if ( rate < DEFAULT_RATE )
{
if ( !fFasterMI->IsMarked() )
fFasterMI->SetMarked( true );
}
else
{
if ( !fSlowerMI->IsMarked() )
fSlowerMI->SetMarked( true );
}
}
/*****************************************************************************
* InterfaceWindow::QuitRequested
* InterfaceWindow::_InputStreamChanged
*****************************************************************************/
bool InterfaceWindow::QuitRequested()
void
InterfaceWindow::_InputStreamChanged()
{
p_intf->p_vlc->b_die = VLC_TRUE;
//printf("InterfaceWindow::_InputStreamChanged()\n");
// TODO: move more stuff from updateInterface() here!
snooze( 400000 );
p_vlc_wrapper->set_volume( p_mediaControl->GetVolume() );
}
return( true );
/*****************************************************************************
* InterfaceWindow::_LoadSettings
*****************************************************************************/
status_t
InterfaceWindow::_LoadSettings( BMessage* message, const char* fileName, const char* folder )
{
status_t ret = B_BAD_VALUE;
if ( message )
{
BPath path;
if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
{
// passing folder is optional
if ( folder )
ret = path.Append( folder );
if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
{
BFile file( path.Path(), B_READ_ONLY );
if ( ( ret = file.InitCheck() ) == B_OK )
{
ret = message->Unflatten( &file );
file.Unset();
}
}
}
}
return ret;
}
/*****************************************************************************
* InterfaceWindow::_SaveSettings
*****************************************************************************/
status_t
InterfaceWindow::_SaveSettings( BMessage* message, const char* fileName, const char* folder )
{
status_t ret = B_BAD_VALUE;
if ( message )
{
BPath path;
if ( ( ret = find_directory( B_USER_SETTINGS_DIRECTORY, &path ) ) == B_OK )
{
// passing folder is optional
if ( folder && ( ret = path.Append( folder ) ) == B_OK )
ret = create_directory( path.Path(), 0777 );
if ( ret == B_OK && ( ret = path.Append( fileName ) ) == B_OK )
{
BFile file( path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE );
if ( ( ret = file.InitCheck() ) == B_OK )
{
ret = message->Flatten( &file );
file.Unset();
}
}
}
}
return ret;
}
/*****************************************************************************
* InterfaceWindow::_RestoreSettings
*****************************************************************************/
bool
make_sure_frame_is_on_screen( BRect& frame )
{
BScreen screen( B_MAIN_SCREEN_ID );
if (frame.IsValid() && screen.IsValid()) {
if (!screen.Frame().Contains(frame)) {
// make sure frame fits in the screen
if (frame.Width() > screen.Frame().Width())
frame.right -= frame.Width() - screen.Frame().Width() + 10.0;
if (frame.Height() > screen.Frame().Height())
frame.bottom -= frame.Height() - screen.Frame().Height() + 30.0;
// frame is now at the most the size of the screen
if (frame.right > screen.Frame().right)
frame.OffsetBy(-(frame.right - screen.Frame().right), 0.0);
if (frame.bottom > screen.Frame().bottom)
frame.OffsetBy(0.0, -(frame.bottom - screen.Frame().bottom));
if (frame.left < screen.Frame().left)
frame.OffsetBy((screen.Frame().left - frame.left), 0.0);
if (frame.top < screen.Frame().top)
frame.OffsetBy(0.0, (screen.Frame().top - frame.top));
}
return true;
}
return false;
}
void
make_sure_frame_is_within_limits( BRect& frame, float minWidth, float minHeight,
float maxWidth, float maxHeight )
{
if ( frame.Width() < minWidth )
frame.right = frame.left + minWidth;
if ( frame.Height() < minHeight )
frame.bottom = frame.top + minHeight;
if ( frame.Width() > maxWidth )
frame.right = frame.left + maxWidth;
if ( frame.Height() > maxHeight )
frame.bottom = frame.top + maxHeight;
}
/*****************************************************************************
* InterfaceWindow::_RestoreSettings
*****************************************************************************/
void
InterfaceWindow::_RestoreSettings()
{
if ( _LoadSettings( fSettings, "interface_settings", "VideoLAN Client" ) == B_OK )
{
BRect mainFrame;
if ( fSettings->FindRect( "main frame", &mainFrame ) == B_OK )
{
// sanity checks: make sure window is not too big/small
// and that it's not off-screen
float minWidth, maxWidth, minHeight, maxHeight;
GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight );
make_sure_frame_is_within_limits( mainFrame,
minWidth, minHeight, maxWidth, maxHeight );
make_sure_frame_is_on_screen( mainFrame );
MoveTo( mainFrame.LeftTop() );
ResizeTo( mainFrame.Width(), mainFrame.Height() );
}
if ( fPlaylistWindow->Lock() )
{
BRect playlistFrame;
if (fSettings->FindRect( "playlist frame", &playlistFrame ) == B_OK )
{
// sanity checks: make sure window is not too big/small
// and that it's not off-screen
float minWidth, maxWidth, minHeight, maxHeight;
fPlaylistWindow->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight );
make_sure_frame_is_within_limits( playlistFrame,
minWidth, minHeight, maxWidth, maxHeight );
make_sure_frame_is_on_screen( playlistFrame );
fPlaylistWindow->MoveTo( playlistFrame.LeftTop() );
fPlaylistWindow->ResizeTo( playlistFrame.Width(), playlistFrame.Height() );
}
bool showing;
if ( fSettings->FindBool( "playlist showing", &showing ) == B_OK )
{
if ( showing )
{
if ( fPlaylistWindow->IsHidden() )
fPlaylistWindow->Show();
}
else
{
if ( !fPlaylistWindow->IsHidden() )
fPlaylistWindow->Hide();
}
}
fPlaylistWindow->Unlock();
}
}
}
/*****************************************************************************
* InterfaceWindow::_StoreSettings
*****************************************************************************/
void
InterfaceWindow::_StoreSettings()
{
if ( fSettings->ReplaceRect( "main frame", Frame() ) != B_OK )
fSettings->AddRect( "main frame", Frame() );
if ( fPlaylistWindow->Lock() )
{
if (fSettings->ReplaceRect( "playlist frame", fPlaylistWindow->Frame() ) != B_OK)
fSettings->AddRect( "playlist frame", fPlaylistWindow->Frame() );
if (fSettings->ReplaceBool( "playlist showing", !fPlaylistWindow->IsHidden() ) != B_OK)
fSettings->AddBool( "playlist showing", !fPlaylistWindow->IsHidden() );
fPlaylistWindow->Unlock();
}
_SaveSettings( fSettings, "interface_settings", "VideoLAN Client" );
}
/*****************************************************************************
......@@ -431,7 +864,9 @@ CDMenu::~CDMenu()
*****************************************************************************/
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");
BMenu::AttachedToWindow();
}
......@@ -488,6 +923,7 @@ int CDMenu::GetCD( const char *directory )
vol->Unset();
status = volRoster->GetNextVolume(vol);
}
return 0;
}
/*****************************************************************************
......@@ -511,81 +947,199 @@ LanguageMenu::~LanguageMenu()
/*****************************************************************************
* LanguageMenu::AttachedToWindow
*****************************************************************************/
void LanguageMenu::AttachedToWindow(void)
void LanguageMenu::AttachedToWindow()
{
while( RemoveItem((long int)0) != NULL )
{
; // remove all items
}
// remove all items
while ( BMenuItem* item = RemoveItem( 0L ) )
delete item;
SetRadioMode(true);
GetChannels();
SetRadioMode( true );
_GetChannels();
BMenu::AttachedToWindow();
}
/*****************************************************************************
* LanguageMenu::GetChannels
* LanguageMenu::_GetChannels
*****************************************************************************/
int LanguageMenu::GetChannels()
void LanguageMenu::_GetChannels()
{
char *psz_name;
bool b_active;
BMessage *msg;
BMenuItem *menu_item;
int i;
es_descriptor_t *p_es = NULL;
/* Insert the null */
if( kind == SPU_ES ) //audio
// Insert the "None" item if in subtitle mode
if( kind != AUDIO_ES ) //subtitle
{
msg = new BMessage(SELECT_SUBTITLE);
msg->AddInt32("subtitle", -1);
BMenuItem *menu_item;
menu_item = new BMenuItem("None", msg);
AddItem(menu_item);
menu_item->SetMarked(TRUE);
msg = new BMessage( SELECT_SUBTITLE );
msg->AddInt32( "subtitle", -1 );
menu_item = new BMenuItem( "None", msg );
AddItem( menu_item );
menu_item->SetMarked( true );
}
if( p_intf->p_sys->p_input == NULL )
input_thread_t* input = p_intf->p_sys->p_input;
if ( input )
{
vlc_mutex_lock( &input->stream.stream_lock );
for( i = 0; i < input->stream.i_selected_es_number; i++ )
{
return 1;
if( kind == input->stream.pp_selected_es[i]->i_cat )
p_es = input->stream.pp_selected_es[i];
}
int32 addedItems = 0;
bool emptyItemAdded = false;
uint32 what = kind == AUDIO_ES ? SELECT_CHANNEL : SELECT_SUBTITLE;
const char* fieldName = kind == AUDIO_ES ? "channel" : "subtitle";
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
for( i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number; i++ )
for ( i = 0; i < input->stream.i_es_number; i++ )
{
if( kind == p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat )
if ( kind == input->stream.pp_es[i]->i_cat )
{
p_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
bool addItem = true;
psz_name = input->stream.pp_es[i]->psz_desc;
// workarround for irritating empty strings
if ( strcmp(psz_name, "") == 0 )
{
// if ( kind != AUDIO_ES ) // don't add empty subtitle items, they don't work anyways
// addItem = false;
// else
// {
if (!emptyItemAdded)
{
psz_name = "<default>";
emptyItemAdded = true;
}
else
psz_name = "<unkown>";
// }
}
for( i = 0; i < p_intf->p_sys->p_input->stream.i_es_number; i++ )
if ( addItem )
{
if( kind == p_intf->p_sys->p_input->stream.pp_es[i]->i_cat )
addedItems++;
msg = new BMessage( what );
msg->AddInt32( fieldName, i );
menu_item = new BMenuItem( psz_name, msg );
AddItem( menu_item );
b_active = ( p_es == input->stream.pp_es[i] );
menu_item->SetMarked( b_active );
}
}
}
vlc_mutex_unlock( &input->stream.stream_lock );
// enhance readability and separate first item from rest
if ( ( emptyItemAdded || kind != AUDIO_ES ) && addedItems > 1 )
AddItem( new BSeparatorItem(), 1 );
}
}
/*****************************************************************************
* TitleMenu::TitleMenu
*****************************************************************************/
TitleMenu::TitleMenu( const char *name, intf_thread_t *p_interface )
: BMenu(name),
p_intf( p_interface )
{
}
/*****************************************************************************
* TitleMenu::~TitleMenu
*****************************************************************************/
TitleMenu::~TitleMenu()
{
}
/*****************************************************************************
* TitleMenu::AttachedToWindow
*****************************************************************************/
void TitleMenu::AttachedToWindow()
{
// make title menu empty
while ( BMenuItem* item = RemoveItem( 0L ) )
delete item;
input_thread_t* input = p_intf->p_sys->p_input;
if ( input )
{
psz_name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
if( kind == AUDIO_ES ) //audio
// lock stream access
vlc_mutex_lock( &input->stream.stream_lock );
// populate menu according to current stream
int32 numTitles = input->stream.i_area_nb;
if ( numTitles > 1 )
{
msg = new BMessage(SELECT_AUDIO);
msg->AddInt32("audio", i);
}
else
// disallow title 0!
for ( int32 i = 1; i < numTitles; i++ )
{
msg = new BMessage(SELECT_SUBTITLE);
msg->AddInt32("subtitle", i);
BMessage* message = new BMessage( TOGGLE_TITLE );
message->AddInt32( "index", i );
BString helper( "" );
helper << i;
BMenuItem* item = new BMenuItem( helper.String(), message );
item->SetMarked( input->stream.p_selected_area->i_id == i );
AddItem( item );
}
BMenuItem *menu_item;
menu_item = new BMenuItem(psz_name, msg);
AddItem(menu_item);
b_active = (p_es == p_intf->p_sys->p_input->stream.pp_es[i]);
menu_item->SetMarked(b_active);
}
// done messing with stream
vlc_mutex_unlock( &input->stream.stream_lock );
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
BMenu::AttachedToWindow();
}
/*****************************************************************************
* ChapterMenu::ChapterMenu
*****************************************************************************/
ChapterMenu::ChapterMenu( const char *name, intf_thread_t *p_interface )
: BMenu(name),
p_intf( p_interface )
{
}
/*****************************************************************************
* ChapterMenu::~ChapterMenu
*****************************************************************************/
ChapterMenu::~ChapterMenu()
{
}
/*****************************************************************************
* ChapterMenu::AttachedToWindow
*****************************************************************************/
void ChapterMenu::AttachedToWindow()
{
// make title menu empty
while ( BMenuItem* item = RemoveItem( 0L ) )
delete item;
input_thread_t* input = p_intf->p_sys->p_input;
if ( input )
{
// lock stream access
vlc_mutex_lock( &input->stream.stream_lock );
// populate menu according to current stream
int32 numChapters = input->stream.p_selected_area->i_part_nb;
if ( numChapters > 1 )
{
for ( int32 i = 0; i < numChapters; i++ )
{
BMessage* message = new BMessage( TOGGLE_CHAPTER );
message->AddInt32( "index", i );
BString helper( "" );
helper << i + 1;
BMenuItem* item = new BMenuItem( helper.String(), message );
item->SetMarked( input->stream.p_selected_area->i_part == i );
AddItem( item );
}
}
// done messing with stream
vlc_mutex_unlock( &input->stream.stream_lock );
}
BMenu::AttachedToWindow();
}
......@@ -2,11 +2,12 @@
* InterfaceWindow.h: BeOS interface window class prototype
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: InterfaceWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: InterfaceWindow.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -22,56 +23,134 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* intf_sys_t: description and status of FB interface
*****************************************************************************/
#ifndef BEOS_INTERFACE_WINDOW_H
#define BEOS_INTERFACE_WINDOW_H
#include <Menu.h>
#include <Window.h>
class BMenuBar;
class MediaControlView;
class PlayListWindow;
class BFilePanel;
class CDMenu : public BMenu
{
public:
CDMenu(const char *name);
~CDMenu();
void AttachedToWindow(void);
private:
int GetCD(const char *directory);
public:
CDMenu( const char* name );
virtual ~CDMenu();
virtual void AttachedToWindow();
private:
int GetCD( const char* directory );
};
class LanguageMenu : public BMenu
{
public:
LanguageMenu(const char *name, int menu_kind,
intf_thread_t *p_interface);
~LanguageMenu();
void AttachedToWindow(void);
private:
intf_thread_t *p_intf;
public:
LanguageMenu( const char* name,
int menu_kind,
intf_thread_t* p_interface );
virtual ~LanguageMenu();
virtual void AttachedToWindow();
private:
void _GetChannels();
intf_thread_t* p_intf;
int kind;
int GetChannels();
};
class TitleMenu : public BMenu
{
public:
TitleMenu( const char* name, intf_thread_t *p_interface );
virtual ~TitleMenu();
virtual void AttachedToWindow();
intf_thread_t *p_intf;
};
class ChapterMenu : public BMenu
{
public:
ChapterMenu( const char* name, intf_thread_t *p_interface );
virtual ~ChapterMenu();
virtual void AttachedToWindow();
intf_thread_t *p_intf;
};
class InterfaceWindow : public BWindow
{
public:
InterfaceWindow( BRect frame, const char *name,
intf_thread_t *p_interface );
~InterfaceWindow();
public:
InterfaceWindow( BRect frame,
const char* name,
intf_thread_t* p_interface );
virtual ~InterfaceWindow();
// standard window member
// BWindow
virtual void FrameResized( float width, float height );
virtual void MessageReceived( BMessage* message );
virtual bool QuitRequested();
virtual void MessageReceived(BMessage *message);
// InterfaceWindow
void updateInterface();
bool IsStopped() const;
MediaControlView *p_mediaControl;
MediaControlView* p_mediaControl;
private:
void _UpdatePlaylist();
void _SetMenusEnabled( bool hasFile,
bool hasChapters = false,
bool hasTitles = false );
void _UpdateSpeedMenu( int rate );
void _InputStreamChanged();
status_t _LoadSettings( BMessage* message,
const char* fileName,
const char* subFolder = NULL );
status_t _SaveSettings( BMessage* message,
const char* fileName,
const char* subFolder = NULL );
void _RestoreSettings();
void _StoreSettings();
intf_thread_t* p_intf;
es_descriptor_t* p_audio_es;
es_descriptor_t* p_spu_es;
input_thread_t* fInputThread;
bool fPlaylistIsEmpty;
BFilePanel* fFilePanel;
PlayListWindow* fPlaylistWindow;
BMenuBar* fMenuBar;
BMenuItem* fNextTitleMI;
BMenuItem* fPrevTitleMI;
BMenuItem* fNextChapterMI;
BMenuItem* fPrevChapterMI;
BMenuItem* fOnTopMI;
BMenuItem* fSlowerMI;
BMenuItem* fNormalMI;
BMenuItem* fFasterMI;
BMenu* fAudioMenu;
BMenu* fNavigationMenu;
BMenu* fTitleMenu;
BMenu* fChapterMenu;
BMenu* fLanguageMenu;
BMenu* fSubtitlesMenu;
BMenu* fSpeedMenu;
bigtime_t fLastUpdateTime;
BMessage* fSettings; // we keep the message arround
// for forward compatibility
private:
intf_thread_t *p_intf;
bool b_empty_playlist;
bool b_mute;
BFilePanel *file_panel;
PlayListWindow* playlist_window;
BMenuItem *miOnTop;
Intf_VLCWrapper * p_vlc_wrapper;
};
#endif // BEOS_INTERFACE_WINDOW_H
/*****************************************************************************
* ListViews.h: BeOS interface list view class implementation
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: ListViews.cpp,v 1.1 2002/09/30 18:30:27 titer Exp $
*
* Authors: Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <stdio.h>
#include <Bitmap.h>
#include <String.h>
/* VLC headers */
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include "VlcWrapper.h"
#include "InterfaceWindow.h"
#include "ListViews.h"
#include "MsgVals.h"
#define MAX_DRAG_HEIGHT 200.0
#define ALPHA 170
#define TEXT_OFFSET 20.0
/*****************************************************************************
* PlaylistItem class
*****************************************************************************/
PlaylistItem::PlaylistItem( const char *name )
: BStringItem( name )
{
}
PlaylistItem::~PlaylistItem()
{
}
/*****************************************************************************
* PlaylistItem::DrawItem
*****************************************************************************/
void
PlaylistItem::Draw( BView *owner, BRect frame, bool tintedLine,
bool active, bool playing )
{
rgb_color color = (rgb_color){ 255, 255, 255, 255 };
if ( tintedLine )
color = tint_color( color, 1.04 );
// background
if ( IsSelected() )
color = tint_color( color, B_DARKEN_2_TINT );
owner->SetLowColor( color );
owner->FillRect( frame, B_SOLID_LOW );
// label
owner->SetHighColor( 0, 0, 0, 255 );
font_height fh;
owner->GetFontHeight( &fh );
BString truncatedString( Text() );
owner->TruncateString( &truncatedString, B_TRUNCATE_MIDDLE,
frame.Width() - TEXT_OFFSET - 4.0 );
owner->DrawString( truncatedString.String(),
BPoint( frame.left + TEXT_OFFSET,
frame.top + fh.ascent + 1.0 ) );
// playmark
if ( active )
{
rgb_color black = (rgb_color){ 0, 0, 0, 255 };
rgb_color green = (rgb_color){ 0, 255, 0, 255 };
BRect r( 0.0, 0.0, 10.0, 10.0 );
r.OffsetTo( frame.left + 4.0,
ceilf( ( frame.top + frame.bottom ) / 2.0 ) - 5.0 );
if ( !playing )
green = tint_color( color, B_DARKEN_1_TINT );
rgb_color lightGreen = tint_color( green, B_LIGHTEN_2_TINT );
rgb_color darkGreen = tint_color( green, B_DARKEN_2_TINT );
BPoint arrow[3];
arrow[0] = r.LeftTop();
arrow[1] = r.LeftBottom();
arrow[2].x = r.right;
arrow[2].y = ( r.top + r.bottom ) / 2.0;
owner->BeginLineArray( 6 );
// black outline
owner->AddLine( arrow[0], arrow[1], black );
owner->AddLine( BPoint( arrow[1].x + 1.0, arrow[1].y - 1.0 ),
arrow[2], black );
owner->AddLine( arrow[0], arrow[2], black );
// inset arrow
arrow[0].x += 1.0;
arrow[0].y += 2.0;
arrow[1].x += 1.0;
arrow[1].y -= 2.0;
arrow[2].x -= 2.0;
// highlights and shadow
owner->AddLine( arrow[1], arrow[2], darkGreen );
owner->AddLine( arrow[0], arrow[2], lightGreen );
owner->AddLine( arrow[0], arrow[1], lightGreen );
owner->EndLineArray();
// fill green
arrow[0].x += 1.0;
arrow[0].y += 1.0;
arrow[1].x += 1.0;
arrow[1].y -= 1.0;
arrow[2].x -= 2.0;
owner->SetHighColor( green );
owner->FillPolygon( arrow, 3 );
}
}
/*****************************************************************************
* DragSortableListView class
*****************************************************************************/
DragSortableListView::DragSortableListView( BRect frame, const char* name,
list_view_type type, uint32 resizingMode,
uint32 flags )
: BListView( frame, name, type, resizingMode, flags ),
fDropIndex( -1 )
{
SetViewColor( B_TRANSPARENT_32_BIT );
}
DragSortableListView::~DragSortableListView()
{
}
/*****************************************************************************
* DragSortableListView::Draw
*****************************************************************************/
void
DragSortableListView::Draw( BRect updateRect )
{
int32 firstIndex = IndexOf( updateRect.LeftTop() );
int32 lastIndex = IndexOf( updateRect.RightBottom() );
if ( firstIndex >= 0 )
{
if ( lastIndex < firstIndex )
lastIndex = CountItems() - 1;
// update rect contains items
BRect r( updateRect );
for ( int32 i = firstIndex; i <= lastIndex; i++)
{
r = ItemFrame( i );
DrawListItem( this, i, r );
}
updateRect.top = r.bottom + 1.0;
if ( updateRect.IsValid() )
{
SetLowColor( 255, 255, 255, 255 );
FillRect( updateRect, B_SOLID_LOW );
}
}
else
{
SetLowColor( 255, 255, 255, 255 );
FillRect( updateRect, B_SOLID_LOW );
}
}
/*****************************************************************************
* DragSortableListView::InitiateDrag
*****************************************************************************/
bool
DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
{
return false;
bool success = false;
BListItem* item = ItemAt( CurrentSelection( 0 ) );
if ( !item )
{
// workarround a timing problem
Select( index );
item = ItemAt( index );
}
if ( item )
{
// create drag message
BMessage msg( B_SIMPLE_DATA );
MakeDragMessage( &msg );
// figure out drag rect
float width = Bounds().Width();
BRect dragRect(0.0, 0.0, width, -1.0);
// figure out, how many items fit into our bitmap
int32 numItems;
bool fade = false;
for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) {
dragRect.bottom += item->Height();
if ( dragRect.Height() > MAX_DRAG_HEIGHT ) {
fade = true;
dragRect.bottom = MAX_DRAG_HEIGHT;
numItems++;
break;
}
}
BBitmap* dragBitmap = new BBitmap( dragRect, B_RGB32, true );
if ( dragBitmap && dragBitmap->IsValid() ) {
if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) {
dragBitmap->AddChild( v );
dragBitmap->Lock();
BRect itemBounds( dragRect) ;
itemBounds.bottom = 0.0;
// let all selected items, that fit into our drag_bitmap, draw
for ( int32 i = 0; i < numItems; i++ ) {
int32 index = CurrentSelection( i );
BListItem* item = ItemAt( index );
itemBounds.bottom = itemBounds.top + item->Height() - 1.0;
if ( itemBounds.bottom > dragRect.bottom )
itemBounds.bottom = dragRect.bottom;
DrawListItem( v, index, itemBounds );
itemBounds.top = itemBounds.bottom + 1.0;
}
// make a black frame arround the edge
v->SetHighColor( 0, 0, 0, 255 );
v->StrokeRect( v->Bounds() );
v->Sync();
uint8 *bits = (uint8 *)dragBitmap->Bits();
int32 height = (int32)dragBitmap->Bounds().Height() + 1;
int32 width = (int32)dragBitmap->Bounds().Width() + 1;
int32 bpr = dragBitmap->BytesPerRow();
if (fade) {
for ( int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr ) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
for ( int32 y = height - ALPHA / 2; y < height; y++, bits += bpr ) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = (height - y) << 1;
}
} else {
for ( int32 y = 0; y < height; y++, bits += bpr ) {
uint8 *line = bits + 3;
for (uint8 *end = line + 4 * width; line < end; line += 4)
*line = ALPHA;
}
}
dragBitmap->Unlock();
success = true;
}
}
if (success)
DragMessage( &msg, dragBitmap, B_OP_ALPHA, BPoint( 0.0, 0.0 ) );
else {
delete dragBitmap;
DragMessage( &msg, dragRect.OffsetToCopy( point ), this );
}
}
return success;
}
/*****************************************************************************
* DragSortableListView::WindowActivated
*****************************************************************************/
void
DragSortableListView::WindowActivated( bool active )
{
// workarround for buggy focus indication of BScrollView
if ( BView* view = Parent() )
view->Invalidate();
}
/*****************************************************************************
* DragSortableListView::MessageReceived
*****************************************************************************/
void
DragSortableListView::MessageReceived(BMessage* message)
{
BListItem *item = NULL;
DragSortableListView *list = NULL;
if ( message->FindPointer( "list", (void **)&list ) == B_OK
&& list == this )
{
int32 count = CountItems();
if ( fDropIndex < 0 || fDropIndex > count )
fDropIndex = count;
bool copy = ( modifiers() & B_SHIFT_KEY );
for ( int32 i = 0; message->FindPointer( "item", i, (void **)&item ) == B_OK; i++ )
{
if ( HasItem( item ) )
{
BListItem* itemToAdd = NULL;
int32 index = IndexOf( item );
if ( copy )
{
// add cloned item
itemToAdd = CloneItem( index );
Deselect( IndexOf( item ) );
}
else
{
// drag sort
if ( index < fDropIndex )
fDropIndex--;
if ( RemoveItem( item ) )
itemToAdd = item;
}
if ( itemToAdd )
{
if ( AddItem( itemToAdd, fDropIndex ) )
Select( IndexOf( itemToAdd ), true );
else
delete itemToAdd;
}
}
fDropIndex++;
}
fDropIndex = -1;
} else
BListView::MessageReceived( message );
}
/*****************************************************************************
* DragSortableListView::MouseMoved
*****************************************************************************/
void
DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *msg)
{
if ( msg && msg->what == B_SIMPLE_DATA )
{
switch ( transit )
{
case B_ENTERED_VIEW:
{
// draw drop mark
BRect r(ItemFrame(0L));
where.y += r.Height() / 2.0;
int32 count = CountItems();
bool found = false;
for (int32 index = 0; index <= count; index++)
{
r = ItemFrame(index);
if (r.Contains(where))
{
SetHighColor(255, 0, 0, 255);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
r.top++;
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
fDropIndex = index;
found = true;
break;
}
}
if (found)
break;
// mouse is after last item
fDropIndex = count;
r = Bounds();
if (count > 0)
r.top = ItemFrame(count - 1).bottom + 1.0;
SetHighColor(255, 0, 0, 255);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
r.top++;
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
break;
}
case B_INSIDE_VIEW:
{
// draw drop mark and invalidate previous drop mark
BRect r(ItemFrame(0L));
where.y += r.Height() / 2.0;
int32 count = CountItems();
// mouse still after last item?
if (fDropIndex == count)
{
r = Bounds();
if (count > 0)
r.top = ItemFrame(count - 1).bottom + 1.0;
if (r.Contains(where))
break;
else
{
r.bottom = r.top + 2.0;
Invalidate(r);
}
}
// mouse still over same item?
if (ItemFrame(fDropIndex).Contains(where))
break;
else
InvalidateItem(fDropIndex);
// mouse over new item
bool found = false;
for (int32 index = 0; index <= count; index++)
{
r = ItemFrame(index);
if (r.Contains(where))
{
SetHighColor(255, 0, 0, 255);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
r.top++;
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
fDropIndex = index;
found = true;
break;
}
}
if (found)
break;
// mouse is after last item
fDropIndex = count;
r = Bounds();
if (count > 0)
r.top = ItemFrame(count - 1).bottom + 1.0;
SetHighColor(255, 0, 0, 255);
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
r.top++;
StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH);
break;
}
case B_EXITED_VIEW:
{
int32 count = CountItems();
if (count > 0)
{
if (fDropIndex == count)
{
BRect r(Bounds());
r.top = ItemFrame(count - 1).bottom + 1.0;
r.bottom = r.top + 2.0;
Invalidate(r);
}
else
InvalidateItem(fDropIndex);
}
break;
}
case B_OUTSIDE_VIEW:
break;
}
}
else
BListView::MouseMoved(where, transit, msg);
}
/*****************************************************************************
* DragSortableListView::MouseUp
*****************************************************************************/
void
DragSortableListView::MouseUp( BPoint where )
{
// remove drop mark
if ( fDropIndex >= 0 && fDropIndex < CountItems() )
InvalidateItem( fDropIndex );
BListView::MouseUp( where );
}
/*****************************************************************************
* DragSortableListView::DrawItem
*****************************************************************************/
void
DragSortableListView::DrawItem( BListItem *item, BRect itemFrame, bool complete )
{
DrawListItem( this, IndexOf( item ), itemFrame );
}
/*****************************************************************************
* PlaylistView class
*****************************************************************************/
PlaylistView::PlaylistView( BRect frame, InterfaceWindow* mainWindow )
: DragSortableListView( frame, "playlist listview",
B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES,
B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED
| B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE ),
fCurrentIndex( -1 ),
fPlaying( false ),
fMainWindow( mainWindow )
{
}
PlaylistView::~PlaylistView()
{
}
/*****************************************************************************
* PlaylistView::AttachedToWindow
*****************************************************************************/
void
PlaylistView::AttachedToWindow()
{
// get pulse message every two frames
Window()->SetPulseRate(80000);
}
/*****************************************************************************
* PlaylistView::MouseDown
*****************************************************************************/
void
PlaylistView::MouseDown( BPoint where )
{
int32 clicks = 1;
Window()->CurrentMessage()->FindInt32( "clicks", &clicks );
bool handled = false;
for ( int32 i = 0; PlaylistItem* item = (PlaylistItem*)ItemAt( i ); i++ )
{
BRect r = ItemFrame( i );
if ( r.Contains( where ) )
{
if ( clicks == 2 )
{
/* Intf_VLCWrapper::playlistJumpTo( i ); */
handled = true;
}
else if ( i == fCurrentIndex )
{
r.right = r.left + TEXT_OFFSET;
if ( r.Contains ( where ) )
{
fMainWindow->PostMessage( PAUSE_PLAYBACK );
InvalidateItem( i );
handled = true;
}
}
break;
}
}
if ( !handled )
DragSortableListView::MouseDown(where);
}
/*****************************************************************************
* PlaylistView::KeyDown
*****************************************************************************/
void
PlaylistView::KeyDown( const char* bytes, int32 numBytes )
{
if (numBytes < 1)
return;
if ( ( bytes[0] == B_BACKSPACE ) || ( bytes[0] == B_DELETE ) )
{
int32 i = CurrentSelection();
if ( BListItem *item = ItemAt( i ) )
{
/* if ( RemoveItem( item ) )
{
delete item;
Select( i + 1 );
}*/
}
}
DragSortableListView::KeyDown( bytes, numBytes );
}
/*****************************************************************************
* PlaylistView::Pulse
*****************************************************************************/
void
PlaylistView::Pulse()
{
if (fMainWindow->IsStopped())
SetPlaying( false );
}
/*****************************************************************************
* PlaylistView::CloneItem
*****************************************************************************/
BListItem*
PlaylistView::CloneItem( int32 atIndex ) const
{
BListItem* clone = NULL;
if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( atIndex ) ) )
clone = new PlaylistItem( item->Text() );
return clone;
}
/*****************************************************************************
* PlaylistView::DrawListItem
*****************************************************************************/
void
PlaylistView::DrawListItem( BView* owner, int32 index, BRect frame ) const
{
if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( index ) ) )
item->Draw( owner, frame, index % 2, index == fCurrentIndex, fPlaying );
}
/*****************************************************************************
* PlaylistView::MakeDragMessage
*****************************************************************************/
void
PlaylistView::MakeDragMessage( BMessage* message ) const
{
if ( message )
{
message->AddPointer( "list", (void*)this );
for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ )
message->AddPointer( "item", (void*)item );
}
}
/*****************************************************************************
* PlaylistView::SetCurrent
*****************************************************************************/
void
PlaylistView::SetCurrent( int32 index )
{
if ( fCurrentIndex != index )
{
InvalidateItem( fCurrentIndex );
fCurrentIndex = index;
InvalidateItem( fCurrentIndex );
}
}
/*****************************************************************************
* PlaylistView::SetPlaying
*****************************************************************************/
void
PlaylistView::SetPlaying( bool playing )
{
if ( fPlaying != playing )
{
fPlaying = playing;
InvalidateItem( fCurrentIndex );
}
}
/*****************************************************************************
* ListViews.h: BeOS interface list view class prototype
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: ListViews.h,v 1.1 2002/09/30 18:30:27 titer Exp $
*
* Authors: Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef LIST_VIEWS_H
#define LIST_VIEWS_H
#include <ListItem.h>
#include <ListView.h>
class InterfaceWindow;
// PlaylistItem
class PlaylistItem : public BStringItem
{
public:
PlaylistItem( const char* name );
virtual ~PlaylistItem();
virtual void Draw( BView* owner, BRect frame,
bool tintedLine,
bool active = false,
bool playing = false );
};
// DragSortableListView
class DragSortableListView : public BListView
{
public:
DragSortableListView( BRect frame,
const char* name,
list_view_type type
= B_SINGLE_SELECTION_LIST,
uint32 resizingMode
= B_FOLLOW_LEFT
| B_FOLLOW_TOP,
uint32 flags
= B_WILL_DRAW
| B_NAVIGABLE
| B_FRAME_EVENTS );
virtual ~DragSortableListView();
// BListView
virtual void Draw( BRect updateRect );
virtual bool InitiateDrag( BPoint point, int32 index,
bool wasSelected );
virtual void MessageReceived( BMessage* message );
virtual void MouseMoved( BPoint where, uint32 transit,
const BMessage* dragMessage );
virtual void MouseUp( BPoint where );
virtual void WindowActivated( bool active );
virtual void DrawItem( BListItem *item, BRect itemFrame,
bool complete = false);
// DragSortableListView
virtual BListItem* CloneItem( int32 atIndex ) const = 0;
virtual void DrawListItem( BView* owner, int32 index,
BRect itemFrame ) const = 0;
virtual void MakeDragMessage( BMessage* message ) const = 0;
private:
int32 fDropIndex;
};
// PlaylistView
class PlaylistView : public DragSortableListView
{
public:
PlaylistView( BRect frame,
InterfaceWindow* mainWindow );
~PlaylistView();
// BListView
virtual void AttachedToWindow();
virtual void MouseDown( BPoint where );
virtual void KeyDown( const char* bytes, int32 numBytes );
virtual void Pulse();
// DragSortableListView
virtual BListItem* CloneItem( int32 atIndex ) const;
virtual void DrawListItem( BView* owner, int32 index,
BRect itemFrame ) const;
virtual void MakeDragMessage( BMessage* message ) const;
// PlaylistView
void SetCurrent( int32 index );
void SetPlaying( bool playing );
private:
int32 fCurrentIndex;
bool fPlaying;
InterfaceWindow* fMainWindow;
};
#endif // LIST_VIEWS_H
......@@ -2,9 +2,10 @@
* MediaControlView.cpp: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: MediaControlView.cpp,v 1.2 2002/09/18 11:50:47 tcastley Exp $
* $Id: MediaControlView.cpp,v 1.3 2002/09/30 18:30:27 titer Exp $
*
* Authors: Tony Castley <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -31,48 +32,77 @@
#include <vlc/intf.h>
/* BeOS interface headers */
#include "MsgVals.h"
#include "VlcWrapper.h"
#include "Bitmaps.h"
#include "DrawingTidbits.h"
#include "InterfaceWindow.h"
#include "MsgVals.h"
#include "TransportButton.h"
#include "ListViews.h"
#include "MediaControlView.h"
#define BORDER_INSET 6.0
#define MIN_SPACE 4.0
#define SPEAKER_SLIDER_DIST 6.0
#define VOLUME_MIN_WIDTH 70.0
#define DIM_LEVEL 0.4
#define VOLUME_SLIDER_LAYOUT_WEIGHT 2.0
#define SEEK_SLIDER_KNOB_WIDTH 8.0
MediaControlView::MediaControlView( BRect frame )
: BBox( frame, NULL, B_FOLLOW_ALL, B_WILL_DRAW, B_PLAIN_BORDER )
{
float xStart = HORZ_SPACE;
float yStart = VERT_SPACE;
fScrubSem = B_ERROR;
// slider colors are hardcoded here, because that's just
// what they currently are within those bitmaps
const rgb_color kGreen = (rgb_color){ 152, 203, 152, 255 };
const rgb_color kGreenShadow = (rgb_color){ 102, 152, 102, 255 };
const rgb_color kBackground = (rgb_color){ 216, 216, 216, 255 };
const rgb_color kSeekGreen = (rgb_color){ 171, 221, 161, 255 };
const rgb_color kSeekGreenShadow = (rgb_color){ 144, 186, 136, 255 };
const rgb_color kSeekRed = (rgb_color){ 255, 0, 0, 255 };
const rgb_color kSeekRedLight = (rgb_color){ 255, 152, 152, 255 };
const rgb_color kSeekRedShadow = (rgb_color){ 178, 0, 0, 255 };
BRect controlRect = BRect(xStart,yStart,
frame.Width() - (HORZ_SPACE * 2), 15);
const char* kDisabledSeekMessage = "Drop files to play";
/* Seek Status */
rgb_color fill_color = {0,255,0};
p_seek = new SeekSlider(controlRect, this, 0, 100, B_TRIANGLE_THUMB);
p_seek->SetValue(0);
p_seek->UseFillColor(true, &fill_color);
AddChild( p_seek );
yStart += 15 + VERT_SPACE;
enum
{
MSG_REWIND = 'rwnd',
MSG_FORWARD = 'frwd',
MSG_SKIP_BACKWARDS = 'skpb',
MSG_SKIP_FORWARD = 'skpf',
};
// constructor
MediaControlView::MediaControlView(BRect frame)
: BBox(frame, NULL, B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS | B_PULSE_NEEDED,
B_PLAIN_BORDER),
fScrubSem(B_ERROR),
fCurrentRate(DEFAULT_RATE),
fCurrentStatus(UNDEF_S),
fBottomControlHeight(0.0)
{
BRect frame(0.0, 0.0, 10.0, 10.0);
// Seek Slider
fSeekSlider = new SeekSlider(frame, "seek slider", this, 0, 2047);
fSeekSlider->SetValue(0);
fSeekSlider->ResizeToPreferred();
AddChild( fSeekSlider );
/* Buttons */
/* Slow play */
controlRect.SetLeftTop(BPoint(xStart, yStart));
controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
xStart += kRewindBitmapWidth;
p_slow = new TransportButton(controlRect, B_EMPTY_STRING,
// Buttons
// Skip Back
frame.SetRightBottom(kSkipButtonSize);
fBottomControlHeight = kRewindBitmapHeight - 1.0;
fSkipBack = new TransportButton(frame, B_EMPTY_STRING,
kSkipBackBitmapBits,
kPressedSkipBackBitmapBits,
kDisabledSkipBackBitmapBits,
new BMessage(SLOWER_PLAY));
AddChild( p_slow );
/* Play Pause */
controlRect.SetLeftTop(BPoint(xStart, yStart));
controlRect.SetRightBottom(controlRect.LeftTop() + kPlayButtonSize);
xStart += kPlayPauseBitmapWidth + 1.0;
p_play = new PlayPauseButton(controlRect, B_EMPTY_STRING,
new BMessage(MSG_SKIP_BACKWARDS));
AddChild( fSkipBack );
// Play Pause
frame.SetRightBottom(kPlayButtonSize);
if (fBottomControlHeight < kPlayPauseBitmapHeight - 1.0)
fBottomControlHeight = kPlayPauseBitmapHeight - 1.0;
fPlayPause = new PlayPauseButton(frame, B_EMPTY_STRING,
kPlayButtonBitmapBits,
kPressedPlayButtonBitmapBits,
kDisabledPlayButtonBitmapBits,
......@@ -82,206 +112,992 @@ MediaControlView::MediaControlView( BRect frame )
kPressedPausedPlayButtonBitmapBits,
new BMessage(START_PLAYBACK));
AddChild( p_play );
AddChild( fPlayPause );
/* Fast Foward */
controlRect.SetLeftTop(BPoint(xStart, yStart));
controlRect.SetRightBottom(controlRect.LeftTop() + kSkipButtonSize);
xStart += kRewindBitmapWidth;
p_fast = new TransportButton(controlRect, B_EMPTY_STRING,
// Skip Foward
frame.SetRightBottom(kSkipButtonSize);
fSkipForward = new TransportButton(frame, 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,
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( p_stop );
controlRect.SetLeftTop(BPoint(xStart + 5, yStart + 6));
controlRect.SetRightBottom(controlRect.LeftTop() + kSpeakerButtonSize);
xStart += kSpeakerIconBitmapWidth;
AddChild( fStop );
p_mute = new TransportButton(controlRect, B_EMPTY_STRING,
// 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( p_mute );
/* Volume Slider */
p_vol = new MediaSlider(BRect(xStart,20,255,30), new BMessage(VOLUME_CHG),
AOUT_VOLUME_MIN, AOUT_VOLUME_MAX);
p_vol->SetValue(AOUT_VOLUME_DEFAULT);
p_vol->UseFillColor(true, &fill_color);
AddChild( p_vol );
AddChild( fMute );
// Volume Slider
fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
kVolumeSliderBitmapHeight - 1.0),
"volume slider", 1, AOUT_VOLUME_MAX,
new BMessage(VOLUME_CHG));
fVolumeSlider->SetValue(AOUT_VOLUME_DEFAULT);
AddChild( fVolumeSlider );
}
// destructor
MediaControlView::~MediaControlView()
{
}
void MediaControlView::MessageReceived(BMessage *message)
// AttachedToWindow
void
MediaControlView::AttachedToWindow()
{
// we are now a valid BHandler
fRewind->SetTarget(this);
fForward->SetTarget(this);
fSkipBack->SetTarget(this);
fSkipForward->SetTarget(this);
fVolumeSlider->SetTarget(Window());
BRect r(_MinFrame());
if (BMenuBar* menuBar = Window()->KeyMenuBar())
r.bottom += menuBar->Bounds().Height();
Window()->SetSizeLimits(r.Width(), r.Width() * 2.0, r.Height(), r.Height() * 2.0);
if (!Window()->Bounds().Contains(r))
Window()->ResizeTo(r.Width(), r.Height());
else
FrameResized(Bounds().Width(), Bounds().Height());
// get pulse message every two frames
Window()->SetPulseRate(80000);
}
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(NAVIGATE_PREV);
break;
case MSG_SKIP_FORWARD:
Window()->PostMessage(NAVIGATE_NEXT);
break;
default:
BBox::MessageReceived(message);
break;
}
}
// Pulse
void
MediaControlView::Pulse()
{
InterfaceWindow* window = dynamic_cast<InterfaceWindow*>(Window());
if (window && window->IsStopped())
fPlayPause->SetStopped();
}
// SetProgress
void
MediaControlView::SetProgress(uint64 seek, uint64 size)
{
fSeekSlider->SetPosition((float)seek / (float)size);
}
// SetStatus
void
MediaControlView::SetStatus(int status, int rate)
{
// we need to set the button status periodically
// (even if it is the same) to get a blinking button
fCurrentStatus = status;
switch( status )
{
case PLAYING_S:
case FORWARD_S:
case BACKWARD_S:
case START_S:
p_play->SetPlaying();
fPlayPause->SetPlaying();
break;
case PAUSE_S:
p_play->SetPaused();
fPlayPause->SetPaused();
break;
case UNDEF_S:
case NOT_STARTED_S:
default:
p_play->SetStopped();
fPlayPause->SetStopped();
break;
}
if (rate != fCurrentRate)
{
fCurrentRate = rate;
if ( rate < DEFAULT_RATE )
{
// TODO: ...
}
}
}
void MediaControlView::SetEnabled(bool enabled)
// SetEnabled
void
MediaControlView::SetEnabled(bool enabled)
{
p_slow->SetEnabled(enabled);
p_play->SetEnabled(enabled);
p_fast->SetEnabled(enabled);
p_stop->SetEnabled(enabled);
p_mute->SetEnabled(enabled);
p_vol->SetEnabled(enabled);
p_seek->SetEnabled(enabled);
fSkipBack->SetEnabled(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);
}
uint32 MediaControlView::GetSeekTo()
// SetAudioEnabled
void
MediaControlView::SetAudioEnabled(bool enabled)
{
return p_seek->seekTo;
fMute->SetEnabled(enabled);
fVolumeSlider->SetEnabled(enabled);
}
uint32 MediaControlView::GetVolume()
// GetSeekTo
uint32
MediaControlView::GetSeekTo() const
{
return p_vol->Value();
return fSeekSlider->Value();
}
// GetVolume
uint32
MediaControlView::GetVolume() const
{
return fVolumeSlider->Value();
}
/*****************************************************************************
* MediaSlider
*****************************************************************************/
MediaSlider::MediaSlider( BRect frame, BMessage *p_message,
int32 i_min, int32 i_max )
:BSlider(frame, NULL, NULL, p_message, i_min, i_max )
// SetSkippable
void
MediaControlView::SetSkippable(bool backward, bool forward)
{
fSkipBack->SetEnabled(backward);
fSkipForward->SetEnabled(forward);
}
// SetMuted
void
MediaControlView::SetMuted(bool mute)
{
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);
}
MediaSlider::~MediaSlider()
// _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);
}
void MediaSlider::DrawThumb(void)
// _LayoutControl
void
MediaControlView::_LayoutControl(BView* view, BRect frame, bool resize) const
{
BRect r;
BView *v;
// 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());
}
rgb_color black = {0,0,0};
r = ThumbFrame();
v = OffscreenView();
if(IsEnabled())
/*****************************************************************************
* SeekSlider
*****************************************************************************/
SeekSlider::SeekSlider(BRect frame, const char* name, MediaControlView *owner,
int32 minValue, int32 maxValue)
: BControl(frame, name, NULL, NULL, B_FOLLOW_NONE,
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fOwner(owner),
fTracking(false),
fMinValue(minValue),
fMaxValue(maxValue)
{
BFont font(be_plain_font);
font.SetSize(9.0);
SetFont(&font);
}
SeekSlider::~SeekSlider()
{
_EndSeek();
}
/*****************************************************************************
* 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++)
{
v->SetHighColor(black);
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
{
v->SetHighColor(tint_color(black, B_LIGHTEN_2_TINT));
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));
}
}
r.InsetBy(r.IntegerWidth()/4, r.IntegerHeight()/(4 * r.IntegerWidth() / r.IntegerHeight()));
v->StrokeEllipse(r);
/*****************************************************************************
* SeekSlider::MouseDown
*****************************************************************************/
void
SeekSlider::MouseDown(BPoint where)
{
if (IsEnabled() && Bounds().Contains(where))
{
SetValue(_ValueFor(where.x));
fTracking = true;
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
_BeginSeek();
}
}
if(IsEnabled())
/*****************************************************************************
* SeekSlider::MouseMoved
*****************************************************************************/
void
SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
{
if (fTracking)
{
v->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetValue(_ValueFor(where.x));
_Seek();
}
else
}
/*****************************************************************************
* SeekSlider::MouseUp
*****************************************************************************/
void
SeekSlider::MouseUp(BPoint where)
{
if (fTracking)
{
v->SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), B_LIGHTEN_2_TINT));
fTracking = false;
_EndSeek();
}
}
r.InsetBy(1,1);
v->FillEllipse(r);
/*****************************************************************************
* SeekSlider::ResizeToPreferred
*****************************************************************************/
void
SeekSlider::ResizeToPreferred()
{
float width = 15.0 + StringWidth(kDisabledSeekMessage) + 15.0;
ResizeTo(width, 17.0);
}
/*****************************************************************************
* SeekSlider
* SeekSlider::SetPosition
*****************************************************************************/
SeekSlider::SeekSlider( BRect frame, MediaControlView *p_owner, int32 i_min,
int32 i_max, thumb_style thumbType = B_TRIANGLE_THUMB )
:MediaSlider( frame, NULL, i_min, i_max )
void
SeekSlider::SetPosition(float position)
{
fOwner = p_owner;
fMouseDown = false;
SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5));
}
SeekSlider::~SeekSlider()
/*****************************************************************************
* 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::MouseDown
* SeekSlider::_StrokeFrame
*****************************************************************************/
void
SeekSlider::_StrokeFrame(BRect r, rgb_color left, rgb_color top,
rgb_color right, rgb_color bottom)
{
BeginLineArray(4);
AddLine(BPoint(r.left, r.bottom), BPoint(r.left, r.top), left);
AddLine(BPoint(r.left + 1.0, r.top), BPoint(r.right, r.top), top);
AddLine(BPoint(r.right, r.top + 1.0), BPoint(r.right, r.bottom), right);
AddLine(BPoint(r.right - 1.0, r.bottom), BPoint(r.left + 1.0, r.bottom), bottom);
EndLineArray();
}
/*****************************************************************************
* SeekSlider::_BeginSeek
*****************************************************************************/
void SeekSlider::MouseDown(BPoint where)
void
SeekSlider::_BeginSeek()
{
BSlider::MouseDown(where);
seekTo = ValueForPoint(where);
fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
if (fOwner->fScrubSem >= B_OK)
release_sem(fOwner->fScrubSem);
fMouseDown = true;
}
/*****************************************************************************
* SeekSlider::MouseUp
* SeekSlider::_Seek
*****************************************************************************/
void SeekSlider::MouseMoved(BPoint where, uint32 code, const BMessage *message)
void
SeekSlider::_Seek()
{
BSlider::MouseMoved(where, code, message);
if (!fMouseDown)
return;
seekTo = ValueForPoint(where);
if (fOwner->fScrubSem >= B_OK)
delete_sem(fOwner->fScrubSem);
fOwner->fScrubSem = create_sem(0, "Vlc::fScrubSem");
if (fOwner->fScrubSem >= B_OK)
release_sem(fOwner->fScrubSem);
}
/*****************************************************************************
* SeekSlider::MouseUp
* SeekSlider::_EndSeek
*****************************************************************************/
void SeekSlider::MouseUp(BPoint where)
void
SeekSlider::_EndSeek()
{
BSlider::MouseUp(where);
seekTo = ValueForPoint(where);
if (fOwner->fScrubSem >= B_OK)
delete_sem(fOwner->fScrubSem);
fOwner->fScrubSem = B_ERROR;
fMouseDown = false;
}
/*****************************************************************************
* VolumeSlider
*****************************************************************************/
VolumeSlider::VolumeSlider(BRect frame, const char* name, int32 minValue, int32 maxValue,
BMessage* message, BHandler* target)
: BControl(frame, name, NULL, message, B_FOLLOW_NONE,
B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
fLeftSideBits(NULL),
fRightSideBits(NULL),
fKnobBits(NULL),
fTracking(false),
fMuted(false),
fMinValue(minValue),
fMaxValue(maxValue)
{
SetTarget(target);
// create bitmaps
BRect r(BPoint(0.0, 0.0), kVolumeSliderBitmapSize);
fLeftSideBits = new BBitmap(r, B_CMAP8);
fRightSideBits = new BBitmap(r, B_CMAP8);
r.Set(0.0, 0.0, kVolumeSliderKnobBitmapSize.x, kVolumeSliderKnobBitmapSize.y);
fKnobBits = new BBitmap(r, B_CMAP8);
_MakeBitmaps();
}
/*****************************************************************************
* VolumeSlider destructor
*****************************************************************************/
VolumeSlider::~VolumeSlider()
{
delete fLeftSideBits;
delete fRightSideBits;
delete fKnobBits;
}
/*****************************************************************************
* VolumeSlider::AttachedToWindow
*****************************************************************************/
void
VolumeSlider::AttachedToWindow()
{
BControl::AttachedToWindow();
SetViewColor(B_TRANSPARENT_32_BIT);
}
/*****************************************************************************
* VolumeSlider::SetValue
*****************************************************************************/
void
VolumeSlider::SetValue(int32 value)
{
if (value != Value())
{
BControl::SetValue(value);
Invoke();
}
}
/*****************************************************************************
* VolumeSlider::SetEnabled
*****************************************************************************/
void
VolumeSlider::SetEnabled(bool enable)
{
if (enable != IsEnabled())
{
BControl::SetEnabled(enable);
_MakeBitmaps();
Invalidate();
}
}
/*****************************************************************************
* VolumeSlider::Draw
*****************************************************************************/
void
VolumeSlider::Draw(BRect updateRect)
{
if (IsValid())
{
BRect r(Bounds());
float sliderSideWidth = kVolumeSliderBitmapWidth;
float sliderStart = (r.left + sliderSideWidth);
float sliderEnd = (r.right - sliderSideWidth);
float knobPos = sliderStart
+ (sliderEnd - sliderStart - 1.0) * (Value() - fMinValue)
/ (fMaxValue - fMinValue);
// draw both sides (the original from Be doesn't seem
// to make a difference for enabled/disabled state)
DrawBitmapAsync(fLeftSideBits, r.LeftTop());
DrawBitmapAsync(fRightSideBits, BPoint(sliderEnd + 1.0, r.top));
// colors for the slider area between the two bitmaps
rgb_color background = kBackground;//ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color shadow = tint_color(background, B_DARKEN_2_TINT);
rgb_color softShadow = tint_color(background, B_DARKEN_1_TINT);
rgb_color darkShadow = tint_color(background, B_DARKEN_4_TINT);
rgb_color midShadow = tint_color(background, B_DARKEN_3_TINT);
rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT);
rgb_color softLight = tint_color(background, B_LIGHTEN_1_TINT);
rgb_color green = kGreen;
rgb_color greenShadow = kGreenShadow;
rgb_color black = kBlack;
rgb_color dotGrey = midShadow;
rgb_color dotGreen = greenShadow;
// make dimmed version of colors if we're disabled
if (!IsEnabled())
{
shadow = (rgb_color){ 200, 200, 200, 255 };
softShadow = dimmed_color_cmap8(softShadow, background, DIM_LEVEL);
darkShadow = dimmed_color_cmap8(darkShadow, background, DIM_LEVEL);
midShadow = shadow;
light = dimmed_color_cmap8(light, background, DIM_LEVEL);
softLight = dimmed_color_cmap8(softLight, background, DIM_LEVEL);
green = dimmed_color_cmap8(green, background, DIM_LEVEL);
greenShadow = dimmed_color_cmap8(greenShadow, background, DIM_LEVEL);
black = dimmed_color_cmap8(black, background, DIM_LEVEL);
dotGreen = dotGrey;
}
else if (fMuted)
{
green = tint_color(kBackground, B_DARKEN_3_TINT);
greenShadow = tint_color(kBackground, B_DARKEN_4_TINT);
dotGreen = greenShadow;
}
// draw slider edges between bitmaps
BeginLineArray(7);
AddLine(BPoint(sliderStart, r.top),
BPoint(sliderEnd, r.top), softShadow);
AddLine(BPoint(sliderStart, r.bottom),
BPoint(sliderEnd, r.bottom), softLight);
r.InsetBy(0.0, 1.0);
AddLine(BPoint(sliderStart, r.top),
BPoint(sliderEnd, r.top), black);
AddLine(BPoint(sliderStart, r.bottom),
BPoint(sliderEnd, r.bottom), light);
r.top++;
AddLine(BPoint(sliderStart, r.top),
BPoint(knobPos, r.top), greenShadow);
AddLine(BPoint(knobPos, r.top),
BPoint(sliderEnd, r.top), midShadow);
r.top++;
AddLine(BPoint(sliderStart, r.top),
BPoint(knobPos, r.top), greenShadow);
EndLineArray();
// fill rest inside of slider
r.InsetBy(0.0, 1.0);
r.left = sliderStart;
r.right = knobPos;
SetHighColor(green);
FillRect(r, B_SOLID_HIGH);
r.left = knobPos + 1.0;
r.right = sliderEnd;
r.top -= 1.0;
SetHighColor(shadow);
FillRect(r, B_SOLID_HIGH);
// draw little dots inside
int32 dotCount = (int32)((sliderEnd - sliderStart) / 5.0);
BPoint dotPos;
dotPos.y = r.top + 4.0;
for (int32 i = 0; i < dotCount; i++)
{
dotPos.x = sliderStart + i * 5.0 + 4.0;
SetHighColor(dotPos.x < knobPos ? dotGreen : dotGrey);
StrokeLine(dotPos, BPoint(dotPos.x, dotPos.y + 1.0));
}
// draw knob
r.top -= 1.0;
SetDrawingMode(B_OP_OVER); // part of knob is transparent
DrawBitmapAsync(fKnobBits, BPoint(knobPos - kVolumeSliderKnobWidth / 2, r.top));
}
else
fprintf(stderr, "VolumeSlider::Draw() - Error: no valid bitmaps!");
}
/*****************************************************************************
* VolumeSlider::MouseDown
*****************************************************************************/
void
VolumeSlider::MouseDown(BPoint where)
{
if (Bounds().Contains(where) && IsEnabled())
{
fTracking = true;
SetValue(_ValueFor(where.x));
SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
}
}
/*****************************************************************************
* VolumeSlider::MouseMoved
*****************************************************************************/
void
VolumeSlider::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage)
{
if (fTracking)
SetValue(_ValueFor(where.x));
}
/*****************************************************************************
* VolumeSlider::MouseUp
*****************************************************************************/
void
VolumeSlider::MouseUp(BPoint where)
{
fTracking = false;
}
/*****************************************************************************
* VolumeSlider::IsValid
*****************************************************************************/
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 @@
* MediaControlView.h: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: MediaControlView.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: MediaControlView.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Tony Castley <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -20,73 +21,148 @@
* along with this program; if not, write to the Free Software
* 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 MediaSlider;
class SeekSlider;
class TransportButton;
class VolumeSlider;
class MediaControlView : public BBox
{
public:
public:
MediaControlView( BRect frame );
~MediaControlView();
virtual ~MediaControlView();
// BBox
virtual void AttachedToWindow();
virtual void FrameResized(float width, float height);
virtual void GetPreferredSize(float* width, float* height);
virtual void MessageReceived(BMessage* message);
virtual void Pulse(); // detect stopped stream
virtual void MessageReceived(BMessage *message);
// MediaControlView
void SetProgress(uint64 seek, uint64 size);
void SetStatus(int status, int rate);
void SetEnabled(bool);
uint32 GetSeekTo();
uint32 GetVolume();
void SetEnabled(bool enable);
void SetAudioEnabled(bool enable);
uint32 GetSeekTo() const;
uint32 GetVolume() const;
void SetSkippable(bool backward,
bool forward);
void SetMuted(bool mute);
sem_id fScrubSem;
bool fSeeking;
private:
MediaSlider * p_vol;
SeekSlider * p_seek;
TransportButton* p_slow;
PlayPauseButton* p_play;
TransportButton* p_fast;
TransportButton* p_stop;
TransportButton* p_mute;
int current_rate;
int current_status;
private:
void _LayoutControls(BRect frame) const;
BRect _MinFrame() const;
void _LayoutControl(BView* view,
BRect frame,
bool resize = false) const;
VolumeSlider* fVolumeSlider;
SeekSlider* fSeekSlider;
TransportButton* fSkipBack;
TransportButton* fSkipForward;
TransportButton* fRewind;
TransportButton* fForward;
PlayPauseButton* fPlayPause;
TransportButton* fStop;
TransportButton* fMute;
int fCurrentRate;
int fCurrentStatus;
float fBottomControlHeight;
BRect fOldBounds;
};
class MediaSlider : public BSlider
class SeekSlider : public BControl
{
public:
MediaSlider(BRect frame,
BMessage *message,
public:
SeekSlider(BRect frame,
const char* name,
MediaControlView* owner,
int32 minValue,
int32 maxValue);
~MediaSlider();
virtual void DrawThumb(void);
};
virtual ~SeekSlider();
class SeekSlider : public MediaSlider
{
public:
SeekSlider(BRect frame,
MediaControlView *owner,
int32 minValue,
int32 maxValue,
thumb_style thumbType = B_TRIANGLE_THUMB);
// BControl
virtual void AttachedToWindow();
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);
~SeekSlider();
uint32 seekTo;
virtual void MouseDown(BPoint);
virtual void MouseUp(BPoint pt);
virtual void MouseMoved(BPoint pt, uint32 c, const BMessage *m);
private:
int32 _ValueFor(float x) const;
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 fMouseDown;
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
......@@ -4,6 +4,7 @@ SOURCES_beos = \
modules/gui/beos/VideoOutput.cpp \
modules/gui/beos/Interface.cpp \
modules/gui/beos/InterfaceWindow.cpp \
modules/gui/beos/ListViews.cpp \
modules/gui/beos/DrawingTidbits.cpp \
modules/gui/beos/TransportButton.cpp \
modules/gui/beos/PlayListWindow.cpp \
......@@ -14,6 +15,7 @@ noinst_HEADERS += \
modules/gui/beos/Bitmaps.h \
modules/gui/beos/DrawingTidbits.h \
modules/gui/beos/InterfaceWindow.h \
modules/gui/beos/ListViews.h \
modules/gui/beos/MediaControlView.h \
modules/gui/beos/MsgVals.h \
modules/gui/beos/PlayListWindow.h \
......
......@@ -2,9 +2,10 @@
* MsgVals.h
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: MsgVals.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: MsgVals.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* 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
* it under the terms of the GNU General Public License as published by
......@@ -21,32 +22,47 @@
* 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 PAUSED 1
const uint32 OPEN_FILE = 'OPFL';
const uint32 OPEN_DVD = 'OPDV';
const uint32 OPEN_PLAYLIST = 'OPPL';
const uint32 STOP_PLAYBACK = 'STPL';
const uint32 START_PLAYBACK = 'PLAY';
const uint32 PAUSE_PLAYBACK = 'PAPL';
const uint32 FASTER_PLAY = 'FAPL';
const uint32 SLOWER_PLAY = 'SLPL';
const uint32 SEEK_PLAYBACK = 'SEEK';
const uint32 VOLUME_CHG = 'VOCH';
const uint32 VOLUME_MUTE = 'MUTE';
const uint32 SELECT_AUDIO = 'AUDI';
const uint32 SELECT_SUBTITLE = 'SUBT';
const uint32 PREV_TITLE = 'PRTI';
const uint32 NEXT_TITLE = 'NXTI';
const uint32 PREV_CHAPTER = 'PRCH';
const uint32 NEXT_CHAPTER = 'NXCH';
const uint32 TOGGLE_ON_TOP = 'ONTP';
const uint32 TOGGLE_FULL_SCREEN = 'TGFS';
const uint32 RESIZE_100 = 'RSOR';
const uint32 RESIZE_200 = 'RSDB';
const uint32 ASPECT_CORRECT = 'ASCO';
const uint32 VERT_SYNC = 'VSYN';
const uint32 WINDOW_FEEL = 'WFEL';
const uint32 OPEN_FILE = 'opfl';
const uint32 OPEN_DVD = 'opdv';
const uint32 OPEN_PLAYLIST = 'oppl';
const uint32 STOP_PLAYBACK = 'stpl';
const uint32 START_PLAYBACK = 'play';
const uint32 PAUSE_PLAYBACK = 'papl';
const uint32 FASTER_PLAY = 'fapl';
const uint32 SLOWER_PLAY = 'slpl';
const uint32 NORMAL_PLAY = 'nrpl';
const uint32 SEEK_PLAYBACK = 'seek';
const uint32 VOLUME_CHG = 'voch';
const uint32 VOLUME_MUTE = 'mute';
const uint32 SELECT_CHANNEL = 'chan';
const uint32 SELECT_SUBTITLE = 'subt';
const uint32 PREV_TITLE = 'prti';
const uint32 NEXT_TITLE = 'nxti';
const uint32 TOGGLE_TITLE = 'tgti';
const uint32 PREV_CHAPTER = 'prch';
const uint32 NEXT_CHAPTER = 'nxch';
const uint32 TOGGLE_CHAPTER = 'tgch';
const uint32 PREV_FILE = 'prfl';
const uint32 NEXT_FILE = 'nxfl';
const uint32 NAVIGATE_PREV = 'navp'; // could be chapter, title or file
const uint32 NAVIGATE_NEXT = 'navn'; // could be chapter, title or file
const uint32 TOGGLE_ON_TOP = 'ontp';
const uint32 TOGGLE_FULL_SCREEN = 'tgfs';
const uint32 RESIZE_50 = 'rshl';
const uint32 RESIZE_100 = 'rsor';
const uint32 RESIZE_200 = 'rsdb';
const uint32 RESIZE_TRUE = 'rstr';
const uint32 ASPECT_CORRECT = 'asco';
const uint32 VERT_SYNC = 'vsyn';
const uint32 WINDOW_FEEL = 'wfel';
const uint32 SCREEN_SHOT = 'scrn';
const uint32 INTERFACE_CREATED = 'ifcr'; /* see VlcApplication::MessageReceived()
* in src/misc/beos_specific.cpp */
#endif // BEOS_MESSAGE_VALUES_H
......@@ -2,12 +2,13 @@
* PlayListWindow.cpp: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: PlayListWindow.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: PlayListWindow.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Tony Castley <tony@castley.net>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -27,7 +28,6 @@
/* System headers */
#include <InterfaceKit.h>
#include <StorageKit.h>
#include <SupportKit.h>
#include <string.h>
/* VLC headers */
......@@ -37,118 +37,161 @@
/* BeOS interface headers */
#include "VlcWrapper.h"
#include "InterfaceWindow.h"
#include "ListViews.h"
#include "MsgVals.h"
#include "PlayListWindow.h"
/*****************************************************************************
* PlayListWindow
*****************************************************************************/
PlayListWindow *PlayListWindow::getPlayList( BRect frame, const char *name,
playlist_t *p_pl)
enum
{
static PlayListWindow *one_playlist;
if (one_playlist == NULL)
{
one_playlist = new PlayListWindow(frame, name, p_pl);
}
return one_playlist;
}
MSG_SELECT_ALL = 'sall',
MSG_SELECT_NONE = 'none',
MSG_RANDOMIZE = 'rndm',
MSG_SORT_NAME = 'srtn',
MSG_SORT_PATH = 'srtp',
MSG_REMOVE = 'rmov',
MSG_REMOVE_ALL = 'rmal',
};
PlayListWindow::PlayListWindow( BRect frame, const char *name,
playlist_t *p_pl)
/*****************************************************************************
* PlayListWindow::PlayListWindow
*****************************************************************************/
PlayListWindow::PlayListWindow( BRect frame, const char* name,
playlist_t *playlist,
InterfaceWindow* mainWindow )
: BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS )
B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
fPlaylist( playlist ),
fMainWindow( mainWindow )
{
SetName( "playlist" );
SetTitle(name);
p_playlist = p_pl;
/* set up the main menu */
BMenuBar *menu_bar;
menu_bar = new BMenuBar(BRect(0,0,0,0), "main menu");
AddChild( menu_bar );
BMenu *mFile;
/* Add the file Menu */
BMenuItem *mItem;
menu_bar->AddItem( mFile = new BMenu( "File" ) );
menu_bar->ResizeToPreferred();
mFile->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
new BMessage(OPEN_FILE), 'O') );
CDMenu *cd_menu = new CDMenu( "Open Disc" );
mFile->AddItem( cd_menu );
BRect rect = Bounds();
rect.top += menu_bar->Bounds().IntegerHeight() + 1;
BView *p_view = new BView(rect, NULL, B_FOLLOW_ALL_SIDES, B_WILL_DRAW);
p_listview = new BListView(rect, "PlayList",
B_MULTIPLE_SELECTION_LIST);
for (int i=0; i < p_playlist->i_size; i++)
{
p_listview->AddItem(new BStringItem(p_playlist->pp_items[i]->psz_name));
}
p_view->AddChild(new BScrollView("scroll_playlist", p_listview,
B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true));
AddChild(p_view);
// set up the main menu bar
fMenuBar = new BMenuBar( BRect(0.0, 0.0, frame.Width(), 15.0), "main menu",
B_FOLLOW_NONE, B_ITEMS_IN_ROW, false );
AddChild( fMenuBar );
// Add the File menu
BMenu *fileMenu = new BMenu( "File" );
fMenuBar->AddItem( fileMenu );
BMenuItem* item = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
new BMessage( OPEN_FILE ), 'O' );
item->SetTarget( fMainWindow );
fileMenu->AddItem( item );
CDMenu* cd_menu = new CDMenu( "Open Disc" );
fileMenu->AddItem( cd_menu );
fileMenu->AddSeparatorItem();
item = new BMenuItem( "Close",
new BMessage( B_QUIT_REQUESTED ), 'W' );
fileMenu->AddItem( item );
// Add the Edit menu
BMenu *editMenu = new BMenu( "Edit" );
fMenuBar->AddItem( editMenu );
item = new BMenuItem( "Select All",
new BMessage( MSG_SELECT_ALL ), 'A' );
editMenu->AddItem( item );
item = new BMenuItem( "Select None",
new BMessage( MSG_SELECT_NONE ), 'A', B_SHIFT_KEY );
editMenu->AddItem( item );
editMenu->AddSeparatorItem();
item = new BMenuItem( "Sort by Name",
new BMessage( MSG_SORT_NAME ), 'N' );
editMenu->AddItem( item );
item = new BMenuItem( "Sort by Path",
new BMessage( MSG_SORT_PATH ), 'P' );
editMenu->AddItem( item );
item = new BMenuItem( "Randomize",
new BMessage( MSG_RANDOMIZE ), 'R' );
editMenu->AddItem( item );
editMenu->AddSeparatorItem();
item = new BMenuItem( "Remove",
new BMessage( MSG_REMOVE ) );
editMenu->AddItem( item );
item = new BMenuItem( "Remove All",
new BMessage( MSG_REMOVE_ALL ) );
editMenu->AddItem( item );
editMenu->SetEnabled( false );
// make menu bar resize to correct height
float menuWidth, menuHeight;
fMenuBar->GetPreferredSize( &menuWidth, &menuHeight );
// don't change next line! it's a workarround!
fMenuBar->ResizeTo( frame.Width(), menuHeight );
frame = Bounds();
frame.top += fMenuBar->Bounds().IntegerHeight() + 1;
frame.right -= B_V_SCROLL_BAR_WIDTH;
fListView = new PlaylistView( frame, fMainWindow );
fBackgroundView = new BScrollView( "playlist scrollview",
fListView, B_FOLLOW_ALL_SIDES,
0, false, true,
B_NO_BORDER );
AddChild( fBackgroundView );
// be up to date
UpdatePlaylist();
FrameResized( Bounds().Width(), Bounds().Height() );
SetSizeLimits( menuWidth * 2.0, menuWidth * 6.0,
menuHeight * 5.0, menuHeight * 25.0 );
UpdatePlaylist( true );
// start window thread in hidden state
Hide();
Show();
}
/*****************************************************************************
* PlayListWindow::~PlayListWindow
*****************************************************************************/
PlayListWindow::~PlayListWindow()
{
}
/*****************************************************************************
* PlayListWindow::MessageReceived
* PlayListWindow::QuitRequested
*****************************************************************************/
void PlayListWindow::MessageReceived( BMessage * p_message )
bool
PlayListWindow::QuitRequested()
{
Activate();
Hide();
return false;
}
switch( p_message->what )
{
case OPEN_FILE:
if( file_panel )
/*****************************************************************************
* PlayListWindow::MessageReceived
*****************************************************************************/
void
PlayListWindow::MessageReceived( BMessage * p_message )
{
switch ( p_message->what )
{
file_panel->Show();
break;
}
file_panel = new BFilePanel();
file_panel->SetTarget( this );
file_panel->Show();
break;
case OPEN_DVD:
{
const char *psz_device;
BString type("dvd");
if( p_message->FindString("device", &psz_device) != B_ERROR )
{
BString device(psz_device);
// p_vlc_wrapper->openDisc(type, device, 0,0);
p_listview->AddItem(new BStringItem(psz_device));
}
}
break;
case B_REFS_RECEIVED:
case B_SIMPLE_DATA:
{
entry_ref ref;
BList* files = new BList();
int i = 0;
while( p_message->FindRef( "refs", i, &ref ) == B_OK )
{
BPath path( &ref );
files->AddItem(new BString((char*)path.Path()) );
p_listview->AddItem(new BStringItem((char*)path.Path()));
i++;
}
// p_vlc_wrapper->openFiles(files);
delete files;
}
// forward to interface window
fMainWindow->PostMessage( p_message );
break;
case MSG_SELECT_ALL:
break;
case MSG_SELECT_NONE:
break;
case MSG_RANDOMIZE:
break;
case MSG_SORT_NAME:
break;
case MSG_SORT_PATH:
break;
case MSG_REMOVE:
break;
case MSG_REMOVE_ALL:
break;
default:
BWindow::MessageReceived( p_message );
......@@ -156,15 +199,50 @@ void PlayListWindow::MessageReceived( BMessage * p_message )
}
}
bool PlayListWindow::QuitRequested()
/*****************************************************************************
* PlayListWindow::FrameResized
*****************************************************************************/
void
PlayListWindow::FrameResized(float width, float height)
{
Hide();
return false;
BRect r(Bounds());
fMenuBar->MoveTo(r.LeftTop());
fMenuBar->ResizeTo(r.Width(), fMenuBar->Bounds().Height());
r.top += fMenuBar->Bounds().Height() + 1.0;
fBackgroundView->MoveTo(r.LeftTop());
// the "+ 1.0" is to make the scrollbar
// be partly covered by the window border
fBackgroundView->ResizeTo(r.Width() + 1.0, r.Height() + 1.0);
}
void PlayListWindow::ReallyQuit()
/*****************************************************************************
* PlayListWindow::ReallyQuit
*****************************************************************************/
void
PlayListWindow::ReallyQuit()
{
Hide();
Lock();
Hide();
Quit();
}
/*****************************************************************************
* PlayListWindow::UpdatePlaylist
*****************************************************************************/
void
PlayListWindow::UpdatePlaylist( bool rebuild )
{
/* if ( rebuild )
{
// remove all items
int32 count = fListView->CountItems();
while ( BListItem* item = fListView->RemoveItem( --count ) )
delete item;
// rebuild listview from VLC's playlist
for ( int i = 0; i < fPlaylist->i_size; i++ )
fListView->AddItem( new PlaylistItem( fPlaylist->p_item[i].psz_name ) );
}
fListView->SetCurrent( fPlaylist->i_index );
fListView->SetPlaying( Intf_VLCWrapper::is_playing() ); */
}
......@@ -2,11 +2,12 @@
* PlayListWindow.h: BeOS interface window class prototype
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: PlayListWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: PlayListWindow.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -22,24 +23,43 @@
* along with this program; if not, write to the Free Software
* 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 BListView;
class CDMenu;
class InterfaceWindow;
class PlaylistView;
class PlayListWindow : public BWindow
{
public:
static PlayListWindow *getPlayList(BRect frame, const char *name,
playlist_t *p_pl);
~PlayListWindow();
bool QuitRequested();
void ReallyQuit();
public:
PlayListWindow(BRect frame,
const char* name,
playlist_t* playlist,
InterfaceWindow* mainWindow );
virtual ~PlayListWindow();
// standard window member
// BWindow
virtual bool QuitRequested();
virtual void MessageReceived(BMessage *message);
virtual void FrameResized(float width, float height);
// PlayListWindow
void ReallyQuit();
void UpdatePlaylist( bool rebuild = false );
private:
private:
PlayListWindow( BRect frame, const char *name, playlist_t *p_pl);
playlist_t *p_playlist;
BListView *p_listview;
BFilePanel *file_panel;
playlist_t* fPlaylist;
PlaylistView* fListView;
BView* fBackgroundView;
BMenuBar* fMenuBar;
InterfaceWindow* fMainWindow;
};
#endif // BEOS_PLAY_LIST_WINDOW_H
......@@ -2,9 +2,10 @@
* TransportButton.cpp
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: TransportButton.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: TransportButton.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* 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
* it under the terms of the GNU General Public License as published by
......@@ -246,10 +247,8 @@ TransportButton::AttachedToWindow()
void
TransportButton::DetachedFromWindow()
{
if (keyPressFilter) {
if (keyPressFilter)
Window()->RemoveCommonFilter(keyPressFilter);
delete keyPressFilter;
}
_inherited::DetachedFromWindow();
}
......@@ -260,6 +259,7 @@ TransportButton::~TransportButton()
delete pressingMessage;
delete donePressingMessage;
delete bitmaps;
delete keyPressFilter;
}
void
......@@ -274,9 +274,11 @@ TransportButton::WindowActivated(bool state)
void
TransportButton::SetEnabled(bool on)
{
if (on != IsEnabled()) {
_inherited::SetEnabled(on);
if (!on)
ShortcutKeyUp();
}
}
const unsigned char *
......@@ -300,11 +302,31 @@ TransportButton::BitsForMask(uint32 mask) const
BBitmap *
TransportButton::MakeBitmap(uint32 mask)
{
BBitmap *result = new BBitmap(Bounds(), B_COLOR_8_BIT);
result->SetBits(BitsForMask(mask), (Bounds().Width() + 1) * (Bounds().Height() + 1),
0, B_COLOR_8_BIT);
BRect r(Bounds());
BBitmap *result = new BBitmap(r, B_CMAP8);
uint8* src = (uint8*)BitsForMask(mask);
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;
}
......
......@@ -2,7 +2,7 @@
* TransportButton.h
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: TransportButton.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: TransportButton.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Tony Castley <tcastley@mail.powerup.com.au>
*
......@@ -180,4 +180,4 @@ private:
typedef TransportButton _inherited;
};
#endif
#endif // __MEDIA_BUTTON__
/*****************************************************************************
* vout.cpp: beos video output display method
* vout_beos.cpp: beos video output display method
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: VideoOutput.cpp,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: VideoOutput.cpp,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Tony Castley <tcastley@mail.powerup.com.au>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -31,11 +32,18 @@
#include <stdlib.h> /* free() */
#include <stdio.h>
#include <string.h> /* strerror() */
#include <InterfaceKit.h>
#include <DirectWindow.h>
#include <Application.h>
#include <BitmapStream.h>
#include <Bitmap.h>
#include <DirectWindow.h>
#include <File.h>
#include <InterfaceKit.h>
#include <NodeInfo.h>
#include <String.h>
#include <TranslatorRoster.h>
/* VLC headers */
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/vout.h>
......@@ -44,7 +52,6 @@
#include "DrawingTidbits.h"
#include "MsgVals.h"
/*****************************************************************************
* vout_sys_t: BeOS video output method descriptor
*****************************************************************************
......@@ -58,14 +65,22 @@ struct vout_sys_t
s32 i_width;
s32 i_height;
// u8 *pp_buffer[3];
u32 source_chroma;
int i_index;
};
#define MOUSE_IDLE_TIMEOUT 2000000 // two seconds
#define MIN_AUTO_VSYNC_REFRESH 61 // Hz
#define DEFAULT_SCREEN_SHOT_FORMAT 'PNG '
#define DEFAULT_SCREEN_SHOT_PATH "/boot/home/vlc screenshot"
/*****************************************************************************
* beos_GetAppWindow : retrieve a BWindow pointer from the window name
*****************************************************************************/
BWindow *beos_GetAppWindow(char *name)
BWindow*
beos_GetAppWindow(char *name)
{
int32 index;
BWindow *window;
......@@ -89,234 +104,386 @@ BWindow *beos_GetAppWindow(char *name)
}
/*****************************************************************************
* VideoWindow constructor and destructor
* get_interface_window
*****************************************************************************/
VideoWindow::VideoWindow( int v_width, int v_height,
BRect frame )
: BWindow( frame, NULL, B_TITLED_WINDOW,
B_NOT_CLOSABLE | B_NOT_MINIMIZABLE )
BWindow*
get_interface_window()
{
BView *mainView = new BView( Bounds(), "mainView",
B_FOLLOW_ALL, B_FULL_UPDATE_ON_RESIZE);
AddChild(mainView);
mainView->SetViewColor(kBlack);
return beos_GetAppWindow(VOUT_TITLE);
}
/* create the view to do the display */
view = new VLCView( Bounds() );
mainView->AddChild(view);
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() {}
/* set the VideoWindow variables */
teardownwindow = false;
is_zoomed = false;
vsync = false;
i_buffer = 0;
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;
};
/* call ScreenChanged to set vsync correctly */
BScreen *screen;
display_mode disp_mode;
float refresh;
/*****************************************************************************
* VideoWindow constructor and destructor
*****************************************************************************/
VideoWindow::VideoWindow(int v_width, int v_height, BRect frame)
: BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE),
i_width(frame.IntegerWidth()),
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)
{
// create the view to do the display
view = new VLCView( Bounds() );
screen = new BScreen(this);
// create background view
BView *mainView = new BackgroundView( Bounds(), view );
AddChild(mainView);
mainView->AddChild(view);
screen-> GetMode(&disp_mode);
refresh =
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
(disp_mode.timing.v_total));
if (refresh < 61)
// figure out if we should use vertical sync by default
BScreen screen(this);
if (screen.IsValid())
{
vsync = true;
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);
}
delete screen;
mode = SelectDrawingMode(v_width, v_height);
// allocate bitmap buffers
for (int32 i = 0; i < 3; i++)
bitmap[i] = NULL;
fInitStatus = _AllocateBuffers(v_width, v_height, &mode);
// remember current settings
i_width = v_width;
i_height = v_height;
FrameResized(v_width, v_height);
// make sure we layout the view correctly
FrameResized(i_width, i_height);
if (mode == OVERLAY)
if (fInitStatus >= B_OK && mode == OVERLAY)
{
overlay_restrictions r;
bitmap[1]->GetOverlayRestrictions(&r);
SetSizeLimits((i_width * r.min_width_scale) + 1, i_width * r.max_width_scale,
(i_height * r.min_height_scale) + 1, i_height * r.max_height_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);
}
Show();
}
VideoWindow::~VideoWindow()
{
int32 result;
teardownwindow = true;
delete bitmap[0];
delete bitmap[1];
delete bitmap[2];
wait_for_thread(fDrawThreadID, &result);
_FreeBuffers();
}
void VideoWindow::MessageReceived( BMessage *p_message )
/*****************************************************************************
* VideoWindow::MessageReceived
*****************************************************************************/
void
VideoWindow::MessageReceived( BMessage *p_message )
{
switch( p_message->what )
{
case TOGGLE_FULL_SCREEN:
((BWindow *)this)->Zoom();
BWindow::Zoom();
break;
case RESIZE_50:
case RESIZE_100:
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);
BWindow::Zoom();
_SetVideoSize(p_message->what);
break;
case VERT_SYNC:
vsync = !vsync;
break;
case WINDOW_FEEL:
{
int16 winFeel;
if (p_message->FindInt16("WinFeel", &winFeel) == B_OK)
window_feel winFeel;
if (p_message->FindInt32("WinFeel", (int32*)&winFeel) == B_OK)
{
SetFeel((window_feel)winFeel);
SetFeel(winFeel);
fCachedFeel = winFeel;
}
}
break;
default:
BWindow::MessageReceived( p_message );
case ASPECT_CORRECT:
SetCorrectAspectRatio(!fCorrectAspect);
break;
}
}
void VideoWindow::drawBuffer(int bufferIndex)
{
i_buffer = bufferIndex;
// sync to the screen if required
if (vsync)
case SCREEN_SHOT:
// save a screen shot
if ( BBitmap* current = bitmap[i_buffer] )
{
BScreen *screen;
screen = new BScreen(this);
screen-> WaitForRetrace(22000);
delete screen;
}
if (LockLooper())
// the following line might be tempting, but does not work for some overlay bitmaps!!!
// BBitmap* temp = new BBitmap( current );
// so we clone the bitmap ourselves
// however, we need to take care of potentially different padding!
// memcpy() is slow when reading from grafix memory, but what the heck...
BBitmap* temp = new BBitmap( current->Bounds(), current->ColorSpace() );
if ( temp && temp->IsValid() )
{
// switch the overlay bitmap
if (mode == OVERLAY)
int32 height = current->Bounds().Height();
uint8* dst = (uint8*)temp->Bits();
uint8* src = (uint8*)current->Bits();
int32 dstBpr = temp->BytesPerRow();
int32 srcBpr = current->BytesPerRow();
int32 validBytes = dstBpr > srcBpr ? srcBpr : dstBpr;
for ( int32 y = 0; y < height; y++ )
{
rgb_color key;
view->SetViewOverlay(bitmap[i_buffer],
bitmap[i_buffer]->Bounds() ,
view->Bounds(),
&key, B_FOLLOW_ALL,
B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
B_OVERLAY_TRANSFER_CHANNEL);
view->SetViewColor(key);
memcpy( dst, src, validBytes );
dst += dstBpr;
src += srcBpr;
}
_SaveScreenShot( temp,
strdup( DEFAULT_SCREEN_SHOT_PATH ),
DEFAULT_SCREEN_SHOT_FORMAT );
}
else
{
// switch the bitmap
view-> DrawBitmap(bitmap[i_buffer], view->Bounds() );
delete temp;
fprintf( stderr, "error copying bitmaps\n" );
}
UnlockLooper();
}
break;
default:
BWindow::MessageReceived( p_message );
break;
}
}
void VideoWindow::Zoom(BPoint origin, float width, float height )
/*****************************************************************************
* VideoWindow::Zoom
*****************************************************************************/
void
VideoWindow::Zoom(BPoint origin, float width, float height )
{
if(is_zoomed)
{
is_zoomed = !is_zoomed;
MoveTo(winSize.left, winSize.top);
ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight());
be_app->ShowCursor();
fInterfaceShowing = true;
}
else
{
is_zoomed = !is_zoomed;
BScreen *screen;
screen = new BScreen(this);
BRect rect = screen->Frame();
delete screen;
MoveTo(0,0);
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;
}
void VideoWindow::FrameMoved(BPoint origin)
/*****************************************************************************
* VideoWindow::FrameMoved
*****************************************************************************/
void
VideoWindow::FrameMoved(BPoint origin)
{
if (is_zoomed) return ;
winSize = Frame();
}
void VideoWindow::FrameResized( float width, float height )
/*****************************************************************************
* VideoWindow::FrameResized
*****************************************************************************/
void
VideoWindow::FrameResized( float width, float height )
{
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 / i_width;
float height_scale = height / i_height;
float width_scale = width / useWidth;
float height_scale = height / useHeight;
if (width_scale <= height_scale)
{
out_width = (i_width * width_scale);
out_height = (i_height * width_scale);
out_width = (useWidth * width_scale);
out_height = (useHeight * 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_width = (useWidth * height_scale);
out_height = (useHeight * height_scale);
out_top = 0;
out_left = (width - out_width) /2;
out_left = (width - out_width) / 2;
}
view->MoveTo(out_left,out_top);
view->ResizeTo(out_width, out_height);
if (!is_zoomed)
{
winSize = Frame();
}
}
void VideoWindow::ScreenChanged(BRect frame, color_space mode)
/*****************************************************************************
* 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)
{
BScreen *screen;
float refresh;
}
screen = new BScreen(this);
display_mode disp_mode;
/*****************************************************************************
* VideoWindow::drawBuffer
*****************************************************************************/
void
VideoWindow::drawBuffer(int bufferIndex)
{
i_buffer = bufferIndex;
screen-> GetMode(&disp_mode);
refresh =
(disp_mode.timing.pixel_clock * 1000)/((disp_mode.timing.h_total)*
(disp_mode.timing.v_total));
if (refresh < 61)
// sync to the screen if required
if (vsync)
{
vsync = true;
BScreen screen(this);
screen.WaitForRetrace(22000);
}
if (fInitStatus >= B_OK && LockLooper())
{
// switch the overlay bitmap
if (mode == OVERLAY)
{
rgb_color key;
view->SetViewOverlay(bitmap[i_buffer],
bitmap[i_buffer]->Bounds() ,
view->Bounds(),
&key, B_FOLLOW_ALL,
B_OVERLAY_FILTER_HORIZONTAL|B_OVERLAY_FILTER_VERTICAL|
B_OVERLAY_TRANSFER_CHANNEL);
view->SetViewColor(key);
}
else
{
// switch the bitmap
view->DrawBitmap(bitmap[i_buffer], view->Bounds() );
}
UnlockLooper();
}
}
void VideoWindow::WindowActivated(bool active)
/*****************************************************************************
* VideoWindow::SetInterfaceShowing
*****************************************************************************/
void
VideoWindow::ToggleInterfaceShowing()
{
SetInterfaceShowing(!fInterfaceShowing);
}
int VideoWindow::SelectDrawingMode(int width, int height)
/*****************************************************************************
* VideoWindow::SetInterfaceShowing
*****************************************************************************/
void
VideoWindow::SetInterfaceShowing(bool showIt)
{
int drawingMode = BITMAP;
int noOverlay = 0;
BWindow* window = get_interface_window();
if (window)
{
if (showIt)
{
if (fCachedFeel != B_NORMAL_WINDOW_FEEL)
SetFeel(B_NORMAL_WINDOW_FEEL);
window->Activate(true);
SendBehind(window);
}
else
{
SetFeel(fCachedFeel);
Activate(true);
window->SendBehind(this);
}
fInterfaceShowing = showIt;
}
}
// int noOverlay = !config_GetIntVariable( "overlay" );
/*****************************************************************************
* VideoWindow::SetCorrectAspectRatio
*****************************************************************************/
void
VideoWindow::SetCorrectAspectRatio(bool doIt)
{
if (fCorrectAspect != doIt)
{
fCorrectAspect = doIt;
FrameResized(Bounds().Width(), Bounds().Height());
}
}
/*****************************************************************************
* VideoWindow::_AllocateBuffers
*****************************************************************************/
status_t
VideoWindow::_AllocateBuffers(int width, int height, int* mode)
{
// 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 = 0;
/* noOverlay = !config_GetInt( , "overlay" ); */
// test for overlay capability
for (int i = 0; i < COLOR_COUNT; i++)
{
if (noOverlay) break;
bitmap[0] = new BBitmap ( BRect( 0, 0, width, height ),
bitmap[0] = new BBitmap ( bitmapFrame,
B_BITMAP_WILL_OVERLAY,
colspace[i].colspace);
......@@ -324,13 +491,13 @@ int VideoWindow::SelectDrawingMode(int width, int height)
{
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);
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);
if ( (bitmap[2] && bitmap[2]->InitCheck() == B_OK) )
{
drawingMode = OVERLAY;
*mode = OVERLAY;
rgb_color key;
view->SetViewOverlay(bitmap[0],
bitmap[0]->Bounds() ,
......@@ -343,35 +510,356 @@ int VideoWindow::SelectDrawingMode(int width, int height)
}
else
{
_FreeBuffers();
*mode = BITMAP; // might want to try again with normal bitmaps
}
}
else
delete bitmap[0];
}
if (*mode == BITMAP)
{
// fallback to RGB
colspace_index = DEFAULT_COL; // B_RGB16
// FIXME: an error in the YUV->RGB32 module prevents this from being used!
/* BScreen screen( B_MAIN_SCREEN_ID );
if ( screen.ColorSpace() == B_RGB32 )
colspace_index = 3; // B_RGB32 (faster on 32 bit screen)*/
SetTitle( VOUT_TITLE " (Bitmap)" );
bitmap[0] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
bitmap[1] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
bitmap[2] = new BBitmap( bitmapFrame, colspace[colspace_index].colspace );
}
// 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;
}
/*****************************************************************************
* VideoWindow::_FreeBuffers
*****************************************************************************/
void
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;
}
else
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)
{
delete bitmap[0];
case RESIZE_50:
width /= 2;
height /= 2;
break;
case RESIZE_200:
width *= 2;
height *= 2;
break;
case RESIZE_100:
default:
break;
}
ResizeTo(width, height);
is_zoomed = false;
}
/*****************************************************************************
* VideoWindow::_SaveScreenShot
*****************************************************************************/
void
VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path,
uint32 translatorID ) const
{
// make the info object from the parameters
screen_shot_info* info = new screen_shot_info;
info->bitmap = bitmap;
info->path = path;
info->translatorID = translatorID;
info->width = fCorrectAspect ? i_width : fTrueWidth;
info->height = fCorrectAspect ? i_height : fTrueHeight;
// spawn a new thread to take care of the actual saving to disk
thread_id thread = spawn_thread( _save_screen_shot,
"screen shot saver",
B_LOW_PRIORITY, (void*)info );
// start thread or do the job ourself if something went wrong
if ( thread < B_OK || resume_thread( thread ) < B_OK )
_save_screen_shot( (void*)info );
}
/*****************************************************************************
* VideoWindow::_save_screen_shot
*****************************************************************************/
int32
VideoWindow::_save_screen_shot( void* cookie )
{
screen_shot_info* info = (screen_shot_info*)cookie;
if ( info && info->bitmap && info->bitmap->IsValid() && info->path )
{
// try to be as quick as possible creating the file (the user might have
// taken the next screen shot already!)
// make sure we have a unique name for the screen shot
BString path( info->path );
BEntry entry( path.String() );
int32 appendedNumber = 0;
if ( entry.Exists() && !entry.IsSymLink() )
{
// we would clobber an existing entry
bool foundUniqueName = false;
appendedNumber = 1;
while ( !foundUniqueName ) {
BString newName( info->path );
newName << " " << appendedNumber;
BEntry possiblyClobberedEntry( newName.String() );
if ( possiblyClobberedEntry.Exists()
&& !possiblyClobberedEntry.IsSymLink() )
appendedNumber++;
else
foundUniqueName = true;
}
}
if ( appendedNumber > 0 )
path << " " << appendedNumber;
// there is still a slight chance to clobber an existing
// file (if it was created in the "meantime"), but we take it...
BFile outFile( path.String(),
B_CREATE_FILE | B_WRITE_ONLY | B_ERASE_FILE );
// make colorspace converted copy of bitmap
BBitmap* converted = new BBitmap( BRect( 0.0, 0.0, info->width, info->height ),
B_RGB32 );
// if ( converted->IsValid() )
// memset( converted->Bits(), 0, converted->BitsLength() );
status_t status = convert_bitmap( info->bitmap, converted );
if ( status == B_OK )
{
BTranslatorRoster* roster = BTranslatorRoster::Default();
uint32 imageFormat = 0;
translator_id translator = 0;
bool found = false;
if (drawingMode == BITMAP)
// find suitable translator
translator_id* ids = NULL;
int32 count = 0;
status = roster->GetAllTranslators( &ids, &count );
if ( status >= B_OK )
{
for ( int tix = 0; tix < count; tix++ )
{
// fallback to RGB16
colspace_index = DEFAULT_COL;
SetTitle(VOUT_TITLE " (Bitmap)");
bitmap[0] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
bitmap[1] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
bitmap[2] = new BBitmap( BRect( 0, 0, width, height ), colspace[colspace_index].colspace);
const translation_format *formats = NULL;
int32 num_formats = 0;
bool ok = false;
status = roster->GetInputFormats( ids[tix],
&formats, &num_formats );
if (status >= B_OK)
{
for ( int iix = 0; iix < num_formats; iix++ )
{
if ( formats[iix].type == B_TRANSLATOR_BITMAP )
{
ok = true;
break;
}
}
}
if ( !ok )
continue;
status = roster->GetOutputFormats( ids[tix],
&formats, &num_formats);
if ( status >= B_OK )
{
for ( int32 oix = 0; oix < num_formats; oix++ )
{
if ( formats[oix].type != B_TRANSLATOR_BITMAP )
{
if ( formats[oix].type == info->translatorID )
{
found = true;
imageFormat = formats[oix].type;
translator = ids[tix];
break;
}
}
}
}
}
}
delete[] ids;
if ( found )
{
// make bitmap stream
BBitmapStream outStream( converted );
status = outFile.InitCheck();
if (status == B_OK) {
status = roster->Translate( &outStream, NULL, NULL,
&outFile, imageFormat );
if ( status == B_OK )
{
BNodeInfo nodeInfo( &outFile );
if ( nodeInfo.InitCheck() == B_OK )
{
translation_format* formats;
int32 count;
status = roster->GetOutputFormats( translator,
(const translation_format **) &formats,
&count);
if ( status >= B_OK )
{
const char * mime = NULL;
for ( int ix = 0; ix < count; ix++ ) {
if ( formats[ix].type == imageFormat ) {
mime = formats[ix].MIME;
break;
}
}
return drawingMode;
if ( mime )
nodeInfo.SetType( mime );
}
}
} else {
fprintf( stderr, " failed to write bitmap: %s\n",
strerror( status ) );
}
} else {
fprintf( stderr, " failed to create output file: %s\n",
strerror( status ) );
}
outStream.DetachBitmap( &converted );
outFile.Unset();
}
else
fprintf( stderr, " failed to find translator\n");
}
else
fprintf( stderr, " failed to convert colorspace: %s\n",
strerror( status ) );
delete converted;
}
if ( info )
{
delete info->bitmap;
delete[] info->path;
}
delete info;
return B_OK;
}
/*****************************************************************************
* VLCView::VLCView
*****************************************************************************/
VLCView::VLCView(BRect bounds) : BView(bounds, "", B_FOLLOW_NONE,
B_WILL_DRAW)
VLCView::VLCView(BRect bounds)
: BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
fLastMouseMovedTime(system_time()),
fCursorHidden(false),
fCursorInside(false),
fIgnoreDoubleClick(false)
{
SetViewColor(B_TRANSPARENT_32_BIT);
}
......@@ -383,69 +871,222 @@ 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
*****************************************************************************/
void VLCView::MouseDown(BPoint point)
void
VLCView::MouseDown(BPoint where)
{
VideoWindow* videoWindow = dynamic_cast<VideoWindow*>(Window());
BMessage* msg = Window()->CurrentMessage();
int32 clicks = msg->FindInt32("clicks");
int32 clicks;
uint32 buttons;
msg->FindInt32("clicks", &clicks);
msg->FindInt32("buttons", (int32*)&buttons);
VideoWindow *vWindow = (VideoWindow *)Window();
uint32 mouseButtons;
BPoint where;
GetMouse(&where, &mouseButtons, true);
if ((mouseButtons & B_PRIMARY_MOUSE_BUTTON) && (clicks == 2))
if (videoWindow)
{
if (buttons & B_PRIMARY_MOUSE_BUTTON)
{
if (clicks == 2 && !fIgnoreDoubleClick)
Window()->Zoom();
return;
else
videoWindow->ToggleInterfaceShowing();
fIgnoreDoubleClick = false;
}
else
{
if (mouseButtons & B_SECONDARY_MOUSE_BUTTON)
if (buttons & B_SECONDARY_MOUSE_BUTTON)
{
// clicks will be 2 next time (if interval short enough)
// even if the first click and the second
// have not been made with the same mouse button
fIgnoreDoubleClick = true;
// launch popup menu
BPopUpMenu *menu = new BPopUpMenu("context menu");
menu->SetRadioMode(false);
// Toggle FullScreen
BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
zoomItem->SetMarked(vWindow->is_zoomed);
menu->AddItem(zoomItem);
// Resize to 50%
BMenuItem *halfItem = new BMenuItem("50%", new BMessage(RESIZE_50));
menu->AddItem(halfItem);
// 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);
// Toggle FullScreen
BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN));
zoomItem->SetMarked(videoWindow->is_zoomed);
menu->AddItem(zoomItem);
menu->AddSeparatorItem();
// Toggle vSync
BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC));
vsyncItem->SetMarked(vWindow->vsync);
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->AddInt16("WinFeel", (int16)B_NORMAL_WINDOW_FEEL);
/* BMessage *winNormFeel = new BMessage(WINDOW_FEEL);
winNormFeel->AddInt32("WinFeel", (int32)B_NORMAL_WINDOW_FEEL);
BMenuItem *normWindItem = new BMenuItem("Normal Window", winNormFeel);
normWindItem->SetMarked(vWindow->Feel() == B_NORMAL_WINDOW_FEEL);
normWindItem->SetMarked(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
menu->AddItem(normWindItem);
BMessage *winFloatFeel = new BMessage(WINDOW_FEEL);
winFloatFeel->AddInt16("WinFeel", (int16)B_MODAL_ALL_WINDOW_FEEL);
winFloatFeel->AddInt32("WinFeel", (int32)B_FLOATING_APP_WINDOW_FEEL);
BMenuItem *onTopWindItem = new BMenuItem("App Top", winFloatFeel);
onTopWindItem->SetMarked(vWindow->Feel() == B_MODAL_ALL_WINDOW_FEEL);
onTopWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_APP_WINDOW_FEEL);
menu->AddItem(onTopWindItem);
BMessage *winAllFeel = new BMessage(WINDOW_FEEL);
winAllFeel->AddInt16("WinFeel", (int16)B_FLOATING_ALL_WINDOW_FEEL);
winAllFeel->AddInt32("WinFeel", (int32)B_FLOATING_ALL_WINDOW_FEEL);
BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
allSpacesWindItem->SetMarked(vWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
menu->AddItem(allSpacesWindItem);
allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
menu->AddItem(allSpacesWindItem);*/
BMessage *windowFeelMsg = new BMessage( WINDOW_FEEL );
bool onTop = videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL;
window_feel feel = onTop ? B_NORMAL_WINDOW_FEEL : B_FLOATING_ALL_WINDOW_FEEL;
windowFeelMsg->AddInt32( "WinFeel", (int32)feel );
BMenuItem *windowFeelItem = new BMenuItem( "Stay On Top", windowFeelMsg );
windowFeelItem->SetMarked( onTop );
menu->AddItem( windowFeelItem );
menu->AddSeparatorItem();
BMenuItem* screenShotItem = new BMenuItem( "Take Screen Shot",
new BMessage( SCREEN_SHOT ) );
menu->AddItem( screenShotItem );
menu->SetTargetForItems( this );
ConvertToScreen( &where );
menu->Go( where, true, false, true );
}
}
}
fLastMouseMovedTime = system_time();
fCursorHidden = false;
}
menu->SetTargetForItems(this);
ConvertToScreen(&where);
menu->Go(where, true, false, true);
/*****************************************************************************
* VLCVIew::MouseMoved
*****************************************************************************/
void
VLCView::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
{
fLastMouseMovedTime = system_time();
fCursorHidden = false;
fCursorInside = (transit == B_INSIDE_VIEW || transit == B_ENTERED_VIEW);
}
/*****************************************************************************
* VLCVIew::Pulse
*****************************************************************************/
void
VLCView::Pulse()
{
// We are getting the pulse messages no matter if the mouse is over
// this view. If we are in full screen mode, we want to hide the cursor
// even if it is not.
if (!fCursorHidden)
{
if (fCursorInside
&& system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
{
be_app->ObscureCursor();
fCursorHidden = true;
VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
// hide the interface window as well if full screen
if (videoWindow && videoWindow->is_zoomed)
videoWindow->SetInterfaceShowing(false);
}
}
}
/*****************************************************************************
* VLCVIew::KeyDown
*****************************************************************************/
void
VLCView::KeyDown(const char *bytes, int32 numBytes)
{
VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
BWindow* interfaceWindow = get_interface_window();
if (videoWindow && numBytes > 0) {
uint32 mods = modifiers();
switch (*bytes) {
case B_TAB:
// toggle window and full screen mode
// not passing on the tab key to the default KeyDown()
// implementation also avoids loosing the keyboard focus
videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
break;
case B_ESCAPE:
// go back to window mode
if (videoWindow->is_zoomed)
videoWindow->PostMessage(TOGGLE_FULL_SCREEN);
break;
case B_SPACE:
// toggle playback
if (interfaceWindow)
interfaceWindow->PostMessage(PAUSE_PLAYBACK);
break;
case B_RIGHT_ARROW:
if (interfaceWindow)
{
if (mods & B_SHIFT_KEY)
// next title
interfaceWindow->PostMessage(NEXT_TITLE);
else
// next chapter
interfaceWindow->PostMessage(NEXT_CHAPTER);
}
break;
case B_LEFT_ARROW:
if (interfaceWindow)
{
if (mods & B_SHIFT_KEY)
// previous title
interfaceWindow->PostMessage(PREV_TITLE);
else
// previous chapter
interfaceWindow->PostMessage(PREV_CHAPTER);
}
break;
case B_UP_ARROW:
// previous file in playlist
interfaceWindow->PostMessage(PREV_FILE);
break;
case B_DOWN_ARROW:
// next file in playlist
interfaceWindow->PostMessage(NEXT_FILE);
break;
case B_PRINT_KEY:
case 's':
case 'S':
videoWindow->PostMessage( SCREEN_SHOT );
break;
default:
BView::KeyDown(bytes, numBytes);
break;
}
}
}
......@@ -453,11 +1094,12 @@ void VLCView::MouseDown(BPoint point)
/*****************************************************************************
* VLCVIew::Draw
*****************************************************************************/
void VLCView::Draw(BRect updateRect)
void
VLCView::Draw(BRect updateRect)
{
VideoWindow *win = (VideoWindow *) Window();
if (win->mode == BITMAP)
FillRect(updateRect);
VideoWindow* window = dynamic_cast<VideoWindow*>( Window() );
if ( window && window->mode == BITMAP )
FillRect( updateRect );
}
/*****************************************************************************
......@@ -621,12 +1263,15 @@ static int BeosOpenDisplay( vout_thread_t *p_vout )
BRect( 20, 50,
20 + p_vout->i_window_width - 1,
50 + p_vout->i_window_height - 1 ));
if( p_vout->p_sys->p_window == NULL )
{
msg_Err( p_vout, "cannot allocate VideoWindow" );
return( 1 );
}
else
{
p_vout->p_sys->p_window->Show();
}
return( 0 );
}
......@@ -650,4 +1295,3 @@ static void BeosCloseDisplay( vout_thread_t *p_vout )
}
p_win = NULL;
}
......@@ -2,11 +2,12 @@
* VideoWindow.h: BeOS video window class prototype
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: VideoWindow.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: VideoWindow.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Tony Castley <tcastley@mail.powerup.com.au>
* 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
* it under the terms of the GNU General Public License as published by
......@@ -22,6 +23,13 @@
* along with this program; if not, write to the Free Software
* 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 OVERLAY 1
#define OPENGL 2
......@@ -50,48 +58,102 @@ colorcombo colspace[]=
class VLCView : public BView
{
public:
public:
VLCView( BRect bounds);
~VLCView();
virtual ~VLCView();
virtual void AttachedToWindow();
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);
void MouseDown(BPoint point);
void Draw(BRect updateRect);
private:
bigtime_t fLastMouseMovedTime;
bool fCursorHidden;
bool fCursorInside;
bool fIgnoreDoubleClick;
};
class VideoWindow : public BWindow
{
public:
// standard constructor and destructor
VideoWindow( int v_width, int v_height,
VideoWindow(int v_width,
int v_height,
BRect frame);
~VideoWindow();
virtual ~VideoWindow();
// BWindow
virtual void MessageReceived(BMessage* message);
virtual void Zoom(BPoint origin,
float width, float height);
virtual void FrameResized(float width, float height);
virtual void FrameMoved(BPoint origin);
virtual void ScreenChanged(BRect frame,
color_space mode);
virtual void WindowActivated(bool active);
void Zoom(BPoint origin, float width, float height);
void FrameResized(float width, float height);
void FrameMoved(BPoint origin);
void ScreenChanged(BRect frame, color_space mode);
// VideoWindow
void drawBuffer(int bufferIndex);
void WindowActivated(bool active);
int SelectDrawingMode(int width, int height);
void MessageReceived(BMessage *message);
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
int32 i_width; // incomming bitmap size
int32 i_width; // aspect corrected bitmap size
int32 i_height;
BRect winSize; // current window size
bool is_zoomed, vsync;
BBitmap *bitmap[3];
BBitmap *overlaybitmap;
VLCView *view;
int i_buffer;
bool teardownwindow;
volatile bool teardownwindow;
thread_id fDrawThreadID;
int mode;
int colspace_index;
private:
vout_thread_t *p_vout;
status_t _AllocateBuffers(int width,
int height,
int* mode);
void _FreeBuffers();
void _BlankBitmap(BBitmap* bitmap) const;
void _SetVideoSize(uint32 mode);
void _SaveScreenShot( BBitmap* bitmap,
char* path,
uint32 translatorID ) const;
static int32 _save_screen_shot( void* cookie );
struct screen_shot_info
{
BBitmap* bitmap;
char* path;
uint32 translatorID;
int32 width;
int32 height;
};
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
/*****************************************************************************
* 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
* $Id: VlcWrapper.cpp,v 1.3 2002/08/18 11:32:06 titer Exp $
* $Id: VlcWrapper.cpp,v 1.4 2002/09/30 18:30:27 titer Exp $
*
* Authors: Florian G. Pflug <fgp@phlo.org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
* Tony Casltey <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software{} you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -49,72 +50,48 @@ Intf_VLCWrapper::~Intf_VLCWrapper()
{
}
//bool Intf_VLCWrapper::manage()
//{
//
// p_intf->pf_manage( p_intf );
//
// if ( p_intf->b_die )
// {
// // exit the lot
// return( 1 );
// }
/* Update the input */
// if( p_intf->p_sys->p_input != NULL )
// {
// if( p_intf->p_sys->p_input->b_dead )
// {
// vlc_object_release( p_intf->p_sys->p_input );
// p_intf->p_sys->p_input = NULL;
// }
// }
//
// p_intf->p_sys->p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
// FIND_ANYWHERE );
// if ( p_intf->p_sys->p_input != NULL )
// {
// vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
// if( !p_intf->p_sys->p_input->b_die )
// {
// /* New input or stream map change */
// if( p_intf->p_sys->p_input->stream.b_changed ||
// p_intf->p_sys->i_part !=
// p_intf->p_sys->p_input->stream.p_selected_area->i_part )
// {
// setupMenus();
// p_intf->p_sys->b_disabled_menus = 0;
// }
// }
// vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
// }
// else if ( !p_intf->p_sys->b_disabled_menus )
// {
// setupMenus();
// p_intf->p_sys->b_disabled_menus = 1;
// }
// return( 0 );
//}
void Intf_VLCWrapper::quit()
#if 0
bool Intf_VLCWrapper::manage()
{
p_intf->b_die = 1;
}
p_main->p_intf->pf_manage( p_main->p_intf );
/* playlist control */
if ( p_main->p_intf->b_die )
{
// exit the lot
return( 1 );
}
int Intf_VLCWrapper::inputGetStatus()
{
if( p_intf->p_sys->p_input != NULL )
if ( p_input_bank->pp_input[0] != NULL )
{
vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
if( !p_input_bank->pp_input[0]->b_die )
{
/* New input or stream map change */
if( p_input_bank->pp_input[0]->stream.b_changed ||
p_main->p_intf->p_sys->i_part !=
p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
{
return( p_intf->p_sys->p_input->stream.control.i_status );
setupMenus();
p_main->p_intf->p_sys->b_disabled_menus = 0;
}
else
}
vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
}
else if ( !p_main->p_intf->p_sys->b_disabled_menus )
{
return( UNDEF_S );
setupMenus();
p_main->p_intf->p_sys->b_disabled_menus = 1;
}
return( 0 );
}
#endif
void Intf_VLCWrapper::quit()
{
p_intf->b_die = 1;
}
/* playlist control */
bool Intf_VLCWrapper::playlistPlay()
{
playlist_t *p_playlist =
......@@ -135,12 +112,11 @@ bool Intf_VLCWrapper::playlistPlay()
}
return( true );
}
void Intf_VLCWrapper::playlistPause()
{
toggleMute( );
toggle_mute( );
playlist_t *p_playlist =
(playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
......@@ -156,7 +132,6 @@ void Intf_VLCWrapper::playlistStop()
playlist_Stop( p_playlist );
vlc_object_release( p_playlist );
}
void Intf_VLCWrapper::playlistNext()
......@@ -199,6 +174,266 @@ void Intf_VLCWrapper::playlistGoto(int i)
vlc_object_release( p_playlist );
}
void Intf_VLCWrapper::playlistJumpTo( int pos )
{
#if 0
// sanity checks
if ( pos < 0 )
pos = 0;
int size = playlistSize();
if (pos >= size)
pos = size - 1;
// weird hack
if( p_input_bank->pp_input[0] != NULL )
pos--;
// stop current stream
playlistStop();
// modify current position in playlist
playlistLock();
p_main->p_playlist->i_index = pos;
playlistUnlock();
// start playing
playlistPlay();
#endif
}
int Intf_VLCWrapper::playlistCurrentPos()
{
/*playlistLock();
int pos = p_main->p_playlist->i_index;
playlistUnlock();
return pos;*/
}
int Intf_VLCWrapper::playlistSize()
{
/*playlistLock();
int size = p_main->p_playlist->i_size;
playlistUnlock();
return size;*/
}
void Intf_VLCWrapper::playlistLock()
{
/*vlc_mutex_lock( &p_main->p_playlist->change_lock );*/
}
void Intf_VLCWrapper::playlistUnlock()
{
/*vlc_mutex_unlock( &p_main->p_playlist->change_lock );*/
}
void Intf_VLCWrapper::getNavCapabilities( bool* canSkipPrev,
bool* canSkipNext )
{
#if 0
if ( canSkipPrev && canSkipNext )
{
// init the parameters
*canSkipPrev = false;
*canSkipNext = false;
// get playlist info
playlistLock();
int pos = p_main->p_playlist->i_index;
int size = p_main->p_playlist->i_size;
playlistUnlock();
input_thread_t* input = p_input_bank->pp_input[0];
// see if we have got a stream going
if ( input )
{
vlc_mutex_lock( &input->stream.stream_lock );
bool hasTitles = input->stream.i_area_nb > 1;
int numChapters = input->stream.p_selected_area->i_part_nb;
bool hasChapters = numChapters > 1;
// first, look for chapters
if ( hasChapters )
{
*canSkipPrev = input->stream.p_selected_area->i_part > 0;
*canSkipNext = input->stream.p_selected_area->i_part <
input->stream.p_selected_area->i_part_nb - 1;
}
// if one of the skip capabilities is false,
// make it depend on titles instead
if ( !*canSkipPrev && hasTitles )
*canSkipPrev = input->stream.p_selected_area->i_id > 1;
if ( !*canSkipNext && hasTitles )
*canSkipNext = input->stream.p_selected_area->i_id < input->stream.i_area_nb - 1;
vlc_mutex_unlock( &input->stream.stream_lock );
}
// last but not least, make capabilities depend on playlist
if ( !*canSkipPrev )
*canSkipPrev = pos > 0;
if ( !*canSkipNext )
*canSkipNext = pos < size - 1;
}
#endif
}
void Intf_VLCWrapper::navigatePrev()
{
#if 0
bool hasSkiped = false;
input_thread_t* input = p_input_bank->pp_input[0];
// see if we have got a stream going
if ( input )
{
// get information from stream (lock it while looking at it)
vlc_mutex_lock( &input->stream.stream_lock );
int currentTitle = input->stream.p_selected_area->i_id;
int currentChapter = input->stream.p_selected_area->i_part;
int numTitles = input->stream.i_area_nb;
bool hasTitles = numTitles > 1;
int numChapters = input->stream.p_selected_area->i_part_nb;
bool hasChapters = numChapters > 1;
vlc_mutex_unlock( &input->stream.stream_lock );
// first, look for chapters
if ( hasChapters )
{
// skip to the previous chapter
currentChapter--;
if ( currentChapter >= 0 )
{
toggleChapter( currentChapter );
hasSkiped = true;
}
}
// if we couldn't skip chapters, try titles instead
if ( !hasSkiped && hasTitles )
{
// skip to the previous title
currentTitle--;
// disallow area 0 since it is used for video_ts.vob
if( currentTitle > 0 )
{
toggleTitle(currentTitle);
hasSkiped = true;
}
}
}
// last but not least, skip to previous file
if ( !hasSkiped )
playlistPrev();
#endif
}
void Intf_VLCWrapper::navigateNext()
{
#if 0
bool hasSkiped = false;
input_thread_t* input = p_input_bank->pp_input[0];
// see if we have got a stream going
if ( input )
{
// get information from stream (lock it while looking at it)
vlc_mutex_lock( &input->stream.stream_lock );
int currentTitle = input->stream.p_selected_area->i_id;
int currentChapter = input->stream.p_selected_area->i_part;
int numTitles = input->stream.i_area_nb;
bool hasTitles = numTitles > 1;
int numChapters = input->stream.p_selected_area->i_part_nb;
bool hasChapters = numChapters > 1;
vlc_mutex_unlock( &input->stream.stream_lock );
// first, look for chapters
if ( hasChapters )
{
// skip to the next chapter
currentChapter++;
if ( currentChapter < numChapters )
{
toggleChapter( currentChapter );
hasSkiped = true;
}
}
// if we couldn't skip chapters, try titles instead
if ( !hasSkiped && hasTitles )
{
// skip to the next title
currentTitle++;
// disallow area 0 since it is used for video_ts.vob
if ( currentTitle < numTitles - 1 )
{
toggleTitle(currentTitle);
hasSkiped = true;
}
}
}
// last but not least, skip to next file
if ( !hasSkiped )
playlistNext();
#endif
}
//void Intf_VLCWrapper::channelNext()
//{
// intf_thread_t * p_intf = p_main->p_intf;
//
// p_intf->p_sys->i_channel++;
//
// intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
//
// vlc_mutex_lock( &p_intf->change_lock );
//
// network_ChannelJoin( p_intf->p_sys->i_channel );
// p_intf->pf_manage( p_intf );
//
// vlc_mutex_unlock( &p_intf->change_lock );
//}
//
//void Intf_VLCWrapper::channelPrev()
//{
// intf_thread_t * p_intf = p_main->p_intf;
//
// if ( p_intf->p_sys->i_channel )
// {
// p_intf->p_sys->i_channel--;
// }
//
// intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
//
// vlc_mutex_lock( &p_intf->change_lock );
//
// network_ChannelJoin( p_intf->p_sys->i_channel );
// p_intf->pf_manage( p_intf );
//
// vlc_mutex_unlock( &p_intf->change_lock );
//
//}
void Intf_VLCWrapper::loop()
{
#if 0
intf_thread_t * p_intf = p_main->p_intf;
if ( p_intf->p_sys->b_loop )
{
intf_PlaylistDelete( p_main->p_playlist,
p_main->p_playlist->i_size - 1 );
}
else
{
intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
"vlc:loop" );
}
p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
#endif
}
/* playback control */
void Intf_VLCWrapper::playSlower()
{
......@@ -208,11 +443,11 @@ void Intf_VLCWrapper::playSlower()
}
if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
{
toggleMute( );
toggle_mute( );
}
else
{
toggleMute ( );
toggle_mute ( );
}
}
......@@ -224,123 +459,172 @@ void Intf_VLCWrapper::playFaster()
}
if (p_intf->p_sys->p_input->stream.control.i_rate == DEFAULT_RATE)
{
toggleMute( );
toggle_mute( );
}
else
{
toggleMute ( );
toggle_mute ( );
}
}
void Intf_VLCWrapper::toggleProgram(int i_program){}
void Intf_VLCWrapper::toggleTitle(int i_title)
void Intf_VLCWrapper::volume_mute()
{
if( p_intf->p_sys->p_input != NULL )
/*
if( p_aout_bank->i_count > 0
&& p_aout_bank->pp_aout[0] != NULL )
{
input_ChangeArea( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_areas[i_title] );
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
//setupMenus();
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
if( !p_main->p_intf->p_sys->b_mute )
{
p_main->p_intf->p_sys->i_saved_volume =
p_aout_bank->pp_aout[0]->i_volume;
p_aout_bank->pp_aout[0]->i_volume = 0;
p_main->p_intf->p_sys->b_mute = 1;
}
}
*/
}
void Intf_VLCWrapper::toggleChapter(int i_chapter)
void Intf_VLCWrapper::volume_restore()
{
if( p_intf->p_sys->p_input != NULL )
/*
if( p_aout_bank->i_count > 0
&& p_aout_bank->pp_aout[0] != NULL )
{
p_intf->p_sys->p_input->stream.p_selected_area->i_part = i_chapter;
input_ChangeArea( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.p_selected_area );
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
// setupMenus();
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
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 = 0;
p_main->p_intf->p_sys->b_mute = 0;
}
*/
}
void Intf_VLCWrapper::toggleLanguage(int i_language)
void Intf_VLCWrapper::set_volume(int value)
{
int32 i_old = -1;
int i_cat = AUDIO_ES;
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
#if 0
if( p_aout_bank->i_count > 0
&& p_aout_bank->pp_aout[0] != NULL )
{
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
// make sure value is within bounds
if (value < 0)
value = 0;
if (value > AOUT_VOLUME_MAX)
value = AOUT_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;
// set every stream to the given value
for ( int i = 0 ; i < p_aout_bank->i_count ; i++ )
{
i_old = i;
break;
if ( p_aout_bank->pp_aout[i] )
p_aout_bank->pp_aout[i]->i_volume = value;
}
vlc_mutex_unlock( &p_aout_bank->lock );
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
#endif
}
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_language);
if( i_language != -1 )
void Intf_VLCWrapper::toggle_mute()
{
/*
if( p_aout_bank->i_count > 0
&& p_aout_bank->pp_aout[0] != NULL )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_language],
VLC_TRUE );
if ( p_main->p_intf->p_sys->b_mute )
{
Intf_VLCWrapper::volume_restore();
}
if( (i_old != -1) && (i_old != i_language) )
else
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
VLC_FALSE );
Intf_VLCWrapper::volume_mute();
}
}
*/
}
void Intf_VLCWrapper::toggleSubtitle(int i_subtitle)
bool Intf_VLCWrapper::is_muted()
{
int32 i_old = -1;
int i_cat = SPU_ES;
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
#if 0
bool muted = true;
if ( p_aout_bank->i_count > 0 )
{
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
vlc_mutex_lock( &p_aout_bank->lock );
for ( int i = 0 ; i < p_aout_bank->i_count ; i++ )
{
i_old = i;
if ( p_aout_bank->pp_aout[i]
&& p_aout_bank->pp_aout[i]->i_volume > 0 )
{
muted = false;
break;
}
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_subtitle);
if( i_subtitle != -1 )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_subtitle],
VLC_TRUE );
vlc_mutex_unlock( &p_aout_bank->lock );
// unfortunately, this is not reliable!
// return p_main->p_intf->p_sys->b_mute;
}
return muted;
#endif
}
if( (i_old != -1) && (i_old != i_subtitle) )
bool Intf_VLCWrapper::is_playing()
{
/*
bool playing = false;
if ( p_input_bank->pp_input[0] )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
VLC_FALSE );
switch ( p_input_bank->pp_input[0]->stream.control.i_status )
{
case PLAYING_S:
case FORWARD_S:
case BACKWARD_S:
case START_S:
playing = true;
break;
case PAUSE_S:
case UNDEF_S:
case NOT_STARTED_S:
default:
break;
}
}
return playing;
*/
}
void Intf_VLCWrapper::channelNext()
void Intf_VLCWrapper::maxvolume()
{
/*
if( p_aout_bank->i_count > 0
&& p_aout_bank->pp_aout[0] != NULL )
{
if( p_main->p_intf->p_sys->b_mute )
{
p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
}
else
{
p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
}
}
*/
}
void Intf_VLCWrapper::channelPrev()
bool Intf_VLCWrapper::has_audio()
{
/* return (p_aout_bank->i_count > 0); */
}
void Intf_VLCWrapper::eject(){}
//void Intf_VLCWrapper::fullscreen()
//{
// if( p_vout_bank->pp_vout[0] != NULL )
// {
// p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
// }
//}
void Intf_VLCWrapper::eject(){}
/* playback info */
/* playback info */
BString* Intf_VLCWrapper::getTimeAsString()
{
......@@ -384,6 +668,11 @@ void Intf_VLCWrapper::setTimeAsFloat(float f_position)
}
}
bool Intf_VLCWrapper::playlistPlaying()
{
/* return( !p_main->p_playlist->b_stopped ); */
}
BList *Intf_VLCWrapper::playlistAsArray()
{
int i;
......@@ -406,7 +695,7 @@ BList *Intf_VLCWrapper::playlistAsArray()
}
/* open file/disc/network */
void Intf_VLCWrapper::openFiles(BList *o_files)
void Intf_VLCWrapper::openFiles( BList* o_files, bool replace )
{
BString *o_file;
playlist_t *p_playlist =
......@@ -422,7 +711,6 @@ void Intf_VLCWrapper::openFiles(BList *o_files)
}
vlc_object_release( p_playlist );
}
void Intf_VLCWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
......@@ -450,10 +738,103 @@ void Intf_VLCWrapper::openNetHTTP(BString o_addr)
{
}
void Intf_VLCWrapper::toggleMute( )
/* menus management */
void Intf_VLCWrapper::toggleProgram(int i_program){}
void Intf_VLCWrapper::toggleTitle(int i_title)
{
/*input_ToggleMute( p_intf->p_sys->p_input );*/
if( p_intf->p_sys->p_input != NULL )
{
input_ChangeArea( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_areas[i_title] );
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
//setupMenus();
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
}
}
void Intf_VLCWrapper::toggleChapter(int i_chapter)
{
if( p_intf->p_sys->p_input != NULL )
{
p_intf->p_sys->p_input->stream.p_selected_area->i_part = i_chapter;
input_ChangeArea( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.p_selected_area );
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
// setupMenus();
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
}
}
void Intf_VLCWrapper::toggleLanguage(int i_language)
{
int32 i_old = -1;
int i_cat = AUDIO_ES;
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
{
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
{
i_old = i;
break;
}
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_language);
if( i_language != -1 )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_language],
VLC_TRUE );
}
if( (i_old != -1) && (i_old != i_language) )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
VLC_FALSE );
}
}
void Intf_VLCWrapper::toggleSubtitle(int i_subtitle)
{
int32 i_old = -1;
int i_cat = SPU_ES;
vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
for( int i = 0; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
{
if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == i_cat )
{
i_old = i;
break;
}
}
vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
msg_Info( p_intf, "Old: %d, New: %d", i_old, i_subtitle);
if( i_subtitle != -1 )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_subtitle],
VLC_TRUE );
}
if( (i_old != -1) && (i_old != i_subtitle) )
{
input_ToggleES( p_intf->p_sys->p_input,
p_intf->p_sys->p_input->stream.pp_selected_es[i_old],
VLC_FALSE );
}
}
/* menus management */
void Intf_VLCWrapper::setupMenus(){}
int Intf_VLCWrapper::inputGetStatus() {}
/*****************************************************************************
* 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
* $Id: VlcWrapper.h,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: VlcWrapper.h,v 1.2 2002/09/30 18:30:27 titer Exp $
*
* Authors: Florian G. Pflug <fgp@phlo.org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
* Tony Casltey <tony@castley.net>
* Stephan Aßmus <stippi@yellowbites.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -29,15 +30,12 @@ class InterfaceWindow;
*****************************************************************************/
struct intf_sys_t
{
InterfaceWindow *p_window;
InterfaceWindow * p_window;
char i_key;
/* The input thread */
input_thread_t * p_input;
/* The messages window */
// msg_subscription_t * p_sub;
/* DVD mode */
vlc_bool_t b_disabled_menus;
vlc_bool_t b_loop;
......@@ -45,7 +43,6 @@ struct intf_sys_t
int i_part;
int i_saved_volume;
int i_channel;
};
/* Intf_VLCWrapper is a singleton class
......@@ -56,17 +53,24 @@ public:
static Intf_VLCWrapper *getVLCWrapper(intf_thread_t *p_if);
~Intf_VLCWrapper();
// bool manage();
/* static bool manage(); */
void quit();
int inputGetStatus();
/* playlist control */
bool playlistPlay();
void playlistPause();
void playlistStop();
void playlistNext();
void playlistPrev();
/* void playlistJumpTo( int pos );
int playlistCurrentPos();
int playlistSize();
playlistLock();
playlistUnlock();*/
void playlistSkip(int i);
void playlistGoto(int i);
/* Playback Modes
PLAYLIST_REPEAT_CURRENT
PLAYLIST_FORWARD
......@@ -77,45 +81,70 @@ public:
PLAYLIST_REVERSE_RANDOM
*/
void getNavCapabilities( bool* canSkipPrev,
bool* canSkipNext );
void navigatePrev();
void navigateNext();
// void channelNext();
// void channelPrev();
// void loop();
/* Stream Control */
void playSlower();
void playFaster();
/* input control */
/* playback control */
void volume_mute();
void volume_restore();
void set_volume(int value);
void toggle_mute( );
bool is_muted();
bool is_playing();
void maxvolume();
bool has_audio();
// void fullscreen();
void eject();
int getStatus();
void setStatus(int status);
void inputSeek();
void toggleProgram(int i_program);
void toggleTitle(int i_title);
void toggleChapter(int i_chapter);
void toggleLanguage(int i_language);
void toggleSubtitle(int i_subtitle);
void channelNext();
void channelPrev();
void eject();
/* playback info */
BString* getTimeAsString();
float getTimeAsFloat();
void setTimeAsFloat(float i_offset);
void setTimeAsFloat( float i_offset );
bool playlistPlaying();
BList* playlistAsArray();
/* open file/disc/network */
void openFiles(BList *o_files);
void openDisc(BString o_type, BString o_device, int i_title, int i_chapter);
void openNet(BString o_addr, int i_port);
void openNetChannel(BString o_addr, int i_port);
void openNetHTTP(BString o_addr);
/* audio stuff */
void toggleMute( );
void openFiles( BList *o_files, bool replace = true );
void openDisc( BString o_type, BString o_device,
int i_title, int i_chapter );
void openNet( BString o_addr, int i_port );
void openNetChannel( BString o_addr, int i_port );
void openNetHTTP( BString o_addr );
/* menus management */
void toggleProgram( int i_program );
void toggleTitle( int i_title );
void toggleChapter( int i_chapter );
void toggleLanguage( int i_language );
void toggleSubtitle( int i_subtitle );
void channelNext();
void channelPrev();
void setupMenus();
private:
void playlistJumpTo( int );
int playlistSize();
int playlistCurrentPos();
void playlistLock();
void playlistUnlock();
void loop();
//private:
Intf_VLCWrapper( intf_thread_t *p_if );
es_descriptor_t * p_audio_es;
intf_thread_t *p_intf;
};
No preview for this file type
......@@ -2,7 +2,7 @@
* beos_init.cpp: Initialization for BeOS specific features
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: beos_specific.cpp,v 1.25 2002/08/29 23:53:22 massiot Exp $
* $Id: beos_specific.cpp,v 1.26 2002/09/30 18:30:28 titer Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
*
......@@ -24,6 +24,9 @@
#include <Roster.h>
#include <Path.h>
#include <Alert.h>
#include <Message.h>
#include <Window.h>
#include <stdio.h>
#include <string.h> /* strdup() */
#include <malloc.h> /* free() */
......@@ -46,6 +49,12 @@ public:
virtual void ReadyToRun();
virtual void AboutRequested();
virtual void RefsReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
private:
BWindow* fInterfaceWindow;
BMessage* fRefsMessage;
};
/*****************************************************************************
......@@ -53,6 +62,9 @@ public:
*****************************************************************************/
static char * psz_program_path;
//const uint32 INTERFACE_CREATED = 'ifcr'; /* message sent from interface */
#include "../../modules/gui/beos/MsgVals.h"
extern "C"
{
......@@ -125,7 +137,9 @@ static void AppThread( vlc_object_t * p_this )
* VlcApplication: application constructor
*****************************************************************************/
VlcApplication::VlcApplication( char * psz_mimetype )
:BApplication( psz_mimetype )
:BApplication( psz_mimetype ),
fInterfaceWindow( NULL ),
fRefsMessage( NULL )
{
/* Nothing to do, we use the default constructor */
}
......@@ -136,6 +150,7 @@ VlcApplication::VlcApplication( char * psz_mimetype )
VlcApplication::~VlcApplication( )
{
/* Nothing to do, we use the default destructor */
delete fRefsMessage;
}
/*****************************************************************************
......@@ -168,3 +183,48 @@ void VlcApplication::ReadyToRun( )
/* Tell the main thread we are finished initializing the BApplication */
vlc_thread_ready( p_this );
}
/*****************************************************************************
* 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