]> git.sesse.net Git - vlc/commitdiff
BeOS enhancements by Stephan Assmus :
authorEric Petit <titer@videolan.org>
Sun, 29 Sep 2002 12:04:28 +0000 (12:04 +0000)
committerEric Petit <titer@videolan.org>
Sun, 29 Sep 2002 12:04:28 +0000 (12:04 +0000)
  - many fixes
  - added ability to open a file by dropping it onto the vlc icon
  - blanks cursor when no activity
  - added "Speed" menu
  - made nicer look similar to BeOS MediaPlayer
  - playlist now functioning
  - screen capture option
  - and more...

22 files changed:
configure
configure.in
plugins/beos/Bitmaps.h
plugins/beos/DrawingTidbits.cpp
plugins/beos/DrawingTidbits.h
plugins/beos/InterfaceWindow.cpp
plugins/beos/InterfaceWindow.h
plugins/beos/Makefile
plugins/beos/MediaControlView.cpp
plugins/beos/MediaControlView.h
plugins/beos/MsgVals.h
plugins/beos/PlayListWindow.cpp
plugins/beos/PlayListWindow.h
plugins/beos/TransportButton.cpp
plugins/beos/TransportButton.h
plugins/beos/VideoWindow.h
plugins/beos/intf_vlc_wrapper.cpp
plugins/beos/intf_vlc_wrapper.h
plugins/beos/vout_beos.cpp
plugins/spudec/spu_decoder.c
share/vlc_beos.rsrc
src/misc/beos_specific.cpp

index 5c9067d8b25dd4b47c1f6ec49e38651a69870778..3576cc369d28a9cbe73a5bc7951d9d00990efb57 100755 (executable)
--- a/configure
+++ b/configure
@@ -3273,7 +3273,7 @@ fi
     save_CFLAGS="${save_CFLAGS} -Wno-multichar -Wno-ctor-dtor-privacy -Woverloaded-virtual"
     vlc_LDFLAGS="${vlc_LDFLAGS} -lbe"
     plugins_LDFLAGS="${plugins_LDFLAGS} -nostart"
-    beos_LDFLAGS="${beos_LDFLAGS} -lbe -lgame -lroot -ltracker -lstdc++.r4"
+    beos_LDFLAGS="${beos_LDFLAGS} -lbe -lgame -lroot -ltracker -ltranslation -lstdc++.r4"
     ipv4_LDFLAGS="${ipv4_LDFLAGS} -lbind"
     ;;
   x*)
index b76fe0ddaae80c8e8e3c07bf836349815c44b3f0..0307c30c7f7de434e4ff2f32aa4a199e6ea47f0b 100644 (file)
@@ -93,7 +93,7 @@ case x"${target_os}" in
     save_CFLAGS="${save_CFLAGS} -Wno-multichar -Wno-ctor-dtor-privacy -Woverloaded-virtual"
     vlc_LDFLAGS="${vlc_LDFLAGS} -lbe"
     plugins_LDFLAGS="${plugins_LDFLAGS} -nostart"
-    beos_LDFLAGS="${beos_LDFLAGS} -lbe -lgame -lroot -ltracker -lstdc++.r4"
+    beos_LDFLAGS="${beos_LDFLAGS} -lbe -lgame -lroot -ltracker -ltranslation -lstdc++.r4"
     ipv4_LDFLAGS="${ipv4_LDFLAGS} -lbind"
     ;;
   x*)
index dbd0ef44e78f87d246e853f332cc3fcaab04c32c..f1aa1ec46e997558e96979da4f25090510a497ca 100644 (file)
@@ -2,7 +2,7 @@
  * Bitmaps.h
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: Bitmaps.h,v 1.4.4.1 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: Bitmaps.h,v 1.4.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *          Stephan Aßmus <stippi@yellowbites.com>
index 898950cd9cf5a3a33c5d6ee7f68809f944426602..c6557623195ea351993ddaffe7ba2ba6fceaeb7c 100644 (file)
@@ -2,7 +2,7 @@
  * DrawingTidbits.cpp
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: DrawingTidbits.cpp,v 1.2.4.1 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: DrawingTidbits.cpp,v 1.2.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *          Stephan Aßmus <stippi@yellowbites.com>
@@ -22,6 +22,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#include <math.h>
+
 #include <Bitmap.h>
 #include <Debug.h>
 #include <Screen.h>
@@ -111,61 +113,247 @@ 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)
+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())
+       // 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))
+               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();
+                       uint8* srcBits = (uint8*)inBitmap->Bits();
+                       uint8* dstBits = (uint8*)outBitmap->Bits();
                        switch (inBitmap->ColorSpace())
                        {
                                case B_YCbCr422:
-                                       for (int32 y = 0; y < height; y ++)
+                                       // 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)
+                                               for ( int32 x = 0; x < width; x += 2 )
                                                {
-                                                       uint8 y = 
-                                                       uint8 cb = 
-                                                       uint8 cr = 
+                                                       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;
+                                               srcBits += srcBpr;
+                                               dstBits += dstBpr;
                                        }
                                        status = B_OK;
                                        break;
                                case B_YCbCr420:
-                                       status = B_OK;
+                                       // 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:
-                                       status = B_OK;
+                                       // 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:
-                                       memcpy(dstBits, srcBits, inBitmap->BitsLength());
+                               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;
 }
 
index 3ec5e9918af849d2bdc6f8d0bb13e7b387eb980d..9d9694bb3a2e12d38845335805cc1a672eeba69e 100644 (file)
@@ -2,7 +2,7 @@
  * DrawingTidbits.h
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: DrawingTidbits.h,v 1.2.4.1 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: DrawingTidbits.h,v 1.2.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *          Stephan Aßmus <stippi@yellowbites.com>
@@ -52,13 +52,23 @@ const float kDimLevel = 0.6;
 
 void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to);
 void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with);
+
+// 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
-//   B_RGB32   -> B_RGB32
-//status_t convert_bitmap(BBitmap* inBitmap, BBitmap* outBitmap);
+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
index 41c2ab90d8f7541f1e91e5fe5393da6c513cc9a9..9af26a1c17d9aaf8f90c89d824fba2c174e34c35 100644 (file)
@@ -2,7 +2,7 @@
  * InterfaceWindow.cpp: beos interface
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: InterfaceWindow.cpp,v 1.16.2.3 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: InterfaceWindow.cpp,v 1.16.2.4 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -67,27 +67,29 @@ extern "C"
  *****************************************************************************/
 
 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_ZOOMABLE | B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS ),
-         p_intf(p_interface),
-         b_empty_playlist(p_main->p_playlist->i_size < 0),
-         file_panel(NULL),
-         playlist_window(NULL),
-         fLastUpdateTime(system_time())
+                                                                 intf_thread_t  *p_interface )
+       : 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 ),
+         fPlaylistIsEmpty( p_main->p_playlist->i_size < 1 ),
+         fFilePanel( NULL ),
+         fPlaylistWindow( new PlayListWindow( BRect( 20.0, 20.0, 170.0, 320.0 ),
+                                                                                  "Playlist", (playlist_t*)p_main->p_playlist, this ) ),
+         fLastUpdateTime( system_time() ),
+         fSettings( new BMessage( 'sett' ) )
 {
        // set the title bar
        SetName( "interface" );
-       SetTitle(VOUT_TITLE);
+       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) );
-       b_empty_playlist = true;
-       p_mediaControl->SetEnabled( !b_empty_playlist );
+       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);
+       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",
@@ -95,90 +97,93 @@ InterfaceWindow::InterfaceWindow( BRect frame, const char *name,
 
        // 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!
+       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);
+       height += fMenuBar->Bounds().Height();
+       ResizeTo( width, height );
 
        p_mediaControl->MoveTo( fMenuBar->Bounds().LeftBottom() + BPoint(0.0, 1.0) );
        AddChild( fMenuBar );
        AddChild( p_mediaControl );
 
-    BMenu *fileMenu;
-//     BMenu *configMenu;
-    
        // Add the file Menu
-       BMenuItem *mItem;
-       fMenuBar->AddItem( fileMenu = new BMenu( "File" ) );
-       fileMenu->AddItem( mItem = new BMenuItem( "Open File" B_UTF8_ELLIPSIS,
-                                           new BMessage(OPEN_FILE), 'O') );
-    
-    fileMenu->AddItem( new CDMenu( "Open Disc" ) );
-    
-    fileMenu->AddSeparatorItem();
-    fileMenu->AddItem( mItem = new BMenuItem( "Play List" B_UTF8_ELLIPSIS,
-                                           new BMessage(OPEN_PLAYLIST), 'P') );
-    
-    fileMenu->AddSeparatorItem();
-    fileMenu->AddItem( mItem = new BMenuItem( "About" B_UTF8_ELLIPSIS,
-                                       new BMessage(B_ABOUT_REQUESTED), 'A') );
-    mItem->SetTarget( be_app );
-    fileMenu->AddItem(mItem = new BMenuItem( "Quit",
-                                        new BMessage(B_QUIT_REQUESTED), 'Q') );
+       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 */
-    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 */
-    fNavigationMenu = new BMenu( "Navigation" );
-    fMenuBar->AddItem( fNavigationMenu );
-    fNavigationMenu->AddItem(fPrevTitleMI);
-    fNavigationMenu->AddItem(fNextTitleMI);
-    fNavigationMenu->AddItem(fPrevChapterMI);
-    fNavigationMenu->AddItem(fNextChapterMI);
+       /* Add the Audio menu */
+       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 */
+       fNavigationMenu = new BMenu( "Navigation" );
+       fMenuBar->AddItem( fNavigationMenu );
+       fNavigationMenu->AddItem( fPrevTitleMI );
+       fNavigationMenu->AddItem( fNextTitleMI );
+       fNavigationMenu->AddItem( fTitleMenu = new TitleMenu( "Go to Title" ) );
+       fNavigationMenu->AddSeparatorItem();
+       fNavigationMenu->AddItem( fPrevChapterMI );
+       fNavigationMenu->AddItem( fNextChapterMI );
+       fNavigationMenu->AddItem( fChapterMenu = new ChapterMenu( "Go to Chapter" ) );
 
        /* Add the Speed menu */
