~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to modules/gui/wxwidgets/dialogs/playlist.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 * playlist.cpp : wxWindows plugin for vlc
3
 
 *****************************************************************************
4
 
 * Copyright (C) 2000-2005 the VideoLAN team
5
 
 * $Id: 4f24afb10c9fe96d7baac7261539cd813531a78f $
6
 
 *
7
 
 * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8
 
 *          Clément Stenac <zorglub@videolan.org>
9
 
 *
10
 
 * This program is free software; you can redistribute it and/OR MODIFy
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation; either version 2 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * This program is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with this program; if not, write to the Free Software
22
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
 
 *****************************************************************************/
24
 
 
25
 
/*****************************************************************************
26
 
 * Preamble
27
 
 *****************************************************************************/
28
 
#include "dialogs/playlist.hpp"
29
 
#include "dialogs/iteminfo.hpp"
30
 
 
31
 
#include "bitmaps/shuffle.xpm"
32
 
#include "bitmaps/repeat.xpm"
33
 
#include "bitmaps/loop.xpm"
34
 
 
35
 
#include "bitmaps/type_unknown.xpm"
36
 
#include "bitmaps/type_afile.xpm"
37
 
#include "bitmaps/type_vfile.xpm"
38
 
#include "bitmaps/type_net.xpm"
39
 
#include "bitmaps/type_card.xpm"
40
 
#include "bitmaps/type_disc.xpm"
41
 
#include "bitmaps/type_cdda.xpm"
42
 
#include "bitmaps/type_directory.xpm"
43
 
#include "bitmaps/type_playlist.xpm"
44
 
#include "bitmaps/type_node.xpm"
45
 
 
46
 
#include <wx/dynarray.h>
47
 
#include <wx/imaglist.h>
48
 
 
49
 
#include <vlc_meta.h>
50
 
#include "charset.h"
51
 
 
52
 
#define HELP_SHUFFLE N_( "Shuffle" )
53
 
#define HELP_LOOP N_( "Repeat All" )
54
 
#define HELP_REPEAT N_( "Repeat One" )
55
 
 
56
 
namespace wxvlc {
57
 
/* Callback prototype */
58
 
static int PlaylistChanged( vlc_object_t *, const char *,
59
 
                            vlc_value_t, vlc_value_t, void * );
60
 
static int PlaylistNext( vlc_object_t *, const char *,
61
 
                         vlc_value_t, vlc_value_t, void * );
62
 
static int ItemChanged( vlc_object_t *, const char *,
63
 
                        vlc_value_t, vlc_value_t, void * );
64
 
static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
65
 
                         vlc_value_t oval, vlc_value_t nval, void *param );
66
 
static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
67
 
                        vlc_value_t oval, vlc_value_t nval, void *param );
68
 
 
69
 
/*****************************************************************************
70
 
 * Event Table.
71
 
 *****************************************************************************/
72
 
 
73
 
/* IDs for the controls and the menu commands */
74
 
enum
75
 
{
76
 
    /* menu items */
77
 
    AddFile_Event = 1,
78
 
    AddDir_Event,
79
 
    AddMRL_Event,
80
 
    Close_Event,
81
 
    Open_Event,
82
 
    Save_Event,
83
 
 
84
 
    SortTitle_Event,
85
 
    RSortTitle_Event,
86
 
    Randomize_Event,
87
 
 
88
 
    DeleteSelection_Event,
89
 
    Random_Event,
90
 
    Loop_Event,
91
 
    Repeat_Event,
92
 
 
93
 
    PopupPlay_Event,
94
 
    PopupPlayThis_Event,
95
 
    PopupPreparse_Event,
96
 
    PopupSort_Event,
97
 
    PopupDel_Event,
98
 
    PopupInfo_Event,
99
 
    PopupAddNode_Event,
100
 
 
101
 
    SearchText_Event,
102
 
    Search_Event,
103
 
 
104
 
    /* controls */
105
 
    TreeCtrl_Event,
106
 
 
107
 
    Browse_Event,  /* For export playlist */
108
 
 
109
 
    /* custom events */
110
 
    UpdateItem_Event,
111
 
    AppendItem_Event,
112
 
    RemoveItem_Event,
113
 
 
114
 
    MenuDummy_Event = wxID_HIGHEST + 999,
115
 
 
116
 
    FirstView_Event = wxID_HIGHEST + 1000,
117
 
    LastView_Event = wxID_HIGHEST + 1100,
118
 
 
119
 
    FirstSD_Event = wxID_HIGHEST + 2000,
120
 
    LastSD_Event = wxID_HIGHEST + 2100,
121
 
};
122
 
 
123
 
DEFINE_LOCAL_EVENT_TYPE( wxEVT_PLAYLIST );
124
 
 
125
 
BEGIN_EVENT_TABLE(Playlist, wxFrame)
126
 
    EVT_SIZE(Playlist::OnSize)
127
 
 
128
 
    /* Menu events */
129
 
    EVT_MENU(AddFile_Event, Playlist::OnAddFile)
130
 
    EVT_MENU(AddDir_Event, Playlist::OnAddDir)
131
 
    EVT_MENU(AddMRL_Event, Playlist::OnAddMRL)
132
 
    EVT_MENU(Close_Event, Playlist::OnMenuClose)
133
 
    EVT_MENU(Open_Event, Playlist::OnOpen)
134
 
    EVT_MENU(Save_Event, Playlist::OnSave)
135
 
 
136
 
    EVT_MENU(SortTitle_Event, Playlist::OnSort)
137
 
    EVT_MENU(RSortTitle_Event, Playlist::OnSort)
138
 
 
139
 
    EVT_MENU(Randomize_Event, Playlist::OnSort)
140
 
 
141
 
    EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
142
 
 
143
 
    EVT_MENU_OPEN( Playlist::OnMenuOpen )
144
 
    EVT_MENU( -1, Playlist::OnMenuEvent )
145
 
 
146
 
    EVT_TOOL(Random_Event, Playlist::OnRandom)
147
 
    EVT_TOOL(Repeat_Event, Playlist::OnRepeat)
148
 
    EVT_TOOL(Loop_Event, Playlist::OnLoop)
149
 
 
150
 
    /* Popup events */
151
 
    EVT_MENU( PopupPlay_Event, Playlist::OnPopupPlay)
152
 
    EVT_MENU( PopupPlayThis_Event, Playlist::OnPopupPlay)
153
 
    EVT_MENU( PopupPreparse_Event, Playlist::OnPopupPreparse)
154
 
    EVT_MENU( PopupSort_Event, Playlist::OnPopupSort)
155
 
    EVT_MENU( PopupDel_Event, Playlist::OnPopupDel)
156
 
    EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo)
157
 
    EVT_MENU( PopupAddNode_Event, Playlist::OnPopupAddNode)
158
 
 
159
 
    /* Tree control events */
160
 
    EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem )
161
 
    EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown )
162
 
    EVT_TREE_BEGIN_DRAG( TreeCtrl_Event, Playlist::OnDragItemBegin )
163
 
    EVT_TREE_END_DRAG( TreeCtrl_Event, Playlist::OnDragItemEnd )
164
 
 
165
 
    EVT_CONTEXT_MENU( Playlist::OnPopup )
166
 
 
167
 
    /* Button events */
168
 
    EVT_BUTTON( Search_Event, Playlist::OnSearch)
169
 
    EVT_BUTTON( Save_Event, Playlist::OnSave)
170
 
 
171
 
    /*EVT_TEXT( SearchText_Event, Playlist::OnSearchTextChange )*/
172
 
    EVT_TEXT_ENTER( SearchText_Event, Playlist::OnSearch )
173
 
 
174
 
    /* Custom events */
175
 
    EVT_COMMAND(-1, wxEVT_PLAYLIST, Playlist::OnPlaylistEvent)
176
 
 
177
 
    /* Special events : we don't want to destroy the window when the user
178
 
     * clicks on (X) */
179
 
    EVT_CLOSE(Playlist::OnClose)
180
 
END_EVENT_TABLE()
181
 
 
182
 
/*****************************************************************************
183
 
 * PlaylistItem class
184
 
 ****************************************************************************/
185
 
class PlaylistItem : public wxTreeItemData
186
 
{
187
 
public:
188
 
    PlaylistItem( playlist_item_t *p_item ) : wxTreeItemData()
189
 
    {
190
 
        i_id = p_item->input.i_id;
191
 
    }
192
 
protected:
193
 
    int i_id;
194
 
friend class Playlist;
195
 
friend class PlaylistFileDropTarget;
196
 
};
197
 
 
198
 
/*****************************************************************************
199
 
 * Constructor.
200
 
 *****************************************************************************/
201
 
Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
202
 
    wxFrame( p_parent, -1, wxU(_("Playlist")), wxDefaultPosition,
203
 
             wxSize(500,300), wxDEFAULT_FRAME_STYLE )
204
 
