X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fwxwidgets%2Fdialogs%2Fplaylist.cpp;h=9ca6fc98ff4a4cf1cc62e92e66a56a2cd23cddf5;hb=7ca4e3eb624251feb1f97cfc25104cce473e04a0;hp=a95b5541bcfd010c59b4ee7cb738361ec6751d22;hpb=2d25a2fca8d42e0dfa40406dd81fdf869841e378;p=vlc diff --git a/modules/gui/wxwidgets/dialogs/playlist.cpp b/modules/gui/wxwidgets/dialogs/playlist.cpp index a95b5541bc..9ca6fc98ff 100644 --- a/modules/gui/wxwidgets/dialogs/playlist.cpp +++ b/modules/gui/wxwidgets/dialogs/playlist.cpp @@ -4,8 +4,8 @@ * Copyright (C) 2000-2005 the VideoLAN team * $Id$ * - * Authors: Olivier Teulière - * Clément Stenac + * Authors: Olivier Teulière + * Clément Stenac * * 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 @@ -19,7 +19,7 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -27,7 +27,6 @@ *****************************************************************************/ #include "dialogs/playlist.hpp" #include "dialogs/iteminfo.hpp" -#include "interface.hpp" // Needed for D&D - TODO: Split #include "bitmaps/shuffle.xpm" #include "bitmaps/repeat.xpm" @@ -47,6 +46,9 @@ #include #include +#include +#include "vlc_charset.h" + #define HELP_SHUFFLE N_( "Shuffle" ) #define HELP_LOOP N_( "Repeat All" ) #define HELP_REPEAT N_( "Repeat One" ) @@ -60,9 +62,9 @@ static int PlaylistNext( vlc_object_t *, const char *, 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 ); + 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 ); + vlc_value_t oval, vlc_value_t nval, void *param ); /***************************************************************************** * Event Table. @@ -94,11 +96,13 @@ enum PopupSort_Event, PopupDel_Event, PopupInfo_Event, + PopupAddNode_Event, SearchText_Event, Search_Event, /* controls */ + Source_Event, TreeCtrl_Event, Browse_Event, /* For export playlist */ @@ -111,6 +115,7 @@ enum MenuDummy_Event = wxID_HIGHEST + 999, FirstView_Event = wxID_HIGHEST + 1000, + CategoryView_Event, OneLevelView_Event, LastView_Event = wxID_HIGHEST + 1100, FirstSD_Event = wxID_HIGHEST + 2000, @@ -151,10 +156,15 @@ BEGIN_EVENT_TABLE(Playlist, wxFrame) EVT_MENU( PopupSort_Event, Playlist::OnPopupSort) EVT_MENU( PopupDel_Event, Playlist::OnPopupDel) EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo) + EVT_MENU( PopupAddNode_Event, Playlist::OnPopupAddNode) + /* Source selector */ + EVT_LIST_ITEM_SELECTED( Source_Event, Playlist::OnSourceSelected ) /* Tree control events */ EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem ) EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown ) + EVT_TREE_BEGIN_DRAG( TreeCtrl_Event, Playlist::OnDragItemBegin ) + EVT_TREE_END_DRAG( TreeCtrl_Event, Playlist::OnDragItemEnd ) EVT_CONTEXT_MENU( Playlist::OnPopup ) @@ -181,11 +191,14 @@ class PlaylistItem : public wxTreeItemData public: PlaylistItem( playlist_item_t *p_item ) : wxTreeItemData() { - i_id = p_item->input.i_id; + i_id = p_item->i_id; + i_input_id = p_item->p_input->i_id; } protected: + int i_input_id; int i_id; friend class Playlist; +friend class PlaylistFileDropTarget; }; /***************************************************************************** @@ -202,10 +215,9 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): pp_sds = NULL; i_update_counter = 0; i_sort_mode = MODE_NONE; - b_need_update = VLC_FALSE; + b_need_update = false; i_items_to_append = 0; - p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); + p_playlist = pl_Yield( p_intf ); if( p_playlist == NULL ) return; SetIcon( *p_intf->p_sys->p_icon ); @@ -213,8 +225,8 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): p_view_menu = NULL; p_sd_menu = SDMenu(); - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_FALSE; + p_current_viewroot = p_playlist->p_root_category; + p_current_treeroot = NULL; i_title_sorted = 0; i_group_sorted = 0; @@ -228,9 +240,9 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): wxMenu *manage_menu = new wxMenu; manage_menu->Append( AddFile_Event, wxU(_("&Simple Add File...")) ); manage_menu->Append( AddDir_Event, wxU(_("Add &Directory...")) ); - manage_menu->Append( AddMRL_Event, wxU(_("&Add MRL...")) ); + manage_menu->Append( AddMRL_Event, wxU(_("&Add URL...")) ); manage_menu->AppendSeparator(); - manage_menu->Append( MenuDummy_Event, wxU(_("Services discovery")), + manage_menu->Append( MenuDummy_Event, wxU(_("Services Discovery")), p_sd_menu ); manage_menu->AppendSeparator(); manage_menu->Append( Open_Event, wxU(_("&Open Playlist...")) ); @@ -240,10 +252,10 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): /* Create our "Sort" menu */ wxMenu *sort_menu = new wxMenu; - sort_menu->Append( SortTitle_Event, wxU(_("Sort by &title")) ); - sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse sort by title")) ); + sort_menu->Append( SortTitle_Event, wxU(_("Sort by &Title")) ); + sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse Sort by Title")) ); sort_menu->AppendSeparator(); - sort_menu->Append( Randomize_Event, wxU(_("&Shuffle Playlist")) ); + sort_menu->Append( Randomize_Event, wxU(_("&Shuffle")) ); /* Create our "Selection" menu */ wxMenu *selection_menu = new wxMenu; @@ -265,11 +277,12 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): /* Create the popup menu */ node_popup = new wxMenu; node_popup->Append( PopupPlay_Event, wxU(_("Play")) ); - node_popup->Append( PopupPlayThis_Event, wxU(_("Play this branch")) ); + node_popup->Append( PopupPlayThis_Event, wxU(_("Play this Branch")) ); node_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) ); - node_popup->Append( PopupSort_Event, wxU(_("Sort this branch")) ); + node_popup->Append( PopupSort_Event, wxU(_("Sort this Branch")) ); node_popup->Append( PopupDel_Event, wxU(_("Delete")) ); node_popup->Append( PopupInfo_Event, wxU(_("Info")) ); + node_popup->Append( PopupAddNode_Event, wxU(_("Add Node")) ); item_popup = new wxMenu; item_popup->Append( PopupPlay_Event, wxU(_("Play")) ); @@ -323,6 +336,11 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): search_button->SetDefault(); toolbar->Realize(); + /* Create teh source selector */ + source_sel = new wxListView( playlist_panel, Source_Event, + wxDefaultPosition, wxDefaultSize, + wxLC_AUTOARRANGE|wxLC_SINGLE_SEL ); + /* Create the tree */ treectrl = new wxTreeCtrl( playlist_panel, TreeCtrl_Event, wxDefaultPosition, wxDefaultSize, @@ -347,14 +365,13 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): p_images->Add( wxIcon( type_node_xpm ) ); treectrl->AssignImageList( p_images ); - treectrl->AddRoot( wxU(_("root" )), -1, -1, NULL ); - /* Reduce font size */ wxFont font= treectrl->GetFont(); font.SetPointSize(9); treectrl->SetFont( font ); - wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL ); + wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL ); + panel_sizer->Add( source_sel, 0, wxALL | wxEXPAND, 5 ); panel_sizer->Add( treectrl, 1, wxEXPAND | wxALL, 5 ); panel_sizer->Layout(); @@ -366,13 +383,13 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): #if wxUSE_DRAG_AND_DROP /* Associate drop targets with the playlist */ - SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) ); + SetDropTarget( new PlaylistFileDropTarget( this ) ); + menubar->SetDropTarget( new PlaylistFileDropTarget( this ) ); + toolbar->SetDropTarget( new PlaylistFileDropTarget( this ) ); #endif i_saved_id = -1; - - - /* We want to be noticed of playlist changes */ + i_saved_input_id = -1; /* Some global changes happened -> Rebuild all */ var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this ); @@ -387,13 +404,18 @@ Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ): var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this ); /* Update the playlist */ - Rebuild( VLC_TRUE ); - + p_current_treeroot = p_playlist->p_local_category; + Rebuild( true ); } Playlist::~Playlist() { - if( pp_sds != NULL ) free( pp_sds ); + if( pp_sds != NULL ) + { + char **pp_sd = pp_sds; + for( ; *pp_sd; pp_sd++ ) free( *pp_sd ); + free( pp_sds ); + } if( p_playlist == NULL ) return; @@ -433,7 +455,7 @@ void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) child = treectrl->GetNextChild( node, cookie ); } } - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); } @@ -441,9 +463,9 @@ void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node ) void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent ) { wxTreeItemId node = - treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ), + treectrl->AppendItem( parent, wxL2U( p_node->p_input->psz_name ), -1,-1, new PlaylistItem( p_node ) ); - treectrl->SetItemImage( node, p_node->input.i_type ); + treectrl->SetItemImage( node, p_node->p_input->i_type ); UpdateNodeChildren( p_node, node ); } @@ -452,18 +474,20 @@ void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent ) void Playlist::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, + if( !(p_node->pp_children[i]->i_flags & PLAYLIST_DBL_FLAG) ) + { + wxTreeItemId item = + treectrl->AppendItem( node, + wxL2U( p_node->pp_children[i]->p_input->psz_name ), -1,-1, new PlaylistItem( p_node->pp_children[i]) ); - UpdateTreeItem( item ); + UpdateTreeItem( item ); + } } else { @@ -475,14 +499,14 @@ void Playlist::UpdateNodeChildren( playlist_item_t *p_node, /* Update an item in the tree */ void Playlist::UpdateTreeItem( wxTreeItemId item ) { + LockPlaylist( p_intf->p_sys, p_playlist ); 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 ); + ((PlaylistItem *)p_data)->i_id, true ); if( !p_item ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); @@ -491,17 +515,12 @@ void Playlist::UpdateTreeItem( wxTreeItemId item ) 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_artist = input_item_GetArtist( p_item->p_input ); + char *psz_name = input_item_GetName( p_item->p_input ); char psz_duration[MSTRTIME_MAX_SIZE]; - mtime_t dur = p_item->input.i_duration; + mtime_t dur = input_item_GetDuration( p_item->p_input ); if( dur != -1 ) { @@ -510,18 +529,19 @@ void Playlist::UpdateTreeItem( wxTreeItemId item ) wxU( " )" ) ); } - if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE ) + if( !psz_artist || !strcmp( psz_artist, "" ) || p_item->p_input->b_fixed_name == true ) { - msg = wxString( wxU( p_item->input.psz_name ) ) + duration; + msg = wxString( wxU( psz_name ) ) + duration; } else { - msg = wxString(wxU( psz_author )) + wxT(" - ") + - wxString(wxU(p_item->input.psz_name)) + duration; + msg = wxString(wxU( psz_artist )) + wxT(" - ") + + wxString(wxU(psz_name)) + duration; } - free( psz_author ); + free( psz_artist ); + free( psz_name ); treectrl->SetItemText( item , msg ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( p_playlist->status.p_item == p_item ) { @@ -529,7 +549,9 @@ void Playlist::UpdateTreeItem( wxTreeItemId item ) while( treectrl->GetItemParent( item ).IsOk() ) { item = treectrl->GetItemParent( item ); - treectrl->Expand( item ); + if( ! (item == treectrl->GetRootItem() && + treectrl->HasFlag( wxTR_HIDE_ROOT ) ) ) + treectrl->Expand( item ); } } else @@ -551,21 +573,20 @@ void Playlist::AppendItem( wxCommandEvent& event ) /* 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 ); + p_item = playlist_ItemGetById( p_playlist, p_add->i_item, true ); if( !p_item ) goto update; + if( (p_item->i_flags & PLAYLIST_DBL_FLAG ) ) 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, + wxL2U( p_item->p_input->psz_name ), -1,-1, new PlaylistItem( p_item ) ); - treectrl->SetItemImage( item, p_item->input.i_type ); + treectrl->SetItemImage( item, p_item->p_input->i_type ); if( item.IsOk() && p_item->i_children == -1 ) { @@ -574,26 +595,8 @@ void Playlist::AppendItem( wxCommandEvent& event ) update: int i_count = CountItems( treectrl->GetRootItem()); - if( i_count != p_playlist->i_size ) - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist (%i not shown)")), - p_playlist->i_size, - p_playlist->i_size - i_count ) ); - if( !b_changed_view ) - { - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_TRUE; - b_need_update = VLC_TRUE; - } - } - else - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist")), - p_playlist->i_size ), 0 ); - } - + statusbar->SetStatusText( wxString::Format( wxU(_( + "%i items in playlist" ) ), i_count ) ); return; } @@ -601,9 +604,7 @@ update: void Playlist::UpdateItem( int i ) { if( i < 0 ) return; /* Sanity check */ - - wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); - + wxTreeItemId item = FindItemByInput( treectrl->GetRootItem(), i ); if( item.IsOk() ) { UpdateTreeItem( item ); @@ -615,6 +616,11 @@ void Playlist::RemoveItem( int i ) if( i <= 0 ) return; /* Sanity check */ if( i == i_saved_id ) i_saved_id = -1; + /* Hack: always invalidate input item cache */ + i_saved_input_id = -1; + + /// \todo Check if it is in the source selector */ + wxTreeItemId item = FindItem( treectrl->GetRootItem(), i ); if( item.IsOk() ) @@ -630,6 +636,16 @@ void Playlist::RemoveItem( int i ) /* Find a wxItem from a playlist id */ wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id ) +{ + return FindItemInner( root, i_id, false ); +} + +wxTreeItemId Playlist::FindItemByInput( wxTreeItemId root, int i_input_id ) +{ + return FindItemInner( root, i_input_id, true ); +} + +wxTreeItemId Playlist::FindItemInner( wxTreeItemId root, int i_id, bool b_byinput ) { wxTreeItemIdValue cookie; PlaylistItem *p_wxcurrent; @@ -641,51 +657,70 @@ wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id ) if( i_id < 0 ) { - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } - if( i_saved_id == i_id ) - { + if( b_byinput && i_saved_input_id == i_id ) + return saved_input_tree_item; + if( !b_byinput && i_saved_id == i_id) return saved_tree_item; - } if( !p_wxcurrent ) { - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } - if( p_wxcurrent->i_id == i_id ) + if( !b_byinput && p_wxcurrent->i_id == i_id ) { i_saved_id = i_id; saved_tree_item = root; return root; } + if( b_byinput && p_wxcurrent->i_input_id == i_id ) + { + i_saved_input_id = i_id; + saved_input_tree_item = root; + return root; + } while( item.IsOk() ) { p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item ); - if( p_wxcurrent->i_id == i_id ) + if( !b_byinput && p_wxcurrent->i_id == i_id ) { i_saved_id = i_id; saved_tree_item = item; return item; } + else if( b_byinput && p_wxcurrent->i_input_id == i_id ) + { + i_saved_input_id = i_id; + saved_input_tree_item = item; + return item; + } if( treectrl->ItemHasChildren( item ) ) { - wxTreeItemId search = FindItem( item, i_id ); + wxTreeItemId search = FindItemInner( item, i_id, b_byinput ); if( search.IsOk() ) { - i_saved_id = i_id; - saved_tree_item = search; - return search; + if( !b_byinput ) + { + i_saved_id = i_id; + saved_tree_item = search; + return search; + } + else + { + i_saved_input_id = i_id; + saved_input_tree_item = search; + return search; + + } } } item = treectrl->GetNextChild( root, cookie ); } /* Not found */ - wxTreeItemId dummy; - return dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } int Playlist::CountItems( wxTreeItemId root ) @@ -704,7 +739,7 @@ int Playlist::CountItems( wxTreeItemId root ) { playlist_item_t *p_item; LockPlaylist( p_intf->p_sys, p_playlist ); - p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id ); + p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id, true ); if( p_item && p_item->i_children == -1 ) count++; UnlockPlaylist( p_intf->p_sys, p_playlist ); @@ -715,7 +750,7 @@ int Playlist::CountItems( wxTreeItemId root ) } /* Find a wxItem from a name (from current) */ -wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found ) +wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, bool *pb_current_found ) { wxTreeItemIdValue cookie; wxTreeItemId search; @@ -727,13 +762,13 @@ wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string if( treectrl->GetItemText( item).Lower().Contains( search_string.Lower() ) ) { - if( !current.IsOk() || *pb_current_found == VLC_TRUE ) + if( !current.IsOk() || *pb_current_found == true ) { return item; } else if( current.IsOk() && item == current ) { - *pb_current_found = VLC_TRUE; + *pb_current_found = true; } } if( treectrl->ItemHasChildren( item ) ) @@ -748,84 +783,54 @@ wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string item = treectrl->GetNextChild( root, cookie); } /* Not found */ - wxTreeItemId dummy; + wxTreeItemId dummy; dummy.Unset(); return dummy; } /********************************************************************** * Rebuild the playlist **********************************************************************/ -void Playlist::Rebuild( vlc_bool_t b_root ) +void Playlist::Rebuild( bool b_root ) { - playlist_view_t *p_view; - i_items_to_append = 0; - /* We can remove the callbacks before locking, anyway, we won't - * miss anything */ - if( b_root ) - { - 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 ); + LockPlaylist( p_intf->p_sys, p_playlist ); - /* ...and rebuild it */ - LockPlaylist( p_intf->p_sys, p_playlist ); - } + /* Invalidate cache */ i_saved_id = -1; + i_saved_input_id = -1; - p_view = playlist_ViewFind( p_playlist, i_current_view ); /* FIXME */ + /* Rebuild the list */ + source_sel->ClearAll(); + for( int i = 0 ; i< p_current_viewroot->i_children ; i++ ) + { + source_sel->InsertItem( i, + wxL2U( p_current_viewroot->pp_children[i]->p_input->psz_name) ); + source_sel->SetItemData( i, + p_current_viewroot->pp_children[i]->i_id ); + if( p_current_viewroot->pp_children[i] == p_current_treeroot ) + source_sel->Select( i ); + } /* HACK we should really get new*/ treectrl->DeleteAllItems(); treectrl->AddRoot( wxU(_("root" )), -1, -1, - new PlaylistItem( p_view->p_root) ); + new PlaylistItem( p_current_treeroot ) ); wxTreeItemId root = treectrl->GetRootItem(); - UpdateNode( p_view->p_root, root ); + UpdateNodeChildren( p_current_treeroot, root ); int i_count = CountItems( treectrl->GetRootItem() ); - if( i_count < p_playlist->i_size && !b_changed_view ) - { - i_current_view = VIEW_CATEGORY; - b_changed_view = VLC_TRUE; - Rebuild( VLC_FALSE ); - } - else if( i_count != p_playlist->i_size ) - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist (%i not shown)")), - p_playlist->i_size, - p_playlist->i_size - i_count ) ); - } - else - { - statusbar->SetStatusText( wxString::Format( wxU(_( - "%i items in playlist")), - p_playlist->i_size ), 0 ); - } - - if( b_root ) - { - /* Put callbacks back online */ - var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this ); - var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this ); - var_AddCallback( p_playlist, "item-change", ItemChanged, this ); - var_AddCallback( p_playlist, "item-append", ItemAppended, this ); - var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this ); + statusbar->SetStatusText( wxString::Format( wxU(_( + "%i items in playlist")), i_count ), 0 ); - UnlockPlaylist( p_intf->p_sys, p_playlist ); - } + UnlockPlaylist( p_intf->p_sys, p_playlist ); } - - void Playlist::ShowPlaylist( bool show ) { - if( show ) Rebuild( VLC_TRUE ); + if( show ) Rebuild( true ); Show( show ); } @@ -839,8 +844,8 @@ void Playlist::UpdatePlaylist() if( this->b_need_update ) { - this->b_need_update = VLC_FALSE; - Rebuild( VLC_TRUE ); + this->b_need_update = false; + Rebuild( true ); } /* Updating the playing status every 0.5s is enough */ @@ -857,7 +862,7 @@ void Playlist::DeleteTreeItem( wxTreeItemId item ) p_wxitem = (PlaylistItem *)treectrl->GetItemData( item ); LockPlaylist( p_intf->p_sys, p_playlist ); - p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id ); + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, true ); if( !p_item ) { @@ -865,21 +870,21 @@ void Playlist::DeleteTreeItem( wxTreeItemId item ) return; } - if( p_item->i_children == -1 ) DeleteItem( p_item->input.i_id ); + if( p_item->i_children == -1 ) DeleteItem( p_item->p_input->i_id ); else DeleteNode( p_item ); - RemoveItem( item ); + RemoveItem( p_item->i_id ); UnlockPlaylist( p_intf->p_sys, p_playlist ); } void Playlist::DeleteItem( int item_id ) { - playlist_LockDelete( p_playlist, item_id ); + playlist_DeleteFromInput( p_playlist, item_id, true ); } void Playlist::DeleteNode( playlist_item_t *p_item ) { - playlist_NodeDelete( p_playlist, p_item, VLC_TRUE , VLC_FALSE ); + playlist_NodeDelete( p_playlist, p_item, true , false ); } void Playlist::OnMenuClose( wxCommandEvent& event ) @@ -899,11 +904,13 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) ) char *psz_desc; char *psz_filter; char *psz_module; - } formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" }}; + } formats[] = {//{ _("M3U file"), "*.m3u", "export-m3u" }, + { _("XSPF playlist"), "*.xspf", "export-xspf"} + }; wxString filter = wxT(""); - if( p_playlist->i_size == 0 ) + if( playlist_IsEmpty( p_playlist ) ) { wxMessageBox( wxU(_("Playlist is empty") ), wxU(_("Can't save")), wxICON_WARNING | wxOK, this ); @@ -922,10 +929,15 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) ) if( dialog.ShowModal() == wxID_OK ) { - if( dialog.GetPath().mb_str() ) + if( dialog.GetPath().mb_str(wxConvUTF8) ) { - playlist_Export( p_playlist, dialog.GetPath().mb_str(), - formats[dialog.GetFilterIndex()].psz_module ); + /* what root should we export? */ + if( p_playlist->p_root_category->i_children > 0 ) + { + playlist_Export( p_playlist, dialog.GetPath().mb_str(wxConvUTF8), + p_playlist->p_root_category->pp_children[0], + formats[dialog.GetFilterIndex()].psz_module ); + } } } @@ -934,11 +946,11 @@ void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) ) void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) ) { wxFileDialog dialog( this, wxU(_("Open playlist")), wxT(""), wxT(""), - wxT("All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u"), wxOPEN ); + wxT("All playlists|" EXTENSIONS_PLAYLIST "|XSPF playlist|*.xspf|M3U files|*.m3u"), wxOPEN ); if( dialog.ShowModal() == wxID_OK ) { - playlist_Import( p_playlist, dialog.GetPath().mb_str() ); + playlist_Import( p_playlist, dialog.GetPath().mb_str(wxConvUTF8) ); } } @@ -973,17 +985,19 @@ void Playlist::OnSort( wxCommandEvent& event ) { case SortTitle_Event: playlist_RecursiveNodeSort( p_playlist, - playlist_ItemGetById( p_playlist, p_wxitem->i_id ), + playlist_ItemGetById( p_playlist, p_wxitem->i_id, + true ), SORT_TITLE_NODES_FIRST, ORDER_NORMAL ); break; case RSortTitle_Event: playlist_RecursiveNodeSort( p_playlist, - playlist_ItemGetById( p_playlist, p_wxitem->i_id ), + playlist_ItemGetById( p_playlist, p_wxitem->i_id, + true ), SORT_TITLE_NODES_FIRST, ORDER_REVERSE ); } UnlockPlaylist( p_intf->p_sys, p_playlist ); - Rebuild( VLC_TRUE ); + Rebuild( true ); } /********************************************************************** @@ -997,27 +1011,17 @@ void Playlist::OnSort( wxCommandEvent& event ) void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) ) { wxString search_string = search_text->GetValue(); + PlaylistItem *p_wxroot; + p_wxroot = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() ); + playlist_item_t *p_root = playlist_ItemGetById( p_playlist, p_wxroot->i_id, + true ); - vlc_bool_t pb_found = VLC_FALSE; - - wxTreeItemId found = - FindItemByName( treectrl->GetRootItem(), search_string, - search_current, &pb_found ); + assert( p_root ); + char *psz_name = wxFromLocale( search_string ); + playlist_LiveSearchUpdate( p_playlist, p_root, psz_name ); + Rebuild( true ); - if( !found.IsOk() ) - { - wxTreeItemId dummy; - search_current = dummy; - found = FindItemByName( treectrl->GetRootItem(), search_string, - search_current, &pb_found ); - } - - if( found.IsOk() ) - { - search_current = found; - treectrl->EnsureVisible( found ); - treectrl->SelectItem( found, true ); - } + wxLocaleFree( psz_name ); } /********************************************************************** @@ -1027,16 +1031,23 @@ void Playlist::RecursiveDeleteSelection( wxTreeItemId root ) { wxTreeItemIdValue cookie; wxTreeItemId child = treectrl->GetFirstChild( root, cookie ); + wxTreeItemId nextchild; + bool childIsSelected = FALSE; + bool nextchildIsSelected = FALSE; + + if( child.IsOk() ) childIsSelected = treectrl->IsSelected( child ); + while( child.IsOk() ) { - if( treectrl->ItemHasChildren( child ) ) - { - RecursiveDeleteSelection( child ); - if( treectrl->IsSelected(child ) ) DeleteTreeItem( child ); - } - else if( treectrl->IsSelected( child ) ) + nextchild = treectrl->GetNextChild( root, cookie ); + if( nextchild.IsOk() ) + nextchildIsSelected = treectrl->IsSelected( nextchild ); + if( childIsSelected ) DeleteTreeItem( child ); - child = treectrl->GetNextChild( root, cookie ); + else if( treectrl->ItemHasChildren( child ) ) + RecursiveDeleteSelection( child ); + child = nextchild; + childIsSelected = nextchildIsSelected; } } @@ -1074,46 +1085,32 @@ void Playlist::OnRepeat( wxCommandEvent& event ) ********************************************************************/ void Playlist::OnActivateItem( wxTreeEvent& event ) { - playlist_item_t *p_item,*p_node,*p_item2,*p_node2; + playlist_item_t *p_item, *p_parent; PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData( event.GetItem() ); - wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() ); - - PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent ); LockPlaylist( p_intf->p_sys, p_playlist ); - if( !( p_wxitem && p_wxparent ) ) + if( !( p_wxitem ) ) { UnlockPlaylist( p_intf->p_sys, p_playlist ); return; } + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, true ); - p_item2 = playlist_ItemGetById(p_playlist, p_wxitem->i_id); - p_node2 = playlist_ItemGetById(p_playlist, p_wxparent->i_id); - if( p_item2 && p_item2->i_children == -1 ) + p_parent = p_item; + while( p_parent ) { - p_node = p_node2; - p_item = p_item2; + if( p_parent == p_current_treeroot ) + break; + p_parent = p_parent->p_parent; } - else + + if( p_parent ) { - p_node = p_item2; - p_item = NULL; -/* if( p_node && p_node->i_children > 0 && - p_node->pp_children[0]->i_children == -1) - { - p_item = p_node->pp_children[0]; - } - else - { - p_item = NULL; - }*/ + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, true, p_parent, p_item ); } - - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view, - p_node, p_item ); UnlockPlaylist( p_intf->p_sys, p_playlist ); } @@ -1121,21 +1118,189 @@ void Playlist::OnKeyDown( wxTreeEvent& event ) { long keycode = event.GetKeyCode(); /* Delete selected items */ - if( keycode == WXK_BACK || keycode == WXK_DELETE ) + if( keycode == WXK_BACK || keycode == WXK_DELETE || keycode == WXK_NUMPAD_DELETE ) { /* We send a dummy event */ OnDeleteSelection( event ); } + /* Work around wxWin32 bug */ + else if( keycode == WXK_RETURN ) + { + wxArrayTreeItemIds items; + if( treectrl->GetSelections( items ) > 0 ) + { + wxTreeEvent event; + event.SetItem( items.Item( 0 ) ); + OnActivateItem( event ); + } + } else { event.Skip(); } } -void Playlist::OnEnDis( wxCommandEvent& event ) +void Playlist::OnDragItemBegin( wxTreeEvent& event ) +{ + event.Allow(); + draged_tree_item = event.GetItem(); +} + +void Playlist::OnDragItemEnd( wxTreeEvent& event ) +{ + wxTreeItemId dest_tree_item = event.GetItem(); + + if( !dest_tree_item.IsOk() ) return; + + /* check that we're not trying to move a node into one of its children */ + wxTreeItemId parent = dest_tree_item; + while( parent != treectrl->GetRootItem() ) + { + if( draged_tree_item == parent ) return; + parent = treectrl->GetItemParent( parent ); + } + + LockPlaylist( p_intf->p_sys, p_playlist ); + + PlaylistItem *p_wxdrageditem = + (PlaylistItem *)treectrl->GetItemData( draged_tree_item ); + PlaylistItem *p_wxdestitem = + (PlaylistItem *)treectrl->GetItemData( dest_tree_item ); + if( !p_wxdrageditem || !p_wxdestitem ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + + playlist_item_t *p_drageditem = + playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id, true ); + playlist_item_t *p_destitem = + playlist_ItemGetById(p_playlist, p_wxdestitem->i_id, true ); + if( !p_drageditem || !p_destitem ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + + if( p_destitem->i_children == -1 ) + /* this is a leaf */ + { + parent = treectrl->GetItemParent( dest_tree_item ); + PlaylistItem *p_parent = + (PlaylistItem *)treectrl->GetItemData( parent ); + if( !p_parent ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + playlist_item_t *p_destitem2 = + playlist_ItemGetById( p_playlist, p_parent->i_id, true ); + if( !p_destitem2 ) + { + UnlockPlaylist( p_intf->p_sys, p_playlist ); + return; + } + int i; + for( i = 0; i < p_destitem2->i_children; i++ ) + { + if( p_destitem2->pp_children[i] == p_destitem ) break; + } + playlist_TreeMove( p_playlist, p_drageditem, p_destitem2, i ); + } + else + /* this is a node */ + { + playlist_TreeMove( p_playlist, p_drageditem, p_destitem, 0 ); + } + + UnlockPlaylist( p_intf->p_sys, p_playlist ); + + /* FIXME: having this Rebuild() is dirty */ + Rebuild( true ); +} + +#if wxUSE_DRAG_AND_DROP +PlaylistFileDropTarget::PlaylistFileDropTarget( Playlist *p ):p( p ){} + +/******************************************************************** + * File Drag And Drop handling + ********************************************************************/ +bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y, + const wxArrayString& filenames ) { - msg_Warn( p_intf, "not implemented" ); + int i_pos = 0; + playlist_item_t *p_dest; + + LockPlaylist( p->p_intf->p_sys, p->p_playlist ); + + /* find the destination node and position in that node */ + const wxPoint pt( x, y ); + wxTreeItemId item = p->treectrl->HitTest( pt ); + + if( !item.IsOk() ) + { + /* We were droped below the last item so we append to the + * general node */ + msg_Err( p->p_playlist, "USE OF P_GENERAL" ); + p_dest = p->p_playlist->p_local_category; + i_pos = PLAYLIST_END; + } + else + { + PlaylistItem *p_plitem = + (PlaylistItem *)p->treectrl->GetItemData( item ); + p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id, true ); + + if( p_dest->i_children == -1 ) + { + /* This is a leaf. Append right after it + * We thus need to find the parrent node and the position of the + * leaf in its children list */ + wxTreeItemId parent = p->treectrl->GetItemParent( item ); + PlaylistItem *p_parent = + (PlaylistItem *)p->treectrl->GetItemData( parent ); + if( !p_parent ) + { + UnlockPlaylist( p->p_intf->p_sys, p->p_playlist ); + return FALSE; + } + playlist_item_t *p_node = + playlist_ItemGetById( p->p_playlist, p_parent->i_id, true ); + if( !p_node ) + { + UnlockPlaylist( p->p_intf->p_sys, p->p_playlist ); + return FALSE; + } + for( i_pos = 0; i_pos < p_node->i_children; i_pos++ ) + { + if( p_node->pp_children[i_pos] == p_dest ) break; + } + p_dest = p_node; + } + } + + UnlockPlaylist( p->p_intf->p_sys, p->p_playlist ); + + /* Put the items in the playlist node */ + for( size_t i = 0; i < filenames.GetCount(); i++ ) + { + char *psz_utf8 = wxDnDFromLocale( filenames[i] ); + input_item_t *p_input = input_ItemNew( p->p_playlist, + psz_utf8, psz_utf8 ); + int i_ret = ( playlist_BothAddInput( p->p_playlist, p_input, p_dest, + PLAYLIST_PREPARSE, i_pos, NULL, NULL, pl_Unlocked ) != VLC_SUCCESS ); + vlc_gc_decref( p_input ); + wxDnDLocaleFree( psz_utf8 ); + if( i_ret != VLC_SUCCESS ) + return FALSE; + } + + /* FIXME: having this Rebuild() is dirty */ + p->Rebuild( true ); + + return TRUE; } +#endif /********************************************************************** * Menu @@ -1165,30 +1330,37 @@ void Playlist::OnMenuEvent( wxCommandEvent& event ) } else if( event.GetId() < LastView_Event ) { - - int i_new_view = event.GetId() - FirstView_Event; - - playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_new_view ); - - if( p_view != NULL ) + if( event.GetId() == CategoryView_Event ) { - b_changed_view = VLC_TRUE; - i_current_view = i_new_view; - playlist_ViewUpdate( p_playlist, i_new_view ); - Rebuild( VLC_TRUE ); - return; + p_current_viewroot = p_playlist->p_root_category; + if( p_current_treeroot == p_playlist->p_local_category || + p_current_treeroot == p_playlist->p_local_onelevel ) + { + p_current_treeroot = p_playlist->p_local_category; + } + else if( p_current_treeroot == p_playlist->p_ml_category || + p_current_treeroot == p_playlist->p_ml_onelevel ) + { + p_current_treeroot = p_playlist->p_ml_category; + } } - else if( i_new_view >= VIEW_FIRST_SORTED && - i_new_view <= VIEW_LAST_SORTED ) + else if( event.GetId() == OneLevelView_Event ) { - b_changed_view = VLC_TRUE; - playlist_ViewInsert( p_playlist, i_new_view, "View" ); - playlist_ViewUpdate( p_playlist, i_new_view ); - - i_current_view = i_new_view; - - Rebuild( VLC_TRUE ); + p_current_viewroot = p_playlist->p_root_onelevel; + if( p_current_treeroot == p_playlist->p_local_category || + p_current_treeroot == p_playlist->p_local_onelevel ) + { + p_current_treeroot = p_playlist->p_local_onelevel; + } + else if( p_current_treeroot == p_playlist->p_ml_category || + p_current_treeroot == p_playlist->p_ml_onelevel ) + { + p_current_treeroot = p_playlist->p_ml_onelevel; + } } + wxCommandEvent event; + OnSearch( event ); + return; } else if( event.GetId() >= FirstSD_Event && event.GetId() < LastSD_Event ) { @@ -1225,14 +1397,8 @@ wxMenu * Playlist::ViewMenu() } } - /* FIXME : have a list of "should have" views */ - p_view_menu->Append( FirstView_Event + VIEW_CATEGORY, - wxU(_("Normal") ) ); - p_view_menu->Append( FirstView_Event + VIEW_S_AUTHOR, - wxU(_("Sorted by artist") ) ); - p_view_menu->Append( FirstView_Event + VIEW_S_ALBUM, - wxU(_("Sorted by Album") ) ); - + p_view_menu->Append( CategoryView_Event, wxU(_("Normal") ) ); + p_view_menu->Append( OneLevelView_Event, wxU(_("One level") ) ); return p_view_menu; } @@ -1240,41 +1406,28 @@ wxMenu *Playlist::SDMenu() { p_sd_menu = new wxMenu; - vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE, - FIND_ANYWHERE ); + char **ppsz_longnames; + char **ppsz_names = services_discovery_GetServicesNames( p_playlist, + &ppsz_longnames ); + if( !ppsz_names ) + return p_sd_menu; - int i_number = 0; - for( int i_index = 0; i_index < p_list->i_count; i_index++ ) - { - module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ; + char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames; - if( !strcmp( p_parser->psz_capability, "services_discovery" ) ) - i_number++; - } - if( i_number ) pp_sds = (char **)calloc( i_number, sizeof(void *) ); + int i_number = 0; - i_number = 0; - for( int i_index = 0; i_index < p_list->i_count; i_index++ ) + for( ; *ppsz_name; ppsz_name++, ppsz_longname++ ) { - module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ; + p_sd_menu->AppendCheckItem( FirstSD_Event + i_number++ , + wxU( *ppsz_longname ) ); - if( !strcmp( p_parser->psz_capability, "services_discovery" ) ) - { - p_sd_menu->AppendCheckItem( FirstSD_Event + i_number , - wxU( p_parser->psz_longname ? p_parser->psz_longname : - (p_parser->psz_shortname ? - p_parser->psz_shortname : p_parser->psz_object_name) ) ); + if( playlist_IsServicesDiscoveryLoaded( p_playlist, *ppsz_name ) ) + p_sd_menu->Check( FirstSD_Event + i_number, TRUE ); - if( playlist_IsServicesDiscoveryLoaded( p_playlist, - p_parser->psz_object_name ) ) - { - p_sd_menu->Check( FirstSD_Event + i_number, TRUE ); - } - - pp_sds[i_number++] = p_parser->psz_object_name; - } + free( *ppsz_longname ); } - vlc_list_release( p_list ); + pp_sds = ppsz_names; + free( ppsz_longnames ); return p_sd_menu; } @@ -1299,7 +1452,7 @@ void Playlist::OnPopup( wxContextMenuEvent& event ) treectrl->SelectItem( i_wx_popup_item ); LockPlaylist( p_intf->p_sys, p_playlist ); - p_item = playlist_ItemGetById( p_playlist, i_popup_item ); + p_item = playlist_ItemGetById( p_playlist, i_popup_item, true ); if( !p_item ) { @@ -1325,34 +1478,20 @@ void Playlist::OnPopupPlay( wxCommandEvent& event ) { playlist_item_t *p_popup_item, *p_popup_parent; LockPlaylist( p_intf->p_sys, p_playlist ); - p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item ); - p_popup_parent = playlist_ItemGetById( p_playlist, i_popup_parent ); - if( p_popup_item != NULL ) + p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item, true ); + + p_popup_parent = p_popup_item; + while( p_popup_parent ) { - if( p_popup_item->i_children > -1 ) - { - if( event.GetId() == PopupPlay_Event && - p_popup_item->i_children > 0 ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_item, - p_popup_item->pp_children[0] ); - } - else - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_item, NULL ); - } - } - else - { - if( event.GetId() == PopupPlay_Event ) - { - playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, - i_current_view, p_popup_parent, - p_popup_item ); - } - } + if( p_popup_parent == p_current_treeroot ) + break; + p_popup_parent = p_popup_parent->p_parent; + } + + if( p_popup_parent ) + { + playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, true, p_popup_parent, + p_popup_item ); } UnlockPlaylist( p_intf->p_sys, p_playlist ); } @@ -1366,13 +1505,13 @@ void Playlist::Preparse() { playlist_item_t *p_popup_item; LockPlaylist( p_intf->p_sys, p_playlist ); - p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item ); + p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item, true ); if( p_popup_item != NULL ) { if( p_popup_item->i_children == -1 ) { - playlist_PreparseEnqueue( p_playlist, &p_popup_item->input ); + playlist_PreparseEnqueue( p_playlist, p_popup_item->p_input ); } else { @@ -1382,8 +1521,8 @@ void Playlist::Preparse() { wxMenuEvent dummy; i_wx_popup_item = FindItem( treectrl->GetRootItem(), - p_parent->pp_children[i]->input.i_id ); - i_popup_item = p_parent->pp_children[i]->input.i_id; + p_parent->pp_children[i]->i_id ); + i_popup_item = p_parent->pp_children[i]->i_id; Preparse(); } } @@ -1404,14 +1543,14 @@ void Playlist::OnPopupSort( wxCommandEvent& event ) p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item ); LockPlaylist( p_intf->p_sys, p_playlist ); - p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id ); + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, true ); if( p_item->i_children >= 0 ) { playlist_RecursiveNodeSort( p_playlist, p_item, SORT_TITLE_NODES_FIRST, ORDER_NORMAL ); treectrl->DeleteChildren( i_wx_popup_item ); - i_saved_id = -1; + i_saved_id = -1; i_saved_input_id = -1; UpdateNodeChildren( p_item, i_wx_popup_item ); } @@ -1421,7 +1560,9 @@ void Playlist::OnPopupSort( wxCommandEvent& event ) void Playlist::OnPopupInfo( wxCommandEvent& event ) { LockPlaylist( p_intf->p_sys, p_playlist ); - playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item ); + playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, + i_popup_item, + true ); if( p_popup_item ) { iteminfo_dialog = new ItemInfoDialog( p_intf, p_popup_item, this ); @@ -1434,6 +1575,43 @@ void Playlist::OnPopupInfo( wxCommandEvent& event ) UnlockPlaylist( p_intf->p_sys, p_playlist ); } +void Playlist::OnPopupAddNode( wxCommandEvent& event ) +{ + wxTextEntryDialog text( NULL, wxU(_( "Please enter node name" )), + wxU(_( "Add node" )), wxU(_( "New node" )) ); + if( text.ShowModal() != wxID_OK ) return; + + char *psz_name = wxFromLocale( text.GetValue() ); + + LockPlaylist( p_intf->p_sys, p_playlist ); + + PlaylistItem *p_wxitem; + playlist_item_t *p_item; + + p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item ); + + p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id, true ); + + playlist_NodeCreate( p_playlist, psz_name, p_item, 0, NULL ); + + UnlockPlaylist( p_intf->p_sys, p_playlist ); + Rebuild( true ); + + wxLocaleFree( psz_name ); +} + +void Playlist::OnSourceSelected( wxListEvent &event ) +{ + int i_id = event.GetData(); + + if( !p_current_treeroot || i_id != p_current_treeroot->i_id ) + { + playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id, + true ); + if( p_item ) p_current_treeroot = p_item; + Rebuild( true ); + } +} /***************************************************************************** * Custom events management @@ -1463,7 +1641,7 @@ static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, vlc_value_t oval, vlc_value_t nval, void *param ) { Playlist *p_playlist_dialog = (Playlist *)param; - p_playlist_dialog->b_need_update = VLC_TRUE; + p_playlist_dialog->b_need_update = true; return VLC_SUCCESS; } @@ -1518,11 +1696,11 @@ static int ItemAppended( vlc_object_t *p_this, const char *psz_variable, 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_dialog->i_items_to_append++ > 50 ) + if( ++p_playlist_dialog->i_items_to_append >= 50 ) { /* Too many items waiting to be added, it will be quicker to rebuild * the whole playlist */ - p_playlist_dialog->b_need_update = VLC_TRUE; + p_playlist_dialog->b_need_update = true; return VLC_SUCCESS; }