-       fSpeedMenu = new BMenu("Speed");
-       fSpeedMenu->SetRadioMode(true);
-    fSpeedMenu->AddItem( new BMenuItem( "Slow",
-                                       new BMessage(SLOWER_PLAY)) );
-       BMenuItem* normalSpeedItem = new BMenuItem( "Normal",
-                                               new BMessage(NORMAL_PLAY));
-       normalSpeedItem->SetMarked(true); // default to normal speed
-    fSpeedMenu->AddItem( normalSpeedItem );
-    fSpeedMenu->AddItem( new BMenuItem( "Fast",
-                                       new BMessage(FASTER_PLAY)) );
-       fSpeedMenu->SetTargetForItems(this);
-       fMenuBar->AddItem(fSpeedMenu);
-
-                                        
-    /* Add the Config menu */
-//    menu_bar->AddItem( configMenu = new BMenu( "Config" ) );
-//    menu_bar->ResizeToPreferred();
-//    configMenu->AddItem( miOnTop = new BMenuItem( "Always on Top",
-//                                        new BMessage(TOGGLE_ON_TOP)) );
-//    miOnTop->SetMarked(false);                                    
-
-    /* Show */
-    _SetMenusEnabled(false);
-    Show();
+       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;
 }
 
 /*****************************************************************************
@@ -200,269 +205,267 @@ InterfaceWindow::FrameResized(float width, float height)
  *****************************************************************************/
 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(); // why ?!?
-    if (p_input_bank->pp_input[0])
-    {
-           playback_status = p_input_bank->pp_input[0]->stream.control.i_status;
-       }
+       int playback_status;      // remember playback state
+       if ( p_input_bank->pp_input[0] )
+               playback_status = p_input_bank->pp_input[0]->stream.control.i_status;
        else
-       {
-           playback_status = UNDEF_S;
-       }
+               playback_status = UNDEF_S;
 
-    switch( p_message->what )
-    {
-    case B_ABOUT_REQUESTED:
-        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 )
-        {
-            file_panel->Show();
-            break;
-        }
-        file_panel = new BFilePanel();
-        file_panel->SetTarget( this );
-        file_panel->Show();
-        b_empty_playlist = false;
-        p_mediaControl->SetEnabled( !b_empty_playlist );
-        break;
-
-       case OPEN_PLAYLIST:
+       switch( p_message->what )
+       {
+               case B_ABOUT_REQUESTED:
                {
-                   BRect rect(20,20,320,420);
-            playlist_window = PlayListWindow::getPlayList(rect,
-                                "Playlist", (playlist_t *)p_main->p_playlist);
-            playlist_window->Show();                    
-        }
-               break;
-    case OPEN_DVD:
-        {
-            const char *psz_device;
-            BString type("dvd");
-            if( p_message->FindString("device", &psz_device) == B_OK )
-            {
-                BString device(psz_device);
-                Intf_VLCWrapper::openDisc(type, device, 0,0);
-                b_empty_playlist = false;
-                p_mediaControl->SetEnabled( !b_empty_playlist );
-            }
-        }
-        break;
-
-    case STOP_PLAYBACK:
-        // this currently stops playback not nicely
-        if (playback_status > UNDEF_S)
-        {
-               Intf_VLCWrapper::volume_mute();
-               snooze( 400000 );
-               Intf_VLCWrapper::playlistStop();
-               p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
-        }
-        break;
-
-    case START_PLAYBACK:
-        /*  starts playing in normal mode */
-
-    case PAUSE_PLAYBACK:
-        /* toggle between pause and play */
-        if (playback_status > UNDEF_S)
-        {
-            /* pause if currently playing */
-            if ( playback_status == PLAYING_S )
-            {
-                Intf_VLCWrapper::volume_mute();
-                snooze( 400000 );
-                Intf_VLCWrapper::playlistPause();
-            }
-            else
-            {
-                Intf_VLCWrapper::volume_restore();
-                Intf_VLCWrapper::playlistPlay();
-            }
-        }
-        else
-        {
-            /* Play a new file */
-            Intf_VLCWrapper::playlistPlay();
-        }    
-        break;
-
-    case FASTER_PLAY:
-        /* cycle the fast playback modes */
-       if (playback_status > UNDEF_S)
-       {
-               Intf_VLCWrapper::volume_mute();
-               snooze( 400000 );
-               Intf_VLCWrapper::playFaster();
-       }
-        break;
-
-    case SLOWER_PLAY:
-        /*  cycle the slow playback modes */
-       if (playback_status > UNDEF_S)
-       {
-               Intf_VLCWrapper::volume_mute();
-               snooze( 400000 );
-               Intf_VLCWrapper::playSlower();
-       }
-        break;
-
-    case NORMAL_PLAY:
-        /*  restore speed to normal if already playing */
-       if (playback_status > UNDEF_S)
-       {
-            Intf_VLCWrapper::volume_restore();
-            Intf_VLCWrapper::playlistPlay();
-       }
-        break;
-
-    case SEEK_PLAYBACK:
-        /* handled by semaphores */
-        break;
-
-    case VOLUME_CHG:
-        /* adjust the volume */
-        if (playback_status > UNDEF_S)
-        {
-/*             vlc_mutex_lock( &p_aout_bank->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 );*/
-               Intf_VLCWrapper::set_volume( vol_val );
-               p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
-        }
-        break;
-
-    case VOLUME_MUTE:
-        /* toggle muting */
-        Intf_VLCWrapper::toggle_mute();
-        p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
-        break;
-
-    case SELECT_CHANNEL:
-        if (playback_status > UNDEF_S)
-        {
-            int32 i = p_message->FindInt32( "channel" );
-            if ( i == -1 )
-            {
-                input_ChangeES( p_input_bank->pp_input[0], NULL, AUDIO_ES );
-            }
-            else
-            {
-                input_ChangeES( p_input_bank->pp_input[0],
-                        p_input_bank->pp_input[0]->stream.pp_es[i], AUDIO_ES );
-            }
-        }
-        break;
-
-    case SELECT_SUBTITLE:
-        if (playback_status > UNDEF_S)
-        {
-            int32 i = p_message->FindInt32( "subtitle" );
-            if ( i == -1 )
-            {
-                input_ChangeES( p_input_bank->pp_input[0], NULL, SPU_ES);
-            }
-            else
-            {
-                input_ChangeES( p_input_bank->pp_input[0],
-                        p_input_bank->pp_input[0]->stream.pp_es[i], SPU_ES );
-            }
-        }
-        break;
-    case PREV_TITLE:
-        if (playback_status > UNDEF_S)
-        {
-            int             i_id;
-            i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1;
-
-            /* Disallow area 0 since it is used for video_ts.vob */
-            if( i_id > 0 )
-            {
-                Intf_VLCWrapper::toggleTitle(i_id);
-            }
-            break;
-        }
-    case NEXT_TITLE:
-        if (playback_status > UNDEF_S)
-        {
-            int             i_id;
-
-            i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id + 1;
-
-            if( i_id < p_input_bank->pp_input[0]->stream.i_area_nb )
-            {
-                Intf_VLCWrapper::toggleTitle(i_id);
-            }
-        }
-        break;
-    case PREV_CHAPTER:
-        if (playback_status > UNDEF_S)
-        {
-            int             i_id;
-
-            i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_part - 1;
-
-            if( i_id >= 0 )
-            {
-                Intf_VLCWrapper::toggleChapter(i_id);
-            }
-        }
-        break;
-    case NEXT_CHAPTER:
-        if (playback_status > UNDEF_S)
-        {
-            int             i_id;
-
-            i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_part + 1;
-
-            if( i_id >= 0 )
-            {
-                Intf_VLCWrapper::toggleChapter(i_id);
-            }
-        }
-        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()) );
-                i++;
-            }
-            Intf_VLCWrapper::openFiles(files);
-            delete files;
-        }
-        break;
-
-    default:
-        BWindow::MessageReceived( p_message );
-        break;
-    }
+                       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( fFilePanel )
+                       {
+                               fFilePanel->Show();
+                               break;
+                       }
+                       fFilePanel = new BFilePanel();
+                       fFilePanel->SetTarget( this );
+                       fFilePanel->Show();
+                       break;
+       
+               case OPEN_PLAYLIST:
+                       if (fPlaylistWindow->Lock())
+                       {
+                               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_OK )
+                               {
+                                       BString device( psz_device );
+                                       Intf_VLCWrapper::openDisc( type, device, 0, 0 );
+                               }
+                               _UpdatePlaylist();
+                       }
+                       break;
+       
+               case STOP_PLAYBACK:
+                       // this currently stops playback not nicely
+                       if (playback_status > UNDEF_S)
+                       {
+                               Intf_VLCWrapper::volume_mute();
+                               snooze( 400000 );
+                               Intf_VLCWrapper::playlistStop();
+                               p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
+                       }
+                       break;
+       
+               case START_PLAYBACK:
+                       /*  starts playing in normal mode */
+       
+               case PAUSE_PLAYBACK:
+                       /* toggle between pause and play */
+                       if (playback_status > UNDEF_S)
+                       {
+                               /* pause if currently playing */
+                               if ( playback_status == PLAYING_S )
+                               {
+                                       Intf_VLCWrapper::volume_mute();
+                                       snooze( 400000 );
+                                       Intf_VLCWrapper::playlistPause();
+                               }
+                               else
+                               {
+                                       Intf_VLCWrapper::volume_restore();
+                                       Intf_VLCWrapper::playlistPlay();
+                               }
+                       }
+                       else
+                       {
+                               /* Play a new file */
+                               Intf_VLCWrapper::playlistPlay();
+                       }       
+                       break;
+       
+               case FASTER_PLAY:
+                       /* cycle the fast playback modes */
+                       if (playback_status > UNDEF_S)
+                       {
+                               Intf_VLCWrapper::volume_mute();
+                               snooze( 400000 );
+                               Intf_VLCWrapper::playFaster();
+                       }
+                       break;
+       
+               case SLOWER_PLAY:
+                       /*  cycle the slow playback modes */
+                       if (playback_status > UNDEF_S)
+                       {
+                               Intf_VLCWrapper::volume_mute();
+                               snooze( 400000 );
+                               Intf_VLCWrapper::playSlower();
+                       }
+                       break;
+       
+               case NORMAL_PLAY:
+                       /*  restore speed to normal if already playing */
+                       if (playback_status > UNDEF_S)
+                       {
+                               Intf_VLCWrapper::volume_restore();
+                               Intf_VLCWrapper::playlistPlay();
+                       }
+                       break;
+       
+               case SEEK_PLAYBACK:
+                       /* handled by semaphores */
+                       break;
+               // volume related messages
+               case VOLUME_CHG:
+                       /* adjust the volume */
+                       if (playback_status > UNDEF_S)
+                       {
+                               Intf_VLCWrapper::set_volume( p_mediaControl->GetVolume() );
+                               p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
+                       }
+                       break;
+       
+               case VOLUME_MUTE:
+                       // toggle muting
+                       Intf_VLCWrapper::toggle_mute();
+                       p_mediaControl->SetMuted( Intf_VLCWrapper::is_muted() );
+                       break;
+       
+               case SELECT_CHANNEL:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int32 channel;
+                               if ( p_message->FindInt32( "channel", &channel ) == B_OK )
+                               {
+                                       Intf_VLCWrapper::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
+                                       Intf_VLCWrapper::set_volume( p_mediaControl->GetVolume() );
+                               }
+                       }
+                       break;
+       
+               case SELECT_SUBTITLE:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int32 subtitle;
+                               if ( p_message->FindInt32( "subtitle", &subtitle ) == B_OK )
+                                       Intf_VLCWrapper::toggleSubtitle( subtitle );
+                       }
+                       break;
+       
+               // specific navigation messages
+               case PREV_TITLE:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id - 1;
+       
+                               /* Disallow area 0 since it is used for video_ts.vob */
+                               if( i_id > 0 )
+                                       Intf_VLCWrapper::toggleTitle( i_id );
+                       }
+                       break;
+               case NEXT_TITLE:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_id + 1;
+       
+                               if( i_id < p_input_bank->pp_input[0]->stream.i_area_nb - 1 )
+                                       Intf_VLCWrapper::toggleTitle( i_id );
+                       }
+                       break;
+               case TOGGLE_TITLE:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int32 index;
+                               if ( p_message->FindInt32( "index", &index ) == B_OK )
+                                       Intf_VLCWrapper::toggleTitle( index );
+                       }
+                       break;
+               case PREV_CHAPTER:
+                       if (playback_status > UNDEF_S)
+                       {
+                               int i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_part - 1;
+       
+                               if( i_id >= 0 )
+                                       Intf_VLCWrapper::toggleChapter( i_id );
+                       }
+                       break;
+               case NEXT_CHAPTER:
+                       if (playback_status > UNDEF_S)
+                       {
+                               int i_id = p_input_bank->pp_input[0]->stream.p_selected_area->i_part + 1;
+       
+                               if( i_id < p_input_bank->pp_input[0]->stream.p_selected_area->i_part_nb - 1 )
+                                       Intf_VLCWrapper::toggleChapter( i_id );
+                       }
+                       break;
+               case TOGGLE_CHAPTER:
+                       if ( playback_status > UNDEF_S )
+                       {
+                               int32 index;
+                               if ( p_message->FindInt32( "index", &index ) == B_OK )
+                                       Intf_VLCWrapper::toggleChapter( index );
+                       }
+                       break;
+               case PREV_FILE:
+                       Intf_VLCWrapper::playlistPrev();
+                       break;
+               case NEXT_FILE:
+                       Intf_VLCWrapper::playlistNext();
+                       break;
+               // general next/prev functionality (skips to whatever makes most sense)
+               case NAVIGATE_PREV:
+                       Intf_VLCWrapper::navigatePrev();
+                       break;
+               case NAVIGATE_NEXT:
+                       Intf_VLCWrapper::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;
+                               for ( int i = 0; p_message->FindRef( "refs", i, &ref ) == B_OK; i++ )
+                               {
+                                       BPath path( &ref );
+                                       if ( path.InitCheck() == B_OK )
+                                               // the BString objects will be deleted
+                                               // by the wrapper function further down
+                                               files.AddItem( new BString( (char*)path.Path() ) );
+                               }
+                               // give the list to VLC
+                               Intf_VLCWrapper::openFiles(&files, replace);
+                               _UpdatePlaylist();
+                       }
+                       break;
+       
+               default:
+                       BWindow::MessageReceived( p_message );
+                       break;
+       }
 
 }
 