{
205
 
    vlc_value_t val;
206
 
 
207
 
    /* Initializations */
208
 
    p_intf = _p_intf;
209
 
    pp_sds = NULL;
210
 
    i_update_counter = 0;
211
 
    i_sort_mode = MODE_NONE;
212
 
    b_need_update = VLC_FALSE;
213
 
    i_items_to_append = 0;
214
 
    p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
215
 
                                                FIND_ANYWHERE );
216
 
    if( p_playlist == NULL ) return;
217
 
 
218
 
    SetIcon( *p_intf->p_sys->p_icon );
219
 
 
220
 
    p_view_menu = NULL;
221
 
    p_sd_menu = SDMenu();
222
 
 
223
 
    i_current_view = VIEW_CATEGORY;
224
 
    b_changed_view = VLC_FALSE;
225
 
 
226
 
    i_title_sorted = 0;
227
 
    i_group_sorted = 0;
228
 
    i_duration_sorted = 0;
229
 
 
230
 
    var_Create( p_intf, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
231
 
    var_Create( p_intf, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
232
 
    var_Create( p_intf, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );;
233
 
 
234
 
    /* Create our "Manage" menu */
235
 
    wxMenu *manage_menu = new wxMenu;
236
 
    manage_menu->Append( AddFile_Event, wxU(_("&Simple Add File...")) );
237
 
    manage_menu->Append( AddDir_Event, wxU(_("Add &Directory...")) );
238
 
    manage_menu->Append( AddMRL_Event, wxU(_("&Add URL...")) );
239
 
    manage_menu->AppendSeparator();
240
 
    manage_menu->Append( MenuDummy_Event, wxU(_("Services Discovery")),
241
 
                         p_sd_menu );
242
 
    manage_menu->AppendSeparator();
243
 
    manage_menu->Append( Open_Event, wxU(_("&Open Playlist...")) );
244
 
    manage_menu->Append( Save_Event, wxU(_("&Save Playlist...")) );
245
 
    manage_menu->AppendSeparator();
246
 
    manage_menu->Append( Close_Event, wxU(_("&Close")) );
247
 
 
248
 
    /* Create our "Sort" menu */
249
 
    wxMenu *sort_menu = new wxMenu;
250
 
    sort_menu->Append( SortTitle_Event, wxU(_("Sort by &Title")) );
251
 
    sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse Sort by Title")) );
252
 
    sort_menu->AppendSeparator();
253
 
    sort_menu->Append( Randomize_Event, wxU(_("&Shuffle")) );
254
 
 
255
 
    /* Create our "Selection" menu */
256
 
    wxMenu *selection_menu = new wxMenu;
257
 
    selection_menu->Append( DeleteSelection_Event, wxU(_("D&elete")) );
258
 
 
259
 
    /* Create our "View" menu */
260
 
    ViewMenu();
261
 
 
262
 
    /* Append the freshly created menus to the menu bar */
263
 
    wxMenuBar *menubar = new wxMenuBar();
264
 
    menubar->Append( manage_menu, wxU(_("&Manage")) );
265
 
    menubar->Append( sort_menu, wxU(_("S&ort")) );
266
 
    menubar->Append( selection_menu, wxU(_("&Selection")) );
267
 
    menubar->Append( p_view_menu, wxU(_("&View items") ) );
268
 
 
269
 
    /* Attach the menu bar to the frame */
270
 
    SetMenuBar( menubar );
271
 
 
272
 
    /* Create the popup menu */
273
 
    node_popup = new wxMenu;
274
 
    node_popup->Append( PopupPlay_Event, wxU(_("Play")) );
275
 
    node_popup->Append( PopupPlayThis_Event, wxU(_("Play this Branch")) );
276
 
    node_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
277
 
    node_popup->Append( PopupSort_Event, wxU(_("Sort this Branch")) );
278
 
    node_popup->Append( PopupDel_Event, wxU(_("Delete")) );
279
 
    node_popup->Append( PopupInfo_Event, wxU(_("Info")) );
280
 
    node_popup->Append( PopupAddNode_Event, wxU(_("Add Node")) );
281
 
 
282
 
    item_popup = new wxMenu;
283
 
    item_popup->Append( PopupPlay_Event, wxU(_("Play")) );
284
 
    item_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
285
 
    item_popup->Append( PopupDel_Event, wxU(_("Delete")) );
286
 
    item_popup->Append( PopupInfo_Event, wxU(_("Info")) );
287
 
 
288
 
    /* Create a panel to put everything in */
289
 
    wxPanel *playlist_panel = new wxPanel( this, -1 );
290
 
    playlist_panel->SetAutoLayout( TRUE );
291
 
 
292
 
    /* Create the toolbar */
293
 
    wxToolBar *toolbar =
294
 
        CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT );
295
 
 
296
 
    /* Create the random tool */
297
 
    toolbar->AddTool( Random_Event, wxT(""), wxBitmap(shuffle_on_xpm),
298
 
                       wxBitmap(shuffle_on_xpm), wxITEM_CHECK,
299
 
                       wxU(_(HELP_SHUFFLE) ) );
300
 
    var_Get( p_intf, "random", &val );
301
 
    toolbar->ToggleTool( Random_Event, val.b_bool );
302
 
 
303
 
    /* Create the Loop tool */
304
 
    toolbar->AddTool( Loop_Event, wxT(""), wxBitmap( loop_xpm),
305
 
                      wxBitmap( loop_xpm), wxITEM_CHECK,
306
 
                      wxU(_(HELP_LOOP )  ) );
307
 
    var_Get( p_intf, "loop", &val );
308
 
    toolbar->ToggleTool( Loop_Event, val.b_bool );
309
 
 
310
 
    /* Create the Repeat one checkbox */
311
 
    toolbar->AddTool( Repeat_Event, wxT(""), wxBitmap( repeat_xpm),
312
 
                      wxBitmap( repeat_xpm), wxITEM_CHECK,
313
 
                      wxU(_(HELP_REPEAT )  ) );
314
 
    var_Get( p_intf, "repeat", &val );
315
 
    toolbar->ToggleTool( Repeat_Event, val.b_bool ) ;
316
 
 
317
 
    /* Create the Search Textbox */
318
 
    search_text = new wxTextCtrl( toolbar, SearchText_Event, wxT(""),
319
 
                                  wxDefaultPosition, wxSize(100, -1),
320
 
                                  wxTE_PROCESS_ENTER);
321
 
 
322
 
    /* Create the search button */
323
 
    search_button = new wxButton( toolbar , Search_Event, wxU(_("Search")) );
324
 
 
325
 
    toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
326
 
                         wxSize(16, 16), wxBORDER_NONE ) );
327
 
    toolbar->AddControl( search_text );
328
 
    toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
329
 
                         wxSize(5, 5), wxBORDER_NONE ) );
330
 
    toolbar->AddControl( search_button );
331
 
    search_button->SetDefault();
332
 
    toolbar->Realize();
333
 
 
334
 
    /* Create the tree */
335
 
    treectrl = new wxTreeCtrl( playlist_panel, TreeCtrl_Event,
336
 
                               wxDefaultPosition, wxDefaultSize,
337
 
                               wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT|
338
 
                               wxTR_NO_LINES |
339
 
                               wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS |
340
 
                               wxTR_MULTIPLE | wxTR_EXTENDED );
341
 
 
342
 
    /* Create image list */
343
 
    wxImageList *p_images = new wxImageList( 16 , 16, TRUE );
344
 
 
345
 
    /* FIXME: absolutely needs to be in the right order FIXME */
346
 
    p_images->Add( wxIcon( type_unknown_xpm ) );
347
 
    p_images->Add( wxIcon( type_afile_xpm ) );
348
 
    p_images->Add( wxIcon( type_vfile_xpm ) );
349
 
    p_images->Add( wxIcon( type_directory_xpm ) );
350
 
    p_images->Add( wxIcon( type_disc_xpm ) );
351
 
    p_images->Add( wxIcon( type_cdda_xpm ) );
352
 
    p_images->Add( wxIcon( type_card_xpm ) );
353
 
    p_images->Add( wxIcon( type_net_xpm ) );
354
 
    p_images->Add( wxIcon( type_playlist_xpm ) );
355
 
    p_images->Add( wxIcon( type_node_xpm ) );
356
 
    treectrl->AssignImageList( p_images );
357
 
 
358
 
    treectrl->AddRoot( wxU(_("root" )), -1, -1, NULL );
359
 
 
360
 
    /* Reduce font size */
361
 
    wxFont font= treectrl->GetFont();
362
 
    font.SetPointSize(9);
363
 
    treectrl->SetFont( font );
364
 
 
365
 
    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
366
 
    panel_sizer->Add( treectrl, 1, wxEXPAND | wxALL, 5 );
367
 
    panel_sizer->Layout();
368
 
 
369
 
    playlist_panel->SetSizerAndFit( panel_sizer );
370
 
 
371
 
    int pi_widths[1] =  { -1 };
372
 
    statusbar = CreateStatusBar( 1 );
373
 
    statusbar->SetStatusWidths( 1, pi_widths );
