From 49173f5e3eff2e7b3c72a618c40b616534a4bfe7 Mon Sep 17 00:00:00 2001 From: Stephan Assmus Date: Sat, 1 Feb 2003 12:01:11 +0000 Subject: [PATCH] Changes done since Feb 28 2003: --- modules/gui/beos/Interface.cpp | 8 +- modules/gui/beos/InterfaceWindow.cpp | 758 +++++++++++++++++--------- modules/gui/beos/InterfaceWindow.h | 26 +- modules/gui/beos/ListViews.cpp | 610 +++++++++++++++------ modules/gui/beos/ListViews.h | 32 +- modules/gui/beos/MediaControlView.cpp | 12 +- modules/gui/beos/MessagesWindow.cpp | 26 +- modules/gui/beos/PlayListWindow.cpp | 123 +++-- modules/gui/beos/PlayListWindow.h | 19 +- modules/gui/beos/VideoOutput.cpp | 307 ++++++++--- modules/gui/beos/VideoWindow.h | 66 ++- modules/gui/beos/VlcWrapper.cpp | 203 +++++-- modules/gui/beos/VlcWrapper.h | 22 +- 13 files changed, 1621 insertions(+), 591 deletions(-) diff --git a/modules/gui/beos/Interface.cpp b/modules/gui/beos/Interface.cpp index 413d49e282..f15d51de98 100644 --- a/modules/gui/beos/Interface.cpp +++ b/modules/gui/beos/Interface.cpp @@ -2,7 +2,7 @@ * intf_beos.cpp: beos interface ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: Interface.cpp,v 1.8 2003/01/25 20:15:41 titer Exp $ + * $Id: Interface.cpp,v 1.9 2003/02/01 12:01:10 stippi Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -70,14 +70,12 @@ int E_(OpenIntf) ( vlc_object_t *p_this ) p_intf->pf_run = Run; /* Create the interface window */ - BScreen *screen; - screen = new BScreen(); - BRect rect = screen->Frame(); + BScreen screen(B_MAIN_SCREEN_ID); + BRect rect = screen.Frame(); rect.top = rect.bottom-100; rect.bottom -= 50; rect.left += 50; rect.right = rect.left + 350; - delete screen; p_intf->p_sys->p_window = new InterfaceWindow( rect, VOUT_TITLE " (BeOS interface)", p_intf ); diff --git a/modules/gui/beos/InterfaceWindow.cpp b/modules/gui/beos/InterfaceWindow.cpp index c6c8a19f23..b42eab20d6 100644 --- a/modules/gui/beos/InterfaceWindow.cpp +++ b/modules/gui/beos/InterfaceWindow.cpp @@ -2,7 +2,7 @@ * InterfaceWindow.cpp: beos interface ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: InterfaceWindow.cpp,v 1.25 2003/01/31 06:45:00 titer Exp $ + * $Id: InterfaceWindow.cpp,v 1.26 2003/02/01 12:01:10 stippi Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -52,30 +52,106 @@ #include "InterfaceWindow.h" #define INTERFACE_UPDATE_TIMEOUT 80000 // 2 frames if at 25 fps +#define INTERFACE_LOCKING_TIMEOUT 5000 + +// make_sure_frame_is_on_screen +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; +} + +// make_sure_frame_is_within_limits +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; +} + +// get_volume_info +bool +get_volume_info( BVolume& volume, BString& volumeName, bool& isCDROM, BString& deviceName ) +{ + bool success = false; + isCDROM = false; + deviceName = ""; + volumeName = ""; + char name[B_FILE_NAME_LENGTH]; + if ( volume.GetName( name ) >= B_OK ) // disk is currently mounted + { + volumeName = name; + dev_t dev = volume.Device(); + fs_info info; + if ( fs_stat_dev( dev, &info ) == B_OK ) + { + success = true; + deviceName = info.device_name; + if ( volume.IsReadOnly() ) + { + int i_dev = open( info.device_name, O_RDONLY ); + if ( i_dev >= 0 ) + { + device_geometry g; + if ( ioctl( i_dev, B_GET_GEOMETRY, &g, sizeof( g ) ) >= 0 ) + isCDROM = ( g.device_type == B_CD ); + close( i_dev ); + } + } + } + } + return success; +} /***************************************************************************** * InterfaceWindow *****************************************************************************/ -InterfaceWindow::InterfaceWindow( BRect frame, const char *name, - intf_thread_t *p_interface ) +InterfaceWindow::InterfaceWindow( BRect frame, const char* name, + 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 ), fFilePanel( NULL ), - fSubtitlesPanel( NULL ), - fLastUpdateTime( system_time() ) + fLastUpdateTime( system_time() ), + fSettings( new BMessage( 'sett' ) ), + p_wrapper( p_intf->p_sys->p_wrapper ) { - p_intf = p_interface; - p_wrapper = p_intf->p_sys->p_wrapper; + // TODO: ?!? what about user settings? p_intf->p_sys->b_dvdmenus = false; fPlaylistIsEmpty = !( p_wrapper->PlaylistSize() > 0 ); - BScreen *p_screen = new BScreen(); - BRect screen_rect = p_screen->Frame(); - delete p_screen; + BScreen screen; + BRect screen_rect = screen.Frame(); BRect window_rect; window_rect.Set( ( screen_rect.right - PREFS_WINDOW_WIDTH ) / 2, ( screen_rect.bottom - PREFS_WINDOW_HEIGHT ) / 2, @@ -129,7 +205,7 @@ InterfaceWindow::InterfaceWindow( BRect frame, const char *name, fileMenu->AddItem( new CDMenu( "Open Disc" ) ); - fileMenu->AddItem( new BMenuItem( "Load a subtitle file" B_UTF8_ELLIPSIS, + fileMenu->AddItem( new BMenuItem( "Open Subtitles" B_UTF8_ELLIPSIS, new BMessage( LOAD_SUBFILE ) ) ); fileMenu->AddSeparatorItem(); @@ -176,7 +252,7 @@ InterfaceWindow::InterfaceWindow( BRect frame, const char *name, fMenuBar->AddItem( fSpeedMenu ); /* Add the Show menu */ - fShowMenu = new BMenu( "Show" ); + fShowMenu = new BMenu( "Window" ); fShowMenu->AddItem( new BMenuItem( "Play List" B_UTF8_ELLIPSIS, new BMessage( OPEN_PLAYLIST ), 'P') ); fShowMenu->AddItem( new BMenuItem( "Messages" B_UTF8_ELLIPSIS, @@ -188,56 +264,106 @@ InterfaceWindow::InterfaceWindow( BRect frame, const char *name, /* Prepare fow showing */ _SetMenusEnabled( false ); p_mediaControl->SetEnabled( false ); + + _RestoreSettings(); - /* Restore interface settings */ +/* // Restore interface settings + // main window size and position int i_width = config_GetInt( p_intf, "beos-intf-width" ), i_height = config_GetInt( p_intf, "beos-intf-height" ), i_xpos = config_GetInt( p_intf, "beos-intf-xpos" ), i_ypos = config_GetInt( p_intf, "beos-intf-ypos" ); - if( i_width && i_height && i_xpos && i_ypos ) + if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 ) { - /* main window size and position */ - ResizeTo( i_width, i_height ); - MoveTo( i_xpos, i_ypos ); + BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height ); + + float minWidth, maxWidth, minHeight, maxHeight; + GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight ); + + make_sure_frame_is_within_limits( r, minWidth, minHeight, maxWidth, maxHeight ); + if ( make_sure_frame_is_on_screen( r ) ) + { + ResizeTo( r.Width(), r.Height() ); + MoveTo( r.LeftTop() ); + } } + // playlist window size and position i_width = config_GetInt( p_intf, "beos-playlist-width" ), i_height = config_GetInt( p_intf, "beos-playlist-height" ), i_xpos = config_GetInt( p_intf, "beos-playlist-xpos" ), i_ypos = config_GetInt( p_intf, "beos-playlist-ypos" ); - if( i_width && i_height && i_xpos && i_ypos ) + if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 ) { - /* playlist window size and position */ - fPlaylistWindow->ResizeTo( i_width, i_height ); - fPlaylistWindow->MoveTo( i_xpos, i_ypos ); + BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height ); + + float minWidth, maxWidth, minHeight, maxHeight; + fPlaylistWindow->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight ); + + make_sure_frame_is_within_limits( r, minWidth, minHeight, maxWidth, maxHeight ); + if ( make_sure_frame_is_on_screen( r ) ) + { + fPlaylistWindow->ResizeTo( r.Width(), r.Height() ); + fPlaylistWindow->MoveTo( r.LeftTop() ); + } } + // child windows are not running yet, that's why we aint locking them + // playlist showing + // messages window size and position i_width = config_GetInt( p_intf, "beos-messages-width" ), i_height = config_GetInt( p_intf, "beos-messages-height" ), i_xpos = config_GetInt( p_intf, "beos-messages-xpos" ), i_ypos = config_GetInt( p_intf, "beos-messages-ypos" ); if( i_width && i_height && i_xpos && i_ypos ) { - /* messages window size and position */ - fMessagesWindow->ResizeTo( i_width, i_height ); - fMessagesWindow->MoveTo( i_xpos, i_ypos ); + BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height ); + + float minWidth, maxWidth, minHeight, maxHeight; + fMessagesWindow->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight ); + + make_sure_frame_is_within_limits( r, minWidth, minHeight, maxWidth, maxHeight ); + if ( make_sure_frame_is_on_screen( r ) ) + { + fMessagesWindow->ResizeTo( r.Width(), r.Height() ); + fMessagesWindow->MoveTo( r.LeftTop() ); + } } if( config_GetInt( p_intf, "beos-playlist-show" ) ) { - /* playlist showing */ - if( fPlaylistWindow->Lock() ) - { - fPlaylistWindow->Show(); - fPlaylistWindow->Unlock(); - } + fPlaylistWindow->Show(); } + else + { + fPlaylistWindow->Hide(); + fPlaylistWindow->Show(); + } + // messages window size and position + i_width = config_GetInt( p_intf, "beos-messages-width" ), + i_height = config_GetInt( p_intf, "beos-messages-height" ), + i_xpos = config_GetInt( p_intf, "beos-messages-xpos" ), + i_ypos = config_GetInt( p_intf, "beos-messages-ypos" ); + if( i_width > 20 && i_height > 20 && i_xpos >= 0 && i_ypos >= 0 ) + { + BRect r( i_xpos, i_ypos, i_xpos + i_width, i_ypos + i_height ); + float minWidth, maxWidth, minHeight, maxHeight; + fMessagesWindow->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight ); + + make_sure_frame_is_within_limits( r, minWidth, minHeight, maxWidth, maxHeight ); + if ( make_sure_frame_is_on_screen( r ) ) + { + fMessagesWindow->ResizeTo( r.Width(), r.Height() ); + fMessagesWindow->MoveTo( r.LeftTop() ); + } + } + // messages showing if( config_GetInt( p_intf, "beos-messages-show" ) ) { - /* messages showing */ - if( fMessagesWindow->Lock() ) - { - fMessagesWindow->Show(); - fMessagesWindow->Unlock(); - } + fMessagesWindow->Show(); } + else + { + fMessagesWindow->Hide(); + fMessagesWindow->Show(); + }*/ Show(); } @@ -246,8 +372,12 @@ InterfaceWindow::~InterfaceWindow() { if( fPlaylistWindow ) fPlaylistWindow->ReallyQuit(); + fPlaylistWindow = NULL; if( fMessagesWindow ) fMessagesWindow->ReallyQuit(); + fMessagesWindow = NULL; + delete fFilePanel; + delete fSettings; } /***************************************************************************** @@ -285,16 +415,13 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) break; case OPEN_FILE: - if( fFilePanel ) - { - fFilePanel->Show(); - break; - } - fFilePanel = new BFilePanel(); - fFilePanel->SetTarget( this ); - fFilePanel->Show(); + _ShowFilePanel( B_REFS_RECEIVED, "VideoLAN Client: Open Media Files" ); break; - + + case LOAD_SUBFILE: + _ShowFilePanel( SUBFILE_RECEIVED, "VideoLAN Client: Open Subtitle File" ); + break; + case OPEN_PLAYLIST: if (fPlaylistWindow->Lock()) { @@ -318,18 +445,6 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) } break; - case LOAD_SUBFILE: - if( fSubtitlesPanel ) - { - fSubtitlesPanel->Show(); - break; - } - fSubtitlesPanel = new BFilePanel(); - fSubtitlesPanel->SetTarget( this ); - fSubtitlesPanel->SetMessage( new BMessage( SUBFILE_RECEIVED ) ); - fSubtitlesPanel->Show(); - break; - case SUBFILE_RECEIVED: { entry_ref ref; @@ -337,7 +452,7 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) { BPath path( &ref ); if ( path.InitCheck() == B_OK ) - p_wrapper->LoadSubFile( (char*)path.Path() ); + p_wrapper->LoadSubFile( path.Path() ); } break; } @@ -346,7 +461,6 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) // this currently stops playback not nicely if (playback_status > UNDEF_S) { - snooze( 400000 ); p_wrapper->PlaylistStop(); p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE); } @@ -512,73 +626,73 @@ void InterfaceWindow::MessageReceived( BMessage * p_message ) if ( path.InitCheck() == B_OK ) { bool add = true; - // has the user dropped a dvd disk icon? + // has the user dropped a folder? BDirectory dir( &ref ); - if ( dir.InitCheck() == B_OK && dir.IsRootDirectory() ) + if ( dir.InitCheck() == B_OK) { - BVolumeRoster volRoster; - BVolume vol; - BDirectory volumeRoot; - status_t status = volRoster.GetNextVolume( &vol ); - while( status == B_NO_ERROR ) - { - if( vol.GetRootDirectory( &volumeRoot ) == B_OK - && dir == volumeRoot ) - { - BString volumeName; - BString deviceName; - bool isCDROM = false; - bool success = false; - deviceName = ""; - volumeName = ""; - char name[B_FILE_NAME_LENGTH]; - if ( vol.GetName( name ) >= B_OK ) // disk is currently mounted - { - volumeName = name; - dev_t dev = vol.Device(); - fs_info info; - if ( fs_stat_dev( dev, &info ) == B_OK ) - { - success = true; - deviceName = info.device_name; - if ( vol.IsReadOnly() ) - { - int i_dev = open( info.device_name, O_RDONLY ); - if ( i_dev >= 0 ) - { - device_geometry g; - if ( ioctl( i_dev, B_GET_GEOMETRY, &g, sizeof( g ) ) >= 0 ) - isCDROM = ( g.device_type == B_CD ); - close( i_dev ); - } - } - } - } - - if( success && isCDROM ) - { - BMessage msg( OPEN_DVD ); - msg.AddString( "device", deviceName.String() ); - PostMessage( &msg ); - add = false; - } - break; - } - else - { - vol.Unset(); - status = volRoster.GetNextVolume( &vol ); - } - } + // has the user dropped a dvd disk icon? + // TODO: this code does not work for the following situation: + // if the user dropped the icon for his partition containing + // all his mp3 files, this routine will not do anything, because + // the folder that was dropped is a root folder, but no DVD drive + if ( dir.IsRootDirectory() ) + { + BVolumeRoster volRoster; + BVolume vol; + BDirectory volumeRoot; + status_t status = volRoster.GetNextVolume( &vol ); + while ( status == B_NO_ERROR ) + { + if ( vol.GetRootDirectory( &volumeRoot ) == B_OK + && dir == volumeRoot ) + { + BString volumeName; + BString deviceName; + bool isCDROM; + if ( get_volume_info( vol, volumeName, isCDROM, deviceName ) + && isCDROM ) + { + BMessage msg( OPEN_DVD ); + msg.AddString( "device", deviceName.String() ); + PostMessage( &msg ); + add = false; + } + break; + } + else + { + vol.Unset(); + status = volRoster.GetNextVolume( &vol ); + } + } + } + else + { + // add all files from the dropped folder + // TODO: do this recursively + dir.Rewind(); + add = false; + BEntry entry; + while ( dir.GetNextEntry( &entry ) == B_OK ) + { + // ", 0" is because we receive the files in reverse order + if ( !entry.IsDirectory() && entry.GetPath( &path ) == B_OK ) + files.AddItem( new BString( path.Path() ), 0 ); + } + } } if( add ) { - files.AddItem( new BString( (char*)path.Path() ) ); + files.AddItem( new BString( path.Path() ) ); } } } // give the list to VLC - p_wrapper->OpenFiles(&files, replace); + // BString objects allocated here will be deleted there + int32 index; + if ( p_message->FindInt32("drop index", &index) != B_OK ) + index = -1; + p_wrapper->OpenFiles( &files, replace, index ); _UpdatePlaylist(); } break; @@ -625,7 +739,7 @@ bool InterfaceWindow::QuitRequested() p_mediaControl->SetStatus(NOT_STARTED_S, DEFAULT_RATE); /* Save interface settings */ - BRect frame = Frame(); +/* BRect frame = Frame(); config_PutInt( p_intf, "beos-intf-width", (int)frame.Width() ); config_PutInt( p_intf, "beos-intf-height", (int)frame.Height() ); config_PutInt( p_intf, "beos-intf-xpos", (int)frame.left ); @@ -649,9 +763,10 @@ bool InterfaceWindow::QuitRequested() config_PutInt( p_intf, "beos-messages-ypos", (int)frame.top ); config_PutInt( p_intf, "beos-messages-show", !fMessagesWindow->IsHidden() ); fMessagesWindow->Unlock(); - } + }*/ config_SaveConfigFile( p_intf, "beos" ); - + _StoreSettings(); + p_intf->b_die = 1; return( true ); @@ -666,9 +781,9 @@ void InterfaceWindow::UpdateInterface() { if ( acquire_sem( p_mediaControl->fScrubSem ) == B_OK ) { - p_wrapper->SetTimeAsFloat(p_mediaControl->GetSeekTo()); + p_wrapper->SetTimeAsFloat( p_mediaControl->GetSeekTo() ); } - else if ( Lock() ) + else if ( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK ) { p_mediaControl->SetEnabled( true ); bool hasTitles = p_wrapper->HasTitles(); @@ -696,7 +811,7 @@ void InterfaceWindow::UpdateInterface() Unlock(); } // update playlist as well - if ( fPlaylistWindow->Lock() ) + if ( fPlaylistWindow->LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK ) { fPlaylistWindow->UpdatePlaylist(); fPlaylistWindow->Unlock(); @@ -706,7 +821,7 @@ void InterfaceWindow::UpdateInterface() { _SetMenusEnabled( false ); if( !( p_wrapper->PlaylistSize() > 0 ) ) - p_mediaControl->SetEnabled( false ); + p_mediaControl->SetEnabled( false ); else p_mediaControl->SetProgress( 0 ); } @@ -718,8 +833,11 @@ void InterfaceWindow::UpdateInterface() { p_wrapper->SetVolume( i_volume ); } - - fMessagesWindow->UpdateMessages(); + + // strangly, someone is calling this function even after the object has been destructed! + // even more strangly, this workarround seems to work + if (fMessagesWindow) + fMessagesWindow->UpdateMessages(); fLastUpdateTime = system_time(); } @@ -758,30 +876,30 @@ InterfaceWindow::_SetMenusEnabled(bool hasFile, bool hasChapters, bool hasTitles hasChapters = false; hasTitles = false; } - if (Lock()) + if ( LockWithTimeout( INTERFACE_LOCKING_TIMEOUT ) == B_OK) { - if (fNextChapterMI->IsEnabled() != hasChapters) - fNextChapterMI->SetEnabled(hasChapters); - if (fPrevChapterMI->IsEnabled() != hasChapters) - fPrevChapterMI->SetEnabled(hasChapters); - if (fChapterMenu->IsEnabled() != hasChapters) - fChapterMenu->SetEnabled(hasChapters); - if (fNextTitleMI->IsEnabled() != hasTitles) - fNextTitleMI->SetEnabled(hasTitles); - if (fPrevTitleMI->IsEnabled() != hasTitles) - fPrevTitleMI->SetEnabled(hasTitles); - if (fTitleMenu->IsEnabled() != hasTitles) - fTitleMenu->SetEnabled(hasTitles); - if (fAudioMenu->IsEnabled() != hasFile) - fAudioMenu->SetEnabled(hasFile); - if (fNavigationMenu->IsEnabled() != hasFile) - fNavigationMenu->SetEnabled(hasFile); - if (fLanguageMenu->IsEnabled() != hasFile) - fLanguageMenu->SetEnabled(hasFile); - if (fSubtitlesMenu->IsEnabled() != hasFile) - fSubtitlesMenu->SetEnabled(hasFile); - if (fSpeedMenu->IsEnabled() != hasFile) - fSpeedMenu->SetEnabled(hasFile); + if ( fNextChapterMI->IsEnabled() != hasChapters ) + fNextChapterMI->SetEnabled( hasChapters ); + if ( fPrevChapterMI->IsEnabled() != hasChapters ) + fPrevChapterMI->SetEnabled( hasChapters ); + if ( fChapterMenu->IsEnabled() != hasChapters ) + fChapterMenu->SetEnabled( hasChapters ); + if ( fNextTitleMI->IsEnabled() != hasTitles ) + fNextTitleMI->SetEnabled( hasTitles ); + if ( fPrevTitleMI->IsEnabled() != hasTitles ) + fPrevTitleMI->SetEnabled( hasTitles ); + if ( fTitleMenu->IsEnabled() != hasTitles ) + fTitleMenu->SetEnabled( hasTitles ); + if ( fAudioMenu->IsEnabled() != hasFile ) + fAudioMenu->SetEnabled( hasFile ); + if ( fNavigationMenu->IsEnabled() != hasFile ) + fNavigationMenu->SetEnabled( hasFile ); + if ( fLanguageMenu->IsEnabled() != hasFile ) + fLanguageMenu->SetEnabled( hasFile ); + if ( fSubtitlesMenu->IsEnabled() != hasFile ) + fSubtitlesMenu->SetEnabled( hasFile ); + if ( fSpeedMenu->IsEnabled() != hasFile ) + fSpeedMenu->SetEnabled( hasFile ); Unlock(); } } @@ -820,20 +938,133 @@ InterfaceWindow::_InputStreamChanged() p_wrapper->SetVolume( p_mediaControl->GetVolume() ); } +/***************************************************************************** + * InterfaceWindow::_ShowFilePanel + *****************************************************************************/ void -make_sure_frame_is_within_limits( BRect& frame, float minWidth, float minHeight, - float maxWidth, float maxHeight ) +InterfaceWindow::_ShowFilePanel( uint32 command, const char* windowTitle ) { - 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; + if( !fFilePanel ) + { + fFilePanel = new BFilePanel(); + fFilePanel->SetTarget( this ); + } + fFilePanel->Window()->SetTitle( windowTitle ); + BMessage message( command ); + fFilePanel->SetMessage( &message ); + if ( !fFilePanel->IsShowing() ) + { + fFilePanel->Refresh(); + fFilePanel->Show(); + } +} + +// set_window_pos +void +set_window_pos( BWindow* window, BRect frame ) +{ + // sanity checks: make sure window is not too big/small + // and that it's not off-screen + float minWidth, maxWidth, minHeight, maxHeight; + window->GetSizeLimits( &minWidth, &maxWidth, &minHeight, &maxHeight ); + + make_sure_frame_is_within_limits( frame, + minWidth, minHeight, maxWidth, maxHeight ); + if ( make_sure_frame_is_on_screen( frame ) ) + { + window->MoveTo( frame.LeftTop() ); + window->ResizeTo( frame.Width(), frame.Height() ); + } +} + +// set_window_pos +void +launch_window( BWindow* window, bool showing ) +{ + if ( window->Lock() ) + { + if ( showing ) + { + if ( window->IsHidden() ) + window->Show(); + } + else + { + if ( !window->IsHidden() ) + window->Hide(); + } + window->Unlock(); + } +} + +/***************************************************************************** + * InterfaceWindow::_RestoreSettings + *****************************************************************************/ +void +InterfaceWindow::_RestoreSettings() +{ + if ( load_settings( fSettings, "interface_settings", "VideoLAN Client" ) == B_OK ) + { + BRect frame; + if ( fSettings->FindRect( "main frame", &frame ) == B_OK ) + set_window_pos( this, frame ); + if (fSettings->FindRect( "playlist frame", &frame ) == B_OK ) + set_window_pos( fPlaylistWindow, frame ); + if (fSettings->FindRect( "messages frame", &frame ) == B_OK ) + set_window_pos( fMessagesWindow, frame ); + if (fSettings->FindRect( "settings frame", &frame ) == B_OK ) + set_window_pos( fPreferencesWindow, frame ); + + bool showing; + if ( fSettings->FindBool( "playlist showing", &showing ) == B_OK ) + launch_window( fPlaylistWindow, showing ); + if ( fSettings->FindBool( "messages showing", &showing ) == B_OK ) + launch_window( fMessagesWindow, showing ); + if ( fSettings->FindBool( "settings showing", &showing ) == B_OK ) + launch_window( fPreferencesWindow, showing ); + } } +/***************************************************************************** + * 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(); + } + if ( fMessagesWindow->Lock() ) + { + if (fSettings->ReplaceRect( "messages frame", fMessagesWindow->Frame() ) != B_OK) + fSettings->AddRect( "messages frame", fMessagesWindow->Frame() ); + if (fSettings->ReplaceBool( "messages showing", !fMessagesWindow->IsHidden() ) != B_OK) + fSettings->AddBool( "messages showing", !fMessagesWindow->IsHidden() ); + fMessagesWindow->Unlock(); + } + if ( fPreferencesWindow->Lock() ) + { + if (fSettings->ReplaceRect( "settings frame", fPreferencesWindow->Frame() ) != B_OK) + fSettings->AddRect( "settings frame", fPreferencesWindow->Frame() ); + if (fSettings->ReplaceBool( "settings showing", !fPreferencesWindow->IsHidden() ) != B_OK) + fSettings->AddBool( "settings showing", !fPreferencesWindow->IsHidden() ); + fPreferencesWindow->Unlock(); + } + save_settings( fSettings, "interface_settings", "VideoLAN Client" ); +} + + + + + + /***************************************************************************** * CDMenu::CDMenu *****************************************************************************/ @@ -855,9 +1086,9 @@ CDMenu::~CDMenu() void CDMenu::AttachedToWindow(void) { // remove all items - while (BMenuItem* item = RemoveItem(0L)) + while ( BMenuItem* item = RemoveItem( 0L ) ) delete item; - GetCD("/dev/disk"); + GetCD( "/dev/disk" ); BMenu::AttachedToWindow(); } @@ -866,54 +1097,26 @@ 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; - - volRoster = new BVolumeRoster(); - vol = new BVolume(); - dir = new BDirectory(); - status = volRoster->GetNextVolume(vol); - 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); - } - return 0; + BVolumeRoster volRoster; + BVolume vol; + BDirectory dir; + status_t status = volRoster.GetNextVolume( &vol ); + while ( status == B_NO_ERROR ) + { + BString deviceName; + BString volumeName; + bool isCDROM; + if ( get_volume_info( vol, volumeName, isCDROM, deviceName ) + && isCDROM ) + { + BMessage* msg = new BMessage( OPEN_DVD ); + msg->AddString( "device", deviceName.String() ); + BMenuItem* item = new BMenuItem( volumeName.String(), msg ); + AddItem( item ); + } + vol.Unset(); + status = volRoster.GetNextVolume( &vol ); + } } /***************************************************************************** @@ -944,32 +1147,17 @@ void LanguageMenu::AttachedToWindow() delete item; SetRadioMode( true ); - _GetChannels(); + if ( BList *list = p_wrapper->GetChannels( kind ) ) + { + for ( int32 i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ ) + AddItem( item ); + + if ( list->CountItems() > 1 ) + AddItem( new BSeparatorItem(), 1 ); + } BMenu::AttachedToWindow(); } -/***************************************************************************** - * LanguageMenu::_GetChannels - *****************************************************************************/ -void LanguageMenu::_GetChannels() -{ - BMenuItem *item; - BList *list; - - if( ( list = p_wrapper->GetChannels( kind ) ) == NULL ) - return; - - for( int i = 0; i < list->CountItems(); i++ ) - { - item = (BMenuItem*)list->ItemAt( i ); - AddItem( item ); - } - - if( list->CountItems() > 1 ) - AddItem( new BSeparatorItem(), 1 ); -} - - /***************************************************************************** * TitleMenu::TitleMenu *****************************************************************************/ @@ -991,21 +1179,14 @@ TitleMenu::~TitleMenu() *****************************************************************************/ void TitleMenu::AttachedToWindow() { - BMenuItem *item; - BList *list; - - while( ( item = RemoveItem( 0L ) ) ) + while( BMenuItem* item = RemoveItem( 0L ) ) delete item; - - if( ( list = p_intf->p_sys->p_wrapper->GetTitles() ) == NULL ) - return; - - for( int i = 0; i < list->CountItems(); i++ ) - { - item = (BMenuItem*)list->ItemAt( i ); - AddItem( item ); - } - + + if ( BList *list = p_intf->p_sys->p_wrapper->GetTitles() ) + { + for( int i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ ) + AddItem( item ); + } BMenu::AttachedToWindow(); } @@ -1031,21 +1212,80 @@ ChapterMenu::~ChapterMenu() *****************************************************************************/ void ChapterMenu::AttachedToWindow() { - BMenuItem *item; - BList *list; - - while( ( item = RemoveItem( 0L ) ) ) + while( BMenuItem* item = RemoveItem( 0L ) ) delete item; - - if( ( list = p_intf->p_sys->p_wrapper->GetChapters() ) == NULL ) - return; - - for( int i = 0; i < list->CountItems(); i++ ) - { - item = (BMenuItem*)list->ItemAt( i ); - AddItem( item ); - } + + if ( BList* list = p_intf->p_sys->p_wrapper->GetChapters() ) + { + for( int i = 0; BMenuItem* item = (BMenuItem*)list->ItemAt( i ); i++ ) + AddItem( item ); + } BMenu::AttachedToWindow(); } + + + + + + + + +/***************************************************************************** + * load_settings + *****************************************************************************/ +status_t +load_settings( 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; +} + +/***************************************************************************** + * save_settings + *****************************************************************************/ +status_t +save_settings( 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; +} diff --git a/modules/gui/beos/InterfaceWindow.h b/modules/gui/beos/InterfaceWindow.h index 53af47bc7a..b5c503ae4a 100644 --- a/modules/gui/beos/InterfaceWindow.h +++ b/modules/gui/beos/InterfaceWindow.h @@ -2,7 +2,7 @@ * InterfaceWindow.h: BeOS interface window class prototype ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: InterfaceWindow.h,v 1.10 2003/01/25 20:15:41 titer Exp $ + * $Id: InterfaceWindow.h,v 1.11 2003/02/01 12:01:11 stippi Exp $ * * Authors: Jean-Marc Dressler * Tony Castley @@ -36,6 +36,7 @@ class PlayListWindow; class BFilePanel; class PreferencesWindow; class MessagesWindow; +class VlcWrapper; class CDMenu : public BMenu { @@ -60,8 +61,6 @@ class LanguageMenu : public BMenu virtual void AttachedToWindow(); private: - void _GetChannels(); - VlcWrapper * p_wrapper; int kind; }; @@ -115,13 +114,16 @@ class InterfaceWindow : public BWindow bool hasTitles = false ); void _UpdateSpeedMenu( int rate ); void _InputStreamChanged(); + void _ShowFilePanel( uint32 command, + const char* windowTitle ); + void _RestoreSettings(); + void _StoreSettings(); intf_thread_t* p_intf; es_descriptor_t* p_spu_es; bool fPlaylistIsEmpty; BFilePanel* fFilePanel; - BFilePanel* fSubtitlesPanel; PlayListWindow* fPlaylistWindow; PreferencesWindow* fPreferencesWindow; MessagesWindow* fMessagesWindow; @@ -143,8 +145,20 @@ class InterfaceWindow : public BWindow BMenu* fSpeedMenu; BMenu* fShowMenu; bigtime_t fLastUpdateTime; - - VlcWrapper * p_wrapper; + BMessage* fSettings; // we keep the message arround + // for forward compatibility + VlcWrapper* p_wrapper; }; + +// some global support functions +status_t load_settings( BMessage* message, + const char* fileName, + const char* folder = NULL ); + +status_t save_settings( BMessage* message, + const char* fileName, + const char* folder = NULL ); + + #endif // BEOS_INTERFACE_WINDOW_H diff --git a/modules/gui/beos/ListViews.cpp b/modules/gui/beos/ListViews.cpp index 130cb16acc..d8ca81e165 100644 --- a/modules/gui/beos/ListViews.cpp +++ b/modules/gui/beos/ListViews.cpp @@ -2,7 +2,7 @@ * ListViews.h: BeOS interface list view class implementation ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: ListViews.cpp,v 1.2 2003/01/22 01:13:22 titer Exp $ + * $Id: ListViews.cpp,v 1.3 2003/02/01 12:01:11 stippi Exp $ * * Authors: Stephan Aßmus * @@ -22,6 +22,7 @@ *****************************************************************************/ #include +#include #include #include @@ -128,6 +129,7 @@ DragSortableListView::DragSortableListView( BRect frame, const char* name, list_view_type type, uint32 resizingMode, uint32 flags ) : BListView( frame, name, type, resizingMode, flags ), + fDropRect( 0.0, 0.0, -1.0, -1.0 ), fDropIndex( -1 ) { SetViewColor( B_TRANSPARENT_32_BIT ); @@ -168,6 +170,12 @@ DragSortableListView::Draw( BRect updateRect ) SetLowColor( 255, 255, 255, 255 ); FillRect( updateRect, B_SOLID_LOW ); } + // drop anticipation indication + if ( fDropRect.IsValid() ) + { + SetHighColor( 255, 0, 0, 255 ); + StrokeRect( fDropRect ); + } } /***************************************************************************** @@ -176,7 +184,6 @@ DragSortableListView::Draw( BRect updateRect ) bool DragSortableListView::InitiateDrag( BPoint point, int32 index, bool ) { -return false; bool success = false; BListItem* item = ItemAt( CurrentSelection( 0 ) ); if ( !item ) @@ -197,7 +204,7 @@ return false; int32 numItems; bool fade = false; for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) { - dragRect.bottom += item->Height(); + dragRect.bottom += ceilf( item->Height() ) + 1.0; if ( dragRect.Height() > MAX_DRAG_HEIGHT ) { fade = true; dragRect.bottom = MAX_DRAG_HEIGHT; @@ -216,7 +223,7 @@ return false; for ( int32 i = 0; i < numItems; i++ ) { int32 index = CurrentSelection( i ); BListItem* item = ItemAt( index ); - itemBounds.bottom = itemBounds.top + item->Height() - 1.0; + itemBounds.bottom = itemBounds.top + ceilf( item->Height() ); if ( itemBounds.bottom > dragRect.bottom ) itemBounds.bottom = dragRect.bottom; DrawListItem( v, index, itemBounds ); @@ -281,49 +288,40 @@ DragSortableListView::WindowActivated( bool active ) void DragSortableListView::MessageReceived(BMessage* message) { - BListItem *item = NULL; - DragSortableListView *list = NULL; - if ( message->FindPointer( "list", (void **)&list ) == B_OK - && list == this ) + switch ( message->what ) { - int32 count = CountItems(); - if ( fDropIndex < 0 || fDropIndex > count ) - fDropIndex = count; - bool copy = ( modifiers() & B_SHIFT_KEY ); - for ( int32 i = 0; message->FindPointer( "item", i, (void **)&item ) == B_OK; i++ ) + case B_MODIFIERS_CHANGED: + ModifiersChanged(); + break; + case B_SIMPLE_DATA: { - - if ( HasItem( item ) ) + DragSortableListView *list = NULL; + if ( message->FindPointer( "list", (void **)&list ) == B_OK + && list == this ) { - BListItem* itemToAdd = NULL; - int32 index = IndexOf( item ); - if ( copy ) - { - // add cloned item - itemToAdd = CloneItem( index ); - Deselect( IndexOf( item ) ); - } - else - { - // drag sort - if ( index < fDropIndex ) - fDropIndex--; - if ( RemoveItem( item ) ) - itemToAdd = item; - } - if ( itemToAdd ) + int32 count = CountItems(); + if ( fDropIndex < 0 || fDropIndex > count ) + fDropIndex = count; + BList items; + int32 index; + for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ ) + if ( BListItem* item = ItemAt(index) ) + items.AddItem( (void*)item ); + if ( items.CountItems() > 0 ) { - if ( AddItem( itemToAdd, fDropIndex ) ) - Select( IndexOf( itemToAdd ), true ); + if ( modifiers() & B_SHIFT_KEY ) + CopyItems( items, fDropIndex ); else - delete itemToAdd; + MoveItems( items, fDropIndex ); } + fDropIndex = -1; } - fDropIndex++; + break; } - fDropIndex = -1; - } else - BListView::MessageReceived( message ); + default: + BListView::MessageReceived( message ); + break; + } } /***************************************************************************** @@ -334,120 +332,46 @@ DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *m { if ( msg && msg->what == B_SIMPLE_DATA ) { + bool replaceAll = !msg->HasPointer("list") && !(modifiers() & B_SHIFT_KEY); switch ( transit ) { case B_ENTERED_VIEW: - { - // draw drop mark - BRect r(ItemFrame(0L)); - where.y += r.Height() / 2.0; - int32 count = CountItems(); - bool found = false; - for (int32 index = 0; index <= count; index++) - { - r = ItemFrame(index); - if (r.Contains(where)) - { - SetHighColor(255, 0, 0, 255); - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - r.top++; - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - fDropIndex = index; - found = true; - break; - } - } - if (found) - break; - // mouse is after last item - fDropIndex = count; - r = Bounds(); - if (count > 0) - r.top = ItemFrame(count - 1).bottom + 1.0; - SetHighColor(255, 0, 0, 255); - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - r.top++; - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - break; - } case B_INSIDE_VIEW: { - // draw drop mark and invalidate previous drop mark - BRect r(ItemFrame(0L)); - where.y += r.Height() / 2.0; - int32 count = CountItems(); - // mouse still after last item? - if (fDropIndex == count) + if ( replaceAll ) { - r = Bounds(); - if (count > 0) - r.top = ItemFrame(count - 1).bottom + 1.0; - if (r.Contains(where)) - break; - else - { - r.bottom = r.top + 2.0; - Invalidate(r); - } + BRect r( Bounds() ); + r.bottom--; // compensate for scrollbar offset + _SetDropAnticipationRect( r ); + fDropIndex = -1; } - // mouse still over same item? - if (ItemFrame(fDropIndex).Contains(where)) - break; else - InvalidateItem(fDropIndex); - - // mouse over new item - bool found = false; - for (int32 index = 0; index <= count; index++) { - r = ItemFrame(index); - if (r.Contains(where)) - { - SetHighColor(255, 0, 0, 255); - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - r.top++; - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - fDropIndex = index; - found = true; - break; - } + // offset where by half of item height + BRect r( ItemFrame( 0 ) ); + where.y += r.Height() / 2.0; + + int32 index = IndexOf( where ); + if ( index < 0 ) + index = CountItems(); + _SetDropIndex( index ); } - if (found) - break; - // mouse is after last item - fDropIndex = count; - r = Bounds(); - if (count > 0) - r.top = ItemFrame(count - 1).bottom + 1.0; - SetHighColor(255, 0, 0, 255); - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); - r.top++; - StrokeLine(r.LeftTop(), r.RightTop(), B_SOLID_HIGH); break; } case B_EXITED_VIEW: - { - int32 count = CountItems(); - if (count > 0) - { - if (fDropIndex == count) - { - BRect r(Bounds()); - r.top = ItemFrame(count - 1).bottom + 1.0; - r.bottom = r.top + 2.0; - Invalidate(r); - } - else - InvalidateItem(fDropIndex); - } - break; - } case B_OUTSIDE_VIEW: + _RemoveDropAnticipationRect(); break; } + // remember drag message + // this is needed to react on modifier changes + fDragMessageCopy = *msg; } else + { + _RemoveDropAnticipationRect(); BListView::MouseMoved(where, transit, msg); + } } /***************************************************************************** @@ -457,8 +381,7 @@ void DragSortableListView::MouseUp( BPoint where ) { // remove drop mark - if ( fDropIndex >= 0 && fDropIndex < CountItems() ) - InvalidateItem( fDropIndex ); + _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) ); BListView::MouseUp( where ); } @@ -471,25 +394,204 @@ DragSortableListView::DrawItem( BListItem *item, BRect itemFrame, bool complete DrawListItem( this, IndexOf( item ), itemFrame ); } +/***************************************************************************** + * DragSortableListView::ModifiersChaned + *****************************************************************************/ +void +DragSortableListView::ModifiersChanged() +{ + BPoint where; + uint32 buttons; + GetMouse( &where, &buttons, false ); + uint32 transit = Bounds().Contains( where ) ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; + MouseMoved( where, transit, &fDragMessageCopy ); +} + +/***************************************************************************** + * DragSortableListView::MoveItems + *****************************************************************************/ +void +DragSortableListView::MoveItems( BList& items, int32 index ) +{ + DeselectAll(); + // we remove the items while we look at them, the insertion index is decreased + // when the items index is lower, so that we insert at the right spot after + // removal + BList removedItems; + int32 count = items.CountItems(); + for ( int32 i = 0; i < count; i++ ) + { + BListItem* item = (BListItem*)items.ItemAt( i ); + int32 removeIndex = IndexOf( item ); + if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) ) + { + if ( removeIndex < index ) + index--; + } + // else ??? -> blow up + } + for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ ) + { + if ( AddItem( item, index ) ) + { + // after we're done, the newly inserted items will be selected + Select( index, true ); + // next items will be inserted after this one + index++; + } + else + delete item; + } +} + +/***************************************************************************** + * DragSortableListView::CopyItems + *****************************************************************************/ +void +DragSortableListView::CopyItems( BList& items, int32 index ) +{ + DeselectAll(); + // by inserting the items after we copied all items first, we avoid + // cloning an item we already inserted and messing everything up + // in other words, don't touch the list before we know which items + // need to be cloned + BList clonedItems; + int32 count = items.CountItems(); + for ( int32 i = 0; i < count; i++ ) + { + BListItem* item = CloneItem( IndexOf( (BListItem*)items.ItemAt( i ) ) ); + if ( item && !clonedItems.AddItem( (void*)item ) ) + delete item; + } + for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ ) + { + if ( AddItem( item, index ) ) + { + // after we're done, the newly inserted items will be selected + Select( index, true ); + // next items will be inserted after this one + index++; + } + else + delete item; + } +} + +/***************************************************************************** + * DragSortableListView::RemoveItemList + *****************************************************************************/ +void +DragSortableListView::RemoveItemList( BList& items ) +{ + int32 count = items.CountItems(); + for ( int32 i = 0; i < count; i++ ) + { + BListItem* item = (BListItem*)items.ItemAt( i ); + if ( RemoveItem( item ) ) + delete item; + } +} + +/***************************************************************************** + * DragSortableListView::RemoveSelected + *****************************************************************************/ +void +DragSortableListView::RemoveSelected() +{ + BList items; + for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ ) + items.AddItem( (void*)item ); + RemoveItemList( items ); +} + +/***************************************************************************** + * DragSortableListView::_SetDropAnticipationRect + *****************************************************************************/ +void +DragSortableListView::_SetDropAnticipationRect( BRect r ) +{ + if ( fDropRect != r ) + { + if ( fDropRect.IsValid() ) + Invalidate( fDropRect ); + fDropRect = r; + if ( fDropRect.IsValid() ) + Invalidate( fDropRect ); + } +} + +/***************************************************************************** + * DragSortableListView::_SetDropAnticipationRect + *****************************************************************************/ +void +DragSortableListView::_SetDropIndex( int32 index ) +{ + if ( fDropIndex != index ) + { + fDropIndex = index; + if ( fDropIndex == -1 ) + _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) ); + else + { + int32 count = CountItems(); + if ( fDropIndex == count ) + { + BRect r; + if ( BListItem* item = ItemAt( count - 1 ) ) + { + r = ItemFrame( count - 1 ); + r.top = r.bottom + 1.0; + r.bottom = r.top + 1.0; + } + else + { + r = Bounds(); + r.bottom--; // compensate for scrollbars moved slightly out of window + } + _SetDropAnticipationRect( r ); + } + else + { + BRect r = ItemFrame( fDropIndex ); + r.bottom = r.top + 1.0; + _SetDropAnticipationRect( r ); + } + } + } +} + +/***************************************************************************** + * DragSortableListView::_RemoveDropAnticipationRect + *****************************************************************************/ +void +DragSortableListView::_RemoveDropAnticipationRect() +{ + _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) ); + _SetDropIndex( -1 ); +} + /***************************************************************************** * PlaylistView class *****************************************************************************/ PlaylistView::PlaylistView( BRect frame, InterfaceWindow* mainWindow, - VlcWrapper * p_wrapper ) + VlcWrapper* wrapper, + BMessage* selectionChangeMessage ) : DragSortableListView( frame, "playlist listview", B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE ), fCurrentIndex( -1 ), fPlaying( false ), - fMainWindow( mainWindow ) + fMainWindow( mainWindow ), + fSelectionChangeMessage( selectionChangeMessage ), + fVlcWrapper( wrapper ) { - this->p_wrapper = p_wrapper; } PlaylistView::~PlaylistView() { + delete fSelectionChangeMessage; } /***************************************************************************** @@ -499,7 +601,34 @@ void PlaylistView::AttachedToWindow() { // get pulse message every two frames - Window()->SetPulseRate(80000); + Window()->SetPulseRate( 80000 ); +} + +/***************************************************************************** + * PlaylistView::MessageReceived + *****************************************************************************/ +void +PlaylistView::MessageReceived( BMessage* message) +{ + switch ( message->what ) + { + case B_SIMPLE_DATA: + if ( message->HasPointer( "list" ) ) + { + // message comes from ourself + DragSortableListView::MessageReceived( message ); + } + else + { + // message comes from another app (for example Tracker) + message->AddInt32( "drop index", fDropIndex ); + fMainWindow->PostMessage( message, fMainWindow ); + } + break; + default: + DragSortableListView::MessageReceived( message ); + break; + } } /***************************************************************************** @@ -518,7 +647,7 @@ PlaylistView::MouseDown( BPoint where ) { if ( clicks == 2 ) { - p_wrapper->PlaylistJumpTo( i ); + fVlcWrapper->PlaylistJumpTo( i ); handled = true; } else if ( i == fCurrentIndex ) @@ -544,20 +673,12 @@ PlaylistView::MouseDown( BPoint where ) void PlaylistView::KeyDown( const char* bytes, int32 numBytes ) { - if (numBytes < 1) + if ( numBytes < 1 ) return; if ( ( bytes[0] == B_BACKSPACE ) || ( bytes[0] == B_DELETE ) ) { - int32 i = CurrentSelection(); - if ( BListItem *item = ItemAt( i ) ) - { -/* if ( RemoveItem( item ) ) - { - delete item; - Select( i + 1 ); - }*/ - } + RemoveSelected(); } DragSortableListView::KeyDown( bytes, numBytes ); } @@ -568,10 +689,173 @@ PlaylistView::KeyDown( const char* bytes, int32 numBytes ) void PlaylistView::Pulse() { - if (fMainWindow->IsStopped()) + if ( fMainWindow->IsStopped() ) SetPlaying( false ); } +/***************************************************************************** + * PlaylistView::SelectionChanged + *****************************************************************************/ +void +PlaylistView::SelectionChanged() +{ + BLooper* looper = Looper(); + if ( fSelectionChangeMessage && looper ) + { + BMessage message( *fSelectionChangeMessage ); + looper->PostMessage( &message ); + } +} + + +/***************************************************************************** + * PlaylistView::MoveItems + *****************************************************************************/ +void +PlaylistView::MoveItems( BList& items, int32 index ) +{ + DeselectAll(); + // we remove the items while we look at them, the insertion index is decreased + // when the items index is lower, so that we insert at the right spot after + // removal + if ( fVlcWrapper->PlaylistLock() ) + { + BList removedItems; + BList removeItems; + int32 count = items.CountItems(); + int32 indexOriginal = index; + // remember currently playing item + int32 currentIndex, size; + fVlcWrapper->GetPlaylistInfo( currentIndex, size ); + BListItem* playingItem = ItemAt( currentIndex ); + // collect item pointers for removal by index + for ( int32 i = 0; i < count; i++ ) + { + int32 removeIndex = IndexOf( (BListItem*)items.ItemAt( i ) ); + void* item = fVlcWrapper->PlaylistItemAt( removeIndex ); + if ( item && removeItems.AddItem( item ) ) + { + if ( removeIndex < index ) + index--; + } + // else ??? -> blow up + } + // actually remove items using pointers + for ( int32 i = 0; i < count; i++ ) + { + void* item = fVlcWrapper->PlaylistRemoveItem( removeItems.ItemAt( i ) ); + if ( item && !removedItems.AddItem( item ) ) + free( item ); + } + // add items at index + for ( int32 i = 0; void* item = removedItems.ItemAt( i ); i++ ) + { + if ( fVlcWrapper->PlaylistAddItem( item, index ) ) + // next items will be inserted after this one + index++; + else + free( item ); + } + // update GUI + DragSortableListView::MoveItems( items, indexOriginal ); + // restore currently playing item + for ( int32 i = 0; BListItem* item = ItemAt( i ); i++ ) + { + if ( item == playingItem ) + { + fVlcWrapper->PlaylistSetPlaying( i ); + SetCurrent( i ); + break; + } + } + fVlcWrapper->PlaylistUnlock(); + } +} + +/***************************************************************************** + * PlaylistView::CopyItems + *****************************************************************************/ +void +PlaylistView::CopyItems( BList& items, int32 toIndex ) +{ + DeselectAll(); + // we remove the items while we look at them, the insertion index is decreased + // when the items index is lower, so that we insert at the right spot after + // removal + if ( fVlcWrapper->PlaylistLock() ) + { + BList clonedItems; + int32 count = items.CountItems(); + // remember currently playing item + int32 currentIndex, size; + fVlcWrapper->GetPlaylistInfo( currentIndex, size ); + BListItem* playingItem = ItemAt( currentIndex ); + // collect cloned item pointers + for ( int32 i = 0; i < count; i++ ) + { + int32 index = IndexOf( (BListItem*)items.ItemAt( i ) ); + void* item = fVlcWrapper->PlaylistItemAt( index ); + void* cloned = fVlcWrapper->PlaylistCloneItem( item ); + if ( cloned && !clonedItems.AddItem( cloned ) ) + free( cloned ); + + } + // add cloned items at index + int32 index = toIndex; + for ( int32 i = 0; void* item = clonedItems.ItemAt( i ); i++ ) + { + if ( fVlcWrapper->PlaylistAddItem( item, index ) ) + // next items will be inserted after this one + index++; + else + free( item ); + } + // update GUI + DragSortableListView::CopyItems( items, toIndex ); + // restore currently playing item + for ( int32 i = 0; BListItem* item = ItemAt( i ); i++ ) + { + if ( item == playingItem ) + { + fVlcWrapper->PlaylistSetPlaying( i ); + SetCurrent( i ); + break; + } + } + fVlcWrapper->PlaylistUnlock(); + } +} + +/***************************************************************************** + * PlaylistView::RemoveItemList + *****************************************************************************/ +void +PlaylistView::RemoveItemList( BList& items ) +{ + if ( fVlcWrapper->PlaylistLock() ) + { + // collect item pointers for removal + BList removeItems; + int32 count = items.CountItems(); + for ( int32 i = 0; i < count; i++ ) + { + int32 index = IndexOf( (BListItem*)items.ItemAt( i ) ); + void* item = fVlcWrapper->PlaylistItemAt( index ); + if ( item && !removeItems.AddItem( item ) ) + free( item ); + } + // remove items from playlist + count = removeItems.CountItems(); + for ( int32 i = 0; void* item = removeItems.ItemAt( i ); i++ ) + { + fVlcWrapper->PlaylistRemoveItem( item ); + } + // update GUI + DragSortableListView::RemoveItemList( items ); + fVlcWrapper->PlaylistUnlock(); + } +} + /***************************************************************************** * PlaylistView::CloneItem *****************************************************************************/ @@ -603,8 +887,10 @@ PlaylistView::MakeDragMessage( BMessage* message ) const if ( message ) { message->AddPointer( "list", (void*)this ); - for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ ) - message->AddPointer( "item", (void*)item ); + int32 index; + for ( int32 i = 0; ( index = CurrentSelection( i ) ) >= 0; i++ ) + message->AddInt32( "index", index ); + // TODO: add refs to message (inter application communication) } } @@ -634,3 +920,19 @@ PlaylistView::SetPlaying( bool playing ) InvalidateItem( fCurrentIndex ); } } + +/***************************************************************************** + * PlaylistView::SetPlaying + *****************************************************************************/ +void +PlaylistView::RebuildList() +{ + // remove all items + int32 count = CountItems(); + while ( BListItem* item = RemoveItem( --count ) ) + delete item; + + // rebuild listview from VLC's playlist + for ( int i = 0; i < fVlcWrapper->PlaylistSize(); i++ ) + AddItem( new PlaylistItem( fVlcWrapper->PlaylistItemName( i ) ) ); +} diff --git a/modules/gui/beos/ListViews.h b/modules/gui/beos/ListViews.h index bbe715c61d..cc93430013 100644 --- a/modules/gui/beos/ListViews.h +++ b/modules/gui/beos/ListViews.h @@ -2,7 +2,7 @@ * ListViews.h: BeOS interface list view class prototype ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: ListViews.h,v 1.2 2003/01/22 01:13:22 titer Exp $ + * $Id: ListViews.h,v 1.3 2003/02/01 12:01:11 stippi Exp $ * * Authors: Stephan Aßmus * @@ -73,13 +73,28 @@ class DragSortableListView : public BListView bool complete = false); // DragSortableListView + virtual void ModifiersChanged(); // called by window + + virtual void MoveItems( BList& items, int32 toIndex ); + virtual void CopyItems( BList& items, int32 toIndex ); + virtual void RemoveItemList( BList& indices ); + void RemoveSelected(); // uses RemoveItemList() + virtual BListItem* CloneItem( int32 atIndex ) const = 0; virtual void DrawListItem( BView* owner, int32 index, BRect itemFrame ) const = 0; virtual void MakeDragMessage( BMessage* message ) const = 0; private: - int32 fDropIndex; + void _SetDropAnticipationRect( BRect r ); + void _SetDropIndex( int32 index ); + void _RemoveDropAnticipationRect(); + + BRect fDropRect; + BMessage fDragMessageCopy; + + protected: + int32 fDropIndex; }; // PlaylistView @@ -88,16 +103,23 @@ class PlaylistView : public DragSortableListView public: PlaylistView( BRect frame, InterfaceWindow* mainWindow, - VlcWrapper * p_wrapper ); + VlcWrapper* wrapper, + BMessage* selectionChangeMessage = NULL ); ~PlaylistView(); // BListView virtual void AttachedToWindow(); + virtual void MessageReceived( BMessage* message ); virtual void MouseDown( BPoint where ); virtual void KeyDown( const char* bytes, int32 numBytes ); virtual void Pulse(); + virtual void SelectionChanged(); // DragSortableListView + virtual void MoveItems( BList& items, int32 toIndex ); + virtual void CopyItems( BList& items, int32 toIndex ); + virtual void RemoveItemList( BList& indices ); + virtual BListItem* CloneItem( int32 atIndex ) const; virtual void DrawListItem( BView* owner, int32 index, BRect itemFrame ) const; @@ -106,13 +128,15 @@ class PlaylistView : public DragSortableListView // PlaylistView void SetCurrent( int32 index ); void SetPlaying( bool playing ); + void RebuildList(); private: int32 fCurrentIndex; bool fPlaying; InterfaceWindow* fMainWindow; + BMessage* fSelectionChangeMessage; - VlcWrapper * p_wrapper; + VlcWrapper* fVlcWrapper; }; #endif // LIST_VIEWS_H diff --git a/modules/gui/beos/MediaControlView.cpp b/modules/gui/beos/MediaControlView.cpp index ccbb319322..32aa9f749c 100644 --- a/modules/gui/beos/MediaControlView.cpp +++ b/modules/gui/beos/MediaControlView.cpp @@ -2,7 +2,7 @@ * MediaControlView.cpp: beos interface ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: MediaControlView.cpp,v 1.13 2003/01/25 01:03:44 titer Exp $ + * $Id: MediaControlView.cpp,v 1.14 2003/02/01 12:01:11 stippi Exp $ * * Authors: Tony Castley * Stephan Aßmus @@ -773,9 +773,11 @@ SeekSlider::ResizeToPreferred() void SeekSlider::SetPosition(float position) { - LockLooper(); - SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5)); - UnlockLooper(); + if ( LockLooper() ) + { + SetValue(fMinValue + (int32)floorf((fMaxValue - fMinValue) * position + 0.5)); + UnlockLooper(); + } } /***************************************************************************** @@ -1321,7 +1323,7 @@ PositionInfoView::Pulse() { int32 index, size; p_intf->p_sys->p_wrapper->GetPlaylistInfo( index, size ); - SetFile( index, size ); + SetFile( index + 1, size ); p_intf->p_sys->p_wrapper->TitleInfo( index, size ); SetTitle( index, size ); p_intf->p_sys->p_wrapper->ChapterInfo( index, size ); diff --git a/modules/gui/beos/MessagesWindow.cpp b/modules/gui/beos/MessagesWindow.cpp index 716b568910..af9d8be88d 100644 --- a/modules/gui/beos/MessagesWindow.cpp +++ b/modules/gui/beos/MessagesWindow.cpp @@ -2,7 +2,7 @@ * MessagesWindow.cpp: beos interface ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: MessagesWindow.cpp,v 1.5 2003/01/31 06:45:00 titer Exp $ + * $Id: MessagesWindow.cpp,v 1.6 2003/02/01 12:01:11 stippi Exp $ * * Authors: Eric Petit * @@ -147,17 +147,19 @@ void MessagesWindow::UpdateMessages() case VLC_OBJECT_SOUT: psz_module_type = "stream output"; break; } - fMessagesView->LockLooper(); - oldLength = fMessagesView->TextLength(); - BString string; - string << p_sub->p_msg[i_start].psz_module << " " << psz_module_type << " : " << - p_sub->p_msg[i_start].psz_msg << "\n"; - fMessagesView->Insert( string.String() ); - fMessagesView->SetFontAndColor( oldLength, - fMessagesView->TextLength(), - NULL, 0, &color ); - fMessagesView->Draw( fMessagesView->Bounds() ); - fMessagesView->UnlockLooper(); + if ( fMessagesView->LockLooper() ) + { + oldLength = fMessagesView->TextLength(); + BString string; + string << p_sub->p_msg[i_start].psz_module << " " << psz_module_type << " : " << + p_sub->p_msg[i_start].psz_msg << "\n"; + fMessagesView->Insert( string.String() ); + fMessagesView->SetFontAndColor( oldLength, + fMessagesView->TextLength(), + NULL, 0, &color ); + fMessagesView->Draw( fMessagesView->Bounds() ); + fMessagesView->UnlockLooper(); + } /* Scroll at the end */ if( fScrollBar->LockLooper() ) diff --git a/modules/gui/beos/PlayListWindow.cpp b/modules/gui/beos/PlayListWindow.cpp index be8a2715ed..12a1ef7426 100644 --- a/modules/gui/beos/PlayListWindow.cpp +++ b/modules/gui/beos/PlayListWindow.cpp @@ -2,7 +2,7 @@ * PlayListWindow.cpp: beos interface ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: PlayListWindow.cpp,v 1.6 2003/01/22 01:13:22 titer Exp $ + * $Id: PlayListWindow.cpp,v 1.7 2003/02/01 12:01:11 stippi Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -43,13 +43,15 @@ 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', + 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', + + MSG_SELECTION_CHANGED = 'slch', }; @@ -93,32 +95,33 @@ PlayListWindow::PlayListWindow( BRect frame, const char* name, // 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 ); + fSelectAllMI = new BMenuItem( "Select All", + new BMessage( MSG_SELECT_ALL ), 'A' ); + editMenu->AddItem( fSelectAllMI ); + fSelectNoneMI = new BMenuItem( "Select None", + new BMessage( MSG_SELECT_NONE ), 'A', B_SHIFT_KEY ); + editMenu->AddItem( fSelectNoneMI ); 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 ); + fSortNameMI = new BMenuItem( "Sort by Name", + new BMessage( MSG_SORT_NAME ), 'N' ); +fSortNameMI->SetEnabled( false ); + editMenu->AddItem( fSortNameMI ); + fSortPathMI = new BMenuItem( "Sort by Path", + new BMessage( MSG_SORT_PATH ), 'P' ); +fSortPathMI->SetEnabled( false ); + editMenu->AddItem( fSortPathMI ); + fRandomizeMI = new BMenuItem( "Randomize", + new BMessage( MSG_RANDOMIZE ), 'R' ); +fRandomizeMI->SetEnabled( false ); + editMenu->AddItem( fRandomizeMI ); editMenu->AddSeparatorItem(); - item = new BMenuItem( "Remove", + fRemoveMI = 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 ); + editMenu->AddItem( fRemoveMI ); + fRemoveAllMI = new BMenuItem( "Remove All", + new BMessage( MSG_REMOVE_ALL ) ); + editMenu->AddItem( fRemoveAllMI ); // make menu bar resize to correct height float menuWidth, menuHeight; @@ -130,7 +133,8 @@ editMenu->SetEnabled( false ); frame.top += fMenuBar->Bounds().IntegerHeight() + 1; frame.right -= B_V_SCROLL_BAR_WIDTH; - fListView = new PlaylistView( frame, fMainWindow, p_wrapper ); + fListView = new PlaylistView( frame, fMainWindow, p_wrapper, + new BMessage( MSG_SELECTION_CHANGED ) ); fBackgroundView = new BScrollView( "playlist scrollview", fListView, B_FOLLOW_ALL_SIDES, 0, false, true, @@ -182,8 +186,10 @@ PlayListWindow::MessageReceived( BMessage * p_message ) fMainWindow->PostMessage( p_message ); break; case MSG_SELECT_ALL: + fListView->Select( 0, fListView->CountItems() - 1 ); break; case MSG_SELECT_NONE: + fListView->DeselectAll(); break; case MSG_RANDOMIZE: break; @@ -192,8 +198,17 @@ PlayListWindow::MessageReceived( BMessage * p_message ) case MSG_SORT_PATH: break; case MSG_REMOVE: + fListView->RemoveSelected(); break; case MSG_REMOVE_ALL: + fListView->Select( 0, fListView->CountItems() - 1 ); + fListView->RemoveSelected(); + break; + case MSG_SELECTION_CHANGED: + _CheckItemsEnableState(); + break; + case B_MODIFIERS_CHANGED: + fListView->ModifiersChanged(); break; default: BWindow::MessageReceived( p_message ); @@ -235,16 +250,42 @@ 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 < p_wrapper->PlaylistSize(); i++ ) - fListView->AddItem( new PlaylistItem( p_wrapper->PlaylistItemName( i ) ) ); - } + fListView->RebuildList(); fListView->SetCurrent( p_wrapper->PlaylistCurrent() ); fListView->SetPlaying( p_wrapper->IsPlaying() ); + + _CheckItemsEnableState(); +} + +/***************************************************************************** + * PlayListWindow::_CheckItemsEnableState + *****************************************************************************/ +void +PlayListWindow::_CheckItemsEnableState() const +{ + // check if one item selected + int32 test = fListView->CurrentSelection( 0 ); + bool enable1 = test >= 0; + // check if at least two items selected +// test = fListView->CurrentSelection( 1 ); +// bool enable2 = test >= 0; + bool notEmpty = fListView->CountItems() > 0; + _SetMenuItemEnabled( fSelectAllMI, notEmpty ); + _SetMenuItemEnabled( fSelectNoneMI, enable1 ); +// _SetMenuItemEnabled( fSortNameMI, enable2 ); +// _SetMenuItemEnabled( fSortPathMI, enable2 ); +// _SetMenuItemEnabled( fRandomizeMI, enable2 ); + _SetMenuItemEnabled( fRemoveMI, enable1 ); + _SetMenuItemEnabled( fRemoveAllMI, notEmpty ); +} + +/***************************************************************************** + * PlayListWindow::_SetMenuItemEnabled + *****************************************************************************/ +void +PlayListWindow::_SetMenuItemEnabled( BMenuItem* item, bool enabled ) const +{ + // this check should actally be done in BMenuItem::SetEnabled(), but it is not... + if ( item->IsEnabled() != enabled ) + item->SetEnabled( enabled ); } diff --git a/modules/gui/beos/PlayListWindow.h b/modules/gui/beos/PlayListWindow.h index ee655c3174..ed098d6545 100644 --- a/modules/gui/beos/PlayListWindow.h +++ b/modules/gui/beos/PlayListWindow.h @@ -2,7 +2,7 @@ * PlayListWindow.h: BeOS interface window class prototype ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: PlayListWindow.h,v 1.5 2002/11/27 05:36:41 titer Exp $ + * $Id: PlayListWindow.h,v 1.6 2003/02/01 12:01:11 stippi Exp $ * * Authors: Jean-Marc Dressler * Tony Castley @@ -29,8 +29,7 @@ #include -class BListView; -class CDMenu; +class BMenuItem; class InterfaceWindow; class PlaylistView; @@ -53,13 +52,25 @@ class PlayListWindow : public BWindow void UpdatePlaylist( bool rebuild = false ); private: + void _CheckItemsEnableState() const; + void _SetMenuItemEnabled( BMenuItem* item, + bool enabled ) const; + PlaylistView * fListView; BView * fBackgroundView; BMenuBar * fMenuBar; InterfaceWindow * fMainWindow; + + BMenuItem* fSelectAllMI; + BMenuItem* fSelectNoneMI; + BMenuItem* fSortNameMI; + BMenuItem* fSortPathMI; + BMenuItem* fRandomizeMI; + BMenuItem* fRemoveMI; + BMenuItem* fRemoveAllMI; intf_thread_t * p_intf; - VlcWrapper * p_wrapper; + VlcWrapper * p_wrapper; }; #endif // BEOS_PLAY_LIST_WINDOW_H diff --git a/modules/gui/beos/VideoOutput.cpp b/modules/gui/beos/VideoOutput.cpp index ad385e37fa..377ab0b25a 100644 --- a/modules/gui/beos/VideoOutput.cpp +++ b/modules/gui/beos/VideoOutput.cpp @@ -2,7 +2,7 @@ * vout_beos.cpp: beos video output display method ***************************************************************************** * Copyright (C) 2000, 2001 VideoLAN - * $Id: VideoOutput.cpp,v 1.10 2003/01/24 06:31:56 titer Exp $ + * $Id: VideoOutput.cpp,v 1.11 2003/02/01 12:01:11 stippi Exp $ * * Authors: Jean-Marc Dressler * Samuel Hocevar @@ -48,10 +48,12 @@ #include #include -#include "VideoWindow.h" +#include "InterfaceWindow.h" // for load/save_settings() #include "DrawingTidbits.h" #include "MsgVals.h" +#include "VideoWindow.h" + /***************************************************************************** * vout_sys_t: BeOS video output method descriptor ***************************************************************************** @@ -147,6 +149,99 @@ class BackgroundView : public BView VLCView* fVideoView; }; + +/***************************************************************************** + * VideoSettings constructor and destructor + *****************************************************************************/ +VideoSettings::VideoSettings() + : fVideoSize( SIZE_100 ), + fFlags( FLAG_CORRECT_RATIO ), + fSettings( new BMessage( 'sett' ) ) +{ + // read settings from disk + status_t ret = load_settings( fSettings, "video_settings", "VideoLAN Client" ); + if ( ret == B_OK ) + { + uint32 flags; + if ( fSettings->FindInt32( "flags", (int32*)&flags ) == B_OK ) + SetFlags( flags ); + uint32 size; + if ( fSettings->FindInt32( "video size", (int32*)&size ) == B_OK ) + SetVideoSize( size ); + } + else + { + fprintf( stderr, "error loading video settings: %s\n", strerror( ret ) ); + + // figure out if we should use vertical sync by default + BScreen screen(B_MAIN_SCREEN_ID); + if (screen.IsValid()) + { + display_mode mode; + screen.GetMode(&mode); + float refresh = (mode.timing.pixel_clock * 1000) + / ((mode.timing.h_total)* (mode.timing.v_total)); + if (refresh < MIN_AUTO_VSYNC_REFRESH) + AddFlags(FLAG_SYNC_RETRACE); + } + } +} + +VideoSettings::VideoSettings( const VideoSettings& clone ) + : fVideoSize( clone.VideoSize() ), + fFlags( clone.Flags() ), + fSettings( NULL ) +{ +} + + +VideoSettings::~VideoSettings() +{ + if ( fSettings ) + { + // we are the default settings + // and write our settings to disk + if (fSettings->ReplaceInt32( "video size", VideoSize() ) != B_OK) + fSettings->AddInt32( "video size", VideoSize() ); + if (fSettings->ReplaceInt32( "flags", Flags() ) != B_OK) + fSettings->AddInt32( "flags", Flags() ); + + status_t ret = save_settings( fSettings, "video_settings", "VideoLAN Client" ); + if ( ret != B_OK ) + fprintf( stderr, "error saving video settings: %s\n", strerror( ret ) ); + delete fSettings; + } + else + { + // we are just a clone of the default settings + fDefaultSettings.SetVideoSize( VideoSize() ); + fDefaultSettings.SetFlags( Flags() ); + } +} + +/***************************************************************************** + * VideoSettings::DefaultSettings + *****************************************************************************/ +VideoSettings* +VideoSettings::DefaultSettings() +{ + return &fDefaultSettings; +} + +/***************************************************************************** + * VideoSettings::SetVideoSize + *****************************************************************************/ +void +VideoSettings::SetVideoSize( uint32 mode ) +{ + fVideoSize = mode; +} + +// static variable initialization +VideoSettings +VideoSettings::fDefaultSettings; + + /***************************************************************************** * VideoWindow constructor and destructor *****************************************************************************/ @@ -155,16 +250,15 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame, : BWindow(frame, NULL, B_TITLED_WINDOW, B_NOT_CLOSABLE | B_NOT_MINIMIZABLE), i_width(frame.IntegerWidth()), i_height(frame.IntegerHeight()), - is_zoomed(false), - vsync(false), + winSize(frame), i_buffer(0), teardownwindow(false), fTrueWidth(v_width), fTrueHeight(v_height), - fCorrectAspect(true), fCachedFeel(B_NORMAL_WINDOW_FEEL), fInterfaceShowing(false), - fInitStatus(B_ERROR) + fInitStatus(B_ERROR), + fSettings(new VideoSettings(*VideoSettings::DefaultSettings())) { p_vout = p_videoout; @@ -176,17 +270,6 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame, AddChild(mainView); mainView->AddChild(view); - // figure out if we should use vertical sync by default - BScreen screen(this); - if (screen.IsValid()) - { - display_mode mode; - screen.GetMode(&mode); - float refresh = (mode.timing.pixel_clock * 1000) - / ((mode.timing.h_total)* (mode.timing.v_total)); - vsync = (refresh < MIN_AUTO_VSYNC_REFRESH); - } - // allocate bitmap buffers for (int32 i = 0; i < 3; i++) bitmap[i] = NULL; @@ -204,10 +287,11 @@ VideoWindow::VideoWindow(int v_width, int v_height, BRect frame, (i_height * r.min_height_scale), i_height * r.max_height_scale); } - if( config_GetInt( p_vout, "fullscreen" ) ) - { - BWindow::Zoom();; - } + // vlc settings override settings from disk + if (config_GetInt(p_vout, "fullscreen")) + fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN); + + _SetToSettings(); } VideoWindow::~VideoWindow() @@ -217,6 +301,7 @@ VideoWindow::~VideoWindow() teardownwindow = true; wait_for_thread(fDrawThreadID, &result); _FreeBuffers(); + delete fSettings; } /***************************************************************************** @@ -233,12 +318,12 @@ VideoWindow::MessageReceived( BMessage *p_message ) case RESIZE_50: case RESIZE_100: case RESIZE_200: - if (is_zoomed) + if (IsFullScreen()) BWindow::Zoom(); _SetVideoSize(p_message->what); break; case VERT_SYNC: - vsync = !vsync; + SetSyncToRetrace(!IsSyncedToRetrace()); break; case WINDOW_FEEL: { @@ -247,11 +332,15 @@ VideoWindow::MessageReceived( BMessage *p_message ) { SetFeel(winFeel); fCachedFeel = winFeel; + if (winFeel == B_FLOATING_ALL_WINDOW_FEEL) + fSettings->AddFlags(VideoSettings::FLAG_ON_TOP_ALL); + else + fSettings->ClearFlags(VideoSettings::FLAG_ON_TOP_ALL); } } break; case ASPECT_CORRECT: - SetCorrectAspectRatio(!fCorrectAspect); + SetCorrectAspectRatio(!CorrectAspectRatio()); break; case SCREEN_SHOT: // save a screen shot @@ -299,24 +388,7 @@ VideoWindow::MessageReceived( BMessage *p_message ) void VideoWindow::Zoom(BPoint origin, float width, float height ) { - if(is_zoomed) - { - MoveTo(winSize.left, winSize.top); - ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight()); - be_app->ShowCursor(); - fInterfaceShowing = true; - } - else - { - BScreen screen(this); - BRect rect = screen.Frame(); - Activate(); - MoveTo(0.0, 0.0); - ResizeTo(rect.IntegerWidth(), rect.IntegerHeight()); - be_app->ObscureCursor(); - fInterfaceShowing = false; - } - is_zoomed = !is_zoomed; + ToggleFullScreen(); } /***************************************************************************** @@ -325,8 +397,9 @@ VideoWindow::Zoom(BPoint origin, float width, float height ) void VideoWindow::FrameMoved(BPoint origin) { - if (is_zoomed) return ; - winSize = Frame(); + if (IsFullScreen()) + return ; + winSize = Frame(); } /***************************************************************************** @@ -335,8 +408,8 @@ VideoWindow::FrameMoved(BPoint origin) void VideoWindow::FrameResized( float width, float height ) { - int32 useWidth = fCorrectAspect ? i_width : fTrueWidth; - int32 useHeight = fCorrectAspect ? i_height : fTrueHeight; + int32 useWidth = CorrectAspectRatio() ? i_width : fTrueWidth; + int32 useHeight = CorrectAspectRatio() ? i_height : fTrueHeight; float out_width, out_height; float out_left, out_top; float width_scale = width / useWidth; @@ -359,7 +432,7 @@ VideoWindow::FrameResized( float width, float height ) view->MoveTo(out_left,out_top); view->ResizeTo(out_width, out_height); - if (!is_zoomed) + if (!IsFullScreen()) winSize = Frame(); } @@ -374,8 +447,7 @@ VideoWindow::ScreenChanged(BRect frame, color_space format) screen.GetMode(&mode); float refresh = (mode.timing.pixel_clock * 1000) / ((mode.timing.h_total) * (mode.timing.v_total)); - if (refresh < MIN_AUTO_VSYNC_REFRESH) - vsync = true; + SetSyncToRetrace(refresh < MIN_AUTO_VSYNC_REFRESH); } /***************************************************************************** @@ -395,7 +467,7 @@ VideoWindow::drawBuffer(int bufferIndex) i_buffer = bufferIndex; // sync to the screen if required - if (vsync) + if (IsSyncedToRetrace()) { BScreen screen(this); screen.WaitForRetrace(22000); @@ -464,13 +536,92 @@ VideoWindow::SetInterfaceShowing(bool showIt) void VideoWindow::SetCorrectAspectRatio(bool doIt) { - if (fCorrectAspect != doIt) + if (CorrectAspectRatio() != doIt) { - fCorrectAspect = doIt; + if (doIt) + fSettings->AddFlags(VideoSettings::FLAG_CORRECT_RATIO); + else + fSettings->ClearFlags(VideoSettings::FLAG_CORRECT_RATIO); FrameResized(Bounds().Width(), Bounds().Height()); } } +/***************************************************************************** + * VideoWindow::CorrectAspectRatio + *****************************************************************************/ +bool +VideoWindow::CorrectAspectRatio() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_CORRECT_RATIO); +} + +/***************************************************************************** + * VideoWindow::ToggleFullScreen + *****************************************************************************/ +void +VideoWindow::ToggleFullScreen() +{ + SetFullScreen(!IsFullScreen()); +} + +/***************************************************************************** + * VideoWindow::SetFullScreen + *****************************************************************************/ +void +VideoWindow::SetFullScreen(bool doIt) +{ + if (doIt) + { + BScreen screen(this); + BRect rect = screen.Frame(); + Activate(); + MoveTo(0.0, 0.0); + ResizeTo(rect.IntegerWidth(), rect.IntegerHeight()); + be_app->ObscureCursor(); + fInterfaceShowing = false; + fSettings->AddFlags(VideoSettings::FLAG_FULL_SCREEN); + } + else + { + MoveTo(winSize.left, winSize.top); + ResizeTo(winSize.IntegerWidth(), winSize.IntegerHeight()); + be_app->ShowCursor(); + fInterfaceShowing = true; + fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN); + } +} + +/***************************************************************************** + * VideoWindow::IsFullScreen + *****************************************************************************/ +bool +VideoWindow::IsFullScreen() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_FULL_SCREEN); +} + +/***************************************************************************** + * VideoWindow::SetSyncToRetrace + *****************************************************************************/ +void +VideoWindow::SetSyncToRetrace(bool doIt) +{ + if (doIt) + fSettings->AddFlags(VideoSettings::FLAG_SYNC_RETRACE); + else + fSettings->ClearFlags(VideoSettings::FLAG_SYNC_RETRACE); +} + +/***************************************************************************** + * VideoWindow::IsSyncedToRetrace + *****************************************************************************/ +bool +VideoWindow::IsSyncedToRetrace() const +{ + return fSettings->HasFlags(VideoSettings::FLAG_SYNC_RETRACE); +} + + /***************************************************************************** * VideoWindow::_AllocateBuffers *****************************************************************************/ @@ -651,8 +802,8 @@ void VideoWindow::_SetVideoSize(uint32 mode) { // let size depend on aspect correction - int32 width = fCorrectAspect ? i_width : fTrueWidth; - int32 height = fCorrectAspect ? i_height : fTrueHeight; + int32 width = CorrectAspectRatio() ? i_width : fTrueWidth; + int32 height = CorrectAspectRatio() ? i_height : fTrueHeight; switch (mode) { case RESIZE_50: @@ -667,8 +818,42 @@ VideoWindow::_SetVideoSize(uint32 mode) default: break; } + fSettings->ClearFlags(VideoSettings::FLAG_FULL_SCREEN); ResizeTo(width, height); - is_zoomed = false; +} + +/***************************************************************************** + * VideoWindow::_SetToSettings + *****************************************************************************/ +void +VideoWindow::_SetToSettings() +{ + // adjust dimensions + uint32 mode = RESIZE_100; + switch (fSettings->VideoSize()) + { + case VideoSettings::SIZE_50: + mode = RESIZE_50; + break; + case VideoSettings::SIZE_200: + mode = RESIZE_200; + break; + case VideoSettings::SIZE_100: + case VideoSettings::SIZE_OTHER: + default: + break; + } + bool fullscreen = IsFullScreen(); // remember settings + _SetVideoSize(mode); // because this will reset settings + // the fullscreen status is reflected in the settings, + // but not yet in the windows state + if (fullscreen) + SetFullScreen(true); + if (fSettings->HasFlags(VideoSettings::FLAG_ON_TOP_ALL)) + fCachedFeel = B_FLOATING_ALL_WINDOW_FEEL; + else + fCachedFeel = B_NORMAL_WINDOW_FEEL; + SetFeel(fCachedFeel); } /***************************************************************************** @@ -683,8 +868,8 @@ VideoWindow::_SaveScreenShot( BBitmap* bitmap, char* path, info->bitmap = bitmap; info->path = path; info->translatorID = translatorID; - info->width = fCorrectAspect ? i_width : fTrueWidth; - info->height = fCorrectAspect ? i_height : fTrueHeight; + info->width = CorrectAspectRatio() ? i_width : fTrueWidth; + info->height = CorrectAspectRatio() ? 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", @@ -921,14 +1106,14 @@ VLCView::MouseDown(BPoint where) menu->AddItem(doubleItem); // Toggle FullScreen BMenuItem *zoomItem = new BMenuItem("Fullscreen", new BMessage(TOGGLE_FULL_SCREEN)); - zoomItem->SetMarked(videoWindow->is_zoomed); + zoomItem->SetMarked(videoWindow->IsFullScreen()); menu->AddItem(zoomItem); menu->AddSeparatorItem(); // Toggle vSync BMenuItem *vsyncItem = new BMenuItem("Vertical Sync", new BMessage(VERT_SYNC)); - vsyncItem->SetMarked(videoWindow->vsync); + vsyncItem->SetMarked(videoWindow->IsSyncedToRetrace()); menu->AddItem(vsyncItem); // Correct Aspect Ratio BMenuItem *aspectItem = new BMenuItem("Correct Aspect Ratio", new BMessage(ASPECT_CORRECT)); @@ -1032,7 +1217,7 @@ VLCView::Pulse() fCursorHidden = true; VideoWindow *videoWindow = dynamic_cast(Window()); // hide the interface window as well if full screen - if (videoWindow && videoWindow->is_zoomed) + if (videoWindow && videoWindow->IsFullScreen()) videoWindow->SetInterfaceShowing(false); } } @@ -1057,7 +1242,7 @@ VLCView::KeyDown(const char *bytes, int32 numBytes) break; case B_ESCAPE: // go back to window mode - if (videoWindow->is_zoomed) + if (videoWindow->IsFullScreen()) videoWindow->PostMessage(TOGGLE_FULL_SCREEN); break; case B_SPACE: diff --git a/modules/gui/beos/VideoWindow.h b/modules/gui/beos/VideoWindow.h index 775c04fddf..a9d185f4cc 100644 --- a/modules/gui/beos/VideoWindow.h +++ b/modules/gui/beos/VideoWindow.h @@ -2,7 +2,7 @@ * VideoWindow.h: BeOS video window class prototype ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN - * $Id: VideoWindow.h,v 1.5 2002/12/07 22:00:36 titer Exp $ + * $Id: VideoWindow.h,v 1.6 2003/02/01 12:01:11 stippi Exp $ * * Authors: Jean-Marc Dressler * Tony Castley @@ -55,6 +55,54 @@ colorcombo colspace[]= #define COLOR_COUNT 5 #define DEFAULT_COL 3 +class VideoSettings +{ + public: + VideoSettings( const VideoSettings& clone ); + virtual ~VideoSettings(); + + static VideoSettings* DefaultSettings(); + + enum + { + SIZE_OTHER = 0, + SIZE_50 = 1, + SIZE_100 = 2, + SIZE_200 = 3, + }; + + void SetVideoSize( uint32 mode ); + inline uint32 VideoSize() const + { return fVideoSize; } + enum + { + FLAG_CORRECT_RATIO = 0x0001, + FLAG_SYNC_RETRACE = 0x0002, + FLAG_ON_TOP_ALL = 0x0004, + FLAG_FULL_SCREEN = 0x0008, + }; + + inline void SetFlags( uint32 flags ) + { fFlags = flags; } + inline void AddFlags( uint32 flags ) + { fFlags |= flags; } + inline void ClearFlags( uint32 flags ) + { fFlags &= ~flags; } + inline bool HasFlags( uint32 flags ) const + { return fFlags & flags; } + inline uint32 Flags() const + { return fFlags; } + + private: + VideoSettings(); // reserved for default settings + + static VideoSettings fDefaultSettings; + + uint32 fVideoSize; + uint32 fFlags; + BMessage* fSettings; +}; + class VLCView : public BView { @@ -107,8 +155,14 @@ public: void SetInterfaceShowing(bool showIt); void SetCorrectAspectRatio(bool doIt); - inline bool CorrectAspectRatio() const - { return fCorrectAspect; } + bool CorrectAspectRatio() const; + void ToggleFullScreen(); + void SetFullScreen(bool doIt); + bool IsFullScreen() const; + void SetOnTop(bool doIt); + bool IsOnTop() const; + void SetSyncToRetrace(bool doIt); + bool IsSyncedToRetrace() const; inline status_t InitCheck() const { return fInitStatus; } @@ -117,9 +171,8 @@ public: int32 i_width; // aspect corrected bitmap size int32 i_height; BRect winSize; // current window size - bool is_zoomed, vsync; BBitmap *bitmap[3]; - BBitmap *overlaybitmap; +// BBitmap *overlaybitmap; VLCView *view; int i_buffer; volatile bool teardownwindow; @@ -134,6 +187,7 @@ private: void _FreeBuffers(); void _BlankBitmap(BBitmap* bitmap) const; void _SetVideoSize(uint32 mode); + void _SetToSettings(); void _SaveScreenShot( BBitmap* bitmap, char* path, @@ -153,10 +207,10 @@ private: int32 fTrueWidth; // incomming bitmap size int32 fTrueHeight; - bool fCorrectAspect; window_feel fCachedFeel; bool fInterfaceShowing; status_t fInitStatus; + VideoSettings* fSettings; }; #endif // BEOS_VIDEO_WINDOW_H diff --git a/modules/gui/beos/VlcWrapper.cpp b/modules/gui/beos/VlcWrapper.cpp index 29e87f78db..0c5b2ca8f9 100644 --- a/modules/gui/beos/VlcWrapper.cpp +++ b/modules/gui/beos/VlcWrapper.cpp @@ -2,7 +2,7 @@ * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port) ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: VlcWrapper.cpp,v 1.23 2003/01/29 00:02:09 titer Exp $ + * $Id: VlcWrapper.cpp,v 1.24 2003/02/01 12:01:11 stippi Exp $ * * Authors: Florian G. Pflug * Jon Lech Johansen @@ -358,35 +358,47 @@ bool VlcWrapper::IsPlaying() * playlist * ************/ -void VlcWrapper::OpenFiles( BList* o_files, bool replace ) +void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index ) { - BString *o_file; - int size = PlaylistSize(); - bool wasEmpty = ( size < 1 ); - - /* delete current playlist */ - if( replace ) - { - for( int i = 0; i < size; i++ ) - { - playlist_Delete( p_playlist, 0 ); - } - } - - /* append files */ - while( ( o_file = (BString *)o_files->LastItem() ) ) - { - playlist_Add( p_playlist, o_file->String(), - PLAYLIST_APPEND, PLAYLIST_END ); - o_files->RemoveItem(o_files->CountItems() - 1); - } - - /* eventually restart playing */ - if( replace || wasEmpty ) - { - playlist_Stop( p_playlist ); - playlist_Play( p_playlist ); - } + if ( o_files && o_files->CountItems() > 0) + { + int size = PlaylistSize(); + bool wasEmpty = ( size < 1 ); + if ( index == -1 ) + index = PLAYLIST_END; + int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT; + + /* delete current playlist */ + if( replace ) + { + for( int i = 0; i < size; i++ ) + { + playlist_Delete( p_playlist, 0 ); + } + } + + /* insert files */ + int32 count = o_files->CountItems(); + for ( int32 i = count - 1; i >= 0; i-- ) + { + if ( BString* o_file = (BString *)o_files->RemoveItem( i ) ) + { + playlist_Add( p_playlist, o_file->String(), + mode, index ); + if ( mode == PLAYLIST_INSERT ) + index++; + delete o_file; + } + } + // TODO: implement a user setting + // if to start automatically + /* eventually restart playing */ + if( replace || wasEmpty ) + { + playlist_Stop( p_playlist ); + playlist_Play( p_playlist ); + } + } } void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter) @@ -455,11 +467,15 @@ void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex ) maxIndex = -1; if ( p_playlist ) { + vlc_mutex_lock( &p_playlist->object_lock ); + maxIndex = p_playlist->i_size; if ( maxIndex > 0 ) - currentIndex = p_playlist->i_index + 1; + currentIndex = p_playlist->i_index/* + 1 -> why?!?*/; else maxIndex = -1; + + vlc_mutex_unlock( &p_playlist->object_lock ); } } @@ -611,6 +627,131 @@ void VlcWrapper::NavigateNext() PlaylistNext(); } +/************************* + * Playlist manipulation * + *************************/ + +// PlaylistLock +bool +VlcWrapper::PlaylistLock() const +{ +// TODO: search and destroy -> deadlock! +return true; + if ( p_playlist ) + { + vlc_mutex_lock( &p_playlist->object_lock ); + return true; + } + return false; +} + +// PlaylistUnlock +void +VlcWrapper::PlaylistUnlock() const +{ +// TODO: search and destroy -> deadlock! +return; + vlc_mutex_unlock( &p_playlist->object_lock ); +} + +// PlaylistItemAt +void* +VlcWrapper::PlaylistItemAt( int index ) const +{ + playlist_item_t* item = NULL; + if ( index >= 0 && index < p_playlist->i_size ) + item = p_playlist->pp_items[index]; + return (void*)item; +} + +// PlaylistRemoveItem +void* +VlcWrapper::PlaylistRemoveItem( int index ) const +{ + playlist_item_t* copy = NULL; + // check if item exists at the provided index + if ( index >= 0 && index < p_playlist->i_size ) + { + playlist_item_t* item = p_playlist->pp_items[index]; + if ( item ) + { + // make a copy of the removed item + copy = (playlist_item_t*)PlaylistCloneItem( (void*)item ); + // remove item from playlist (unfortunately, this frees it) + playlist_Delete( p_playlist, index ); + } + } + return (void*)copy; +} + +// PlaylistRemoveItem +void* +VlcWrapper::PlaylistRemoveItem( void* item ) const +{ + playlist_item_t* copy = NULL; + for ( int32 i = 0; i < p_playlist->i_size; i++ ) + { + if ( p_playlist->pp_items[i] == item ) + { + copy = (playlist_item_t*)PlaylistRemoveItem( i ); + break; + } + } + return (void*)copy; +} + +// PlaylistAddItem +bool +VlcWrapper::PlaylistAddItem( void* item, int index ) const +{ + if ( item ) + { + playlist_AddItem( p_playlist, (playlist_item_t*)item, + PLAYLIST_INSERT, index ); + } + // TODO: once playlist is returning useful info, return that instead + return true; +} + +// PlaylistCloneItem +void* +VlcWrapper::PlaylistCloneItem( void* castToItem ) const +{ + playlist_item_t* copy = NULL; + playlist_item_t* item = (playlist_item_t*)castToItem; + if ( item ) + { + copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) ); + if ( copy ) + { + // make a copy of the item at index + copy->psz_name = strdup( item->psz_name ); + copy->psz_uri = strdup( item->psz_uri ); + copy->i_type = item->i_type; + copy->i_status = item->i_status; + copy->b_autodeletion = item->b_autodeletion; + } + } + return (void*)copy; +} + +// Careful! You need to know what you're doing here! +// The reason for having it, is to be able to deal with +// the rather lame list implementation of the playlist. +// It is meant to help manipulate the playlist with the above +// methods while keeping it valid. +// +// PlaylistSetPlaying +void +VlcWrapper::PlaylistSetPlaying( int index ) const +{ + if ( index < 0 ) + index = 0; + if ( index >= p_playlist->i_size ) + index = p_playlist->i_size - 1; + p_playlist->i_index = index; +} + /********* * audio * @@ -853,7 +994,7 @@ void VlcWrapper::ChapterInfo( int32 ¤tIndex, int32 &maxIndex ) * Miscellanous * ****************/ -void VlcWrapper::LoadSubFile( char * psz_file ) +void VlcWrapper::LoadSubFile( const char * psz_file ) { config_PutPsz( p_intf, "sub-file", strdup( psz_file ) ); } diff --git a/modules/gui/beos/VlcWrapper.h b/modules/gui/beos/VlcWrapper.h index 4623ebbf5a..c873b77194 100644 --- a/modules/gui/beos/VlcWrapper.h +++ b/modules/gui/beos/VlcWrapper.h @@ -2,7 +2,7 @@ * VlcWrapper.h: BeOS plugin for vlc (derived from MacOS X port) ***************************************************************************** * Copyright (C) 2001 VideoLAN - * $Id: VlcWrapper.h,v 1.18 2003/01/29 00:02:09 titer Exp $ + * $Id: VlcWrapper.h,v 1.19 2003/02/01 12:01:11 stippi Exp $ * * Authors: Florian G. Pflug * Jon Lech Johansen @@ -79,7 +79,8 @@ public: bool IsPlaying(); /* Playlist */ - void OpenFiles( BList *o_files, bool replace = true ); + void OpenFiles( BList *o_files, bool replace = true, + int32 index = -1 ); void OpenDisc( BString o_type, BString o_device, int i_title, int i_chapter ); int PlaylistSize(); @@ -99,6 +100,21 @@ public: void NavigatePrev(); void NavigateNext(); + /* Playlist manipulation */ + bool PlaylistLock() const; + void PlaylistUnlock() const; + // playlist must be locked prior to calling all of these! + void* PlaylistItemAt( int index ) const; + // both functions return a copy of the removed item + // so that it can be added at another index + void* PlaylistRemoveItem( int index ) const; + void* PlaylistRemoveItem( void* item ) const; + // uses playlist_AddItem() + bool PlaylistAddItem( void* item, int index ) const; + void* PlaylistCloneItem( void* item ) const; + // only modifies playlist, doesn't effect playback + void PlaylistSetPlaying( int index ) const; + /* Audio */ bool HasAudio(); unsigned short GetVolume(); @@ -123,7 +139,7 @@ public: void ChapterInfo( int32& currentIndex, int32& maxIndex ); /* Miscellanous */ - void LoadSubFile( char * psz_file ); + void LoadSubFile( const char * psz_file ); void FilterChange(); private: -- 2.39.2