@@ -479,9 +482,11 @@ bool InterfaceWindow::QuitRequested()
                p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE);
        }
        
-    p_intf->b_die = 1;
+       p_intf->b_die = 1;
+
+       _StoreSettings();
 
-    return( true );
+       return( true );
 }
 
 /*****************************************************************************
@@ -489,49 +494,71 @@ bool InterfaceWindow::QuitRequested()
  *****************************************************************************/
 void InterfaceWindow::updateInterface()
 {
-       if ( p_input_bank->pp_input[0] )
+       input_thread_s* input = p_input_bank->pp_input[0];
+       if ( input )
        {
-        if ( acquire_sem(p_mediaControl->fScrubSem) == B_OK )
-        {
-            uint64 seekTo = (p_mediaControl->GetSeekTo() *
-                        p_input_bank->pp_input[0]->stream.p_selected_area->i_size) / 2048;
-            input_Seek( p_input_bank->pp_input[0], seekTo);
-        }
-        else if( Lock() )
-        {
-               bool hasTitles = p_input_bank->pp_input[0]->stream.i_area_nb > 1;
-               bool hasChapters = p_input_bank->pp_input[0]->stream.p_selected_area->i_part_nb > 1;
-            p_mediaControl->SetStatus(p_input_bank->pp_input[0]->stream.control.i_status, 
-                                      p_input_bank->pp_input[0]->stream.control.i_rate);
-            p_mediaControl->SetProgress(p_input_bank->pp_input[0]->stream.p_selected_area->i_tell,
-                                        p_input_bank->pp_input[0]->stream.p_selected_area->i_size);
-               _SetMenusEnabled(true, hasChapters, hasTitles);
-               bool canSkipBack = false;
-               bool canSkipForward = false;
-               if (hasChapters)
-               {
-                               canSkipBack = p_input_bank->pp_input[0]->stream.p_selected_area->i_part > 0;
-                               canSkipForward = p_input_bank->pp_input[0]->stream.p_selected_area->i_part <
-                                                                p_input_bank->pp_input[0]->stream.p_selected_area->i_part_nb - 1;
-               }
-               p_mediaControl->SetSkippable(canSkipBack, canSkipForward);
-               p_mediaControl->SetMuted(Intf_VLCWrapper::is_muted());
-            Unlock();
-        }
-    }
-    else
+               if ( acquire_sem( p_mediaControl->fScrubSem ) == B_OK )
+               {
+                       uint64 seekTo = ( p_mediaControl->GetSeekTo()
+                                                       * input->stream.p_selected_area->i_size ) / 2048;
+                       input_Seek( input, seekTo );
+               }
+               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;
+                       Intf_VLCWrapper::getNavCapabilities( &canSkipPrev, &canSkipNext );
+                       p_mediaControl->SetSkippable( canSkipPrev, canSkipNext );
+
+                       if ( Intf_VLCWrapper::has_audio() )
+                       {
+                               p_mediaControl->SetAudioEnabled( true );
+                               p_mediaControl->SetMuted( Intf_VLCWrapper::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);
 
-    if ( b_empty_playlist != (p_main->p_playlist->i_size < 1) )
-    {
-        if (Lock())
-        {
-            b_empty_playlist = !b_empty_playlist;
-            p_mediaControl->SetEnabled( !b_empty_playlist );
-            Unlock();
-        }
-    }
-    fLastUpdateTime = system_time();
+       if ( fPlaylistIsEmpty != ( p_main->p_playlist->i_size < 1 ) )
+       {
+               if ( Lock() )
+               {
+                       fPlaylistIsEmpty = !fPlaylistIsEmpty;
+                       p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
+                       Unlock();
+               }
+       }
+       if ( input != fInputThread )
+               fInputThread = input;
+
+       fLastUpdateTime = system_time();
 }
 
 /*****************************************************************************
@@ -543,6 +570,21 @@ InterfaceWindow::IsStopped() const
        return (system_time() - fLastUpdateTime > INTERFACE_UPDATE_TIMEOUT);
 }
 
+/*****************************************************************************
+ * InterfaceWindow::_UpdatePlaylist
+ *****************************************************************************/
+void
+InterfaceWindow::_UpdatePlaylist()
+{
+       if ( fPlaylistWindow->Lock() )
+       {
+               fPlaylistWindow->UpdatePlaylist( true );
+               fPlaylistWindow->Unlock();
+               fPlaylistIsEmpty = p_main->p_playlist->i_size < 1;
+               p_mediaControl->SetEnabled( !fPlaylistIsEmpty );
+       }
+}
+
 /*****************************************************************************
  * InterfaceWindow::_SetMenusEnabled
  *****************************************************************************/
@@ -560,10 +602,14 @@ InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles
                        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)