374
 
 
375
 
#if wxUSE_DRAG_AND_DROP
376
 
    /* Associate drop targets with the playlist */
377
 
    SetDropTarget( new PlaylistFileDropTarget( this ) );
378
 
    menubar->SetDropTarget( new PlaylistFileDropTarget( this ) );
379
 
    toolbar->SetDropTarget( new PlaylistFileDropTarget( this ) );
380
 
#endif
381
 
 
382
 
    i_saved_id = -1;
383
 
 
384
 
 
385
 
    /* We want to be noticed of playlist changes */
386
 
 
387
 
    /* Some global changes happened -> Rebuild all */
388
 
    var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
389
 
 
390
 
    /* We went to the next item */
391
 
    var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
392
 
 
393
 
    /* One item has been updated */
394
 
    var_AddCallback( p_playlist, "item-change", ItemChanged, this );
395
 
 
396
 
    var_AddCallback( p_playlist, "item-append", ItemAppended, this );
397
 
    var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
398
 
 
399
 
    /* Update the playlist */
400
 
    Rebuild( VLC_TRUE );
401
 
 
402
 
}
403
 
 
404
 
Playlist::~Playlist()
405
 
{
406
 
    if( pp_sds != NULL ) free( pp_sds );
407
 
 
408
 
    if( p_playlist == NULL ) return;
409
 
 
410
 
    var_DelCallback( p_playlist, "item-change", ItemChanged, this );
411
 
    var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
412
 
    var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
413
 
    var_DelCallback( p_playlist, "item-append", ItemAppended, this );
414
 
    var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
415
 
    vlc_object_release( p_playlist );
416
 
}
417
 
 
418
 
/**********************************************************************
419
 
 * Update functions
420
 
 **********************************************************************/
421
 
 
422
 
/* Update a node */
423
 
void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node )
424
 
{
425
 
    wxTreeItemIdValue cookie;
426
 
    wxTreeItemId child;
427
 
    for( int i = 0; i< p_node->i_children ; i++ )
428
 
    {
429
 
        if( i == 0 )
430
 
        {
431
 
            child = treectrl->GetFirstChild( node, cookie);
432
 
        }
433
 
        else
434
 
        {
435
 
            child = treectrl->GetNextChild( node, cookie );
436
 
        }
437
 
 
438
 
        if( !child.IsOk() )
439
 
        {
440
 
            /* Not enough children */
441
 
            CreateNode( p_node->pp_children[i], node );
442
 
            /* Keep the tree pointer up to date */
443
 
            child = treectrl->GetNextChild( node, cookie );
444
 
        }
445
 
    }
446
 
    treectrl->SetItemImage( node, p_node->input.i_type );
447
 
 
448
 
}
449
 
 
450
 
/* Creates the node p_node as last child of parent */
451
 
void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent )
452
 
{
453
 
    wxTreeItemId node =
454
 
        treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ),
455
 
                              -1,-1, new PlaylistItem( p_node ) );
456
 
    treectrl->SetItemImage( node, p_node->input.i_type );
457
 
 
458
 
    UpdateNodeChildren( p_node, node );
459
 
}
460
 
 
461
 
/* Update all children (recursively) of this node */
462
 
void Playlist::UpdateNodeChildren( playlist_item_t *p_node,
463
 
                                   wxTreeItemId node )
464
 
{
465
 
 
466
 
    for( int i = 0; i< p_node->i_children ; i++ )
467
 
    {
468
 
        /* Append the item */
469
 
        if( p_node->pp_children[i]->i_children == -1 )
470
 
        {
471
 
            wxTreeItemId item =
472
 
                treectrl->AppendItem( node,
473
 
                    wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1,
474
 
                           new PlaylistItem( p_node->pp_children[i]) );
475
 
 
476
 
            UpdateTreeItem( item );
477
 
        }
478
 
        else
479
 
        {
480
 
            CreateNode( p_node->pp_children[i], node );
481
 
        }
482
 
    }
483
 
}
484
 
 
485
 
/* Update an item in the tree */
486
 
void Playlist::UpdateTreeItem( wxTreeItemId item )
487
 
{
488
 
    if( ! item.IsOk() ) return;
489
 
 
490
 
    wxTreeItemData *p_data = treectrl->GetItemData( item );
491
 
    if( !p_data ) return;
492
 
 
493
 
    LockPlaylist( p_intf->p_sys, p_playlist );
494
 
    playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
495
 
                                          ((PlaylistItem *)p_data)->i_id );
496
 
    if( !p_item )
497
 
    {
498
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
499
 
        return;
500
 
    }
501
 
 
502
 
    wxString msg;
503
 
    wxString duration = wxU( "" );
504
 
    char *psz_author = vlc_input_item_GetInfo( &p_item->input,
505
 
                                               _(VLC_META_INFO_CAT), _(VLC_META_ARTIST) );
506
 
    if( !psz_author )
507
 
    {
508
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
509
 
        return;
510
 
    }
511
 
 
512
 
    char psz_duration[MSTRTIME_MAX_SIZE];
513
 
    mtime_t dur = p_item->input.i_duration;
514
 
 
515
 
    if( dur != -1 )
516
 
    {
517
 
        secstotimestr( psz_duration, dur/1000000 );
518
 
        duration.Append( wxU( " ( " ) +  wxString( wxU( psz_duration ) ) +
519
 
                         wxU( " )" ) );
520
 
    }
521
 
 
522
 
    if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE )
523
 
    {
524
 
        msg = wxString( wxU( p_item->input.psz_name ) ) + duration;
525
 
    }
526
 
    else
527
 
    {
528
 
        msg = wxString(wxU( psz_author )) + wxT(" - ") +
529
 
              wxString(wxU(p_item->input.psz_name)) + duration;
530
 
    }
531
 
    free( psz_author );
532
 
    treectrl->SetItemText( item , msg );
533
 
    treectrl->SetItemImage( item, p_item->input.i_type );
534
 
 
535
 
    if( p_playlist->status.p_item == p_item )
536
 
    {
537
 
        treectrl->SetItemBold( item, true );
538
 
        while( treectrl->GetItemParent( item ).IsOk() )
539
 
        {
540
 
            item = treectrl->GetItemParent( item );
541
 
            if( ! (item == treectrl->GetRootItem() &&
542
 
                treectrl->HasFlag( wxTR_HIDE_ROOT ) ) )
543
 
                treectrl->Expand( item );
544
 
        }
545
 
    }
546
 
    else
547
 
    {
548
 
        treectrl->SetItemBold( item, false );
549
 
    }
550
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
551
 
}
552
 
 
553
 
/* Process a AppendIt em request */
554
 
void Playlist::AppendItem( wxCommandEvent& event )
555
 
{
556
 
    playlist_add_t *p_add = (playlist_add_t *)event.GetClientData();
557
 
    playlist_item_t *p_item = NULL;
558
 
    wxTreeItemId item, node;
559
 
 
560
 
    i_items_to_append--;
561
 
 
562
 
    /* No need to do anything if the playlist is going to be rebuilt */
563
 
    if( b_need_update ) return;
564
 
 
565
 
    if( p_add->i_view != i_current_view ) goto update;
566
 
 
567
 
    node = FindItem( treectrl->GetRootItem(), p_add->i_node );
568
 
    if( !node.IsOk() ) goto update;
569
 
 
570
 
    p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
571
 
    if( !p_item ) goto update;
572
 
 
573
 
    item = FindItem( treectrl->GetRootItem(), p_add->i_item );
574
 
    if( item.IsOk() ) goto update;
575
 
 
576
 
    item = treectrl->AppendItem( node,
577
 
                                 wxL2U( p_item->input.psz_name ), -1,-1,
578
 
                                 new PlaylistItem( p_item ) );
579
 
    treectrl->SetItemImage( item, p_item->input.i_type );
580
 
 
581
 
    if( item.IsOk() && p_item->i_children == -1 )
582
 
    {
583
 
        UpdateTreeItem( item );
584
 
    }
585
 
 
586
 
update:
587
 
    int i_count = CountItems( treectrl->GetRootItem());
588
 
    if( i_count != p_playlist->i_size )
589
 
    {
590
 
        statusbar->SetStatusText( wxString::Format( wxU(_(
591
 
                                  "%i items in playlist (%i not shown)")),
592
 
                                  p_playlist->i_size,
593
 
                                  p_playlist->i_size - i_count ) );
594
 
        if( !b_changed_view )
595
 
        {
596
 
            i_current_view = VIEW_CATEGORY;
597
 
            b_changed_view = VLC_TRUE;
598
 
            b_need_update = VLC_TRUE;
599
 
        }
600
 
    }
601
 
    else
602
 
    {
603
 
        statusbar->SetStatusText( wxString::Format( wxU(_(
604
 
                                  "%i items in playlist")),
605
 
                                  p_playlist->i_size ), 0 );
606
 
    }
607
 
 
608
 
    return;
609
 
}
610
 
 
611
 
