00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <vlc/vlc.h>
00029 #include <vlc/intf.h>
00030
00031 #include "wxwidgets.h"
00032
00033 #include "bitmaps/shuffle.xpm"
00034 #include "bitmaps/repeat.xpm"
00035 #include "bitmaps/loop.xpm"
00036
00037 #include "bitmaps/type_unknown.xpm"
00038 #include "bitmaps/type_afile.xpm"
00039 #include "bitmaps/type_vfile.xpm"
00040 #include "bitmaps/type_net.xpm"
00041 #include "bitmaps/type_card.xpm"
00042 #include "bitmaps/type_disc.xpm"
00043 #include "bitmaps/type_cdda.xpm"
00044 #include "bitmaps/type_directory.xpm"
00045 #include "bitmaps/type_playlist.xpm"
00046 #include "bitmaps/type_node.xpm"
00047
00048 #include <wx/dynarray.h>
00049 #include <wx/imaglist.h>
00050
00051 #define HELP_SHUFFLE N_( "Shuffle" )
00052 #define HELP_LOOP N_( "Repeat All" )
00053 #define HELP_REPEAT N_( "Repeat One" )
00054
00055 namespace wxvlc {
00056
00057 static int PlaylistChanged( vlc_object_t *, const char *,
00058 vlc_value_t, vlc_value_t, void * );
00059 static int PlaylistNext( vlc_object_t *, const char *,
00060 vlc_value_t, vlc_value_t, void * );
00061 static int ItemChanged( vlc_object_t *, const char *,
00062 vlc_value_t, vlc_value_t, void * );
00063 static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
00064 vlc_value_t oval, vlc_value_t nval, void *param );
00065 static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
00066 vlc_value_t oval, vlc_value_t nval, void *param );
00067
00068
00069
00070
00071
00072
00073 enum
00074 {
00075
00076 AddFile_Event = 1,
00077 AddDir_Event,
00078 AddMRL_Event,
00079 Close_Event,
00080 Open_Event,
00081 Save_Event,
00082
00083 SortTitle_Event,
00084 RSortTitle_Event,
00085 Randomize_Event,
00086
00087 DeleteSelection_Event,
00088 Random_Event,
00089 Loop_Event,
00090 Repeat_Event,
00091
00092 PopupPlay_Event,
00093 PopupPlayThis_Event,
00094 PopupPreparse_Event,
00095 PopupSort_Event,
00096 PopupDel_Event,
00097 PopupInfo_Event,
00098
00099 SearchText_Event,
00100 Search_Event,
00101
00102
00103 TreeCtrl_Event,
00104
00105 Browse_Event,
00106
00107
00108 UpdateItem_Event,
00109 AppendItem_Event,
00110 RemoveItem_Event,
00111
00112 MenuDummy_Event = wxID_HIGHEST + 999,
00113
00114 FirstView_Event = wxID_HIGHEST + 1000,
00115 LastView_Event = wxID_HIGHEST + 1100,
00116
00117 FirstSD_Event = wxID_HIGHEST + 2000,
00118 LastSD_Event = wxID_HIGHEST + 2100,
00119 };
00120
00121 DEFINE_LOCAL_EVENT_TYPE( wxEVT_PLAYLIST );
00122
00123 BEGIN_EVENT_TABLE(Playlist, wxFrame)
00124 EVT_SIZE(Playlist::OnSize)
00125
00126
00127 EVT_MENU(AddFile_Event, Playlist::OnAddFile)
00128 EVT_MENU(AddDir_Event, Playlist::OnAddDir)
00129 EVT_MENU(AddMRL_Event, Playlist::OnAddMRL)
00130 EVT_MENU(Close_Event, Playlist::OnMenuClose)
00131 EVT_MENU(Open_Event, Playlist::OnOpen)
00132 EVT_MENU(Save_Event, Playlist::OnSave)
00133
00134 EVT_MENU(SortTitle_Event, Playlist::OnSort)
00135 EVT_MENU(RSortTitle_Event, Playlist::OnSort)
00136
00137 EVT_MENU(Randomize_Event, Playlist::OnSort)
00138
00139 EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
00140
00141 EVT_MENU_OPEN( Playlist::OnMenuOpen )
00142 EVT_MENU( -1, Playlist::OnMenuEvent )
00143
00144 EVT_TOOL(Random_Event, Playlist::OnRandom)
00145 EVT_TOOL(Repeat_Event, Playlist::OnRepeat)
00146 EVT_TOOL(Loop_Event, Playlist::OnLoop)
00147
00148
00149 EVT_MENU( PopupPlay_Event, Playlist::OnPopupPlay)
00150 EVT_MENU( PopupPlayThis_Event, Playlist::OnPopupPlay)
00151 EVT_MENU( PopupPreparse_Event, Playlist::OnPopupPreparse)
00152 EVT_MENU( PopupSort_Event, Playlist::OnPopupSort)
00153 EVT_MENU( PopupDel_Event, Playlist::OnPopupDel)
00154 EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo)
00155
00156
00157 EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem )
00158 EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown )
00159
00160 EVT_CONTEXT_MENU( Playlist::OnPopup )
00161
00162
00163 EVT_BUTTON( Search_Event, Playlist::OnSearch)
00164 EVT_BUTTON( Save_Event, Playlist::OnSave)
00165
00166
00167 EVT_TEXT_ENTER( SearchText_Event, Playlist::OnSearch )
00168
00169
00170 EVT_COMMAND(-1, wxEVT_PLAYLIST, Playlist::OnPlaylistEvent)
00171
00172
00173
00174 EVT_CLOSE(Playlist::OnClose)
00175 END_EVENT_TABLE()
00176
00177
00178
00179
00180 class PlaylistItem : public wxTreeItemData
00181 {
00182 public:
00183 PlaylistItem( playlist_item_t *p_item ) : wxTreeItemData()
00184 {
00185 i_id = p_item->input.i_id;
00186 }
00187 protected:
00188 int i_id;
00189 friend class Playlist;
00190 };
00191
00192
00193
00194
00195 Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
00196 wxFrame( p_parent, -1, wxU(_("Playlist")), wxDefaultPosition,
00197 wxSize(500,300), wxDEFAULT_FRAME_STYLE )
00198 {
00199 vlc_value_t val;
00200
00201
00202 p_intf = _p_intf;
00203 pp_sds = NULL;
00204 i_update_counter = 0;
00205 i_sort_mode = MODE_NONE;
00206 b_need_update = VLC_FALSE;
00207 i_items_to_append = 0;
00208 p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
00209 FIND_ANYWHERE );
00210 if( p_playlist == NULL ) return;
00211
00212 SetIcon( *p_intf->p_sys->p_icon );
00213
00214 p_view_menu = NULL;
00215 p_sd_menu = SDMenu();
00216
00217 i_current_view = VIEW_CATEGORY;
00218 b_changed_view = VLC_FALSE;
00219
00220 i_title_sorted = 0;
00221 i_group_sorted = 0;
00222 i_duration_sorted = 0;
00223
00224 var_Create( p_intf, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00225 var_Create( p_intf, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
00226 var_Create( p_intf, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );;
00227
00228
00229 wxMenu *manage_menu = new wxMenu;
00230 manage_menu->Append( AddFile_Event, wxU(_("&Simple Add File...")) );
00231 manage_menu->Append( AddDir_Event, wxU(_("Add &Directory...")) );
00232 manage_menu->Append( AddMRL_Event, wxU(_("&Add MRL...")) );
00233 manage_menu->AppendSeparator();
00234 manage_menu->Append( MenuDummy_Event, wxU(_("Services discovery")),
00235 p_sd_menu );
00236 manage_menu->AppendSeparator();
00237 manage_menu->Append( Open_Event, wxU(_("&Open Playlist...")) );
00238 manage_menu->Append( Save_Event, wxU(_("&Save Playlist...")) );
00239 manage_menu->AppendSeparator();
00240 manage_menu->Append( Close_Event, wxU(_("&Close")) );
00241
00242
00243 wxMenu *sort_menu = new wxMenu;
00244 sort_menu->Append( SortTitle_Event, wxU(_("Sort by &title")) );
00245 sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse sort by title")) );
00246 sort_menu->AppendSeparator();
00247 sort_menu->Append( Randomize_Event, wxU(_("&Shuffle Playlist")) );
00248
00249
00250 wxMenu *selection_menu = new wxMenu;
00251 selection_menu->Append( DeleteSelection_Event, wxU(_("D&elete")) );
00252
00253
00254 ViewMenu();
00255
00256
00257 wxMenuBar *menubar = new wxMenuBar();
00258 menubar->Append( manage_menu, wxU(_("&Manage")) );
00259 menubar->Append( sort_menu, wxU(_("S&ort")) );
00260 menubar->Append( selection_menu, wxU(_("&Selection")) );
00261 menubar->Append( p_view_menu, wxU(_("&View items") ) );
00262
00263
00264 SetMenuBar( menubar );
00265
00266
00267 node_popup = new wxMenu;
00268 node_popup->Append( PopupPlay_Event, wxU(_("Play")) );
00269 node_popup->Append( PopupPlayThis_Event, wxU(_("Play this branch")) );
00270 node_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
00271 node_popup->Append( PopupSort_Event, wxU(_("Sort this branch")) );
00272 node_popup->Append( PopupDel_Event, wxU(_("Delete")) );
00273 node_popup->Append( PopupInfo_Event, wxU(_("Info")) );
00274
00275 item_popup = new wxMenu;
00276 item_popup->Append( PopupPlay_Event, wxU(_("Play")) );
00277 item_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
00278 item_popup->Append( PopupDel_Event, wxU(_("Delete")) );
00279 item_popup->Append( PopupInfo_Event, wxU(_("Info")) );
00280
00281
00282 wxPanel *playlist_panel = new wxPanel( this, -1 );
00283 playlist_panel->SetAutoLayout( TRUE );
00284
00285
00286 wxToolBar *toolbar =
00287 CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT );
00288
00289
00290 toolbar->AddTool( Random_Event, wxT(""), wxBitmap(shuffle_on_xpm),
00291 wxBitmap(shuffle_on_xpm), wxITEM_CHECK,
00292 wxU(_(HELP_SHUFFLE) ) );
00293 var_Get( p_intf, "random", &val );
00294 toolbar->ToggleTool( Random_Event, val.b_bool );
00295
00296
00297 toolbar->AddTool( Loop_Event, wxT(""), wxBitmap( loop_xpm),
00298 wxBitmap( loop_xpm), wxITEM_CHECK,
00299 wxU(_(HELP_LOOP ) ) );
00300 var_Get( p_intf, "loop", &val );
00301 toolbar->ToggleTool( Loop_Event, val.b_bool );
00302
00303
00304 toolbar->AddTool( Repeat_Event, wxT(""), wxBitmap( repeat_xpm),
00305 wxBitmap( repeat_xpm), wxITEM_CHECK,
00306 wxU(_(HELP_REPEAT ) ) );
00307 var_Get( p_intf, "repeat", &val );
00308 toolbar->ToggleTool( Repeat_Event, val.b_bool ) ;
00309
00310
00311 search_text = new wxTextCtrl( toolbar, SearchText_Event, wxT(""),
00312 wxDefaultPosition, wxSize(100, -1),
00313 wxTE_PROCESS_ENTER);
00314
00315
00316 search_button = new wxButton( toolbar , Search_Event, wxU(_("Search")) );
00317
00318 toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
00319 wxSize(16, 16), wxBORDER_NONE ) );
00320 toolbar->AddControl( search_text );
00321 toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
00322 wxSize(5, 5), wxBORDER_NONE ) );
00323 toolbar->AddControl( search_button );
00324 search_button->SetDefault();
00325 toolbar->Realize();
00326
00327
00328 treectrl = new wxTreeCtrl( playlist_panel, TreeCtrl_Event,
00329 wxDefaultPosition, wxDefaultSize,
00330 wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT|
00331 wxTR_NO_LINES |
00332 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS |
00333 wxTR_MULTIPLE | wxTR_EXTENDED );
00334
00335
00336 wxImageList *p_images = new wxImageList( 16 , 16, TRUE );
00337
00338
00339 p_images->Add( wxIcon( type_unknown_xpm ) );
00340 p_images->Add( wxIcon( type_afile_xpm ) );
00341 p_images->Add( wxIcon( type_vfile_xpm ) );
00342 p_images->Add( wxIcon( type_directory_xpm ) );
00343 p_images->Add( wxIcon( type_disc_xpm ) );
00344 p_images->Add( wxIcon( type_cdda_xpm ) );
00345 p_images->Add( wxIcon( type_card_xpm ) );
00346 p_images->Add( wxIcon( type_net_xpm ) );
00347 p_images->Add( wxIcon( type_playlist_xpm ) );
00348 p_images->Add( wxIcon( type_node_xpm ) );
00349 treectrl->AssignImageList( p_images );
00350
00351 treectrl->AddRoot( wxU(_("root" )), -1, -1, NULL );
00352
00353
00354 wxFont font= treectrl->GetFont();
00355 font.SetPointSize(9);
00356 treectrl->SetFont( font );
00357
00358 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
00359 panel_sizer->Add( treectrl, 1, wxEXPAND | wxALL, 5 );
00360 panel_sizer->Layout();
00361
00362 playlist_panel->SetSizerAndFit( panel_sizer );
00363
00364 int pi_widths[1] = { -1 };
00365 statusbar = CreateStatusBar( 1 );
00366 statusbar->SetStatusWidths( 1, pi_widths );
00367
00368 #if wxUSE_DRAG_AND_DROP
00369
00370 SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) );
00371 #endif
00372
00373 i_saved_id = -1;
00374
00375
00376
00377
00378
00379 var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
00380
00381
00382 var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
00383
00384
00385 var_AddCallback( p_playlist, "item-change", ItemChanged, this );
00386
00387 var_AddCallback( p_playlist, "item-append", ItemAppended, this );
00388 var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
00389
00390
00391 Rebuild( VLC_TRUE );
00392
00393 }
00394
00395 Playlist::~Playlist()
00396 {
00397 if( pp_sds != NULL ) free( pp_sds );
00398
00399 if( p_playlist == NULL ) return;
00400
00401 var_DelCallback( p_playlist, "item-change", ItemChanged, this );
00402 var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
00403 var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
00404 var_DelCallback( p_playlist, "item-append", ItemAppended, this );
00405 var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
00406 vlc_object_release( p_playlist );
00407 }
00408
00409
00410
00411
00412
00413
00414 void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node )
00415 {
00416 wxTreeItemIdValue cookie;
00417 wxTreeItemId child;
00418 for( int i = 0; i< p_node->i_children ; i++ )
00419 {
00420 if( i == 0 )
00421 {
00422 child = treectrl->GetFirstChild( node, cookie);
00423 }
00424 else
00425 {
00426 child = treectrl->GetNextChild( node, cookie );
00427 }
00428
00429 if( !child.IsOk() )
00430 {
00431
00432 CreateNode( p_node->pp_children[i], node );
00433
00434 child = treectrl->GetNextChild( node, cookie );
00435 }
00436 }
00437 treectrl->SetItemImage( node, p_node->input.i_type );
00438
00439 }
00440
00441
00442 void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent )
00443 {
00444 wxTreeItemId node =
00445 treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ),
00446 -1,-1, new PlaylistItem( p_node ) );
00447 treectrl->SetItemImage( node, p_node->input.i_type );
00448
00449 UpdateNodeChildren( p_node, node );
00450 }
00451
00452
00453 void Playlist::UpdateNodeChildren( playlist_item_t *p_node,
00454 wxTreeItemId node )
00455 {
00456
00457 for( int i = 0; i< p_node->i_children ; i++ )
00458 {
00459
00460 if( p_node->pp_children[i]->i_children == -1 )
00461 {
00462 wxTreeItemId item =
00463 treectrl->AppendItem( node,
00464 wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1,
00465 new PlaylistItem( p_node->pp_children[i]) );
00466
00467 UpdateTreeItem( item );
00468 }
00469 else
00470 {
00471 CreateNode( p_node->pp_children[i], node );
00472 }
00473 }
00474 }
00475
00476
00477 void Playlist::UpdateTreeItem( wxTreeItemId item )
00478 {
00479 if( ! item.IsOk() ) return;
00480
00481 wxTreeItemData *p_data = treectrl->GetItemData( item );
00482 if( !p_data ) return;
00483
00484 LockPlaylist( p_intf->p_sys, p_playlist );
00485 playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
00486 ((PlaylistItem *)p_data)->i_id );
00487 if( !p_item )
00488 {
00489 UnlockPlaylist( p_intf->p_sys, p_playlist );
00490 return;
00491 }
00492
00493 wxString msg;
00494 wxString duration = wxU( "" );
00495 char *psz_author = vlc_input_item_GetInfo( &p_item->input,
00496 _("Meta-information"),
00497 _("Artist"));
00498 if( !psz_author )
00499 {
00500 UnlockPlaylist( p_intf->p_sys, p_playlist );
00501 return;
00502 }
00503
00504 char psz_duration[MSTRTIME_MAX_SIZE];
00505 mtime_t dur = p_item->input.i_duration;
00506
00507 if( dur != -1 )
00508 {
00509 secstotimestr( psz_duration, dur/1000000 );
00510 duration.Append( wxU( " ( " ) + wxString( wxU( psz_duration ) ) +
00511 wxU( " )" ) );
00512 }
00513
00514 if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE )
00515 {
00516 msg = wxString( wxU( p_item->input.psz_name ) ) + duration;
00517 }
00518 else
00519 {
00520 msg = wxString(wxU( psz_author )) + wxT(" - ") +
00521 wxString(wxU(p_item->input.psz_name)) + duration;
00522 }
00523 free( psz_author );
00524 treectrl->SetItemText( item , msg );
00525 treectrl->SetItemImage( item, p_item->input.i_type );
00526
00527 if( p_playlist->status.p_item == p_item )
00528 {
00529 treectrl->SetItemBold( item, true );
00530 while( treectrl->GetItemParent( item ).IsOk() )
00531 {
00532 item = treectrl->GetItemParent( item );
00533 treectrl->Expand( item );
00534 }
00535 }
00536 else
00537 {
00538 treectrl->SetItemBold( item, false );
00539 }
00540 UnlockPlaylist( p_intf->p_sys, p_playlist );
00541 }
00542
00543
00544 void Playlist::AppendItem( wxCommandEvent& event )
00545 {
00546 playlist_add_t *p_add = (playlist_add_t *)event.GetClientData();
00547 playlist_item_t *p_item = NULL;
00548 wxTreeItemId item, node;
00549
00550 i_items_to_append--;
00551
00552
00553 if( b_need_update ) return;
00554
00555 if( p_add->i_view != i_current_view ) goto update;
00556
00557 node = FindItem( treectrl->GetRootItem(), p_add->i_node );
00558 if( !node.IsOk() ) goto update;
00559
00560 p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
00561 if( !p_item ) goto update;
00562
00563 item = FindItem( treectrl->GetRootItem(), p_add->i_item );
00564 if( item.IsOk() ) goto update;
00565
00566 item = treectrl->AppendItem( node,
00567 wxL2U( p_item->input.psz_name ), -1,-1,
00568 new PlaylistItem( p_item ) );
00569 treectrl->SetItemImage( item, p_item->input.i_type );
00570
00571 if( item.IsOk() && p_item->i_children == -1 )
00572 {
00573 UpdateTreeItem( item );
00574 }
00575
00576 update:
00577 int i_count = CountItems( treectrl->GetRootItem());
00578 if( i_count != p_playlist->i_size )
00579 {
00580 statusbar->SetStatusText( wxString::Format( wxU(_(
00581 "%i items in playlist (%i not shown)")),
00582 p_playlist->i_size,
00583 p_playlist->i_size - i_count ) );
00584 if( !b_changed_view )
00585 {
00586 i_current_view = VIEW_CATEGORY;
00587 b_changed_view = VLC_TRUE;
00588 b_need_update = VLC_TRUE;
00589 }
00590 }
00591 else
00592 {
00593 statusbar->SetStatusText( wxString::Format( wxU(_(
00594 "%i items in playlist")),
00595 p_playlist->i_size ), 0 );
00596 }
00597
00598 return;
00599 }
00600
00601
00602 void Playlist::UpdateItem( int i )
00603 {
00604 if( i < 0 ) return;
00605
00606 wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
00607
00608 if( item.IsOk() )
00609 {
00610 UpdateTreeItem( item );
00611 }
00612 }
00613
00614 void Playlist::RemoveItem( int i )
00615 {
00616 if( i <= 0 ) return;
00617 if( i == i_saved_id ) i_saved_id = -1;
00618
00619 wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
00620
00621 if( item.IsOk() )
00622 {
00623 treectrl->Delete( item );
00624 }
00625 }
00626
00627
00628
00629
00630
00631
00632
00633 wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id )
00634 {
00635 wxTreeItemIdValue cookie;
00636 PlaylistItem *p_wxcurrent;
00637 wxTreeItemId search;
00638 wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
00639 wxTreeItemId child;
00640
00641 p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root );
00642
00643 if( i_id < 0 )
00644 {
00645 wxTreeItemId dummy;
00646 return dummy;
00647 }
00648 if( i_saved_id == i_id )
00649 {
00650 return saved_tree_item;
00651 }
00652
00653 if( !p_wxcurrent )
00654 {
00655 wxTreeItemId dummy;
00656 return dummy;
00657 }
00658
00659 if( p_wxcurrent->i_id == i_id )
00660 {
00661 i_saved_id = i_id;
00662 saved_tree_item = root;
00663 return root;
00664 }
00665
00666 while( item.IsOk() )
00667 {
00668 p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item );
00669 if( p_wxcurrent->i_id == i_id )
00670 {
00671 i_saved_id = i_id;
00672 saved_tree_item = item;
00673 return item;
00674 }
00675 if( treectrl->ItemHasChildren( item ) )
00676 {
00677 wxTreeItemId search = FindItem( item, i_id );
00678 if( search.IsOk() )
00679 {
00680 i_saved_id = i_id;
00681 saved_tree_item = search;
00682 return search;
00683 }
00684 }
00685 item = treectrl->GetNextChild( root, cookie );
00686 }
00687
00688 wxTreeItemId dummy;
00689 return dummy;
00690 }
00691
00692 int Playlist::CountItems( wxTreeItemId root )
00693 {
00694 wxTreeItemIdValue cookie;
00695 int count = 0;
00696 wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
00697
00698 while( item.IsOk() )
00699 {
00700 if( treectrl->ItemHasChildren( item ) )
00701 {
00702 count += CountItems( item );
00703 }
00704 else
00705 {
00706 playlist_item_t *p_item;
00707 LockPlaylist( p_intf->p_sys, p_playlist );
00708 p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id );
00709 if( p_item && p_item->i_children == -1 )
00710 count++;
00711 UnlockPlaylist( p_intf->p_sys, p_playlist );
00712 }
00713 item = treectrl->GetNextChild( root, cookie );
00714 }
00715 return count;
00716 }
00717
00718
00719 wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found )
00720 {
00721 wxTreeItemIdValue cookie;
00722 wxTreeItemId search;
00723 wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
00724 wxTreeItemId child;
00725
00726 while( item.IsOk() )
00727 {
00728 if( treectrl->GetItemText( item).Lower().Contains(
00729 search_string.Lower() ) )
00730 {
00731 if( !current.IsOk() || *pb_current_found == VLC_TRUE )
00732 {
00733 return item;
00734 }
00735 else if( current.IsOk() && item == current )
00736 {
00737 *pb_current_found = VLC_TRUE;
00738 }
00739 }
00740 if( treectrl->ItemHasChildren( item ) )
00741 {
00742 wxTreeItemId search = FindItemByName( item, search_string, current,
00743 pb_current_found );
00744 if( search.IsOk() )
00745 {
00746 return search;
00747 }
00748 }
00749 item = treectrl->GetNextChild( root, cookie);
00750 }
00751
00752 wxTreeItemId dummy;
00753 return dummy;
00754 }
00755
00756
00757
00758
00759 void Playlist::Rebuild( vlc_bool_t b_root )
00760 {
00761 playlist_view_t *p_view;
00762
00763 i_items_to_append = 0;
00764
00765
00766
00767 if( b_root )
00768 {
00769 var_DelCallback( p_playlist, "item-change", ItemChanged, this );
00770 var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
00771 var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
00772 var_DelCallback( p_playlist, "item-append", ItemAppended, this );
00773 var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
00774
00775
00776 LockPlaylist( p_intf->p_sys, p_playlist );
00777 }
00778 i_saved_id = -1;
00779
00780 p_view = playlist_ViewFind( p_playlist, i_current_view );
00781
00782
00783 treectrl->DeleteAllItems();
00784 treectrl->AddRoot( wxU(_("root" )), -1, -1,
00785 new PlaylistItem( p_view->p_root) );
00786
00787 wxTreeItemId root = treectrl->GetRootItem();
00788 UpdateNode( p_view->p_root, root );
00789
00790 int i_count = CountItems( treectrl->GetRootItem() );
00791
00792 if( i_count < p_playlist->i_size && !b_changed_view )
00793 {
00794 i_current_view = VIEW_CATEGORY;
00795 b_changed_view = VLC_TRUE;
00796 Rebuild( VLC_FALSE );
00797 }
00798 else if( i_count != p_playlist->i_size )
00799 {
00800 statusbar->SetStatusText( wxString::Format( wxU(_(
00801 "%i items in playlist (%i not shown)")),
00802 p_playlist->i_size,
00803 p_playlist->i_size - i_count ) );
00804 }
00805 else
00806 {
00807 statusbar->SetStatusText( wxString::Format( wxU(_(
00808 "%i items in playlist")),
00809 p_playlist->i_size ), 0 );
00810 }
00811
00812 if( b_root )
00813 {
00814
00815 var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
00816 var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
00817 var_AddCallback( p_playlist, "item-change", ItemChanged, this );
00818 var_AddCallback( p_playlist, "item-append", ItemAppended, this );
00819 var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
00820
00821 UnlockPlaylist( p_intf->p_sys, p_playlist );
00822 }
00823 }
00824
00825
00826
00827 void Playlist::ShowPlaylist( bool show )
00828 {
00829 if( show ) Rebuild( VLC_TRUE );
00830 Show( show );
00831 }
00832
00833
00834 void Playlist::UpdatePlaylist()
00835 {
00836 i_update_counter++;
00837
00838
00839 if( !IsShown() ) return;
00840
00841 if( this->b_need_update )
00842 {
00843 this->b_need_update = VLC_FALSE;
00844 Rebuild( VLC_TRUE );
00845 }
00846
00847
00848 if( i_update_counter % 5 ) return;
00849 }
00850
00851
00852
00853
00854 void Playlist::DeleteTreeItem( wxTreeItemId item )
00855 {
00856 PlaylistItem *p_wxitem;
00857 playlist_item_t *p_item;
00858 p_wxitem = (PlaylistItem *)treectrl->GetItemData( item );
00859
00860 LockPlaylist( p_intf->p_sys, p_playlist );
00861 p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
00862
00863 if( !p_item )
00864 {
00865 UnlockPlaylist( p_intf->p_sys, p_playlist );
00866 return;
00867 }
00868
00869 if( p_item->i_children == -1 ) DeleteItem( p_item->input.i_id );
00870 else DeleteNode( p_item );
00871
00872 RemoveItem( item );
00873 UnlockPlaylist( p_intf->p_sys, p_playlist );
00874 }
00875
00876 void Playlist::DeleteItem( int item_id )
00877 {
00878 playlist_LockDelete( p_playlist, item_id );
00879 }
00880
00881 void Playlist::DeleteNode( playlist_item_t *p_item )
00882 {
00883 playlist_NodeDelete( p_playlist, p_item, VLC_TRUE , VLC_FALSE );
00884 }
00885
00886 void Playlist::OnMenuClose( wxCommandEvent& event )
00887 {
00888 wxCloseEvent cevent;
00889 OnClose(cevent);
00890 }
00891
00892 void Playlist::OnClose( wxCloseEvent& WXUNUSED(event) )
00893 {
00894 Hide();
00895 }
00896
00897 void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
00898 {
00899 struct {
00900 char *psz_desc;
00901 char *psz_filter;
00902 char *psz_module;
00903 } formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" }};
00904
00905 wxString filter = wxT("");
00906
00907 if( p_playlist->i_size == 0 )
00908 {
00909 wxMessageBox( wxU(_("Playlist is empty") ), wxU(_("Can't save")),
00910 wxICON_WARNING | wxOK, this );
00911 return;
00912 }
00913
00914 for( unsigned int i = 0; i < sizeof(formats)/sizeof(formats[0]); i++)
00915 {
00916 filter.Append( wxU(formats[i].psz_desc) );
00917 filter.Append( wxT("|") );
00918 filter.Append( wxU(formats[i].psz_filter) );
00919 filter.Append( wxT("|") );
00920 }
00921 wxFileDialog dialog( this, wxU(_("Save playlist")),
00922 wxT(""), wxT(""), filter, wxSAVE );
00923
00924 if( dialog.ShowModal() == wxID_OK )
00925 {
00926 if( dialog.GetPath().mb_str() )
00927 {
00928 playlist_Export( p_playlist, dialog.GetPath().mb_str(),
00929 formats[dialog.GetFilterIndex()].psz_module );
00930 }
00931 }
00932
00933 }
00934
00935 void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) )
00936 {
00937 wxFileDialog dialog( this, wxU(_("Open playlist")), wxT(""), wxT(""),
00938 wxT("All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u"), wxOPEN );
00939
00940 if( dialog.ShowModal() == wxID_OK )
00941 {
00942 playlist_Import( p_playlist, dialog.GetPath().mb_str() );
00943 }
00944 }
00945
00946 void Playlist::OnAddFile( wxCommandEvent& WXUNUSED(event) )
00947 {
00948 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_SIMPLE, 0, 0 );
00949
00950 }
00951
00952 void Playlist::OnAddDir( wxCommandEvent& WXUNUSED(event) )
00953 {
00954 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_DIRECTORY, 0, 0 );
00955
00956 }
00957
00958 void Playlist::OnAddMRL( wxCommandEvent& WXUNUSED(event) )
00959 {
00960 p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE, 0, 0 );
00961
00962 }
00963
00964
00965
00966
00967 void Playlist::OnSort( wxCommandEvent& event )
00968 {
00969 PlaylistItem *p_wxitem;
00970 p_wxitem = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() );
00971
00972 LockPlaylist( p_intf->p_sys, p_playlist );
00973 switch( event.GetId() )
00974 {
00975 case SortTitle_Event:
00976 playlist_RecursiveNodeSort( p_playlist,
00977 playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
00978 SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
00979 break;
00980 case RSortTitle_Event:
00981 playlist_RecursiveNodeSort( p_playlist,
00982 playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
00983 SORT_TITLE_NODES_FIRST, ORDER_REVERSE );
00984 }
00985 UnlockPlaylist( p_intf->p_sys, p_playlist );
00986
00987 Rebuild( VLC_TRUE );
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998 void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) )
00999 {
01000 wxString search_string = search_text->GetValue();
01001
01002 vlc_bool_t pb_found = VLC_FALSE;
01003
01004 wxTreeItemId found =
01005 FindItemByName( treectrl->GetRootItem(), search_string,
01006 search_current, &pb_found );
01007
01008 if( !found.IsOk() )
01009 {
01010 wxTreeItemId dummy;
01011 search_current = dummy;
01012 found = FindItemByName( treectrl->GetRootItem(), search_string,
01013 search_current, &pb_found );
01014 }
01015
01016 if( found.IsOk() )
01017 {
01018 search_current = found;
01019 treectrl->EnsureVisible( found );
01020 treectrl->UnselectAll();
01021 treectrl->SelectItem( found, true );
01022 }
01023 }
01024
01025
01026
01027
01028 void Playlist::RecursiveDeleteSelection( wxTreeItemId root )
01029 {
01030 wxTreeItemIdValue cookie;
01031 wxTreeItemId child = treectrl->GetFirstChild( root, cookie );
01032 while( child.IsOk() )
01033 {
01034 if( treectrl->ItemHasChildren( child ) )
01035 {
01036 RecursiveDeleteSelection( child );
01037 if( treectrl->IsSelected(child ) ) DeleteTreeItem( child );
01038 }
01039 else if( treectrl->IsSelected( child ) )
01040 DeleteTreeItem( child );
01041 child = treectrl->GetNextChild( root, cookie );
01042 }
01043 }
01044
01045 void Playlist::OnDeleteSelection( wxCommandEvent& WXUNUSED(event) )
01046 {
01047 RecursiveDeleteSelection( treectrl->GetRootItem() );
01048 }
01049
01050
01051
01052
01053 void Playlist::OnRandom( wxCommandEvent& event )
01054 {
01055 vlc_value_t val;
01056 val.b_bool = event.IsChecked();
01057 var_Set( p_playlist, "random", val);
01058 }
01059
01060 void Playlist::OnLoop( wxCommandEvent& event )
01061 {
01062 vlc_value_t val;
01063 val.b_bool = event.IsChecked();
01064 var_Set( p_playlist, "loop", val);
01065 }
01066
01067 void Playlist::OnRepeat( wxCommandEvent& event )
01068 {
01069 vlc_value_t val;
01070 val.b_bool = event.IsChecked();
01071 var_Set( p_playlist, "repeat", val);
01072 }
01073
01074
01075
01076
01077 void Playlist::OnActivateItem( wxTreeEvent& event )
01078 {
01079 playlist_item_t *p_item,*p_node,*p_item2,*p_node2;
01080
01081 PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
01082 event.GetItem() );
01083 wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() );
01084
01085 PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent );
01086
01087 LockPlaylist( p_intf->p_sys, p_playlist );
01088
01089 if( !( p_wxitem && p_wxparent ) )
01090 {
01091 UnlockPlaylist( p_intf->p_sys, p_playlist );
01092 return;
01093 }
01094
01095 p_item2 = playlist_ItemGetById(p_playlist, p_wxitem->i_id);
01096 p_node2 = playlist_ItemGetById(p_playlist, p_wxparent->i_id);
01097 if( p_item2 && p_item2->i_children == -1 )
01098 {
01099 p_node = p_node2;
01100 p_item = p_item2;
01101 }
01102 else
01103 {
01104 p_node = p_item2;
01105 if( p_node && p_node->i_children > 0 &&
01106 p_node->pp_children[0]->i_children == -1)
01107 {
01108 p_item = p_node->pp_children[0];
01109 }
01110 else
01111 {
01112 p_item = NULL;
01113 }
01114 }
01115
01116 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view,
01117 p_node, p_item );
01118 UnlockPlaylist( p_intf->p_sys, p_playlist );
01119 }
01120
01121 void Playlist::OnKeyDown( wxTreeEvent& event )
01122 {
01123 long keycode = event.GetKeyCode();
01124
01125 if( keycode == WXK_BACK || keycode == WXK_DELETE )
01126 {
01127
01128 OnDeleteSelection( event );
01129 }
01130 else
01131 {
01132 event.Skip();
01133 }
01134 }
01135
01136 void Playlist::OnEnDis( wxCommandEvent& event )
01137 {
01138 msg_Warn( p_intf, "not implemented" );
01139 }
01140
01141
01142
01143
01144
01145 void Playlist::OnMenuOpen( wxMenuEvent& event)
01146 {
01147 #if defined( __WXMSW__ )
01148 # define GetEventObject GetMenu
01149 #endif
01150
01151 if( event.GetEventObject() == p_view_menu )
01152 {
01153 p_view_menu = ViewMenu();
01154 }
01155 #if defined( __WXMSW__ )
01156 # undef GetEventObject
01157 #endif
01158 }
01159
01160 void Playlist::OnMenuEvent( wxCommandEvent& event )
01161 {
01162 if( event.GetId() < FirstView_Event )
01163 {
01164 event.Skip();
01165 return;
01166 }
01167 else if( event.GetId() < LastView_Event )
01168 {
01169
01170 int i_new_view = event.GetId() - FirstView_Event;
01171
01172 playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_new_view );
01173
01174 if( p_view != NULL )
01175 {
01176 b_changed_view = VLC_TRUE;
01177 i_current_view = i_new_view;
01178 playlist_ViewUpdate( p_playlist, i_new_view );
01179 Rebuild( VLC_TRUE );
01180 return;
01181 }
01182 else if( i_new_view >= VIEW_FIRST_SORTED &&
01183 i_new_view <= VIEW_LAST_SORTED )
01184 {
01185 b_changed_view = VLC_TRUE;
01186 playlist_ViewInsert( p_playlist, i_new_view, "View" );
01187 playlist_ViewUpdate( p_playlist, i_new_view );
01188
01189 i_current_view = i_new_view;
01190
01191 Rebuild( VLC_TRUE );
01192 }
01193 }
01194 else if( event.GetId() >= FirstSD_Event && event.GetId() < LastSD_Event )
01195 {
01196 if( !playlist_IsServicesDiscoveryLoaded( p_playlist,
01197 pp_sds[event.GetId() - FirstSD_Event] ) )
01198 {
01199 playlist_ServicesDiscoveryAdd( p_playlist,
01200 pp_sds[event.GetId() - FirstSD_Event] );
01201 }
01202 else
01203 {
01204
01205 playlist_ServicesDiscoveryRemove( p_playlist,
01206 pp_sds[event.GetId() - FirstSD_Event] );
01207
01208 }
01209 }
01210 }
01211
01212 wxMenu * Playlist::ViewMenu()
01213 {
01214 if( !p_view_menu )
01215 {
01216 p_view_menu = new wxMenu;
01217 }
01218 else
01219 {
01220 wxMenuItemList::Node *node = p_view_menu->GetMenuItems().GetFirst();
01221 for( ; node; )
01222 {
01223 wxMenuItem *item = node->GetData();
01224 node = node->GetNext();
01225 p_view_menu->Delete( item );
01226 }
01227 }
01228
01229
01230 p_view_menu->Append( FirstView_Event + VIEW_CATEGORY,
01231 wxU(_("Normal") ) );
01232 p_view_menu->Append( FirstView_Event + VIEW_S_AUTHOR,
01233 wxU(_("Sorted by artist") ) );
01234 p_view_menu->Append( FirstView_Event + VIEW_S_ALBUM,
01235 wxU(_("Sorted by Album") ) );
01236
01237 return p_view_menu;
01238 }
01239
01240 wxMenu *Playlist::SDMenu()
01241 {
01242 p_sd_menu = new wxMenu;
01243
01244 vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE,
01245 FIND_ANYWHERE );
01246
01247 int i_number = 0;
01248 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
01249 {
01250 module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
01251
01252 if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
01253 i_number++;
01254 }
01255 if( i_number ) pp_sds = (char **)calloc( i_number, sizeof(void *) );
01256
01257 i_number = 0;
01258 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
01259 {
01260 module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
01261
01262 if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
01263 {
01264 p_sd_menu->AppendCheckItem( FirstSD_Event + i_number ,
01265 wxU( p_parser->psz_longname ? p_parser->psz_longname :
01266 (p_parser->psz_shortname ?
01267 p_parser->psz_shortname : p_parser->psz_object_name) ) );
01268
01269 if( playlist_IsServicesDiscoveryLoaded( p_playlist,
01270 p_parser->psz_object_name ) )
01271 {
01272 p_sd_menu->Check( FirstSD_Event + i_number, TRUE );
01273 }
01274
01275 pp_sds[i_number++] = p_parser->psz_object_name;
01276 }
01277 }
01278 vlc_list_release( p_list );
01279 return p_sd_menu;
01280 }
01281
01282
01283
01284
01285
01286 void Playlist::OnPopup( wxContextMenuEvent& event )
01287 {
01288 wxPoint pt = event.GetPosition();
01289 playlist_item_t *p_item;
01290
01291 i_wx_popup_item = treectrl->HitTest( ScreenToClient( pt ) );
01292 if( i_wx_popup_item.IsOk() )
01293 {
01294 PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
01295 i_wx_popup_item );
01296 PlaylistItem *p_wxparent= (PlaylistItem *)treectrl->GetItemData(
01297 treectrl->GetItemParent( i_wx_popup_item ) );
01298 i_popup_item = p_wxitem->i_id;
01299 i_popup_parent = p_wxparent->i_id;
01300 treectrl->SelectItem( i_wx_popup_item );
01301
01302 LockPlaylist( p_intf->p_sys, p_playlist );
01303 p_item = playlist_ItemGetById( p_playlist, i_popup_item );
01304
01305 if( !p_item )
01306 {
01307 UnlockPlaylist( p_intf->p_sys, p_playlist );
01308 return;
01309 }
01310 if( p_item->i_children == -1 )
01311 {
01312 UnlockPlaylist( p_intf->p_sys, p_playlist );
01313 Playlist::PopupMenu( item_popup,
01314 ScreenToClient( wxGetMousePosition() ) );
01315 }
01316 else
01317 {
01318 UnlockPlaylist( p_intf->p_sys, p_playlist );
01319 Playlist::PopupMenu( node_popup,
01320 ScreenToClient( wxGetMousePosition() ) );
01321 }
01322 }
01323 }
01324
01325 void Playlist::OnPopupPlay( wxCommandEvent& event )
01326 {
01327 playlist_item_t *p_popup_item, *p_popup_parent;
01328 LockPlaylist( p_intf->p_sys, p_playlist );
01329 p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
01330 p_popup_parent = playlist_ItemGetById( p_playlist, i_popup_parent );
01331 if( p_popup_item != NULL )
01332 {
01333 if( p_popup_item->i_children > -1 )
01334 {
01335 if( event.GetId() == PopupPlay_Event &&
01336 p_popup_item->i_children > 0 )
01337 {
01338 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
01339 i_current_view, p_popup_item,
01340 p_popup_item->pp_children[0] );
01341 }
01342 else
01343 {
01344 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
01345 i_current_view, p_popup_item, NULL );
01346 }
01347 }
01348 else
01349 {
01350 if( event.GetId() == PopupPlay_Event )
01351 {
01352 playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
01353 i_current_view, p_popup_parent,
01354 p_popup_item );
01355 }
01356 }
01357 }
01358 UnlockPlaylist( p_intf->p_sys, p_playlist );
01359 }
01360
01361 void Playlist::OnPopupPreparse( wxCommandEvent& event )
01362 {
01363 Preparse();
01364 }
01365
01366 void Playlist::Preparse()
01367 {
01368 playlist_item_t *p_popup_item;
01369 LockPlaylist( p_intf->p_sys, p_playlist );
01370 p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
01371
01372 if( p_popup_item != NULL )
01373 {
01374 if( p_popup_item->i_children == -1 )
01375 {
01376 playlist_PreparseEnqueue( p_playlist, &p_popup_item->input );
01377 }
01378 else
01379 {
01380 int i = 0;
01381 playlist_item_t *p_parent = p_popup_item;
01382 for( i = 0; i< p_parent->i_children ; i++ )
01383 {
01384 wxMenuEvent dummy;
01385 i_wx_popup_item = FindItem( treectrl->GetRootItem(),
01386 p_parent->pp_children[i]->input.i_id );
01387 i_popup_item = p_parent->pp_children[i]->input.i_id;
01388 Preparse();
01389 }
01390 }
01391 }
01392 UnlockPlaylist( p_intf->p_sys, p_playlist );
01393 }
01394
01395 void Playlist::OnPopupDel( wxCommandEvent& event )
01396 {
01397 DeleteTreeItem( i_wx_popup_item );
01398 }
01399
01400 void Playlist::OnPopupSort( wxCommandEvent& event )
01401 {
01402 PlaylistItem *p_wxitem;
01403 playlist_item_t *p_item;
01404
01405 p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
01406 LockPlaylist( p_intf->p_sys, p_playlist );
01407
01408 p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
01409 if( p_item->i_children >= 0 )
01410 {
01411 playlist_RecursiveNodeSort( p_playlist, p_item,
01412 SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
01413
01414 treectrl->DeleteChildren( i_wx_popup_item );
01415 i_saved_id = -1;
01416 UpdateNodeChildren( p_item, i_wx_popup_item );
01417
01418 }
01419 UnlockPlaylist( p_intf->p_sys, p_playlist );
01420 }
01421
01422 void Playlist::OnPopupInfo( wxCommandEvent& event )
01423 {
01424 LockPlaylist( p_intf->p_sys, p_playlist );
01425 playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
01426 if( p_popup_item )
01427 {
01428 iteminfo_dialog = new ItemInfoDialog( p_intf, p_popup_item, this );
01429 if( iteminfo_dialog->ShowModal() == wxID_OK )
01430 {
01431 UpdateItem( i_wx_popup_item );
01432 }
01433 delete iteminfo_dialog;
01434 }
01435 UnlockPlaylist( p_intf->p_sys, p_playlist );
01436 }
01437
01438
01439
01440
01441
01442 void Playlist::OnPlaylistEvent( wxCommandEvent& event )
01443 {
01444 switch( event.GetId() )
01445 {
01446 case UpdateItem_Event:
01447 UpdateItem( event.GetInt() );
01448 break;
01449 case AppendItem_Event:
01450 AppendItem( event );
01451 break;
01452 case RemoveItem_Event:
01453 RemoveItem( event.GetInt() );
01454 break;
01455 }
01456 }
01457
01458
01459
01460
01461
01462
01463 static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
01464 vlc_value_t oval, vlc_value_t nval, void *param )
01465 {
01466 Playlist *p_playlist_dialog = (Playlist *)param;
01467 p_playlist_dialog->b_need_update = VLC_TRUE;
01468 return VLC_SUCCESS;
01469 }
01470
01471
01472
01473
01474 static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable,
01475 vlc_value_t oval, vlc_value_t nval, void *param )
01476 {
01477 Playlist *p_playlist_dialog = (Playlist *)param;
01478
01479 wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
01480 event.SetInt( oval.i_int );
01481 p_playlist_dialog->AddPendingEvent( event );
01482 event.SetInt( nval.i_int );
01483 p_playlist_dialog->AddPendingEvent( event );
01484
01485 return 0;
01486 }
01487
01488
01489
01490
01491 static int ItemChanged( vlc_object_t *p_this, const char *psz_variable,
01492 vlc_value_t old_val, vlc_value_t new_val, void *param )
01493 {
01494 Playlist *p_playlist_dialog = (Playlist *)param;
01495
01496 wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
01497 event.SetInt( new_val.i_int );
01498 p_playlist_dialog->AddPendingEvent( event );
01499
01500 return 0;
01501 }
01502 static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
01503 vlc_value_t old_val, vlc_value_t new_val, void *param )
01504 {
01505 Playlist *p_playlist_dialog = (Playlist *)param;
01506
01507 wxCommandEvent event( wxEVT_PLAYLIST, RemoveItem_Event );
01508 event.SetInt( new_val.i_int );
01509 p_playlist_dialog->AddPendingEvent( event );
01510
01511 return 0;
01512 }
01513
01514 static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
01515 vlc_value_t oval, vlc_value_t nval, void *param )
01516 {
01517 Playlist *p_playlist_dialog = (Playlist *)param;
01518
01519 playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));
01520 memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) );
01521
01522 if( p_playlist_dialog->i_items_to_append++ > 50 )
01523 {
01524
01525
01526 p_playlist_dialog->b_need_update = VLC_TRUE;
01527 return VLC_SUCCESS;
01528 }
01529
01530 wxCommandEvent event( wxEVT_PLAYLIST, AppendItem_Event );
01531 event.SetClientData( (void *)p_add );
01532 p_playlist_dialog->AddPendingEvent( event );
01533
01534 return VLC_SUCCESS;
01535 }
01536 }