@@ -578,11 +624,228 @@ InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles
        }
 }
 
+/*****************************************************************************
+ * 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::_InputStreamChanged
+ *****************************************************************************/
+void
+InterfaceWindow::_InputStreamChanged()
+{
+//printf("InterfaceWindow::_InputStreamChanged()\n");
+       // TODO: move more stuff from updateInterface() here!
+       snooze( 400000 );
+       Intf_VLCWrapper::set_volume( p_mediaControl->GetVolume() );
+}
+
+/*****************************************************************************
+ * 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" );
+}
+
 /*****************************************************************************
  * CDMenu::CDMenu
  *****************************************************************************/
 CDMenu::CDMenu(const char *name)
-      : BMenu(name)
+         : BMenu(name)
 {
 }
 
@@ -599,10 +862,10 @@ CDMenu::~CDMenu()
 void CDMenu::AttachedToWindow(void)
 {
        // remove all items
-    while (BMenuItem* item = RemoveItem(0L))
-       delete item;
-    GetCD("/dev/disk");
-    BMenu::AttachedToWindow();
+       while (BMenuItem* item = RemoveItem(0L))
+               delete item;
+       GetCD("/dev/disk");
+       BMenu::AttachedToWindow();
 }
 
 /*****************************************************************************
@@ -611,13 +874,13 @@ void CDMenu::AttachedToWindow(void)
 int CDMenu::GetCD( const char *directory )
 {
        BVolumeRoster *volRoster;
-       BVolume       *vol;
-       BDirectory    *dir;
-       int           status;
-       int           mounted;   
-       char          name[B_FILE_NAME_LENGTH]; 
-    fs_info       info;
-       dev_t         dev;
+       BVolume    *vol;
+       BDirectory      *dir;
+       int                status;
+       int                mounted;   
+       char              name[B_FILE_NAME_LENGTH]; 
+       fs_info    info;
+       dev_t            dev;
        
        volRoster = new BVolumeRoster();
        vol = new BVolume();
@@ -626,36 +889,36 @@ int CDMenu::GetCD( const char *directory )
        status = vol->GetRootDirectory(dir);
        while (status ==  B_NO_ERROR)
        {
-           mounted = vol->GetName(name);       
-           if ((mounted == B_OK) && /* Disk is currently Mounted */
-               (vol->IsReadOnly()) ) /* Disk is read-only */
-           {
-               dev = vol->Device();
-            fs_stat_dev(dev, &info);
-            
-            device_geometry g;
-            int i_dev;
-            i_dev = open( info.device_name, O_RDONLY );
-           
-            if( i_dev >= 0 )
-            {
-                if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
-                {
-                    if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
-                    {
-                        BMessage *msg;
-                        msg = new BMessage( OPEN_DVD );
-                        msg->AddString( "device", info.device_name );
-                        BMenuItem *menu_item;
-                        menu_item = new BMenuItem( name, msg );
-                        AddItem( menu_item );
-                    }
-                    close(i_dev);
-                }
-            }
-           }
-           vol->Unset();
-           status = volRoster->GetNextVolume(vol);
+               mounted = vol->GetName(name);   
+               if ((mounted == B_OK) && /* Disk is currently Mounted */
+                       (vol->IsReadOnly()) ) /* Disk is read-only */
+               {
+                       dev = vol->Device();
+                       fs_stat_dev(dev, &info);
+                       
+                       device_geometry g;
+                       int i_dev;
+                       i_dev = open( info.device_name, O_RDONLY );
+                  
+                       if( i_dev >= 0 )
+                       {
+                               if( ioctl(i_dev, B_GET_GEOMETRY, &g, sizeof(g)) >= 0 )
+                               {
+                                       if( g.device_type == B_CD ) //ensure the drive is a CD-ROM
+                                       {
+                                               BMessage *msg;
+                                               msg = new BMessage( OPEN_DVD );
+                                               msg->AddString( "device", info.device_name );
+                                               BMenuItem *menu_item;
+                                               menu_item = new BMenuItem( name, msg );
+                                               AddItem( menu_item );
+                                       }
+                                       close(i_dev);
+                               }
+                       }
+               }
+               vol->Unset();
+               status = volRoster->GetNextVolume(vol);
        }
 }
 
@@ -663,11 +926,11 @@ int CDMenu::GetCD( const char *directory )
  * LanguageMenu::LanguageMenu
  *****************************************************************************/
 LanguageMenu::LanguageMenu(const char *name, int menu_kind, 
-                            intf_thread_t  *p_interface)
-    :BMenu(name)
+                                                       intf_thread_t  *p_interface)
+       :BMenu(name)
 {
-    kind = menu_kind;
-    p_intf = p_interface;
+       kind = menu_kind;
+       p_intf = p_interface;
 }
 
 /*****************************************************************************
@@ -680,87 +943,197 @@ LanguageMenu::~LanguageMenu()
 /*****************************************************************************
  * LanguageMenu::AttachedToWindow
  *****************************************************************************/
-void LanguageMenu::AttachedToWindow(void)
+void LanguageMenu::AttachedToWindow()
 {
        // remove all items
-    while (BMenuItem* item = RemoveItem(0L))
-       delete item;
+       while ( BMenuItem* item = RemoveItem( 0L ) )
+               delete item;
+
+       SetRadioMode( true );
+       _GetChannels();
+       BMenu::AttachedToWindow();
+}
+
+/*****************************************************************************
+ * 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 "None" item if in subtitle mode
+       if( kind != AUDIO_ES ) //subtitle
+       {
+               msg = new BMessage( SELECT_SUBTITLE );
+               msg->AddInt32( "subtitle", -1 );
+               menu_item = new BMenuItem( "None", msg );
+               AddItem( menu_item );
+               menu_item->SetMarked( true );
+       }
+
+       input_thread_s* input = p_input_bank->pp_input[0];
+       if ( input )
+       {
+               vlc_mutex_lock( &input->stream.stream_lock );
+               for( i = 0; i < input->stream.i_selected_es_number; i++ )
+               {
+                       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";
+       
+               for ( i = 0; i < input->stream.i_es_number; i++ )
+               {
+                       if ( kind == input->stream.pp_es[i]->i_cat )
+                       {
+                               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>";
+//                                     }
+                               }
+                               if ( addItem )
+                               {
+                                       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 );
+       }
+}
+
 
-    SetRadioMode(true);
-    GetChannels();
-    BMenu::AttachedToWindow();
+
+/*****************************************************************************
+ * TitleMenu::TitleMenu
+ *****************************************************************************/
+TitleMenu::TitleMenu( const char *name )
+       : BMenu(name)
+{
 }
 
 /*****************************************************************************
- * LanguageMenu::GetChannels
+ * TitleMenu::~TitleMenu
  *****************************************************************************/
-int 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 != AUDIO_ES ) //subtitle
-    {
-        msg = new BMessage(SELECT_SUBTITLE);
-        msg->AddInt32("subtitle", -1);
-           menu_item = new BMenuItem("None", msg);
-           AddItem(menu_item);
-           menu_item->SetMarked(true);
-    }
-
-    if( p_input_bank->pp_input[0] == NULL )
-    {
-        return 1;
-    }
-
-       int32 addedItems = 0;
-
-    vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
-    for( i = 0; i < p_input_bank->pp_input[0]->stream.i_selected_es_number; i++ )
-    {
-        if( kind == p_input_bank->pp_input[0]->stream.pp_selected_es[i]->i_cat )
-        {
-            p_es = p_input_bank->pp_input[0]->stream.pp_selected_es[i];
-        }
-    }
-
-    for( i = 0; i < p_input_bank->pp_input[0]->stream.i_es_number; i++ )
-    {
-        if( kind == p_input_bank->pp_input[0]->stream.pp_es[i]->i_cat )
-        {
-               addedItems++;
-            psz_name = p_input_bank->pp_input[0]->stream.pp_es[i]->psz_desc;
-            if( kind == AUDIO_ES ) //audio
-            {
-                msg = new BMessage(SELECT_CHANNEL);
-                msg->AddInt32("channel", i);
-            }
-            else
-            {
-                msg = new BMessage(SELECT_SUBTITLE);
-                msg->AddInt32("subtitle", i);
-            }
-            BMenuItem *menu_item;
-            // workarround for irritating empty strings
-            if (strcmp(psz_name, "") == 0)
-               psz_name = "Default";
-            menu_item = new BMenuItem(psz_name, msg);
-            AddItem(menu_item);
-            b_active = (p_es == p_input_bank->pp_input[0]->stream.pp_es[i]);
-            menu_item->SetMarked(b_active);
-        }
-    }
-    vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
-
-       // enhance readability and separate first item from rest
-       if (addedItems > 1)
-                AddItem(new BSeparatorItem(), 1);
+TitleMenu::~TitleMenu()
+{
 }
 
+/*****************************************************************************
+ * TitleMenu::AttachedToWindow
+ *****************************************************************************/
+void TitleMenu::AttachedToWindow()
+{
+       // make title menu empty
+       while ( BMenuItem* item = RemoveItem( 0L ) )
+               delete item;
 
+       input_thread_s* input = p_input_bank->pp_input[0];
+       if ( input )
+       {
+               // 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 )
+               {
+                       // disallow title 0!
+                       for ( int32 i = 1; i < numTitles; 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 );
+                       }
+               }
+               // done messing with stream
+               vlc_mutex_unlock( &input->stream.stream_lock );
+       }
+       BMenu::AttachedToWindow();
+}
+
+
+/*****************************************************************************
+ * ChapterMenu::ChapterMenu
+ *****************************************************************************/
+ChapterMenu::ChapterMenu( const char *name )
+       : BMenu(name)
+{
+}
+
+/*****************************************************************************
+ * ChapterMenu::~ChapterMenu
+ *****************************************************************************/
+ChapterMenu::~ChapterMenu()
+{
+}
+
+/*****************************************************************************
+ * ChapterMenu::AttachedToWindow
+ *****************************************************************************/
+void ChapterMenu::AttachedToWindow()
+{
+       // make title menu empty
+       while ( BMenuItem* item = RemoveItem( 0L ) )
+               delete item;
+
+       input_thread_s* input = p_input_bank->pp_input[0];
+       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();
+}
 