/* Process a updateitem request */
612
 
void Playlist::UpdateItem( int i )
613
 
{
614
 
    if( i < 0 ) return; /* Sanity check */
615
 
 
616
 
    wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
617
 
 
618
 
    if( item.IsOk() )
619
 
    {
620
 
        UpdateTreeItem( item );
621
 
    }
622
 
}
623
 
 
624
 
void Playlist::RemoveItem( int i )
625
 
{
626
 
    if( i <= 0 ) return; /* Sanity check */
627
 
    if( i == i_saved_id ) i_saved_id = -1;
628
 
 
629
 
    wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
630
 
 
631
 
    if( item.IsOk() )
632
 
    {
633
 
        treectrl->Delete( item );
634
 
    }
635
 
}
636
 
 
637
 
 
638
 
/**********************************************************************
639
 
 * Search functions (internal)
640
 
 **********************************************************************/
641
 
 
642
 
/* Find a wxItem from a playlist id */
643
 
wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id )
644
 
{
645
 
    wxTreeItemIdValue cookie;
646
 
    PlaylistItem *p_wxcurrent;
647
 
    wxTreeItemId search;
648
 
    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
649
 
    wxTreeItemId child;
650
 
 
651
 
    p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root );
652
 
 
653
 
    if( i_id < 0 )
654
 
    {
655
 
        wxTreeItemId dummy;
656
 
        return dummy;
657
 
    }
658
 
    if( i_saved_id == i_id )
659
 
    {
660
 
        return saved_tree_item;
661
 
    }
662
 
 
663
 
    if( !p_wxcurrent )
664
 
    {
665
 
        wxTreeItemId dummy;
666
 
        return dummy;
667
 
    }
668
 
 
669
 
    if( p_wxcurrent->i_id == i_id )
670
 
    {
671
 
        i_saved_id = i_id;
672
 
        saved_tree_item = root;
673
 
        return root;
674
 
    }
675
 
 
676
 
    while( item.IsOk() )
677
 
    {
678
 
        p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item );
679
 
        if( p_wxcurrent->i_id == i_id )
680
 
        {
681
 
            i_saved_id = i_id;
682
 
            saved_tree_item = item;
683
 
            return item;
684
 
        }
685
 
        if( treectrl->ItemHasChildren( item ) )
686
 
        {
687
 
            wxTreeItemId search = FindItem( item, i_id );
688
 
            if( search.IsOk() )
689
 
            {
690
 
                i_saved_id = i_id;
691
 
                saved_tree_item = search;
692
 
                return search;
693
 
            }
694
 
        }
695
 
        item = treectrl->GetNextChild( root, cookie );
696
 
    }
697
 
    /* Not found */
698
 
    wxTreeItemId dummy;
699
 
    return dummy;
700
 
}
701
 
 
702
 
int Playlist::CountItems( wxTreeItemId root )
703
 
{
704
 
    wxTreeItemIdValue cookie;
705
 
    int count = 0;
706
 
    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
707
 
 
708
 
    while( item.IsOk() )
709
 
    {
710
 
        if( treectrl->ItemHasChildren( item ) )
711
 
        {
712
 
            count += CountItems( item );
713
 
        }
714
 
        else
715
 
        {
716
 
            playlist_item_t *p_item;
717
 
            LockPlaylist( p_intf->p_sys, p_playlist );
718
 
            p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id );
719
 
            if( p_item && p_item->i_children == -1 )
720
 
                count++;
721
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
722
 
        }
723
 
        item = treectrl->GetNextChild( root, cookie );
724
 
    }
725
 
    return count;
726
 
}
727
 
 
728
 
/* Find a wxItem from a name (from current) */
729
 
wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found )
730
 
{
731
 
    wxTreeItemIdValue cookie;
732
 
    wxTreeItemId search;
733
 
    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
734
 
    wxTreeItemId child;
735
 
 
736
 
    while( item.IsOk() )
737
 
    {
738
 
        if( treectrl->GetItemText( item).Lower().Contains(
739
 
                                                 search_string.Lower() ) )
740
 
        {
741
 
            if( !current.IsOk() || *pb_current_found == VLC_TRUE )
742
 
            {
743
 
                return item;
744
 
            }
745
 
            else if( current.IsOk() && item == current )
746
 
            {
747
 
                *pb_current_found = VLC_TRUE;
748
 
            }
749
 
        }
750
 
        if( treectrl->ItemHasChildren( item ) )
751
 
        {
752
 
            wxTreeItemId search = FindItemByName( item, search_string, current,
753
 
                                                  pb_current_found );
754
 
            if( search.IsOk() )
755
 
            {
756
 
                return search;
757
 
            }
758
 
        }
759
 
        item = treectrl->GetNextChild( root, cookie);
760
 
    }
761
 
    /* Not found */
762
 
    wxTreeItemId dummy;
763
 
    return dummy;
764
 
}
765
 
 
766
 
/**********************************************************************
767
 
 * Rebuild the playlist
768
 
 **********************************************************************/
769
 
void Playlist::Rebuild( vlc_bool_t b_root )
770
 
{
771
 
    playlist_view_t *p_view;
772
 
 
773
 
    i_items_to_append = 0;
774
 
 
775
 
    /* We can remove the callbacks before locking, anyway, we won't
776
 
     * miss anything */
777
 
    if( b_root )
778
 
    {
779
 
        var_DelCallback( p_playlist, "item-change", ItemChanged, this );
780
 
        var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
781
 
        var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
782
 
        var_DelCallback( p_playlist, "item-append", ItemAppended, this );
783
 
        var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
784
 
 
785
 
        /* ...and rebuild it */
786
 
        LockPlaylist( p_intf->p_sys, p_playlist );
787
 
    }
788
 
    i_saved_id = -1;
789
 
 
790
 
    p_view = playlist_ViewFind( p_playlist, i_current_view ); /* FIXME */
791
 
 
792
 
    /* HACK we should really get new*/
793
 
    treectrl->DeleteAllItems();
794
 
    treectrl->AddRoot( wxU(_("root" )), -1, -1,
795
 
                         new PlaylistItem( p_view->p_root) );
796
 
 
797
 
    wxTreeItemId root = treectrl->GetRootItem();
798
 
    UpdateNode( p_view->p_root, root );
799
 
 
800
 
    int i_count = CountItems( treectrl->GetRootItem() );
801
 
 
802
 
    if( i_count < p_playlist->i_size && !b_changed_view )
803
 
    {
804
 
        i_current_view = VIEW_CATEGORY;
805
 
        b_changed_view = VLC_TRUE;
806
 
        Rebuild( VLC_FALSE );
807
 
    }
808
 
    else if( i_count != p_playlist->i_size )
809
 
    {
810
 
        statusbar->SetStatusText( wxString::Format( wxU(_(
811
 
                                  "%i items in playlist (%i not shown)")),
812
 
                                  p_playlist->i_size,
813
 
                                  p_playlist->i_size - i_count ) );
814
 
    }
815
 
    else
816
 
    {
817
 
        statusbar->SetStatusText( wxString::Format( wxU(_(
818
 
                                  "%i items in playlist")),
819
 
                                  p_playlist->i_size ), 0 );
820
 
    }
821
 
 
822
 
    if( b_root )
823
 
    {
824
 
        /* Put callbacks back online */
825
 
        var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
826
 
        var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
827
 
        var_AddCallback( p_playlist, "item-change", ItemChanged, this );
828
 
        var_AddCallback( p_playlist, "item-append", ItemAppended, this );
829
 
        var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
830
 
 
831
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
832
 
    }
833
 
}
834
 
 
835
 
 
836
 
 
837
 
void Playlist::ShowPlaylist( bool show )
838
 
{
839
 
    if( show ) Rebuild( VLC_TRUE );
840
 
    Show( show );
841
 
}
842
 
 
843
 
/* This function is called on a regular basis */
844
 
void Playlist::UpdatePlaylist()
845
 
{
846
 
    i_update_counter++;
847
 
 
848
 
    /* If the playlist isn't show there's no need to update it */
849
 
    if( !IsShown() ) return;
850
 
 
851
 
    if( this->b_need_update )
852
 
    {
853
 
        this->b_need_update = VLC_FALSE;
854
 
        Rebuild( VLC_TRUE );
855
 
    }
856
 
 
857
 
    /* Updating the playing status every 0.5s is enough */
858
 
    if( i_update_counter % 5 ) return;
859
 
}
860
 
 
861
 
/*****************************************************************************
862
 
 * Private methods.
863
 
 *****************************************************************************/
864
 
void Playlist::DeleteTreeItem( wxTreeItemId item )
865
 
