1 /*****************************************************************************
2 * bookmarks.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2004 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include "dialogs/bookmarks.hpp"
31 /* Callback prototype */
32 static int PlaylistChanged( vlc_object_t *, const char *,
33 vlc_value_t, vlc_value_t, void * );
35 /*****************************************************************************
37 *****************************************************************************/
39 /* IDs for the controls and the menu commands */
43 ButtonAdd_Event = wxID_HIGHEST + 1,
50 DEFINE_LOCAL_EVENT_TYPE( wxEVT_BOOKMARKS );
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 )
61 EVT_LIST_ITEM_ACTIVATED( -1, BookmarksDialog::OnActivateItem )
63 EVT_COMMAND( -1, wxEVT_BOOKMARKS, BookmarksDialog::OnUpdate )
66 BEGIN_EVENT_TABLE( BookmarkEditDialog, wxDialog)
67 EVT_BUTTON( wxID_OK, BookmarkEditDialog::OnOK)
70 /****************************************************************************
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 )
80 p_seekpoint = _p_seekpoint;
81 SetIcon( *p_intf->p_sys->p_icon );
83 /* Create a panel to put everything in*/
84 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
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) );
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);
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") ) ) );
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 );
116 BookmarkEditDialog::~BookmarkEditDialog()
119 void BookmarkEditDialog::OnOK( wxCommandEvent &event )
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) ) ;
129 void BookmarkEditDialog::OnCancel( wxCommandEvent &event )
131 EndModal( wxID_CANCEL );
134 /*****************************************************************************
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 ),
145 wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
147 /* Initializations */
149 SetIcon( *p_intf->p_sys->p_icon );
151 wxPanel *main_panel = new wxPanel( this, -1 );
152 wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
154 wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
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")) );
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 ) ) );
182 panel_sizer->Add( button_add, 0, wxEXPAND );
183 panel_sizer->Add( button_del, 0, wxEXPAND );
184 panel_sizer->Add( button_clear, 0, wxEXPAND );
186 panel_sizer->Add( button_edit, 0, wxEXPAND );
187 panel_sizer->Add( 0, 0, 1 );
188 panel_sizer->Add( button_extract, 0, wxEXPAND );
190 panel->SetSizerAndFit( panel_sizer );
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")) );
200 sizer->Add( panel, 0, wxEXPAND | wxALL, 1 );
201 sizer->Add( list_ctrl, 1, wxEXPAND | wxALL, 1 );
202 main_panel->SetSizer( sizer );
204 main_sizer->Add( main_panel, 1, wxEXPAND );
205 SetSizer( main_sizer );
207 playlist_t *p_playlist =
208 (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
212 /* Some global changes happened -> Rebuild all */
213 var_AddCallback( p_playlist, "playlist-current",
214 PlaylistChanged, this );
215 vlc_object_release( p_playlist );
219 BookmarksDialog::~BookmarksDialog()
221 playlist_t *p_playlist =
222 (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
226 var_DelCallback( p_playlist, "playlist-current",
227 PlaylistChanged, this );
228 vlc_object_release( p_playlist );
232 /*****************************************************************************
234 *****************************************************************************/
235 //wxFrame *BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent )
237 // return new class BookmarksDialog( p_intf, p_parent );
240 void BookmarksDialog::Update()
242 input_thread_t *p_input =
243 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
245 if( !p_input ) return;
247 seekpoint_t **pp_bookmarks;
250 list_ctrl->DeleteAllItems();
251 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
252 &i_bookmarks ) != VLC_SUCCESS )
254 vlc_object_release( p_input );
258 for( int i = 0; i < i_bookmarks; i++ )
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) ) );
268 vlc_object_release( p_input );
271 bool BookmarksDialog::Show( bool show )
274 return wxFrame::Show( show );
277 void BookmarksDialog::OnClose( wxCloseEvent& event )
282 void BookmarksDialog::OnAdd( wxCommandEvent& event )
284 input_thread_t *p_input =
285 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
287 if( !p_input ) return;
289 seekpoint_t bookmark;
291 bookmark.psz_name = NULL;
292 bookmark.i_byte_offset = 0;
293 bookmark.i_time_offset = 0;
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 );
306 void BookmarksDialog::OnDel( wxCommandEvent& event )
308 input_thread_t *p_input =
309 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
311 if( !p_input ) return;
313 int i_focused = list_ctrl->GetFocusedItem();
316 input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
319 vlc_object_release( p_input );
324 void BookmarksDialog::OnClear( wxCommandEvent& event )
326 input_thread_t *p_input =
327 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
329 if( !p_input ) return;
331 input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
333 vlc_object_release( p_input );
338 void BookmarksDialog::OnExtract( wxCommandEvent& event )
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 );
345 if( i_first == -1 || i_second == -1 )
347 wxMessageBox( wxU(_("You must select two bookmarks") ),
348 wxU(_("Invalid selection") ), wxICON_WARNING | wxOK,
352 input_thread_t *p_input =
353 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
357 wxMessageBox( wxU(_("The stream must be playing or paused for "
358 "bookmarks to work" ) ), wxU(_("No input found")),
359 wxICON_WARNING | wxOK,
364 seekpoint_t **pp_bookmarks;
367 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
368 &i_bookmarks ) != VLC_SUCCESS )
370 vlc_object_release( p_input );
374 if( i_first < i_bookmarks && i_second <= i_bookmarks )
376 char *psz_uri = input_item_GetURI( input_GetItem( p_input ) );
377 WizardDialog *p_wizard_dialog = new WizardDialog( p_intf, this,
379 pp_bookmarks[i_first]->i_time_offset/1000000,
380 pp_bookmarks[i_second]->i_time_offset/1000000 );
382 vlc_object_release( p_input );
383 if( p_wizard_dialog )
385 p_wizard_dialog->Run();
386 delete p_wizard_dialog;
391 vlc_object_release( p_input );
395 void BookmarksDialog::OnActivateItem( wxListEvent& event )
397 input_thread_t *p_input =
398 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
400 if( !p_input ) return;
402 input_Control( p_input, INPUT_SET_BOOKMARK, event.GetIndex() );
404 vlc_object_release( p_input );
407 void BookmarksDialog::OnEdit( wxCommandEvent& event )
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,
413 if( !p_input ) return;
416 seekpoint_t **pp_bookmarks;
419 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
420 &i_bookmarks ) != VLC_SUCCESS )
422 vlc_object_release( p_input );
425 p_old_input = p_input;
426 vlc_object_release( p_input );
428 long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
429 wxLIST_STATE_SELECTED );
431 if( i_first > -1 && i_first <= i_bookmarks )
433 BookmarkEditDialog *p_bmk_edit;
434 p_bmk_edit = new BookmarkEditDialog( p_intf, this,
435 pp_bookmarks[i_first]);
437 if( p_bmk_edit->ShowModal() == wxID_OK )
439 p_input =(input_thread_t *)vlc_object_find( p_intf,
440 VLC_OBJECT_INPUT, FIND_ANYWHERE );
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,
449 if( p_old_input != p_input )
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 );
460 if( input_Control( p_input, INPUT_CHANGE_BOOKMARK,
461 p_bmk_edit->p_seekpoint, i_first ) !=
464 vlc_object_release( p_input );
468 vlc_object_release( p_input );
474 void BookmarksDialog::OnUpdate( wxCommandEvent &event )
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 )
487 class BookmarksDialog *p_dialog = (class BookmarksDialog *)param;
489 wxCommandEvent bookmarks_event( wxEVT_BOOKMARKS, 0 );
490 p_dialog->AddPendingEvent( bookmarks_event );