index f2dc8e773ad57153c45fb8dc600d17039b6e5cda..d3aa1bef671cbf43c596b9b89246a2ca076abdf9 100644 (file)
@@ -2,7 +2,7 @@
  * InterfaceWindow.h: BeOS interface window class prototype
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: InterfaceWindow.h,v 1.12.2.3 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: InterfaceWindow.h,v 1.12.2.4 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Tony Castley <tcastley@mail.powerup.com.au>
@@ -38,42 +38,62 @@ class BFilePanel;
 class CDMenu : public BMenu
 {
  public:
-                                                       CDMenu(const char* name);
+                                                       CDMenu( const char* name );
        virtual                                 ~CDMenu();
 
-       virtual void                    AttachedToWindow(void);
+       virtual void                    AttachedToWindow();
 
  private:
-       int                                             GetCD(const char* directory);
+       int                                             GetCD( const char* directory );
 };
 
 class LanguageMenu : public BMenu
 {
  public:
-                                                       LanguageMenu(const char* name,
-                                                                                int menu_kind,
-                                                                                intf_thread_t* p_interface);
+                                                       LanguageMenu( const char* name,
+                                                                                 int menu_kind,
+                                                                                 intf_thread_t* p_interface );
        virtual                                 ~LanguageMenu();
 
-       virtual void                    AttachedToWindow(void);
+       virtual void                    AttachedToWindow();
 
  private:
+                       void                    _GetChannels();
+
        intf_thread_t*                  p_intf;
        int                                             kind;
-       int                                             GetChannels();
 };
 
+class TitleMenu : public BMenu
+{
+ public:
+                                                       TitleMenu( const char* name );
+       virtual                                 ~TitleMenu();
+
+       virtual void                    AttachedToWindow();
+};
+
+class ChapterMenu : public BMenu
+{
+ public:
+                                                       ChapterMenu( const char* name );
+       virtual                                 ~ChapterMenu();
+
+       virtual void                    AttachedToWindow();
+};
+
+
 class InterfaceWindow : public BWindow
 {
  public:
-                                                       InterfaceWindow(BRect frame,
-                                                                                       const char* name,
-                                                                                       intf_thread_t* p_interface);
+                                                       InterfaceWindow( BRect frame,
+                                                                                        const char* name,
+                                                                                        intf_thread_t* p_interface );
        virtual                                 ~InterfaceWindow();
 
-                                                       // standard window member
-       virtual void                    FrameResized(float width, float height);
-       virtual void                    MessageReceived(BMessage* message);
+                                                       // BWindow
+       virtual void                    FrameResized( float width, float height );
+       virtual void                    MessageReceived( BMessage* message );
        virtual bool                    QuitRequested();
 
                                                        // InterfaceWindow
@@ -83,28 +103,48 @@ class InterfaceWindow : public BWindow
        MediaControlView*               p_mediaControl;
 
  private:      
-       void                                    _SetMenusEnabled(bool hasFile,
-                                                                                        bool hasChapters = false,
-                                                                                        bool hasTitles = false);
+                       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;
-       bool                                    b_empty_playlist;
-       BFilePanel*                             file_panel;
-       PlayListWindow*                 playlist_window;
-       BMenuItem*                              miOnTop;
        es_descriptor_t*                p_audio_es;
        es_descriptor_t*                p_spu_es;
+       input_thread_s*                 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
 };
 
 #endif // BEOS_INTERFACE_WINDOW_H
index 802ff0cd6a56ec6136635843e791260905275809..e5278f8a8833db1ef4177cd968f37b4affd79782 100644 (file)
@@ -1 +1 @@
-beos_SOURCES = beos.cpp aout_beos.cpp vout_beos.cpp intf_beos.cpp InterfaceWindow.cpp DrawingTidbits.cpp TransportButton.cpp PlayListWindow.cpp MediaControlView.cpp intf_vlc_wrapper.cpp
+beos_SOURCES = beos.cpp aout_beos.cpp vout_beos.cpp intf_beos.cpp InterfaceWindow.cpp DrawingTidbits.cpp TransportButton.cpp PlayListWindow.cpp MediaControlView.cpp intf_vlc_wrapper.cpp ListViews.cpp
index dd69c1ee3244e0159d34f962ef3757b4dc614f01..b75ef3a94e1217a4e79d6c052cc724ca99b6beac 100644 (file)
@@ -2,7 +2,7 @@
  * MediaControlView.cpp: beos interface
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: MediaControlView.cpp,v 1.7.2.2 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: MediaControlView.cpp,v 1.7.2.3 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tony@castley.net>
  *          Stephan Aßmus <stippi@yellowbites.com>
@@ -172,7 +172,7 @@ MediaControlView::MediaControlView(BRect frame)
     // Volume Slider
        fVolumeSlider = new VolumeSlider(BRect(0.0, 0.0, VOLUME_MIN_WIDTH,
                                                                                   kVolumeSliderBitmapHeight - 1.0),
-                                                                        "volume slider", 0, VOLUME_MAX,
+                                                                        "volume slider", 1, VOLUME_MAX,
                                                                         new BMessage(VOLUME_CHG));
        fVolumeSlider->SetValue(VOLUME_DEFAULT);
        AddChild( fVolumeSlider );
@@ -257,10 +257,10 @@ MediaControlView::MessageReceived(BMessage* message)
                case MSG_FORWARD:
                        break;
                case MSG_SKIP_BACKWARDS:
-                       Window()->PostMessage(PREV_CHAPTER);
+                       Window()->PostMessage(NAVIGATE_PREV);
                        break;
                case MSG_SKIP_FORWARD:
-                       Window()->PostMessage(NEXT_CHAPTER);
+                       Window()->PostMessage(NAVIGATE_NEXT);
                        break;
                default:
                    BBox::MessageReceived(message);
@@ -333,6 +333,14 @@ MediaControlView::SetEnabled(bool enabled)
        fForward->SetEnabled(enabled);
 }
 
+// SetAudioEnabled
+void
+MediaControlView::SetAudioEnabled(bool enabled)
+{
+       fMute->SetEnabled(enabled);
+       fVolumeSlider->SetEnabled(enabled);
+}
+
 // GetSeekTo
 uint32
 MediaControlView::GetSeekTo() const
index ed67d1f20ce3e034089803da39755e399ca49476..9649992da1d85a725fd58cfea4ae77db1eb84dee 100644 (file)
@@ -2,7 +2,7 @@
  * MediaControlView.h: beos interface
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: MediaControlView.h,v 1.2.4.1 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: MediaControlView.h,v 1.2.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tony@castley.net>
  *          Stephan Aßmus <stippi@yellowbites.com>
@@ -52,6 +52,7 @@ class MediaControlView : public BBox
 
                        void                            SetStatus(int status, int rate); 
                        void                            SetEnabled(bool enable);
+                       void                            SetAudioEnabled(bool enable);
                        uint32                          GetSeekTo() const;
                        uint32                          GetVolume() const;
                        void                            SetSkippable(bool backward,
index 2b575d2ead6887d27d315d6feea13e1609c1964b..49951872bbd1297482ebf21a532a17eabd9072db 100644 (file)
@@ -2,7 +2,7 @@
  * MsgVals.h
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: MsgVals.h,v 1.9.2.3 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: MsgVals.h,v 1.9.2.4 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *          Stephan Aßmus <stippi@yellowbites.com>
@@ -44,16 +44,24 @@ 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 */
 
index e32a39845d1534e7717177fa7b91382e4a7f73b7..aa308afe2a2562f8a2f05136cb9a97c652e53c1a 100644 (file)
@@ -2,12 +2,13 @@
  * PlayListWindow.cpp: beos interface
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: PlayListWindow.cpp,v 1.5.2.1 2002/06/01 10:12:10 tcastley Exp $
+ * $Id: PlayListWindow.cpp,v 1.5.2.2 2002/09/29 12:04: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
@@ -42,128 +43,214 @@ extern "C"
 }
 
 /* BeOS interface headers */
+#include "intf_vlc_wrapper.h"
 #include "InterfaceWindow.h"
+#include "ListViews.h"
 #include "MsgVals.h"
 #include "PlayListWindow.h"
 
+enum
+{
+       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::PlayListWindow
  *****************************************************************************/
-PlayListWindow *PlayListWindow::getPlayList( BRect frame, const char *name,
-                                  playlist_t *p_pl)
+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 ),
+               fPlaylist( playlist ),
+               fMainWindow( mainWindow )
 {
-    static PlayListWindow *one_playlist;
-    if (one_playlist == NULL)
-    {
-       one_playlist = new PlayListWindow(frame, name, p_pl);
-    }
-    return one_playlist;
+    SetName( "playlist" );
+
+    // 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( BRect frame, const char *name,
-                                  playlist_t *p_pl)
-    : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
-                B_WILL_ACCEPT_FIRST_CLICK | B_ASYNCHRONOUS_CONTROLS )
+/*****************************************************************************
+ * PlayListWindow::~PlayListWindow
+ *****************************************************************************/
+PlayListWindow::~PlayListWindow()
 {
-    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->p_item[i].psz_name)); 
-    }
-    p_view->AddChild(new BScrollView("scroll_playlist", p_listview,
-             B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true)); 
-             
-    AddChild(p_view);
 }
 
-PlayListWindow::~PlayListWindow()
+/*****************************************************************************
+ * PlayListWindow::QuitRequested
+ *****************************************************************************/
+bool
+PlayListWindow::QuitRequested()
 {
+       Hide(); 
+       return false;
 }
 
 /*****************************************************************************
  * PlayListWindow::MessageReceived
  *****************************************************************************/