{
866
 
   PlaylistItem *p_wxitem;
867
 
   playlist_item_t *p_item;
868
 
   p_wxitem = (PlaylistItem *)treectrl->GetItemData( item );
869
 
 
870
 
   LockPlaylist( p_intf->p_sys, p_playlist );
871
 
   p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
872
 
 
873
 
   if( !p_item )
874
 
   {
875
 
       UnlockPlaylist( p_intf->p_sys, p_playlist );
876
 
       return;
877
 
   }
878
 
 
879
 
   if( p_item->i_children == -1 ) DeleteItem( p_item->input.i_id );
880
 
   else DeleteNode( p_item );
881
 
 
882
 
   RemoveItem( p_item->input.i_id );
883
 
   UnlockPlaylist( p_intf->p_sys, p_playlist );
884
 
}
885
 
 
886
 
void Playlist::DeleteItem( int item_id )
887
 
{
888
 
    playlist_Delete( p_playlist, item_id );
889
 
}
890
 
 
891
 
void Playlist::DeleteNode( playlist_item_t *p_item )
892
 
{
893
 
    playlist_NodeDelete( p_playlist, p_item, VLC_TRUE , VLC_FALSE );
894
 
}
895
 
 
896
 
void Playlist::OnMenuClose( wxCommandEvent& event )
897
 
{
898
 
    wxCloseEvent cevent;
899
 
    OnClose(cevent);
900
 
}
901
 
 
902
 
void Playlist::OnClose( wxCloseEvent& WXUNUSED(event) )
903
 
{
904
 
    Hide();
905
 
}
906
 
 
907
 
void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
908
 
{
909
 
    struct {
910
 
        char *psz_desc;
911
 
        char *psz_filter;
912
 
        char *psz_module;
913
 
    } formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" },
914
 
                   { _("XSPF playlist"), "*.xspf", "export-xspf"}
915
 
    };
916
 
 
917
 
    wxString filter = wxT("");
918
 
 
919
 
    if( p_playlist->i_size == 0 )
920
 
    {
921
 
        wxMessageBox( wxU(_("Playlist is empty") ), wxU(_("Can't save")),
922
 
                      wxICON_WARNING | wxOK, this );
923
 
        return;
924
 
    }
925
 
 
926
 
    for( unsigned int i = 0; i < sizeof(formats)/sizeof(formats[0]); i++)
927
 
    {
928
 
        filter.Append( wxU(formats[i].psz_desc) );
929
 
        filter.Append( wxT("|") );
930
 
        filter.Append( wxU(formats[i].psz_filter) );
931
 
        filter.Append( wxT("|") );
932
 
    }
933
 
    wxFileDialog dialog( this, wxU(_("Save playlist")),
934
 
                         wxT(""), wxT(""), filter, wxSAVE );
935
 
 
936
 
    if( dialog.ShowModal() == wxID_OK )
937
 
    {
938
 
        if( dialog.GetPath().mb_str(wxConvUTF8) )
939
 
        {
940
 
            playlist_Export( p_playlist, dialog.GetPath().mb_str(wxConvUTF8),
941
 
                             formats[dialog.GetFilterIndex()].psz_module );
942
 
        }
943
 
    }
944
 
 
945
 
}
946
 
 
947
 
void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) )
948
 
{
949
 
    wxFileDialog dialog( this, wxU(_("Open playlist")), wxT(""), wxT(""),
950
 
        wxT("All playlists|" EXTENSIONS_PLAYLIST "|XSPF playlist|*.xspf|M3U files|*.m3u"), wxOPEN );
951
 
 
952
 
    if( dialog.ShowModal() == wxID_OK )
953
 
    {
954
 
        playlist_Import( p_playlist, dialog.GetPath().mb_str(wxConvUTF8) );
955
 
    }
956
 
}
957
 
 
958
 
void Playlist::OnAddFile( wxCommandEvent& WXUNUSED(event) )
959
 
{
960
 
    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_SIMPLE, 0, 0 );
961
 
 
962
 
}
963
 
 
964
 
void Playlist::OnAddDir( wxCommandEvent& WXUNUSED(event) )
965
 
{
966
 
    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_DIRECTORY, 0, 0 );
967
 
 
968
 
}
969
 
 
970
 
void Playlist::OnAddMRL( wxCommandEvent& WXUNUSED(event) )
971
 
{
972
 
    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE, 0, 0 );
973
 
 
974
 
}
975
 
 
976
 
/********************************************************************
977
 
 * Sorting functions
978
 
 ********************************************************************/
979
 
void Playlist::OnSort( wxCommandEvent& event )
980
 
{
981
 
    PlaylistItem *p_wxitem;
982
 
    p_wxitem = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() );
983
 
 
984
 
    LockPlaylist( p_intf->p_sys, p_playlist );
985
 
    switch( event.GetId() )
986
 
    {
987
 
        case SortTitle_Event:
988
 
            playlist_RecursiveNodeSort( p_playlist,
989
 
                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
990
 
                            SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
991
 
            break;
992
 
        case RSortTitle_Event:
993
 
            playlist_RecursiveNodeSort( p_playlist,
994
 
                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
995
 
                            SORT_TITLE_NODES_FIRST, ORDER_REVERSE );
996
 
    }
997
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
998
 
 
999
 
    Rebuild( VLC_TRUE );
1000
 
}
1001
 
 
1002
 
/**********************************************************************
1003
 
 * Search functions (user)
1004
 
 **********************************************************************/
1005
 
/*void Playlist::OnSearchTextChange( wxCommandEvent& WXUNUSED(event) )
1006
 
{
1007
 
   search_button->SetDefault();
1008
 
}*/
1009
 
 
1010
 
void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) )
1011
 
{
1012
 
    wxString search_string = search_text->GetValue();
1013
 
 
1014
 
    vlc_bool_t pb_found = VLC_FALSE;
1015
 
 
1016
 
    wxTreeItemId found =
1017
 
     FindItemByName( treectrl->GetRootItem(), search_string,
1018
 
                     search_current, &pb_found );
1019
 
 
1020
 
    if( !found.IsOk() )
1021
 
    {
1022
 
        wxTreeItemId dummy;
1023
 
        search_current = dummy;
1024
 
        found =  FindItemByName( treectrl->GetRootItem(), search_string,
1025
 
                                 search_current, &pb_found );
1026
 
    }
1027
 
 
1028
 
    if( found.IsOk() )
1029
 
    {
1030
 
        search_current = found;
1031
 
        treectrl->EnsureVisible( found );
1032
 
        treectrl->UnselectAll();
1033
 
        treectrl->SelectItem( found, true );
1034
 
    }
1035
 
}
1036
 
 
1037
 
/**********************************************************************
1038
 
 * Selection functions
1039
 
 **********************************************************************/
1040
 
void Playlist::RecursiveDeleteSelection(  wxTreeItemId root )
1041
 
{
1042
 
    wxTreeItemIdValue cookie;
1043
 
    wxTreeItemId child = treectrl->GetFirstChild( root, cookie );
1044
 
    wxTreeItemId nextchild;
1045
 
    bool childIsSelected = FALSE;
1046
 
    bool nextchildIsSelected = FALSE;
1047
 
 
1048
 
    if( child.IsOk() ) childIsSelected = treectrl->IsSelected( child );
1049
 
 
1050
 
    while( child.IsOk() )
1051
 
    {
1052
 
        nextchild = treectrl->GetNextChild( root, cookie );
1053
 
        if( nextchild.IsOk() )
1054
 
            nextchildIsSelected = treectrl->IsSelected( nextchild );
1055
 
        if( childIsSelected ) 
1056
 
            DeleteTreeItem( child );
1057
 
        else if( treectrl->ItemHasChildren( child ) )
1058
 
            RecursiveDeleteSelection( child );
1059
 
        child = nextchild;
1060
 
        childIsSelected = nextchildIsSelected;
1061
 
    }
1062
 
}
1063
 
 
1064
 
void Playlist::OnDeleteSelection( wxCommandEvent& WXUNUSED(event) )
1065
 
{
1066
 
    RecursiveDeleteSelection( treectrl->GetRootItem() );
1067
 
}
1068
 
 
1069
 
/**********************************************************************
1070
 
 * Playlist mode functions
1071
 
 **********************************************************************/
1072
 
void Playlist::OnRandom( wxCommandEvent& event )
1073
 
{
1074
 
    vlc_value_t val;
1075
 
    val.b_bool = event.IsChecked();
1076
 
    var_Set( p_playlist, "random", val);
1077
 
}
1078
 
 
1079
 
void Playlist::OnLoop( wxCommandEvent& event )
1080
 
{
1081
 
    vlc_value_t val;
1082
 
    val.b_bool = event.IsChecked();
1083
 
    var_Set( p_playlist, "loop", val);
1084
 
}
1085
 
 
1086
 
void Playlist::OnRepeat( wxCommandEvent& event )
1087
 
{
1088
 
    vlc_value_t val;
1089
 
    val.b_bool = event.IsChecked();
1090
 
    var_Set( p_playlist, "repeat", val);
1091
 
}
1092
 
 
1093
 
/********************************************************************
1094
 
 * Event
1095
 
 ********************************************************************/
1096
 
void Playlist::OnActivateItem( wxTreeEvent& event )
1097
 
