]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/bookmarks.cpp
5f6ebed466c812df3515d9c49ee176f4ccb2bcc0
[vlc] / modules / gui / wxwidgets / dialogs / bookmarks.cpp
1 /*****************************************************************************
2  * bookmarks.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "dialogs/bookmarks.hpp"
28
29 #include "wizard.hpp"
30
31 /* Callback prototype */
32 static int PlaylistChanged( vlc_object_t *, const char *,
33                             vlc_value_t, vlc_value_t, void * );
34
35 /*****************************************************************************
36  * Event Table.
37  *****************************************************************************/
38
39 /* IDs for the controls and the menu commands */
40 enum
41 {
42     /* menu items */
43     ButtonAdd_Event = wxID_HIGHEST + 1,
44     ButtonDel_Event,
45     ButtonClear_Event,
46     ButtonExtract_Event,
47     ButtonEdit_Event
48 };
49
50 DEFINE_LOCAL_EVENT_TYPE( wxEVT_BOOKMARKS );
51
52 BEGIN_EVENT_TABLE(BookmarksDialog, wxFrame)
53     /* Hide the window when the user closes the window */
54     EVT_CLOSE(BookmarksDialog::OnClose )
55     EVT_BUTTON( wxID_ADD, BookmarksDialog::OnAdd )
56     EVT_BUTTON( wxID_DELETE, BookmarksDialog::OnDel )
57     EVT_BUTTON( wxID_CLEAR, BookmarksDialog::OnClear )
58     EVT_BUTTON( ButtonExtract_Event, BookmarksDialog::OnExtract )
59     EVT_BUTTON( ButtonEdit_Event, BookmarksDialog::OnEdit )
60
61     EVT_LIST_ITEM_ACTIVATED( -1, BookmarksDialog::OnActivateItem )
62
63     EVT_COMMAND( -1, wxEVT_BOOKMARKS, BookmarksDialog::OnUpdate )
64 END_EVENT_TABLE()
65
66 BEGIN_EVENT_TABLE( BookmarkEditDialog, wxDialog)
67     EVT_BUTTON( wxID_OK, BookmarkEditDialog::OnOK)
68 END_EVENT_TABLE()
69
70 /****************************************************************************
71  * BookmarkEditDialog
72  ***************************************************************************/
73 BookmarkEditDialog::BookmarkEditDialog( intf_thread_t *_p_intf,
74            wxWindow *_p_parent, seekpoint_t *_p_seekpoint ):wxDialog(
75             _p_parent, -1, wxU(_("Edit bookmark")), wxDefaultPosition,
76             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
77 {
78     /* Initializations */
79     p_intf = _p_intf;
80     p_seekpoint = _p_seekpoint;
81     SetIcon( *p_intf->p_sys->p_icon );
82
83     /* Create a panel to put everything in*/
84     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
85
86     wxFlexGridSizer * sizer = new wxFlexGridSizer( 2 , 3 , 1 );
87     name_text = new wxTextCtrl( this, -1, wxU( p_seekpoint->psz_name ?
88                                                p_seekpoint->psz_name : "" ),
89                                 wxDefaultPosition, wxSize( 100, 20) );
90     time_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
91                                 (int)(p_seekpoint->i_time_offset / 1000000) ),
92                                 wxDefaultPosition, wxSize( 100, 20) );
93     bytes_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
94                                 (int)p_seekpoint->i_byte_offset ),
95                                 wxDefaultPosition, wxSize( 100, 20) );
96
97     sizer->Add( new wxStaticText( this, -1, wxU(_("Name") ) ), 0, wxLEFT, 5 );
98     sizer->Add( name_text, 0, wxEXPAND|wxRIGHT , 5 );
99     sizer->Add( new wxStaticText( this, -1, wxU(_("Time") ) ), 0, wxLEFT, 5 );
100     sizer->Add( time_text , 0, wxEXPAND|wxRIGHT , 5);
101     sizer->Add( new wxStaticText( this, -1, wxU(_("Bytes") ) ), 0, wxLEFT, 5 );
102     sizer->Add( bytes_text, 0, wxEXPAND|wxRIGHT, 5);
103
104     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
105     wxButton *ok_button = new wxButton( this, wxID_OK, wxU(_("&OK") ) );
106     ok_button->SetDefault();
107     button_sizer->Add( ok_button );
108     button_sizer->Add( new wxButton( this, wxID_CANCEL, wxU(_("&Cancel") ) ) );
109
110     panel_sizer->Add( sizer, 0, wxEXPAND | wxTOP|wxBOTTOM, 5 );
111     panel_sizer->Add( button_sizer, 0, wxEXPAND | wxBOTTOM, 5 );
112     panel_sizer->Layout();
113     SetSizerAndFit( panel_sizer );
114 }
115
116 BookmarkEditDialog::~BookmarkEditDialog()
117 {
118 }
119 void BookmarkEditDialog::OnOK( wxCommandEvent &event )
120 {
121     if( p_seekpoint->psz_name ) free( p_seekpoint->psz_name );
122     p_seekpoint->psz_name = strdup( name_text->GetValue().mb_str(wxConvUTF8) );
123     p_seekpoint->i_byte_offset = atoi( bytes_text->GetValue().mb_str(wxConvUTF8) );
124     p_seekpoint->i_time_offset =  1000000 *
125                                   atoll( time_text->GetValue().mb_str(wxConvUTF8) ) ;
126     EndModal( wxID_OK );
127 }
128
129 void BookmarkEditDialog::OnCancel( wxCommandEvent &event )
130 {
131     EndModal( wxID_CANCEL );
132 }
133
134 /*****************************************************************************
135  * Constructor.
136  *****************************************************************************/
137 BookmarksDialog::BookmarksDialog( intf_thread_t *_p_intf, wxWindow *p_parent )
138   : wxFrame( p_parent->GetParent() ? p_parent->GetParent() : p_parent,
139              -1, wxU(_("Bookmarks")),
140              !p_parent->GetParent() ? wxDefaultPosition :
141                wxPoint( p_parent->GetParent()->GetRect().GetX(),
142                         p_parent->GetParent()->GetRect().GetY() +
143                         p_parent->GetParent()->GetRect().GetHeight() + 40 ),
144              wxSize( 500, -1 ),
145              wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
146 {
147     /* Initializations */
148     p_intf = _p_intf;
149     SetIcon( *p_intf->p_sys->p_icon );
150
151     wxPanel *main_panel = new wxPanel( this, -1 );
152     wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
153
154     wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
155
156     wxPanel *panel = new wxPanel( main_panel, -1 );
157     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
158     wxButton *button_add =
159         new wxButton( panel, wxID_ADD, wxU(_("Add")) );
160     wxButton *button_del =
161         new wxButton( panel, wxID_DELETE, wxU(_("&Delete")) );
162     wxButton *button_clear =
163         new wxButton( panel, wxID_CLEAR, wxU(_("&Clear")) );
164     wxButton *button_edit =
165         new wxButton( panel, ButtonEdit_Event, wxU(_("Edit")) );
166     wxButton *button_extract =
167         new wxButton( panel, ButtonExtract_Event, wxU(_("Extract")) );
168
169 #define ADD_TEXT N_("Adds a bookmark at the current position in the stream")
170 #define REMOVE_TEXT N_("Removes the selected bookmarks")
171 #define CLEAR_TEXT N_("Removes all the bookmarks for that stream")
172 #define EDIT_TEXT N_("Edit the properties of a bookmark")
173 #define EXTRACT_TEXT N_("If you select two or more bookmarks, this will " \
174                "launch the streaming/transcoding wizard to allow you to " \
175               "stream or save the part of the stream between these bookmarks")
176     button_add->SetToolTip(  wxU(_( ADD_TEXT ) ) );
177     button_del->SetToolTip(  wxU(_( REMOVE_TEXT ) ) );
178     button_clear->SetToolTip(  wxU(_( CLEAR_TEXT ) ) );
179     button_edit->SetToolTip(  wxU(_( EDIT_TEXT ) ) );
180     button_extract->SetToolTip( wxU(_( EXTRACT_TEXT ) ) );
181
182     panel_sizer->Add( button_add, 0, wxEXPAND );
183     panel_sizer->Add( button_del, 0, wxEXPAND );
184     panel_sizer->Add( button_clear, 0, wxEXPAND );
185
186     panel_sizer->Add( button_edit, 0, wxEXPAND );
187     panel_sizer->Add( 0, 0, 1 );
188     panel_sizer->Add( button_extract, 0, wxEXPAND );
189
190     panel->SetSizerAndFit( panel_sizer );
191
192     list_ctrl = new wxListView( main_panel, -1,
193                                 wxDefaultPosition, wxDefaultSize,
194                                 wxLC_REPORT | wxSUNKEN_BORDER );
195     list_ctrl->InsertColumn( 0, wxU(_("Description")) );
196     list_ctrl->SetColumnWidth( 0, 240 );
197     list_ctrl->InsertColumn( 1, wxU(_("Bytes")) );
198     list_ctrl->InsertColumn( 2, wxU(_("Time")) );
199
200     sizer->Add( panel, 0, wxEXPAND | wxALL, 1 );
201     sizer->Add( list_ctrl, 1, wxEXPAND | wxALL, 1 );
202     main_panel->SetSizer( sizer );
203
204     main_sizer->Add( main_panel, 1, wxEXPAND );
205     SetSizer( main_sizer );
206
207     playlist_t *p_playlist =
208         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
209                                        FIND_ANYWHERE );
210     if( p_playlist )
211     {
212        /* Some global changes happened -> Rebuild all */
213        var_AddCallback( p_playlist, "playlist-current",
214                         PlaylistChanged, this );
215        vlc_object_release( p_playlist );
216     }
217 }
218
219 BookmarksDialog::~BookmarksDialog()
220 {
221     playlist_t *p_playlist =
222         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
223                                        FIND_ANYWHERE );
224     if( p_playlist )
225     {
226        var_DelCallback( p_playlist, "playlist-current",
227                         PlaylistChanged, this );
228        vlc_object_release( p_playlist );
229     }
230 }
231
232 /*****************************************************************************
233  * Private methods.
234  *****************************************************************************/
235 //wxFrame *BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent )
236 //{
237 //    return new class BookmarksDialog( p_intf, p_parent );
238 //}
239
240 void BookmarksDialog::Update()
241 {
242     input_thread_t *p_input =
243         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
244                                            FIND_ANYWHERE );
245     if( !p_input ) return;
246
247     seekpoint_t **pp_bookmarks;
248     int i_bookmarks;
249
250     list_ctrl->DeleteAllItems();
251     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
252                        &i_bookmarks ) != VLC_SUCCESS )
253     {
254         vlc_object_release( p_input );
255         return;
256     }
257
258     for( int i = 0; i < i_bookmarks; i++ )
259     {
260         list_ctrl->InsertItem( i, wxL2U( pp_bookmarks[i]->psz_name ) );
261         /* FIXME: see if we can use the 64 bits integer format string */
262         list_ctrl->SetItem( i, 1, wxString::Format(wxT("%d"),
263                             (int)(pp_bookmarks[i]->i_byte_offset) ) );
264         list_ctrl->SetItem( i, 2, wxString::Format(wxT("%d"),
265                             (int)(pp_bookmarks[i]->i_time_offset / 1000000) ) );
266     }
267
268     vlc_object_release( p_input );
269 }
270
271 bool BookmarksDialog::Show( bool show )
272 {
273     Update();
274     return wxFrame::Show( show );
275 }
276
277 void BookmarksDialog::OnClose( wxCloseEvent& event )
278 {
279     Hide();
280 }
281
282 void BookmarksDialog::OnAdd( wxCommandEvent& event )
283 {
284     input_thread_t *p_input =
285         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
286                                            FIND_ANYWHERE );
287     if( !p_input ) return;
288
289     seekpoint_t bookmark;
290     vlc_value_t pos;
291     bookmark.psz_name = NULL;
292     bookmark.i_byte_offset = 0;
293     bookmark.i_time_offset = 0;
294
295     var_Get( p_input, "position", &pos );
296     bookmark.psz_name = NULL;
297     input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
298     var_Get( p_input, "time", &pos );
299     bookmark.i_time_offset = pos.i_time;
300     input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
301     vlc_object_release( p_input );
302
303     Update();
304 }
305
306 void BookmarksDialog::OnDel( wxCommandEvent& event )
307 {
308     input_thread_t *p_input =
309         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
310                                            FIND_ANYWHERE );
311     if( !p_input ) return;
312
313     int i_focused = list_ctrl->GetFocusedItem();
314     if( i_focused >= 0 )
315     {
316         input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
317     }
318
319     vlc_object_release( p_input );
320
321     Update();
322 }
323
324 void BookmarksDialog::OnClear( wxCommandEvent& event )
325 {
326     input_thread_t *p_input =
327         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
328                                            FIND_ANYWHERE );
329     if( !p_input ) return;
330
331     input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
332
333     vlc_object_release( p_input );
334
335     Update();
336 }
337
338 void BookmarksDialog::OnExtract( wxCommandEvent& event )
339 {
340     long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
341                                           wxLIST_STATE_SELECTED );
342     long i_second = list_ctrl->GetNextItem( i_first, wxLIST_NEXT_ALL,
343                                           wxLIST_STATE_SELECTED );
344
345     if( i_first == -1 || i_second == -1 )
346     {
347         wxMessageBox( wxU(_("You must select two bookmarks") ),
348                       wxU(_("Invalid selection") ), wxICON_WARNING | wxOK,
349                       this );
350         return;
351     }
352     input_thread_t *p_input =
353         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
354                                            FIND_ANYWHERE );
355     if( !p_input )
356     {
357         wxMessageBox( wxU(_("The stream must be playing or paused for "
358                             "bookmarks to work" ) ), wxU(_("No input found")),
359                             wxICON_WARNING | wxOK,
360                             this );
361         return;
362     }
363
364     seekpoint_t **pp_bookmarks;
365     int i_bookmarks ;
366
367     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
368                        &i_bookmarks ) != VLC_SUCCESS )
369     {
370         vlc_object_release( p_input );
371         return;
372     }
373
374     if( i_first < i_bookmarks && i_second <= i_bookmarks )
375     {
376         char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
377         WizardDialog *p_wizard_dialog = new WizardDialog( p_intf, this,
378                                psz_uri,
379                                pp_bookmarks[i_first]->i_time_offset/1000000,
380                                pp_bookmarks[i_second]->i_time_offset/1000000 );
381         free( psz_uri );
382         vlc_object_release( p_input );
383         if( p_wizard_dialog )
384         {
385             p_wizard_dialog->Run();
386             delete p_wizard_dialog;
387         }
388     }
389     else
390     {
391         vlc_object_release( p_input );
392     }
393 }
394
395 void BookmarksDialog::OnActivateItem( wxListEvent& event )
396 {
397     input_thread_t *p_input =
398         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
399                                            FIND_ANYWHERE );
400     if( !p_input ) return;
401
402     input_Control( p_input, INPUT_SET_BOOKMARK, event.GetIndex() );
403
404     vlc_object_release( p_input );
405 }
406
407 void BookmarksDialog::OnEdit( wxCommandEvent& event )
408 {
409     input_thread_t *p_old_input;
410     input_thread_t *p_input =
411         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
412                                            FIND_ANYWHERE );
413     if( !p_input ) return;
414
415
416     seekpoint_t **pp_bookmarks;
417     int i_bookmarks;
418
419     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
420                        &i_bookmarks ) != VLC_SUCCESS )
421     {
422         vlc_object_release( p_input );
423         return;
424     }
425     p_old_input = p_input;
426     vlc_object_release( p_input );
427
428     long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
429                                                wxLIST_STATE_SELECTED );
430
431     if( i_first > -1 && i_first <= i_bookmarks )
432     {
433         BookmarkEditDialog *p_bmk_edit;
434         p_bmk_edit = new BookmarkEditDialog( p_intf, this,
435                                              pp_bookmarks[i_first]);
436
437         if( p_bmk_edit->ShowModal() == wxID_OK )
438         {
439             p_input =(input_thread_t *)vlc_object_find( p_intf,
440                             VLC_OBJECT_INPUT, FIND_ANYWHERE );
441            if( !p_input )
442            {
443                 wxMessageBox( wxU( _("No input found. The stream must be "
444                                   "playing or paused for bookmarks to work.") ),
445                               wxU( _("No input") ), wxICON_WARNING | wxOK,
446                               this );
447                 return;
448            }
449            if( p_old_input != p_input )
450            {
451                 wxMessageBox( wxU( _("Input has changed, unable to save "
452                                   "bookmark. Use \"pause\" while editing "
453                                   "bookmarks to keep the same input.") ),
454                               wxU( _("Input has changed ") ),
455                               wxICON_WARNING | wxOK, this );
456                 vlc_object_release( p_input );
457                 return;
458
459            }
460            if( input_Control( p_input, INPUT_CHANGE_BOOKMARK,
461                               p_bmk_edit->p_seekpoint, i_first ) !=
462                VLC_SUCCESS )
463            {
464                vlc_object_release( p_input );
465                return;
466            }
467            Update();
468            vlc_object_release( p_input );
469         }
470     }
471 }
472
473
474 void BookmarksDialog::OnUpdate( wxCommandEvent &event )
475 {
476     Update();
477 }
478
479 /*****************************************************************************
480  * PlaylistChanged: callback triggered by the intf-change playlist variable
481  *  We don't rebuild the playlist directly here because we don't want the
482  *  caller to block for a too long time.
483  *****************************************************************************/
484 static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
485                             vlc_value_t oval, vlc_value_t nval, void *param )
486 {
487     class BookmarksDialog *p_dialog = (class BookmarksDialog *)param;
488
489     wxCommandEvent bookmarks_event( wxEVT_BOOKMARKS, 0 );
490     p_dialog->AddPendingEvent( bookmarks_event );
491
492     return VLC_SUCCESS;
493 }