-void PlayListWindow::MessageReceived( BMessage * p_message )
+void
+PlayListWindow::MessageReceived( BMessage * p_message )
 {
-    Activate();
-
-    switch( p_message->what )
-    {
-    case OPEN_FILE:
-        if( file_panel )
-        {
-            file_panel->Show();
-            break;
-        }
-        file_panel = new BFilePanel();
-        file_panel->SetTarget( this );
-        file_panel->Show();
-        break;
-
-    case OPEN_DVD:
-        const char *psz_device;
-        char psz_source[ B_FILE_NAME_LENGTH + 4 ];
-        if( p_message->FindString("device", &psz_device) != B_ERROR )
-        {
-            snprintf( psz_source, B_FILE_NAME_LENGTH + 4,
-                      "dvd:%s", psz_device );
-            psz_source[ strlen(psz_source) ] = '\0';
-            intf_PlaylistAdd( p_playlist, PLAYLIST_END, (char*)psz_source );
-            p_listview->AddItem(new BStringItem((char*)psz_source));
-        }
-    case B_REFS_RECEIVED:
-    case B_SIMPLE_DATA:
-        {
-            entry_ref ref;
-            if( p_message->FindRef( "refs", &ref ) == B_OK )
-            {
-                BPath path( &ref );
-                intf_PlaylistAdd( p_playlist,
-                                  PLAYLIST_END, (char*)path.Path() );
-                p_listview->AddItem(new BStringItem((char*)path.Path()));
-            }
-        }
-        break;
-    default:
-        BWindow::MessageReceived( p_message );
-        break;
-    }
+       switch ( p_message->what )
+       {
+               case OPEN_DVD:
+               case B_REFS_RECEIVED:
+               case B_SIMPLE_DATA:
+                       // 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 );
+                       break;
+       }
 }
 
-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();
-}
\ No newline at end of file
+}
+
+/*****************************************************************************
+ * 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() );
+}
index 7e8f7f18e952adc84f04cd534c57701d2b889403..ba7eb3f1e5f2f0f64e2ed4420e2d1bc38a551ec4 100644 (file)
@@ -2,11 +2,12 @@
  * PlayListWindow.h: BeOS interface window class prototype
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: PlayListWindow.h,v 1.1.4.2 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: PlayListWindow.h,v 1.1.4.3 2002/09/29 12:04: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
 
 #include <Window.h>
 
-class BFilePanel;
 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();
-
-    // standard window member
-    virtual void    MessageReceived(BMessage *message);
-    
-private:       
-    PlayListWindow( BRect frame, const char *name, playlist_t *p_pl);
-    playlist_t  *p_playlist;
-    BListView  *p_listview;
-    BFilePanel *file_panel;
+ public:
+                                                               PlayListWindow(BRect frame,
+                                                                                          const char* name,
+                                                                                          playlist_t* playlist,
+                                                                                          InterfaceWindow* mainWindow );
+       virtual                                         ~PlayListWindow();
+
+                                                               // 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:      
+
+                       playlist_t*                     fPlaylist;
+                       PlaylistView*           fListView;
+                       BView*                          fBackgroundView;
+                       BMenuBar*                       fMenuBar;
+                       InterfaceWindow*        fMainWindow;
 };
 
 #endif // BEOS_PLAY_LIST_WINDOW_H
index 970244155c2221e2445ad3a3772317638437d624..2fa12af4660ba32215a56cd0f918524e5af90401 100644 (file)
@@ -2,7 +2,7 @@
  * TransportButton.cpp
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: TransportButton.cpp,v 1.3.4.1 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: TransportButton.cpp,v 1.3.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *          Stephan Aßmus <stippi@yellowbites.com>
index 51aa6a87abf59298010a16d72e9f9e6d3455caa7..392bcdedc63e95309f05b8fb2946f684ea496f75 100644 (file)
@@ -2,7 +2,7 @@
  * TransportButton.h
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: TransportButton.h,v 1.3.4.1 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: TransportButton.h,v 1.3.4.2 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Tony Castley <tcastley@mail.powerup.com.au>
  *
index 341d74ce0c5db02ef8733ec1d7354d4239177b5a..fbe8764ec305cf6b5f2fa8e16c46cbfce286ca64 100644 (file)
@@ -2,7 +2,7 @@
  * VideoWindow.h: BeOS video window class prototype
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: VideoWindow.h,v 1.19.2.5 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: VideoWindow.h,v 1.19.2.6 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Tony Castley <tcastley@mail.powerup.com.au>
@@ -74,6 +74,7 @@ class VLCView : public BView
                        bigtime_t               fLastMouseMovedTime;
                        bool                    fCursorHidden;
                        bool                    fCursorInside;
+                       bool                    fIgnoreDoubleClick;
 };
 
 
@@ -130,6 +131,20 @@ private:
                        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 
index f2cbd5b668680c538beed434163c77211b142084..0b6415511153be46c3f44775b78692af3c4cfa3b 100644 (file)
@@ -2,7 +2,7 @@
  * intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: intf_vlc_wrapper.cpp,v 1.1.2.2 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: intf_vlc_wrapper.cpp,v 1.1.2.3 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Florian G. Pflug <fgp@phlo.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
@@ -90,30 +90,32 @@ bool Intf_VLCWrapper::playlistPlay()
 {
     if( p_input_bank->pp_input[0] != NULL )
     {
-        input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
-        p_main->p_playlist->b_stopped = 0;
+               input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
+
+               playlistLock();
+               p_main->p_playlist->b_stopped = 0;
+               playlistUnlock();
+
+               p_main->p_intf->p_sys->b_mute = 0;
     }
     else
     {
-        vlc_mutex_lock( &p_main->p_playlist->change_lock );
+        playlistLock();
 
         if( p_main->p_playlist->b_stopped )
         {
             if( p_main->p_playlist->i_size )
             {
-                vlc_mutex_unlock( &p_main->p_playlist->change_lock );
+                playlistUnlock();
                 intf_PlaylistJumpto( p_main->p_playlist,
-                                     p_main->p_playlist->i_index );
+                                     p_main->p_playlist->i_index - 1 );
+                               p_main->p_intf->p_sys->b_mute = 0;
             }
             else
-            {
-                vlc_mutex_unlock( &p_main->p_playlist->change_lock );
-            }
+                playlistUnlock();
         }
         else
-        {
-            vlc_mutex_unlock( &p_main->p_playlist->change_lock );
-        }
+            playlistUnlock();
     }
 
     return( true );
@@ -126,9 +128,9 @@ void Intf_VLCWrapper::playlistPause()
     {
         input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PAUSE );
 
-        vlc_mutex_lock( &p_main->p_playlist->change_lock );
+        playlistLock();
         p_main->p_playlist->b_stopped = 0;
-        vlc_mutex_unlock( &p_main->p_playlist->change_lock );
+        playlistUnlock();
     }
 }
 
@@ -137,38 +139,222 @@ void Intf_VLCWrapper::playlistStop()
     if( p_input_bank->pp_input[0] != NULL )
     {
         /* end playing item */
-        p_input_bank->pp_input[0]->b_eof = 1;
+        input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_END );
 
         /* update playlist */
-        vlc_mutex_lock( &p_main->p_playlist->change_lock );
-
-        p_main->p_playlist->i_index--;
+        playlistLock();
         p_main->p_playlist->b_stopped = 1;
-
-        vlc_mutex_unlock( &p_main->p_playlist->change_lock );
+        playlistUnlock();
     }
 
 }
 
 void Intf_VLCWrapper::playlistNext()
 {
-    if( p_input_bank->pp_input[0] != NULL )
-    {
-        p_input_bank->pp_input[0]->b_eof = 1;
-    }
+       playlistJumpTo( playlistCurrentPos() + 1 );
 }
 
 void Intf_VLCWrapper::playlistPrev()
 {
+       playlistJumpTo( playlistCurrentPos() - 1 );
+}
+
+void Intf_VLCWrapper::playlistJumpTo( int pos )
+{
+       // 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 )
-    {
-        /* FIXME: temporary hack */
-        intf_PlaylistPrev( p_main->p_playlist );
-        intf_PlaylistPrev( p_main->p_playlist );
-        p_input_bank->pp_input[0]->b_eof = 1;
-    }
+               pos--;
+       // stop current stream
+       playlistStop();
+       // modify current position in playlist
+       playlistLock();
+       p_main->p_playlist->i_index = pos;
+       playlistUnlock();
+       // start playing
+       playlistPlay();
+}
+
+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 ( 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_s* 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;
+       }
+}
+
+void Intf_VLCWrapper::navigatePrev()
+{
+       bool hasSkiped = false;
+
+       input_thread_s* 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();
+}
+
+void Intf_VLCWrapper::navigateNext()
+{
+       bool hasSkiped = false;
+
+       input_thread_s* 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();
 }
 
+
 //void Intf_VLCWrapper::channelNext()
 //{
 //    intf_thread_t * p_intf = p_main->p_intf;