{
1098
 
    playlist_item_t *p_item,*p_node,*p_item2,*p_node2;
1099
 
 
1100
 
    PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
1101
 
                                                            event.GetItem() );
1102
 
    wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() );
1103
 
 
1104
 
    PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent );
1105
 
 
1106
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1107
 
 
1108
 
    if( !( p_wxitem && p_wxparent ) )
1109
 
    {
1110
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
1111
 
        return;
1112
 
    }
1113
 
 
1114
 
    p_item2 = playlist_ItemGetById(p_playlist, p_wxitem->i_id);
1115
 
    p_node2 = playlist_ItemGetById(p_playlist, p_wxparent->i_id);
1116
 
    if( p_item2 && p_item2->i_children == -1 )
1117
 
    {
1118
 
        p_node = p_node2;
1119
 
        p_item = p_item2;
1120
 
    }
1121
 
    else
1122
 
    {
1123
 
        p_node = p_item2;
1124
 
        p_item = NULL;
1125
 
/*        if( p_node && p_node->i_children > 0 &&
1126
 
            p_node->pp_children[0]->i_children == -1)
1127
 
        {
1128
 
            p_item = p_node->pp_children[0];
1129
 
        }
1130
 
        else
1131
 
        {
1132
 
            p_item = NULL;
1133
 
        }*/
1134
 
    }
1135
 
 
1136
 
    playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view,
1137
 
                      p_node, p_item );
1138
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1139
 
}
1140
 
 
1141
 
void Playlist::OnKeyDown( wxTreeEvent& event )
1142
 
{
1143
 
    long keycode = event.GetKeyCode();
1144
 
    /* Delete selected items */
1145
 
    if( keycode == WXK_BACK || keycode == WXK_DELETE || keycode == WXK_NUMPAD_DELETE )
1146
 
    {
1147
 
        /* We send a dummy event */
1148
 
        OnDeleteSelection( event );
1149
 
    }
1150
 
    /* Work around wxWin32 bug */
1151
 
    else if( keycode == WXK_RETURN )
1152
 
    {
1153
 
        wxArrayTreeItemIds items;
1154
 
        if( treectrl->GetSelections( items ) > 0 )
1155
 
        {
1156
 
            wxTreeEvent event;
1157
 
            event.SetItem( items.Item( 0 ) );
1158
 
            OnActivateItem( event );
1159
 
        }
1160
 
    }
1161
 
    else
1162
 
    {
1163
 
        event.Skip();
1164
 
    }
1165
 
}
1166
 
 
1167
 
void Playlist::OnEnDis( wxCommandEvent& event )
1168
 
{
1169
 
    msg_Warn( p_intf, "not implemented" );
1170
 
}
1171
 
 
1172
 
void Playlist::OnDragItemBegin( wxTreeEvent& event )
1173
 
{
1174
 
    event.Allow();
1175
 
    draged_tree_item = event.GetItem();
1176
 
}
1177
 
 
1178
 
void Playlist::OnDragItemEnd( wxTreeEvent& event )
1179
 
{
1180
 
    wxTreeItemId dest_tree_item = event.GetItem();
1181
 
 
1182
 
    if( !dest_tree_item.IsOk() ) return;
1183
 
 
1184
 
    /* check that we're not trying to move a node into one of it's children */
1185
 
    wxTreeItemId parent = dest_tree_item;
1186
 
    while( parent != treectrl->GetRootItem() )
1187
 
    {
1188
 
        if( draged_tree_item == parent ) return;
1189
 
        parent = treectrl->GetItemParent( parent );
1190
 
    }
1191
 
 
1192
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1193
 
 
1194
 
    PlaylistItem *p_wxdrageditem =
1195
 
        (PlaylistItem *)treectrl->GetItemData( draged_tree_item );
1196
 
    PlaylistItem *p_wxdestitem =
1197
 
        (PlaylistItem *)treectrl->GetItemData( dest_tree_item );
1198
 
    if( !p_wxdrageditem || !p_wxdestitem )
1199
 
    {
1200
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
1201
 
        return;
1202
 
    }
1203
 
 
1204
 
    playlist_item_t *p_drageditem =
1205
 
        playlist_ItemGetById(p_playlist, p_wxdrageditem->i_id );
1206
 
    playlist_item_t *p_destitem =
1207
 
        playlist_ItemGetById(p_playlist, p_wxdestitem->i_id );
1208
 
    if( !p_drageditem || !p_destitem )
1209
 
    {
1210
 
        UnlockPlaylist( p_intf->p_sys, p_playlist );
1211
 
        return;
1212
 
    }
1213
 
 
1214
 
    if( p_destitem->i_children == -1 )
1215
 
    /* this is a leaf */
1216
 
    {
1217
 
        parent = treectrl->GetItemParent( dest_tree_item );
1218
 
        PlaylistItem *p_parent =
1219
 
            (PlaylistItem *)treectrl->GetItemData( parent );
1220
 
        if( !p_parent )
1221
 
        {
1222
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
1223
 
            return;
1224
 
        }
1225
 
        playlist_item_t *p_destitem2 =
1226
 
            playlist_ItemGetById( p_playlist, p_parent->i_id );
1227
 
        if( !p_destitem2 )
1228
 
        {
1229
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
1230
 
            return;
1231
 
        }
1232
 
        int i;
1233
 
        for( i = 0; i < p_destitem2->i_children; i++ )
1234
 
        {
1235
 
            if( p_destitem2->pp_children[i] == p_destitem ) break;
1236
 
        }
1237
 
        playlist_TreeMove( p_playlist, p_drageditem, p_destitem2,
1238
 
                           i, i_current_view );
1239
 
    }
1240
 
    else
1241
 
    /* this is a node */
1242
 
    {
1243
 
        playlist_TreeMove( p_playlist, p_drageditem, p_destitem,
1244
 
                           0, i_current_view );
1245
 
    }
1246
 
 
1247
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1248
 
 
1249
 
    /* FIXME: having this Rebuild() is dirty */
1250
 
    Rebuild( VLC_TRUE );
1251
 
}
1252
 
 
1253
 
#if wxUSE_DRAG_AND_DROP
1254
 
PlaylistFileDropTarget::PlaylistFileDropTarget( Playlist *p ):p( p ){}
1255
 
 
1256
 
/********************************************************************
1257
 
 * File Drag And Drop handling
1258
 
 ********************************************************************/
1259
 
bool PlaylistFileDropTarget::OnDropFiles( wxCoord x, wxCoord y,
1260
 
                               const wxArrayString& filenames )
1261
 
{
1262
 
    int i_pos = 0;
1263
 
    playlist_item_t *p_dest;
1264
 
 
1265
 
    LockPlaylist( p->p_intf->p_sys, p->p_playlist );
1266
 
 
1267
 
    /* find the destination node and position in that node */
1268
 
    const wxPoint pt( x, y );
1269
 
    wxTreeItemId item = p->treectrl->HitTest( pt );
1270
 
 
1271
 
    if( !item.IsOk() )
1272
 
    {
1273
 
        /* We were droped below the last item so we append to the
1274
 
         * general node */
1275
 
        p_dest = p->p_playlist->p_general;
1276
 
        i_pos = PLAYLIST_END;
1277
 
    }
1278
 
    else
1279
 
    {
1280
 
        PlaylistItem *p_plitem =
1281
 
            (PlaylistItem *)p->treectrl->GetItemData( item );
1282
 
        p_dest = playlist_ItemGetById( p->p_playlist, p_plitem->i_id );
1283
 
 
1284
 
        if( p_dest->i_children == -1 )
1285
 
        {
1286
 
            /* This is a leaf. Append right after it
1287
 
             * We thus need to find the parrent node and the position of the
1288
 
             * leaf in it's children list */
1289
 
            wxTreeItemId parent = p->treectrl->GetItemParent( item );
1290
 
            PlaylistItem *p_parent =
1291
 
                (PlaylistItem *)p->treectrl->GetItemData( parent );
1292
 
            if( !p_parent )
1293
 
            {
1294
 
                UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
1295
 
                return FALSE;
1296
 
            }
1297
 
            playlist_item_t *p_node =
1298
 
                playlist_ItemGetById( p->p_playlist, p_parent->i_id );
1299
 
            if( !p_node )
1300
 
            {
1301
 
                UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
1302
 
                return FALSE;
1303
 
            }
1304
 
            for( i_pos = 0; i_pos < p_node->i_children; i_pos++ )
1305
 
            {
1306
 
                if( p_node->pp_children[i_pos] == p_dest ) break;
1307
 
            }
1308
 
            p_dest = p_node;
1309
 
        }
1310
 
    }
1311
 
 
1312
 
    UnlockPlaylist( p->p_intf->p_sys, p->p_playlist );
1313
 
 
1314
 
    /* Put the items in the playlist node */
1315
 
    for( size_t i = 0; i < filenames.GetCount(); i++ )
1316
 
    {
1317
 
        char *psz_utf8 = wxDnDFromLocale( filenames[i] );
1318
 
        playlist_item_t *p_item =
1319
 
            playlist_ItemNew( p->p_playlist, psz_utf8, psz_utf8 );
1320
 
        playlist_NodeAddItem( p->p_playlist, p_item, p->i_current_view,
1321
 
                              p_dest, PLAYLIST_PREPARSE, i_pos );
1322
 
        wxDnDLocaleFree( psz_utf8 );
1323
 
    }
1324
 
 
1325
 
    /* FIXME: having this Rebuild() is dirty */
1326
 
    p->Rebuild( VLC_TRUE );
1327
 
 
1328
 
    return TRUE;
1329
 
}
1330
 
