From d63b9e39f853676075ca171f093f0dc3d8fc1902 Mon Sep 17 00:00:00 2001 From: Gildas Bazin Date: Fri, 2 Dec 2005 00:25:52 +0000 Subject: [PATCH] * modules/gui/wxwidgets: start of a playlist_manager widget. This is based on code from the current playlist dialog but this dialog should eventually make use of the widget as well (when enough features have been implemented). --- modules/gui/wxwidgets/Modules.am | 3 + .../gui/wxwidgets/bitmaps/playlist_small.xpm | 21 + modules/gui/wxwidgets/interface.cpp | 42 +- modules/gui/wxwidgets/interface.hpp | 13 +- modules/gui/wxwidgets/playlist_manager.cpp | 576 ++++++++++++++++++ modules/gui/wxwidgets/playlist_manager.hpp | 81 +++ modules/gui/wxwidgets/timer.cpp | 7 +- 7 files changed, 731 insertions(+), 12 deletions(-) create mode 100644 modules/gui/wxwidgets/bitmaps/playlist_small.xpm create mode 100644 modules/gui/wxwidgets/playlist_manager.cpp create mode 100644 modules/gui/wxwidgets/playlist_manager.hpp diff --git a/modules/gui/wxwidgets/Modules.am b/modules/gui/wxwidgets/Modules.am index 2603d4660b..ed94845d22 100644 --- a/modules/gui/wxwidgets/Modules.am +++ b/modules/gui/wxwidgets/Modules.am @@ -9,6 +9,7 @@ SOURCES_wxwidgets = \ timer.cpp \ video.cpp \ input_manager.cpp \ + playlist_manager.cpp \ dialogs.cpp \ dialogs/open.cpp \ dialogs/streamout.cpp \ @@ -41,6 +42,7 @@ EXTRA_DIST += \ timer.hpp \ video.hpp \ input_manager.hpp \ + playlist_manager.hpp \ dialogs/fileinfo.hpp \ dialogs/preferences.hpp \ dialogs/wizard.hpp \ @@ -67,6 +69,7 @@ EXTRA_DIST += \ bitmaps/next.xpm \ bitmaps/pause.xpm \ bitmaps/playlist.xpm \ + bitmaps/playlist_small.xpm \ bitmaps/play.xpm \ bitmaps/prev.xpm \ bitmaps/repeat.xpm \ diff --git a/modules/gui/wxwidgets/bitmaps/playlist_small.xpm b/modules/gui/wxwidgets/bitmaps/playlist_small.xpm new file mode 100644 index 0000000000..ba464fd121 --- /dev/null +++ b/modules/gui/wxwidgets/bitmaps/playlist_small.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static char * playlist_small_xpm[] = { +"16 16 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" .. ....... ", +" ", +" .. ....... ", +" ", +" .. ....... ", +" ", +" .. ....... ", +" ", +" ", +" "}; diff --git a/modules/gui/wxwidgets/interface.cpp b/modules/gui/wxwidgets/interface.cpp index 8d93a936a0..699a121200 100644 --- a/modules/gui/wxwidgets/interface.cpp +++ b/modules/gui/wxwidgets/interface.cpp @@ -25,6 +25,7 @@ * Preamble *****************************************************************************/ #include "interface.hpp" +#include "playlist_manager.hpp" #include "extrapanel.hpp" #include "timer.hpp" #include "video.hpp" @@ -45,6 +46,7 @@ #include "bitmaps/slow.xpm" #include "bitmaps/fast.xpm" #include "bitmaps/playlist.xpm" +#include "bitmaps/playlist_small.xpm" #include "bitmaps/speaker.xpm" #include "bitmaps/speaker_mute.xpm" @@ -134,6 +136,7 @@ enum Wizard_Event, Playlist_Event, + PlaylistSmall_Event, Logs_Event, FileInfo_Event, @@ -167,6 +170,7 @@ BEGIN_EVENT_TABLE(Interface, wxFrame) EVT_MENU(VLM_Event, Interface::OnShowDialog) EVT_MENU(Playlist_Event, Interface::OnShowDialog) + EVT_MENU(PlaylistSmall_Event, Interface::OnSmallPlaylist) EVT_MENU(Logs_Event, Interface::OnShowDialog) EVT_MENU(FileInfo_Event, Interface::OnShowDialog) EVT_MENU(Prefs_Event, Interface::OnShowDialog) @@ -215,6 +219,8 @@ Interface::Interface( intf_thread_t *_p_intf, long style ): p_intf = _p_intf; b_extra = VLC_FALSE; extra_frame = 0; + b_playlist_manager = VLC_FALSE; + playlist_manager = 0; /* Give our interface a nice little icon */ SetIcon( wxIcon( vlc_xpm ) ); @@ -348,6 +354,8 @@ void Interface::Update() { /* Misc updates */ ((VLCVolCtrl *)volctrl)->UpdateVolume(); + + if( playlist_manager ) playlist_manager->Update(); } void Interface::OnControlEvent( wxCommandEvent& event ) @@ -490,6 +498,7 @@ void Interface::CreateOurToolBar() #define HELP_PLAY N_("Play") #define HELP_PAUSE N_("Pause") #define HELP_PLO N_("Playlist") +#define HELP_SPLO N_("Small playlist") #define HELP_PLP N_("Previous playlist item") #define HELP_PLN N_("Next playlist item") #define HELP_SLOW N_("Play slower") @@ -533,15 +542,15 @@ void Interface::CreateOurToolBar() toolbar->AddSeparator(); toolbar->AddTool( Playlist_Event, wxT(""), wxBitmap( playlist_xpm ), wxU(_(HELP_PLO)) ); + toolbar->AddTool( PlaylistSmall_Event, wxT(""), + wxBitmap( playlist_small_xpm ), wxU(_(HELP_SPLO)) ); } -#if !( (wxMAJOR_VERSION <= 2) && (wxMINOR_VERSION <= 6) && (wxRELEASE_NUMBER < 2) ) wxControl *p_dummy_ctrl = new wxControl( toolbar, -1, wxDefaultPosition, - wxSize(35, 16 ), wxBORDER_NONE ); + wxSize(16, 16 ), wxBORDER_NONE ); toolbar->AddControl( p_dummy_ctrl ); -#endif volctrl = new VLCVolCtrl( p_intf, toolbar ); toolbar->AddControl( volctrl ); @@ -658,6 +667,13 @@ void Interface::SetIntfMinSize() ms.SetWidth( ext_min_size.GetWidth() ); } + if( playlist_manager && playlist_manager->IsShown() ) + { + ms.SetHeight( ms.GetHeight() + playlist_min_size.GetHeight() ); + if( playlist_min_size.GetWidth() > ms.GetWidth() ) + ms.SetWidth( playlist_min_size.GetWidth() ); + } + SetSizeHints( ms ); } @@ -837,6 +853,26 @@ void Interface::OnExtended( wxCommandEvent& WXUNUSED(event) ) main_sizer->Fit( this ); } +void Interface::OnSmallPlaylist( wxCommandEvent& WXUNUSED(event) ) +{ + UpdateVideoWindow( p_intf, video_window ); + + if( !playlist_manager ) + { + /* Create the extra panel */ + playlist_manager = new PlaylistManager( p_intf, main_panel ); + panel_sizer->Add( playlist_manager, 0, wxEXPAND , 0 ); + playlist_min_size = playlist_manager->GetBestSize(); + } + + b_playlist_manager = !b_playlist_manager; + panel_sizer->Show( playlist_manager, b_playlist_manager ); + + SetIntfMinSize(); + main_sizer->Layout(); + main_sizer->Fit( this ); +} + void Interface::OnPlayStream( wxCommandEvent& WXUNUSED(event) ) { PlayStream(); diff --git a/modules/gui/wxwidgets/interface.hpp b/modules/gui/wxwidgets/interface.hpp index ca359af76a..221d436839 100644 --- a/modules/gui/wxwidgets/interface.hpp +++ b/modules/gui/wxwidgets/interface.hpp @@ -100,9 +100,6 @@ namespace wxvlc InputManager *input_manager; - vlc_bool_t b_extra; - wxPanel *extra_frame; - wxControl *volctrl; #ifdef wxHAS_TASK_BAR_ICON @@ -132,6 +129,7 @@ namespace wxvlc void OnOpenSat( wxCommandEvent& event ); void OnExtended( wxCommandEvent& event ); + void OnSmallPlaylist( wxCommandEvent& event ); void OnBookmarks( wxCommandEvent& event ); void OnShowDialog( wxCommandEvent& event ); @@ -164,8 +162,17 @@ namespace wxvlc wxMenu *p_video_menu; wxMenu *p_navig_menu; + /* Extended panel */ + vlc_bool_t b_extra; + wxPanel *extra_frame; + + /* Playlist panel */ + vlc_bool_t b_playlist_manager; + wxPanel *playlist_manager; + /* Utility dimensions */ wxSize main_min_size; + wxSize playlist_min_size; wxSize ext_min_size; }; diff --git a/modules/gui/wxwidgets/playlist_manager.cpp b/modules/gui/wxwidgets/playlist_manager.cpp new file mode 100644 index 0000000000..c920b1900a --- /dev/null +++ b/modules/gui/wxwidgets/playlist_manager.cpp @@ -0,0 +1,576 @@ +/***************************************************************************** + * playlist_manager.cpp : wxWindows plugin for vlc + ***************************************************************************** + * Copyright (C) 2000-2005 the VideoLAN team + * $Id$ + * + * Authors: Olivier Teulière + * Clément Stenac + * Gildas Bazin + * + * This program is free software; you can redistribute it and/OR MODIFy + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "playlist_manager.hpp" +#include "interface.hpp" + +#include "bitmaps/type_unknown.xpm" +#include "bitmaps/type_afile.xpm" +#include "bitmaps/type_vfile.xpm" +#include "bitmaps/type_net.xpm" +#include "bitmaps/type_card.xpm" +#include "bitmaps/type_disc.xpm" +#include "bitmaps/type_cdda.xpm" +#include "bitmaps/type_directory.xpm" +#include "bitmaps/type_playlist.xpm" +#include "bitmaps/type_node.xpm" + +#include +#include + +namespace wxvlc { +/* Callback prototype */ +static int PlaylistChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int PlaylistNext( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int ItemChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int ItemAppended( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ); +static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ); + +/***************************************************************************** + * Event Table. + *****************************************************************************/ + +/* IDs for the controls and the menu commands */ +enum +{ + TreeCtrl_Event, + + UpdateItem_Event, + AppendItem_Event, + RemoveItem_Event, +}; + +DEFINE_LOCAL_EVENT_TYPE( wxEVT_PLAYLIST ); + +BEGIN_EVENT_TABLE(PlaylistManager, wxPanel) + /* Tree control events */ + EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, PlaylistManager::OnActivateItem ) + + /* Custom events */ + EVT_COMMAND(-1, wxEVT_PLAYLIST, PlaylistManager::OnPlaylistEvent) +END_EVENT_TABLE() + +/***************************************************************************** + * PlaylistItem class + ****************************************************************************/ +class PlaylistItem : public wxTreeItemData +{ +public: + PlaylistItem( playlist_item_t *p_item ) : i_id(p_item->input.i_id) {} + int i_id; +}; + +/***************************************************************************** + * Constructor. + *****************************************************************************/ +PlaylistManager::PlaylistManager( intf_thread_t *_p_intf, wxWindow *p_parent ): + wxPanel( p_parent, -1, wxDefaultPosition, wxSize(500,300) ) +{ + /* Initializations */ + p_intf = _p_intf; + b_need_update = VLC_FALSE; + i_items_to_append = 0; + i_cached_item_id = -1; + i_update_counter = 0; + + p_playlist = (playlist_t *) + vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); + if( p_playlist == NULL ) return; + + var_Create( p_intf, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + var_Create( p_intf, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); + var_Create( p_intf, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );; + + /* Create the tree */ + treectrl = new wxTreeCtrl( this, TreeCtrl_Event, + wxDefaultPosition, wxDefaultSize, + wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT| + wxTR_NO_LINES | + wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | + wxTR_MULTIPLE | wxTR_EXTENDED ); + + /* Add everything to the panel */ + sizer = new wxBoxSizer( wxHORIZONTAL ); + SetSizer( sizer ); + sizer->Add( treectrl, 1, wxEXPAND ); + + /* Create image list */ + wxImageList *p_images = new wxImageList( 16 , 16, TRUE ); + + /* FIXME: absolutely needs to be in the right order FIXME */ + p_images->Add( wxIcon( type_unknown_xpm ) ); + p_images->Add( wxIcon( type_afile_xpm ) ); + p_images->Add( wxIcon( type_vfile_xpm ) ); + p_images->Add( wxIcon( type_directory_xpm ) ); + p_images->Add( wxIcon( type_disc_xpm ) ); + p_images->Add( wxIcon( type_cdda_xpm ) ); + p_images->Add( wxIcon( type_card_xpm ) ); + p_images->Add( wxIcon( type_net_xpm ) ); + p_images->Add( wxIcon( type_playlist_xpm ) ); + p_images->Add( wxIcon( type_node_xpm ) ); + treectrl->AssignImageList( p_images ); + + /* Reduce font size */ + wxFont font = treectrl->GetFont(); font.SetPointSize(9); + treectrl->SetFont( font ); + +#if wxUSE_DRAG_AND_DROP + /* Associate drop targets with the playlist */ + SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) ); +#endif + + /* Update the playlist */ + Rebuild( VLC_TRUE ); + + /* + * We want to be notified of playlist changes + */ + + /* Some global changes happened -> Rebuild all */ + var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this ); + + /* We went to the next item */ + var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this ); + + /* One item has been updated */ + var_AddCallback( p_playlist, "item-change", ItemChanged, this ); + + var_AddCallback( p_playlist, "item-append", ItemAppended, this ); + var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this ); +} + +PlaylistManager::~PlaylistManager() +{ + if( p_playlist == NULL ) return; + + var_DelCallback( p_playlist, "item-change", ItemChanged, this ); + var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this ); + var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this ); + var_DelCallback( p_playlist, "item-append", ItemAppended, this ); + var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this ); + vlc_object_release( p_playlist ); +} + +/***************************************************************************** + * PlaylistChanged: callback triggered by the intf-change playlist variable + * We don't rebuild the playlist directly here because we don't want the + * caller to block for a too long time. + *****************************************************************************/ +static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ) +{ + PlaylistManager *p_playlist = (PlaylistManager *)param; + p_playlist->b_need_update = VLC_TRUE; + return VLC_SUCCESS; +} + +/***************************************************************************** + * Next: callback triggered by the playlist-current playlist variable + *****************************************************************************/ +static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ) +{ + PlaylistManager *p_playlist = (PlaylistManager *)param; + + wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event ); + event.SetInt( oval.i_int ); + p_playlist->AddPendingEvent( event ); + event.SetInt( nval.i_int ); + p_playlist->AddPendingEvent( event ); + + return VLC_SUCCESS; +} + +/***************************************************************************** + * Update functions + *****************************************************************************/ +void PlaylistManager::CreateNode( playlist_item_t *p_node, wxTreeItemId parent) +{ + wxTreeItemId node = + treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ), -1, -1, + new PlaylistItem( p_node ) ); + treectrl->SetItemImage( node, p_node->input.i_type ); + + UpdateNodeChildren( p_node, node ); +} + +void PlaylistManager::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) +{ + wxTreeItemIdValue cookie; + wxTreeItemId child; + + for( int i = 0; i < p_node->i_children ; i++ ) + { + if( !i ) child = treectrl->GetFirstChild( node, cookie); + else child = treectrl->GetNextChild( node, cookie ); + + if( !child.IsOk() ) + { + /* Not enough children */ + CreateNode( p_node->pp_children[i], node ); + /* Keep the tree pointer up to date */ + child = treectrl->GetNextChild( node, cookie ); + } + } + + treectrl->SetItemImage( node, p_node->input.i_type ); + +} + +void PlaylistManager::UpdateNodeChildren( playlist_item_t *p_node, + wxTreeItemId node ) +{ + for( int i = 0; i< p_node->i_children ; i++ ) + { + /* Append the item */ + if( p_node->pp_children[i]->i_children == -1 ) + { + wxTreeItemId item = + treectrl->AppendItem( node, + wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1, + new PlaylistItem( p_node->pp_children[i]) ); + + UpdateTreeItem( item ); + } + else + { + CreateNode( p_node->pp_children[i], node ); + } + } +} + +void PlaylistManager::UpdateTreeItem( wxTreeItemId item ) +{ + if( ! item.IsOk() ) return; + + wxTreeItemData *p_data = treectrl->GetItemData( item ); + if( !p_data ) return; + + LockPlaylist( p_intf->p_sys, p_playlist ); + playlist_item_t *p_item = + playlist_ItemGetById( p_playlist, ((PlaylistItem *)p_data)->i_id ); + if( !p_item ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + + wxString msg; + wxString duration = wxU( "" ); + char *psz_author = + vlc_input_item_GetInfo( &p_item->input, + _("Meta-information"), _("Artist")); + if( !psz_author ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + + char psz_duration[MSTRTIME_MAX_SIZE]; + mtime_t dur = p_item->input.i_duration; + + if( dur != -1 ) + { + secstotimestr( psz_duration, dur/1000000 ); + duration.Append( wxU( " ( " ) + wxString( wxU( psz_duration ) ) + + wxU( " )" ) ); + } + + if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE ) + { + msg = wxString( wxU( p_item->input.psz_name ) ) + duration; + } + else + { + msg = wxString(wxU( psz_author )) + wxT(" - ") + + wxString(wxU(p_item->input.psz_name)) + duration; + } + free( psz_author ); + treectrl->SetItemText( item , msg ); + treectrl->SetItemImage( item, p_item->input.i_type ); + + if( p_playlist->status.p_item == p_item ) + { + treectrl->SetItemBold( item, true ); + while( treectrl->GetItemParent( item ).IsOk() ) + { + item = treectrl->GetItemParent( item ); + treectrl->Expand( item ); + } + } + else + { + treectrl->SetItemBold( item, false ); + } + UnlockPlaylist( p_intf->p_sys, p_playlist ); +} + +void PlaylistManager::AppendItem( wxCommandEvent& event ) +{ + playlist_add_t *p_add = (playlist_add_t *)event.GetClientData(); + playlist_item_t *p_item = NULL; + wxTreeItemId item, node; + + i_items_to_append--; + + /* No need to do anything if the playlist is going to be rebuilt */ + if( b_need_update ) return; + + //if( p_add->i_view != i_current_view ) goto update; + + node = FindItem( treectrl->GetRootItem(), p_add->i_node ); + if( !node.IsOk() ) goto update; + + p_item = playlist_ItemGetById( p_playlist, p_add->i_item ); + if( !p_item ) goto update; + + item = FindItem( treectrl->GetRootItem(), p_add->i_item ); + if( item.IsOk() ) goto update; + + item = treectrl->AppendItem( node, wxL2U( p_item->input.psz_name ), -1,-1, + new PlaylistItem( p_item ) ); + treectrl->SetItemImage( item, p_item->input.i_type ); + + if( item.IsOk() && p_item->i_children == -1 ) UpdateTreeItem( item ); + +update: + return; +} + +void PlaylistManager::UpdateItem( int i ) +{ + if( i < 0 ) return; /* Sanity check */ + + wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); + if( item.IsOk() ) UpdateTreeItem( item ); +} + +void PlaylistManager::RemoveItem( int i ) +{ + if( i <= 0 ) return; /* Sanity check */ + + wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); + if( item.IsOk() ) + { + treectrl->Delete( item ); + + /* Invalidate cache */ + i_cached_item_id = -1; + } +} + +/* This function is called on a regular basis */ +void PlaylistManager::Update() +{ + i_update_counter++; + + /* If the playlist isn't show there's no need to update it */ + if( !IsShown() ) return; + + if( this->b_need_update ) + { + this->b_need_update = VLC_FALSE; + Rebuild( VLC_TRUE ); + } + + /* Updating the playing status every 0.5s is enough */ + if( i_update_counter % 5 ) return; +} + +/********************************************************************** + * Rebuild the playlist + **********************************************************************/ +void PlaylistManager::Rebuild( vlc_bool_t b_root ) +{ + playlist_view_t *p_view; + + i_items_to_append = 0; + i_cached_item_id = -1; + + p_view = playlist_ViewFind( p_playlist, VIEW_CATEGORY ); + + treectrl->DeleteAllItems(); + treectrl->AddRoot( wxU(_("root" )), -1, -1, + new PlaylistItem( p_view->p_root ) ); + + wxTreeItemId root = treectrl->GetRootItem(); + UpdateNode( p_view->p_root, root ); +} + +/********************************************************************** + * Search functions (internal) + **********************************************************************/ + +/* Find a wxItem from a playlist id */ +wxTreeItemId PlaylistManager::FindItem( wxTreeItemId root, int i_id ) +{ + wxTreeItemIdValue cookie; + PlaylistItem *p_wxcurrent; + wxTreeItemId dummy, search, item, child; + + if( i_id < 0 ) return dummy; + if( i_cached_item_id == i_id ) return cached_item; + + p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root ); + if( !p_wxcurrent ) return dummy; + + if( p_wxcurrent->i_id == i_id ) + { + i_cached_item_id = i_id; + cached_item = root; + return root; + } + + item = treectrl->GetFirstChild( root, cookie ); + while( item.IsOk() ) + { + p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item ); + if( !p_wxcurrent ) + { + item = treectrl->GetNextChild( root, cookie ); + continue; + } + + if( p_wxcurrent->i_id == i_id ) + { + i_cached_item_id = i_id; + cached_item = item; + return item; + } + + if( treectrl->ItemHasChildren( item ) ) + { + wxTreeItemId search = FindItem( item, i_id ); + if( search.IsOk() ) return search; + } + + item = treectrl->GetNextChild( root, cookie ); + } + + return dummy; +} + +/******************************************************************** + * Events + ********************************************************************/ +void PlaylistManager::OnActivateItem( wxTreeEvent& event ) +{ + playlist_item_t *p_item, *p_node; + wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() ); + PlaylistItem *p_wxitem = (PlaylistItem *) + treectrl->GetItemData( event.GetItem() ); + + if( !p_wxitem || !parent.IsOk() ) return; + + PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent ); + if( !p_wxparent ) return; + + LockPlaylist( p_intf->p_sys, p_playlist ); + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id ); + p_node = playlist_ItemGetById( p_playlist, p_wxparent->i_id ); + if( !p_item || p_item->i_children >= 0 ) + { + p_node = p_item; + p_item = NULL; + } + + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, VIEW_CATEGORY, + p_node, p_item ); + UnlockPlaylist( p_intf->p_sys, p_playlist ); +} + +void PlaylistManager::OnPlaylistEvent( wxCommandEvent& event ) +{ + switch( event.GetId() ) + { + case UpdateItem_Event: + UpdateItem( event.GetInt() ); + break; + case AppendItem_Event: + AppendItem( event ); + break; + case RemoveItem_Event: + RemoveItem( event.GetInt() ); + break; + } +} + +/***************************************************************************** + * ItemChanged: callback triggered by the item-change playlist variable + *****************************************************************************/ +static int ItemChanged( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t old_val, vlc_value_t new_val, void *param ) +{ + PlaylistManager *p_playlist = (PlaylistManager *)param; + + wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event ); + event.SetInt( new_val.i_int ); + p_playlist->AddPendingEvent( event ); + + return VLC_SUCCESS; +} +static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t old_val, vlc_value_t new_val, void *param ) +{ + PlaylistManager *p_playlist = (PlaylistManager *)param; + + wxCommandEvent event( wxEVT_PLAYLIST, RemoveItem_Event ); + event.SetInt( new_val.i_int ); + p_playlist->AddPendingEvent( event ); + + return VLC_SUCCESS; +} + +static int ItemAppended( vlc_object_t *p_this, const char *psz_variable, + vlc_value_t oval, vlc_value_t nval, void *param ) +{ + PlaylistManager *p_playlist = (PlaylistManager *)param; + + playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t)); + memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) ); + + if( p_playlist->i_items_to_append++ > 50 ) + { + /* Too many items waiting to be added, it will be quicker to rebuild + * the whole playlist */ + p_playlist->b_need_update = VLC_TRUE; + return VLC_SUCCESS; + } + + wxCommandEvent event( wxEVT_PLAYLIST, AppendItem_Event ); + event.SetClientData( (void *)p_add ); + p_playlist->AddPendingEvent( event ); + + return VLC_SUCCESS; +} +} diff --git a/modules/gui/wxwidgets/playlist_manager.hpp b/modules/gui/wxwidgets/playlist_manager.hpp new file mode 100644 index 0000000000..7f517ead25 --- /dev/null +++ b/modules/gui/wxwidgets/playlist_manager.hpp @@ -0,0 +1,81 @@ +/***************************************************************************** + * playlist_manager.hpp: Header for the playlist manager + ***************************************************************************** + * Copyright (C) 1999-2005 the VideoLAN team + * $Id$ + * + * Authors: Clément Stenac + * Gildas Bazin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +#ifndef _WXVLC_PLAYLIST_MANAGER_H_ +#define _WXVLC_PLAYLIST_MANAGER_H_ + +#include "wxwidgets.hpp" +#include + +namespace wxvlc +{ +/* PlaylistManager */ +class PlaylistManager: public wxPanel +{ +public: + /* Constructor */ + PlaylistManager( intf_thread_t *p_intf, wxWindow *p_parent ); + virtual ~PlaylistManager(); + + void Update(); + + bool b_need_update; + int i_items_to_append; + +private: + DECLARE_EVENT_TABLE(); + + /* Update */ + void Rebuild( vlc_bool_t ); + void CreateNode( playlist_item_t*, wxTreeItemId ); + void UpdateNode( playlist_item_t*, wxTreeItemId ); + void UpdateNodeChildren( playlist_item_t*, wxTreeItemId ); + void UpdateTreeItem( wxTreeItemId ); + + void UpdateItem( int ); + void AppendItem( wxCommandEvent& ); + void RemoveItem( int ); + + wxTreeItemId FindItem( wxTreeItemId, int ); + + /* Events */ + void OnActivateItem( wxTreeEvent& event ); + /* Custom events */ + void OnPlaylistEvent( wxCommandEvent& event ); + + /* Simple cache for FindItem() */ + int i_cached_item_id; + wxTreeItemId cached_item; + + intf_thread_t *p_intf; + playlist_t *p_playlist; + wxTreeCtrl *treectrl; + wxSizer *sizer; + + int i_update_counter; +}; + +} // end of wxvlc namespace + +#endif diff --git a/modules/gui/wxwidgets/timer.cpp b/modules/gui/wxwidgets/timer.cpp index e8514be145..50555e61c3 100644 --- a/modules/gui/wxwidgets/timer.cpp +++ b/modules/gui/wxwidgets/timer.cpp @@ -98,12 +98,7 @@ void Timer::Notify() /* Call update */ p_main_interface->input_manager->Update(); - - if( p_main_interface->input_manager->IsPlaying() ) - { - /* Take care of the volume, etc... */ - p_main_interface->Update(); - } + p_main_interface->Update(); /* Show the interface, if requested */ if( p_intf->p_sys->b_intf_show ) -- 2.39.2