@@ -250,86 +436,137 @@ void Intf_VLCWrapper::playFaster()
 
 void Intf_VLCWrapper::volume_mute()
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return;
-    if( p_main->p_intf->p_sys->b_mute ) return;
-    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;
+    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 = 
+                                       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::volume_restore()
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return;
-
-    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;
+    if( p_aout_bank->i_count > 0
+       && p_aout_bank->pp_aout[0] != NULL )
+    {
+           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::set_volume(int value)
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return;
-//printf("Intf_VLCWrapper::set_volume(%ld)\n", value);
-       // make sure value is within bounds
-       if (value < 0)
-               value = 0;
-       if (value > VOLUME_MAX)
-               value = VOLUME_MAX;
-       vlc_mutex_lock( &p_aout_bank->lock );
-               // unmute volume if muted
-               if (p_main->p_intf->p_sys->b_mute)
-               {
-                       p_main->p_intf->p_sys->b_mute = 0;
-//                     p_main->p_intf->p_sys->i_saved_volume = 0;
-               }
-               // set every stream to the given value
-               for(int i = 0 ; i < p_aout_bank->i_count ; i++ )
-               {
-                       if (p_aout_bank->pp_aout[i])
+    if( p_aout_bank->i_count > 0
+       && p_aout_bank->pp_aout[0] != NULL )
+    {
+               // make sure value is within bounds
+               if (value < 0)
+                       value = 0;
+               if (value > VOLUME_MAX)
+                       value = VOLUME_MAX;
+               vlc_mutex_lock( &p_aout_bank->lock );
+                       // unmute volume if muted
+                       if ( p_main->p_intf->p_sys->b_mute )
+                               p_main->p_intf->p_sys->b_mute = 0;
+                       // set every stream to the given value
+                       for ( int i = 0 ; i < p_aout_bank->i_count ; i++ )
                        {
-//                             p_aout_bank->pp_aout[i]->i_savedvolume = 0;
-                               p_aout_bank->pp_aout[i]->i_volume = value;
+                               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_aout_bank->lock );
+    }
 }
 
 void Intf_VLCWrapper::toggle_mute()
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return;
-    if ( p_main->p_intf->p_sys->b_mute )
-    {
-        Intf_VLCWrapper::volume_restore();
-    }
-    else
-    {
-        Intf_VLCWrapper::volume_mute();
-    }
-//    p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
+    if( p_aout_bank->i_count > 0
+       && p_aout_bank->pp_aout[0] != NULL )
+       {
+           if ( p_main->p_intf->p_sys->b_mute )
+           {
+               Intf_VLCWrapper::volume_restore();
+           }
+           else
+           {
+               Intf_VLCWrapper::volume_mute();
+           }
+       }
 }
 
 bool Intf_VLCWrapper::is_muted()
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return false;
-    return p_main->p_intf->p_sys->b_mute;
+       bool muted = true;
+       if ( p_aout_bank->i_count > 0 )
+       {
+               vlc_mutex_lock( &p_aout_bank->lock );
+                       for ( int i = 0 ; i < p_aout_bank->i_count ; i++ )
+                       {
+                               if ( p_aout_bank->pp_aout[i]
+                                        && p_aout_bank->pp_aout[i]->i_volume > 0 )
+                               {
+                                       muted = false;
+                                       break;
+                               }
+                       }
+               vlc_mutex_unlock( &p_aout_bank->lock );
+// unfortunately, this is not reliable!
+//             return p_main->p_intf->p_sys->b_mute;
+       }
+       return muted;
 }
 
-void Intf_VLCWrapper::maxvolume()
+bool Intf_VLCWrapper::is_playing()
 {
-    if( p_aout_bank->pp_aout[0] == NULL ) return;
+       bool playing = false;
+       if ( p_input_bank->pp_input[0] )
+       {
+               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;
+}
 
-    if( p_main->p_intf->p_sys->b_mute )
-    {
-        p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
-    }
-    else
+void Intf_VLCWrapper::maxvolume()
+{
+    if( p_aout_bank->i_count > 0
+       && p_aout_bank->pp_aout[0] != NULL )
     {
-        p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
+           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;
+           }
     }
 }
 
+bool Intf_VLCWrapper::has_audio()
+{
+       return (p_aout_bank->i_count > 0);
+}
+
 //void Intf_VLCWrapper::fullscreen()
 //{
 //    if( p_vout_bank->pp_vout[0] != NULL )
@@ -403,39 +640,43 @@ 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;
-    int i_end = p_main->p_playlist->i_size;
-    intf_thread_t * p_intf = p_main->p_intf;
+       BString *o_file;
+       int i_end = p_main->p_playlist->i_size;
+       intf_thread_t * p_intf = p_main->p_intf;
 
+       // make sure we remove the "loop" item from the end before mucking arround
     if ( p_intf->p_sys->b_loop )
     {
-        intf_PlaylistDelete( p_main->p_playlist,
-                             p_main->p_playlist->i_size - 1 );
+               intf_PlaylistDelete( p_main->p_playlist, i_end - 1 );
+               i_end--;
     }
 
-    while( ( o_file = (BString *)o_files->LastItem() ) )
-    {
-        o_files->RemoveItem(o_files->CountItems() - 1);
-        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, 
-                          o_file->String() );
-        delete o_file;
+       // add the new files to the playlist
+       while ( ( o_file = (BString *)o_files->LastItem() ) )
+       {
+               o_files->RemoveItem(o_files->CountItems() - 1);
+               intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, 
+                                                 o_file->String() );
+               delete o_file;
     }
 
-    /* end current item, select first added item */
-    if( p_input_bank->pp_input[0] != NULL )
-    {
-        p_input_bank->pp_input[0]->b_eof = 1;
-    }
-
-    intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
-
-    if ( p_intf->p_sys->b_loop )
-    {
-        intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, 
-                          "vlc:loop" );
-    }
+       if ( replace || i_end < 1 )
+       {
+               // end current item
+               if ( p_input_bank->pp_input[0] != NULL )
+                       p_input_bank->pp_input[0]->b_eof = 1;
+               // remove everything that was in playlist before
+               for ( int i = 0; i < i_end; i++ )
+                       intf_PlaylistDelete( p_main->p_playlist, 0 );
+               // jump to beginning and start playing
+               intf_PlaylistJumpto( p_main->p_playlist, -1 );
+       }
+
+       // if we were looping, add special "loop" item back to list
+       if ( p_intf->p_sys->b_loop )
+               intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END, "vlc:loop" );
 }
 
 void Intf_VLCWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
@@ -445,7 +686,6 @@ void Intf_VLCWrapper::openDisc(BString o_type, BString o_device, int i_title, in
     intf_thread_t * p_intf = p_main->p_intf;
 
     o_source << o_type << ":" << o_device ;
-    //i_title, i_chapter;
 
     if ( p_intf->p_sys->b_loop )
     {
@@ -515,7 +755,38 @@ void Intf_VLCWrapper::toggleChapter(int i_chapter)
     input_SetStatus( p_input, INPUT_STATUS_PLAY );
 }
 
-    void Intf_VLCWrapper::toggleLanguage(int i_language){}
-    void Intf_VLCWrapper::toggleSubtitle(int i_subtitle){}
+void Intf_VLCWrapper::toggleLanguage( int i_language )
+{
+       if ( input_thread_t * p_input = p_input_bank->pp_input[0] )
+       {
+               if ( i_language == -1 )
+               {
+                       input_ChangeES( p_input, NULL, AUDIO_ES );
+               }
+               else if ( i_language >= 0
+                                 && i_language < p_input->stream.i_es_number )
+               {
+                       input_ChangeES( p_input, p_input->stream.pp_es[i_language], AUDIO_ES );
+               }
+       }
+}
+
+void Intf_VLCWrapper::toggleSubtitle(int i_subtitle)
+{
+       if ( input_thread_t * p_input = p_input_bank->pp_input[0] )
+       {
+               if ( i_subtitle == -1 )
+               {
+                       input_ChangeES( p_input, NULL, SPU_ES );
+               }
+               else if ( i_subtitle >= 0
+                                 && i_subtitle < p_input->stream.i_es_number )
+               {
+                       input_ChangeES( p_input, p_input->stream.pp_es[i_subtitle], SPU_ES );
+               }
+       }
+}
+
+
     void Intf_VLCWrapper::setupMenus(){}
     
index a110e2594eeb4507eeec4f5b9e5ea7a607b1ef1c..314646792ec93782028345aa04bcce6821871764 100644 (file)
@@ -2,7 +2,7 @@
  * intf_vlc_wrapper.h: BeOS plugin for vlc (derived from MacOS X port )
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: intf_vlc_wrapper.h,v 1.1.2.2 2002/09/03 12:00:25 tcastley Exp $
+ * $Id: intf_vlc_wrapper.h,v 1.1.2.3 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Florian G. Pflug <fgp@phlo.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
@@ -53,6 +53,17 @@ public:
     static void playlistStop();
     static void playlistNext();
     static void playlistPrev();
+    static void playlistJumpTo( int pos );
+    static int playlistCurrentPos();
+    static int playlistSize();
+       static void playlistLock();
+       static void playlistUnlock();
+
+    static void getNavCapabilities( bool* canSkipPrev,
+                                                               bool* canSkipNext );
+       static void     navigatePrev();
+       static void     navigateNext();
+
 //    static void channelNext();
 //    static void channelPrev();
     static void loop();
@@ -65,30 +76,33 @@ public:
     static void set_volume(int value);
     static void toggle_mute();
     static bool is_muted();
+    static bool is_playing();
     static void maxvolume();
+    static bool has_audio();
 //    static void fullscreen();
     static void eject();
 
     /* playback info */
     static BString* getTimeAsString();
     static float  getTimeAsFloat();
-    static void   setTimeAsFloat(float i_offset);
+    static void   setTimeAsFloat( float i_offset );
     static bool   playlistPlaying();
     static BList* playlistAsArray();
 
     /* open file/disc/network */
-    static void openFiles(BList *o_files);
-    static void openDisc(BString o_type, BString o_device, int i_title, int i_chapter);
-    static void openNet(BString o_addr, int i_port);
-    static void openNetChannel(BString o_addr, int i_port);
-    static void openNetHTTP(BString o_addr);
+    static void openFiles( BList *o_files, bool replace = true );
+    static void openDisc( BString o_type, BString o_device,
+                                         int i_title, int i_chapter );
+    static void openNet( BString o_addr, int i_port );
+    static void openNetChannel( BString o_addr, int i_port );
+    static void openNetHTTP( BString o_addr );
 
     /* menus management */
-    static void toggleProgram(int i_program);
-    static void toggleTitle(int i_title);
-    static void toggleChapter(int i_chapter);
-    static void toggleLanguage(int i_language);
-    static void toggleSubtitle(int i_subtitle);
+    static void toggleProgram( int i_program );
+    static void toggleTitle( int i_title );
+    static void toggleChapter( int i_chapter );
+    static void toggleLanguage( int i_language );
+    static void toggleSubtitle( int i_subtitle );
     static void setupMenus();
 };
 