#endif
1331
 
 
1332
 
/**********************************************************************
1333
 
 * Menu
1334
 
 **********************************************************************/
1335
 
 
1336
 
void Playlist::OnMenuOpen( wxMenuEvent& event)
1337
 
{
1338
 
#if defined( __WXMSW__ )
1339
 
#   define GetEventObject GetMenu
1340
 
#endif
1341
 
 
1342
 
    if( event.GetEventObject() == p_view_menu )
1343
 
    {
1344
 
        p_view_menu = ViewMenu();
1345
 
    }
1346
 
#if defined( __WXMSW__ )
1347
 
#   undef GetEventObject
1348
 
#endif
1349
 
}
1350
 
 
1351
 
void Playlist::OnMenuEvent( wxCommandEvent& event )
1352
 
{
1353
 
    if( event.GetId() < FirstView_Event )
1354
 
    {
1355
 
        event.Skip();
1356
 
        return;
1357
 
    }
1358
 
    else if( event.GetId() < LastView_Event )
1359
 
    {
1360
 
 
1361
 
        int i_new_view = event.GetId() - FirstView_Event;
1362
 
 
1363
 
        playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_new_view );
1364
 
 
1365
 
        if( p_view != NULL )
1366
 
        {
1367
 
            b_changed_view = VLC_TRUE;
1368
 
            i_current_view = i_new_view;
1369
 
            playlist_ViewUpdate( p_playlist, i_new_view );
1370
 
            Rebuild( VLC_TRUE );
1371
 
            return;
1372
 
        }
1373
 
        else if( i_new_view >= VIEW_FIRST_SORTED &&
1374
 
                 i_new_view <= VIEW_LAST_SORTED )
1375
 
        {
1376
 
            b_changed_view = VLC_TRUE;
1377
 
            playlist_ViewInsert( p_playlist, i_new_view, "View" );
1378
 
            playlist_ViewUpdate( p_playlist, i_new_view );
1379
 
 
1380
 
            i_current_view = i_new_view;
1381
 
 
1382
 
            Rebuild( VLC_TRUE );
1383
 
        }
1384
 
    }
1385
 
    else if( event.GetId() >= FirstSD_Event && event.GetId() < LastSD_Event )
1386
 
    {
1387
 
        if( !playlist_IsServicesDiscoveryLoaded( p_playlist,
1388
 
                                pp_sds[event.GetId() - FirstSD_Event] ) )
1389
 
        {
1390
 
            playlist_ServicesDiscoveryAdd( p_playlist,
1391
 
                            pp_sds[event.GetId() - FirstSD_Event] );
1392
 
        }
1393
 
        else
1394
 
        {
1395
 
            //wxMutexGuiLeave();
1396
 
            playlist_ServicesDiscoveryRemove( p_playlist,
1397
 
                            pp_sds[event.GetId() - FirstSD_Event] );
1398
 
            //wxMutexGuiEnter();
1399
 
        }
1400
 
    }
1401
 
}
1402
 
 
1403
 
wxMenu * Playlist::ViewMenu()
1404
 
{
1405
 
    if( !p_view_menu )
1406
 
    {
1407
 
        p_view_menu = new wxMenu;
1408
 
    }
1409
 
    else
1410
 
    {
1411
 
        wxMenuItemList::Node *node = p_view_menu->GetMenuItems().GetFirst();
1412
 
        for( ; node; )
1413
 
        {
1414
 
            wxMenuItem *item = node->GetData();
1415
 
            node = node->GetNext();
1416
 
            p_view_menu->Delete( item );
1417
 
        }
1418
 
    }
1419
 
 
1420
 
    /* FIXME : have a list of "should have" views */
1421
 
    p_view_menu->Append( FirstView_Event + VIEW_CATEGORY,
1422
 
                           wxU(_("Normal") ) );
1423
 
    p_view_menu->Append( FirstView_Event + VIEW_S_AUTHOR,
1424
 
                           wxU(_("Sorted by Artist") ) );
1425
 
    p_view_menu->Append( FirstView_Event + VIEW_S_ALBUM,
1426
 
                           wxU(_("Sorted by Album") ) );
1427
 
 
1428
 
    return p_view_menu;
1429
 
}
1430
 
 
1431
 
wxMenu *Playlist::SDMenu()
1432
 
{
1433
 
    p_sd_menu = new wxMenu;
1434
 
 
1435
 
    vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE,
1436
 
                                        FIND_ANYWHERE );
1437
 
 
1438
 
    int i_number = 0;
1439
 
    for( int i_index = 0; i_index < p_list->i_count; i_index++ )
1440
 
    {
1441
 
        module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1442
 
 
1443
 
        if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
1444
 
            i_number++;
1445
 
    }
1446
 
    if( i_number ) pp_sds = (char **)calloc( i_number, sizeof(void *) );
1447
 
 
1448
 
    i_number = 0;
1449
 
    for( int i_index = 0; i_index < p_list->i_count; i_index++ )
1450
 
    {
1451
 
        module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1452
 
 
1453
 
        if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
1454
 
        {
1455
 
            p_sd_menu->AppendCheckItem( FirstSD_Event + i_number ,
1456
 
                wxU( p_parser->psz_longname ? p_parser->psz_longname :
1457
 
                     (p_parser->psz_shortname ?
1458
 
                      p_parser->psz_shortname : p_parser->psz_object_name) ) );
1459
 
 
1460
 
            /* hack to handle submodules properly */
1461
 
            int i = -1;
1462
 
            while( p_parser->pp_shortcuts[++i] != NULL );
1463
 
            i--;
1464
 
            if( playlist_IsServicesDiscoveryLoaded( p_playlist,
1465
 
                                    i>=0?p_parser->pp_shortcuts[i]
1466
 
                                    :p_parser->psz_object_name ) )
1467
 
            {
1468
 
                p_sd_menu->Check( FirstSD_Event + i_number, TRUE );
1469
 
            }
1470
 
 
1471
 
            pp_sds[i_number++] = i>=0?p_parser->pp_shortcuts[i]
1472
 
                                 :p_parser->psz_object_name;
1473
 
        }
1474
 
    }
1475
 
    vlc_list_release( p_list );
1476
 
    return p_sd_menu;
1477
 
}
1478
 
 
1479
 
 
1480
 
/*****************************************************************************
1481
 
 * Popup management functions
1482
 
 *****************************************************************************/
1483
 
void Playlist::OnPopup( wxContextMenuEvent& event )
1484
 
{
1485
 
    wxPoint pt = event.GetPosition();
1486
 
    playlist_item_t *p_item;
1487
 
 
1488
 
    i_wx_popup_item = treectrl->HitTest( ScreenToClient( pt ) );
1489
 
    if( i_wx_popup_item.IsOk() )
1490
 
    {
1491
 
        PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
1492
 
                                                            i_wx_popup_item );
1493
 
        PlaylistItem *p_wxparent= (PlaylistItem *)treectrl->GetItemData(
1494
 
                                  treectrl->GetItemParent( i_wx_popup_item ) );
1495
 
        i_popup_item = p_wxitem->i_id;
1496
 
        i_popup_parent = p_wxparent->i_id;
1497
 
        treectrl->SelectItem( i_wx_popup_item );
1498
 
 
1499
 
        LockPlaylist( p_intf->p_sys, p_playlist );
1500
 
        p_item = playlist_ItemGetById( p_playlist, i_popup_item );
1501
 
 
1502
 
        if( !p_item )
1503
 
        {
1504
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
1505
 
            return;
1506
 
        }
1507
 
        if( p_item->i_children == -1 )
1508
 
        {
1509
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
1510
 
            Playlist::PopupMenu( item_popup,
1511
 
                                 ScreenToClient( wxGetMousePosition() ) );
1512
 
        }
1513
 
        else
1514
 
        {
1515
 
            UnlockPlaylist( p_intf->p_sys, p_playlist );
1516
 
            Playlist::PopupMenu( node_popup,
1517
 
                                 ScreenToClient( wxGetMousePosition() ) );
1518
 
        }
1519
 
    }
1520
 
}
1521
 
 
1522
 
void Playlist::OnPopupPlay( wxCommandEvent& event )
1523
 