index 53a04386282b5b564d08e95a20823e11fbad8d48..29315001782845213fa1f5b25e0725a40e53a079 100644 (file)
@@ -2,7 +2,7 @@
  * vout_beos.cpp: beos video output display method
  *****************************************************************************
  * Copyright (C) 2000, 2001 VideoLAN
- * $Id: vout_beos.cpp,v 1.58.2.5 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: vout_beos.cpp,v 1.58.2.6 2002/09/29 12:04:27 titer Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
 #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>
 
 extern "C"
 {
@@ -73,6 +79,8 @@ typedef struct vout_sys_s
 
 #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
@@ -220,6 +228,7 @@ VideoWindow::MessageReceived( BMessage *p_message )
                case TOGGLE_FULL_SCREEN:
                        BWindow::Zoom();
                        break;
+               case RESIZE_50:
                case RESIZE_100:
                case RESIZE_200:
                        if (is_zoomed)
@@ -242,6 +251,41 @@ VideoWindow::MessageReceived( BMessage *p_message )
                case ASPECT_CORRECT:
                        SetCorrectAspectRatio(!fCorrectAspect);
                        break;
+               case SCREEN_SHOT:
+                       // save a screen shot
+                       if ( BBitmap* current = bitmap[i_buffer] )
+                       {
+// 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() )
+                               {
+                                       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++ )
+                                       {
+                                               memcpy( dst, src, validBytes );
+                                               dst += dstBpr;
+                                               src += srcBpr;
+                                       }
+                                       _SaveScreenShot( temp,
+                                                                        strdup( DEFAULT_SCREEN_SHOT_PATH ),
+                                                                        DEFAULT_SCREEN_SHOT_FORMAT );
+                               }
+                               else
+                               {
+                                       delete temp;
+                                       fprintf( stderr, "error copying bitmaps\n" );
+                               }
+                       }
+                       break;
                default:
                        BWindow::MessageReceived( p_message );
                        break;
@@ -481,12 +525,16 @@ VideoWindow::_AllocateBuffers(int width, int height, int* mode)
 
     if (*mode == BITMAP)
        {
-        // fallback to RGB32
-        colspace_index = DEFAULT_COL;
-        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);
+        // 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;
@@ -609,6 +657,10 @@ VideoWindow::_SetVideoSize(uint32 mode)
        int32 height = fCorrectAspect ? i_height : fTrueHeight;
        switch (mode)
        {
+               case RESIZE_50:
+                       width /= 2;
+                       height /= 2;
+                       break;
                case RESIZE_200:
                        width *= 2;
                        height *= 2;
@@ -621,6 +673,187 @@ VideoWindow::_SetVideoSize(uint32 mode)
        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;
+
+                       // 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++ )
+                               { 
+                                       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;
+                                                                       }
+                                                               } 
+                                                               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;
+}
 
 
 /*****************************************************************************
@@ -630,7 +863,8 @@ VLCView::VLCView(BRect bounds)
        : BView(bounds, "video view", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED),
          fLastMouseMovedTime(system_time()),
          fCursorHidden(false),
-         fCursorInside(false)
+         fCursorInside(false),
+         fIgnoreDoubleClick(false)
 {
     SetViewColor(B_TRANSPARENT_32_BIT);
 }
@@ -671,27 +905,36 @@ VLCView::MouseDown(BPoint where)
        {
                if (buttons & B_PRIMARY_MOUSE_BUTTON)
                {
-                       if (clicks == 2)
+                       if (clicks == 2 && !fIgnoreDoubleClick)
                                Window()->Zoom();
                        else
                                videoWindow->ToggleInterfaceShowing();
+                       fIgnoreDoubleClick = false;
                }
            else
            {
                        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(videoWindow->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();
        
@@ -707,7 +950,7 @@ VLCView::MouseDown(BPoint where)
                                menu->AddSeparatorItem();
        
                                // Windwo Feel Items
-                               BMessage *winNormFeel = new BMessage(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(videoWindow->Feel() == B_NORMAL_WINDOW_FEEL);
@@ -723,11 +966,25 @@ VLCView::MouseDown(BPoint where)
                                winAllFeel->AddInt32("WinFeel", (int32)B_FLOATING_ALL_WINDOW_FEEL);
                                BMenuItem *allSpacesWindItem = new BMenuItem("On Top All Workspaces", winAllFeel);
                                allSpacesWindItem->SetMarked(videoWindow->Feel() == B_FLOATING_ALL_WINDOW_FEEL);
-                               menu->AddItem(allSpacesWindItem);
-                          
-                               menu->SetTargetForItems(this);
-                               ConvertToScreen(&where);
-                               menu->Go(where, true, false, true);
+                               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 );
                }
                }
        }
@@ -755,14 +1012,17 @@ 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) {
-           VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
+       if (!fCursorHidden)
+       {
                if (fCursorInside
-                       && system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT) {
+                       && system_time() - fLastMouseMovedTime > MOUSE_IDLE_TIMEOUT)
+               {
                        be_app->ObscureCursor();
                        fCursorHidden = true;
-                       // hide the interface window as well
-                       videoWindow->SetInterfaceShowing(false);
+                       VideoWindow *videoWindow = dynamic_cast<VideoWindow*>(Window());
+                       // hide the interface window as well if full screen
+                       if (videoWindow && videoWindow->is_zoomed)
+                               videoWindow->SetInterfaceShowing(false);
                }
        }
 }
@@ -799,10 +1059,10 @@ VLCView::KeyDown(const char *bytes, int32 numBytes)
                                {
                                        if (mods & B_SHIFT_KEY)
                                                // next title
-                                               interfaceWindow->PostMessage(NEXT_CHAPTER);
+                                               interfaceWindow->PostMessage(NEXT_TITLE);
                                        else
                                                // next chapter
-                                               interfaceWindow->PostMessage(NEXT_TITLE);
+                                               interfaceWindow->PostMessage(NEXT_CHAPTER);
                                }
                                break;
                        case B_LEFT_ARROW:
@@ -810,17 +1070,24 @@ VLCView::KeyDown(const char *bytes, int32 numBytes)
                                {
                                        if (mods & B_SHIFT_KEY)
                                                // previous title
-                                               interfaceWindow->PostMessage(PREV_CHAPTER);
+                                               interfaceWindow->PostMessage(PREV_TITLE);
                                        else
                                                // previous chapter
-                                               interfaceWindow->PostMessage(PREV_TITLE);
+                                               interfaceWindow->PostMessage(PREV_CHAPTER);
                                }
                                break;
                        case B_UP_ARROW:
-                               // previous file in playlist?
+                               // previous file in playlist
+                               interfaceWindow->PostMessage(PREV_FILE);
                                break;
                        case B_DOWN_ARROW:
-                               // next file in playlist?
+                               // 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);
@@ -835,9 +1102,9 @@ VLCView::KeyDown(const char *bytes, int32 numBytes)
 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 );
 }
 
 
@@ -1026,10 +1293,10 @@ void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
     if (!p_win->teardownwindow)
     { 
        p_win->drawBuffer(p_vout->p_sys->i_index);
+           /* change buffer */
+           p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
+           p_pic->p->p_pixels = (u8*)p_win->bitmap[p_vout->p_sys->i_index]->Bits();
     }
-    /* change buffer */
-    p_vout->p_sys->i_index = ++p_vout->p_sys->i_index % 3;
-    p_pic->p->p_pixels = (u8*)p_vout->p_sys->p_window->bitmap[p_vout->p_sys->i_index]->Bits();
 }
 
 /* following functions are local */
index 234396065d8d2430593ce56c5b1166f57149452c..f2b05da18bdb9749e9a70f6522830e30d5f54f96 100644 (file)
@@ -2,7 +2,7 @@
  * spu_decoder.c : spu decoder thread
  *****************************************************************************
  * Copyright (C) 2000-2001 VideoLAN
- * $Id: spu_decoder.c,v 1.24.2.4 2002/09/25 23:11:54 massiot Exp $
+ * $Id: spu_decoder.c,v 1.24.2.5 2002/09/29 12:04:28 titer Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *          Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
@@ -1146,12 +1146,14 @@ static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic,
     case FOURCC_YUY2:
 
     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 ; )
index 5c730451302081e2a6e93efb7c0ea01bfcb0f804..aad79c69f199e270b83cb69758b531b035dc85a2 100644 (file)
Binary files a/share/vlc_beos.rsrc and b/share/vlc_beos.rsrc differ
index 346e17deea432924fdd80eba84223ffcb1726eb0..3b3b9f02f414575d80e1d52d522f5c06608153ab 100644 (file)
@@ -2,7 +2,7 @@
  * beos_init.cpp: Initialization for BeOS specific features 
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: beos_specific.cpp,v 1.18.2.1 2002/09/03 12:00:24 tcastley Exp $
+ * $Id: beos_specific.cpp,v 1.18.2.2 2002/09/29 12:04:28 titer Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *
@@ -131,9 +131,9 @@ char * system_GetProgramPath( void )
  *****************************************************************************/
 static void system_AppThread( void * args )
 {
-    VlcApplication *BeApp = new VlcApplication("application/x-vnd.Ink-vlc");
-    BeApp->Run();
-    delete BeApp;
+    new VlcApplication("application/x-vnd.Ink-vlc");
+    be_app->Run();
+    delete be_app;
 }
 
 } /* extern "C" */