{
1524
 
    playlist_item_t *p_popup_item, *p_popup_parent;
1525
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1526
 
    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
1527
 
    p_popup_parent = playlist_ItemGetById( p_playlist, i_popup_parent );
1528
 
    if( p_popup_item != NULL )
1529
 
    {
1530
 
        if( p_popup_item->i_children > -1 )
1531
 
        {
1532
 
            if( event.GetId() == PopupPlay_Event &&
1533
 
                p_popup_item->i_children > 0 )
1534
 
            {
1535
 
                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1536
 
                                  i_current_view, p_popup_item,
1537
 
                                  p_popup_item->pp_children[0] );
1538
 
            }
1539
 
            else
1540
 
            {
1541
 
                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1542
 
                                  i_current_view, p_popup_item, NULL );
1543
 
            }
1544
 
        }
1545
 
        else
1546
 
        {
1547
 
            if( event.GetId() == PopupPlay_Event )
1548
 
            {
1549
 
                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
1550
 
                                  i_current_view, p_popup_parent,
1551
 
                                  p_popup_item );
1552
 
            }
1553
 
        }
1554
 
    }
1555
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1556
 
}
1557
 
 
1558
 
void Playlist::OnPopupPreparse( wxCommandEvent& event )
1559
 
{
1560
 
    Preparse();
1561
 
}
1562
 
 
1563
 
void Playlist::Preparse()
1564
 
{
1565
 
    playlist_item_t *p_popup_item;
1566
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1567
 
    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
1568
 
 
1569
 
    if( p_popup_item != NULL )
1570
 
    {
1571
 
        if( p_popup_item->i_children == -1 )
1572
 
        {
1573
 
            playlist_PreparseEnqueue( p_playlist, &p_popup_item->input );
1574
 
        }
1575
 
        else
1576
 
        {
1577
 
            int i = 0;
1578
 
            playlist_item_t *p_parent = p_popup_item;
1579
 
            for( i = 0; i< p_parent->i_children ; i++ )
1580
 
            {
1581
 
                wxMenuEvent dummy;
1582
 
                i_wx_popup_item = FindItem( treectrl->GetRootItem(),
1583
 
                                         p_parent->pp_children[i]->input.i_id );
1584
 
                i_popup_item = p_parent->pp_children[i]->input.i_id;
1585
 
                Preparse();
1586
 
            }
1587
 
        }
1588
 
    }
1589
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1590
 
}
1591
 
 
1592
 
void Playlist::OnPopupDel( wxCommandEvent& event )
1593
 
{
1594
 
    DeleteTreeItem( i_wx_popup_item );
1595
 
}
1596
 
 
1597
 
void Playlist::OnPopupSort( wxCommandEvent& event )
1598
 
{
1599
 
    PlaylistItem *p_wxitem;
1600
 
    playlist_item_t *p_item;
1601
 
 
1602
 
    p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
1603
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1604
 
 
1605
 
    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
1606
 
    if( p_item->i_children >= 0 )
1607
 
    {
1608
 
        playlist_RecursiveNodeSort( p_playlist, p_item,
1609
 
                                    SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
1610
 
 
1611
 
        treectrl->DeleteChildren( i_wx_popup_item );
1612
 
        i_saved_id = -1;
1613
 
        UpdateNodeChildren( p_item, i_wx_popup_item );
1614
 
 
1615
 
    }
1616
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1617
 
}
1618
 
 
1619
 
void Playlist::OnPopupInfo( wxCommandEvent& event )
1620
 
{
1621
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1622
 
    playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
1623
 
    if( p_popup_item )
1624
 
    {
1625
 
        iteminfo_dialog = new ItemInfoDialog( p_intf, p_popup_item, this );
1626
 
        if( iteminfo_dialog->ShowModal() == wxID_OK )
1627
 
        {
1628
 
            UpdateItem( i_wx_popup_item );
1629
 
        }
1630
 
        delete iteminfo_dialog;
1631
 
    }
1632
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1633
 
}
1634
 
 
1635
 
void Playlist::OnPopupAddNode( wxCommandEvent& event )
1636
 
{
1637
 
    wxTextEntryDialog text( NULL, wxU(_( "Please enter node name" )),
1638
 
        wxU(_( "Add node" )), wxU(_( "New node" )) );
1639
 
    if( text.ShowModal() != wxID_OK ) return;
1640
 
 
1641
 
    char *psz_name = wxFromLocale( text.GetValue() );
1642
 
 
1643
 
    LockPlaylist( p_intf->p_sys, p_playlist );
1644
 
 
1645
 
    PlaylistItem *p_wxitem;
1646
 
    playlist_item_t *p_item;
1647
 
 
1648
 
    p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
1649
 
 
1650
 
    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
1651
 
 
1652
 
    playlist_NodeCreate( p_playlist, i_current_view, psz_name, p_item );
1653
 
 
1654
 
    UnlockPlaylist( p_intf->p_sys, p_playlist );
1655
 
    Rebuild( VLC_TRUE );
1656
 
 
1657
 
    wxLocaleFree( psz_name );
1658
 
}
1659
 
 
1660
 
 
1661
 
/*****************************************************************************
1662
 
 * Custom events management
1663
 
 *****************************************************************************/
1664
 
void Playlist::OnPlaylistEvent( wxCommandEvent& event )
1665
 
{
1666
 
    switch( event.GetId() )
1667
 
    {
1668
 
        case UpdateItem_Event:
1669
 
            UpdateItem( event.GetInt() );
1670
 
            break;
1671
 
        case AppendItem_Event:
1672
 
            AppendItem( event );
1673
 
            break;
1674
 
        case RemoveItem_Event:
1675
 
            RemoveItem( event.GetInt() );
1676
 
            break;
1677
 
    }
1678
 
}
1679
 
 
1680
 
/*****************************************************************************
1681
 
 * PlaylistChanged: callback triggered by the intf-change playlist variable
1682
 
 *  We don't rebuild the playlist directly here because we don't want the
1683
 
 *  caller to block for a too long time.
1684
 
 *****************************************************************************/
1685
 
static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
1686
 
                            vlc_value_t oval, vlc_value_t nval, void *param )
1687
 
{
1688
 
    Playlist *p_playlist_dialog = (Playlist *)param;
1689
 
    p_playlist_dialog->b_need_update = VLC_TRUE;
1690
 
    return VLC_SUCCESS;
1691
 
}
1692
 
 
1693
 
/*****************************************************************************
1694
 
 * Next: callback triggered by the playlist-current playlist variable
1695
 
 *****************************************************************************/
1696
 
static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable,
1697
 
                         vlc_value_t oval, vlc_value_t nval, void *param )
1698
 
{
1699
 
    Playlist *p_playlist_dialog = (Playlist *)param;
1700
 
 
1701
 
    wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
1702
 
    event.SetInt( oval.i_int );
1703
 
    p_playlist_dialog->AddPendingEvent( event );
1704
 
    event.SetInt( nval.i_int );
1705
 
    p_playlist_dialog->AddPendingEvent( event );
1706
 
 
1707
 
    return 0;
1708
 
}
1709
 
 
1710
 
/*****************************************************************************
1711
 
 * ItemChanged: callback triggered by the item-change playlist variable
1712
 
 *****************************************************************************/
1713
 
static int ItemChanged( vlc_object_t *p_this, const char *psz_variable,
1714
 
                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1715
 
{
1716
 
    Playlist *p_playlist_dialog = (Playlist *)param;
1717
 
 
1718
 
    wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
1719
 
    event.SetInt( new_val.i_int );
1720
 
    p_playlist_dialog->AddPendingEvent( event );
1721
 
 
1722
 
    return 0;
1723
 
}
1724
 
static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
1725
 
                        vlc_value_t old_val, vlc_value_t new_val, void *param )
1726
 
{
1727
 
    Playlist *p_playlist_dialog = (Playlist *)param;
1728
 
 
1729
 
    wxCommandEvent event( wxEVT_PLAYLIST, RemoveItem_Event );
1730
 
    event.SetInt( new_val.i_int );
1731
 
    p_playlist_dialog->AddPendingEvent( event );
1732
 
 
1733
 
    return 0;
1734
 
}
1735
 
 
1736
 
static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
1737
 
                         vlc_value_t oval, vlc_value_t nval, void *param )
1738
 
{
1739
 
    Playlist *p_playlist_dialog = (Playlist *)param;
1740
 
 
1741
 
    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));
1742
 
    memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) );
1743
 
 
1744
 
    if( ++p_playlist_dialog->i_items_to_append >= 50 )
1745
 
    {
1746
 
        /* Too many items waiting to be added, it will be quicker to rebuild
1747
 
         * the whole playlist */
1748
 
        p_playlist_dialog->b_need_update = VLC_TRUE;
1749
 
        return VLC_SUCCESS;
1750
 
    }
1751
 
 
1752
 
    wxCommandEvent event( wxEVT_PLAYLIST, AppendItem_Event );
1753
 
    event.SetClientData( (void *)p_add );
1754
 
    p_playlist_dialog->AddPendingEvent( event );
1755
 
 
1756
 
    return VLC_SUCCESS;
1757
 
}
1758
 
}