Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

bookmarks.cpp

00001 /*****************************************************************************
00002  * bookmarks.cpp : wxWindows plugin for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2000-2004 the VideoLAN team
00005  * $Id: bookmarks.cpp 11981 2005-08-03 15:03:23Z xtophe $
00006  *
00007  * Authors: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 #include <stdlib.h>                                      /* malloc(), free() */
00028 #include <errno.h>                                                 /* ENOMEM */
00029 #include <string.h>                                            /* strerror() */
00030 #include <stdio.h>
00031 
00032 #include <vlc/vlc.h>
00033 #include <vlc/intf.h>
00034 
00035 #include "wxwidgets.h"
00036 #include <wx/dialog.h>
00037 
00038 /* Callback prototype */
00039 static int PlaylistChanged( vlc_object_t *, const char *,
00040                             vlc_value_t, vlc_value_t, void * );
00041 
00042 /*****************************************************************************
00043  * Class declaration.
00044  *****************************************************************************/
00045 
00046 /* IDs for the controls and the menu commands */
00047 enum
00048 {
00049     /* menu items */
00050     ButtonAdd_Event = wxID_HIGHEST + 1,
00051     ButtonDel_Event,
00052     ButtonClear_Event,
00053     ButtonExtract_Event,
00054     ButtonEdit_Event
00055 };
00056 
00057 class BookmarksDialog: public wxFrame
00058 {
00059 public:
00060     /* Constructor */
00061     BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent );
00062     virtual ~BookmarksDialog();
00063 
00064     bool Show( bool );
00065 
00066 private:
00067 
00068     void Update();
00069 
00070     /* Event handlers (these functions should _not_ be virtual) */
00071     void OnClose( wxCloseEvent& event );
00072     void OnAdd( wxCommandEvent& event );
00073     void OnDel( wxCommandEvent& event );
00074     void OnClear( wxCommandEvent& event );
00075     void OnActivateItem( wxListEvent& event );
00076     void OnUpdate( wxCommandEvent &event );
00077     void OnEdit( wxCommandEvent& event );
00078     void OnExtract( wxCommandEvent& event );
00079 
00080     DECLARE_EVENT_TABLE();
00081 
00082     intf_thread_t *p_intf;
00083     wxWindow *p_parent;
00084 
00085     wxListView *list_ctrl;
00086 };
00087 
00088 /*****************************************************************************
00089  * Event Table.
00090  *****************************************************************************/
00091 
00092 DEFINE_LOCAL_EVENT_TYPE( wxEVT_BOOKMARKS );
00093 
00094 BEGIN_EVENT_TABLE(BookmarksDialog, wxFrame)
00095     /* Hide the window when the user closes the window */
00096     EVT_CLOSE(BookmarksDialog::OnClose )
00097     EVT_BUTTON( ButtonAdd_Event, BookmarksDialog::OnAdd )
00098     EVT_BUTTON( ButtonDel_Event, BookmarksDialog::OnDel )
00099     EVT_BUTTON( ButtonClear_Event, BookmarksDialog::OnClear )
00100     EVT_BUTTON( ButtonExtract_Event, BookmarksDialog::OnExtract )
00101     EVT_BUTTON( ButtonEdit_Event, BookmarksDialog::OnEdit )
00102 
00103     EVT_LIST_ITEM_ACTIVATED( -1, BookmarksDialog::OnActivateItem )
00104 
00105     EVT_COMMAND( -1, wxEVT_BOOKMARKS, BookmarksDialog::OnUpdate )
00106 END_EVENT_TABLE()
00107 
00108 /* Declaration of class BookmarkEditDialog */
00109 class BookmarkEditDialog : public wxDialog
00110 {
00111 public:
00112     /* Constructor */
00113     BookmarkEditDialog( intf_thread_t *p_intf, wxWindow *p_parent,
00114                   seekpoint_t *p_seekpoint );
00115     virtual ~BookmarkEditDialog();
00116     seekpoint_t *p_seekpoint;
00117 private:
00118 
00119     wxTextCtrl *name_text, *time_text, *bytes_text;
00120 
00121     void OnOK( wxCommandEvent& event);
00122     void OnCancel( wxCommandEvent& event);
00123 
00124     DECLARE_EVENT_TABLE();
00125 
00126     intf_thread_t *p_intf;
00127 };
00128 
00129 BEGIN_EVENT_TABLE( BookmarkEditDialog, wxDialog)
00130             EVT_BUTTON( wxID_OK, BookmarkEditDialog::OnOK)
00131 END_EVENT_TABLE()
00132 /****************************************************************************
00133  * BookmarkEditDialog
00134  ***************************************************************************/
00135 BookmarkEditDialog::BookmarkEditDialog( intf_thread_t *_p_intf,
00136            wxWindow *_p_parent, seekpoint_t *_p_seekpoint ):wxDialog(
00137             _p_parent, -1, wxU(_("Edit bookmark")), wxDefaultPosition,
00138             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
00139 {
00140     /* Initializations */
00141     p_intf = _p_intf;
00142     p_seekpoint = _p_seekpoint;
00143     SetIcon( *p_intf->p_sys->p_icon );
00144 
00145     /* Create a panel to put everything in*/
00146     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
00147 
00148     wxFlexGridSizer * sizer = new wxFlexGridSizer( 2 , 3 , 1 );
00149     name_text = new wxTextCtrl( this, -1, wxU( p_seekpoint->psz_name ?
00150                                                p_seekpoint->psz_name : "" ),
00151                                 wxDefaultPosition, wxSize( 100, 20) );
00152     time_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
00153                                 (int)(p_seekpoint->i_time_offset / 1000000) ),
00154                                 wxDefaultPosition, wxSize( 100, 20) );
00155     bytes_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
00156                                 (int)p_seekpoint->i_byte_offset ),
00157                                 wxDefaultPosition, wxSize( 100, 20) );
00158 
00159     sizer->Add( new wxStaticText( this, -1, wxU(_("Name") ) ), 0, wxLEFT, 5 );
00160     sizer->Add( name_text, 0, wxEXPAND|wxRIGHT , 5 );
00161     sizer->Add( new wxStaticText( this, -1, wxU(_("Time") ) ), 0, wxLEFT, 5 );
00162     sizer->Add( time_text , 0, wxEXPAND|wxRIGHT , 5);
00163     sizer->Add( new wxStaticText( this, -1, wxU(_("Bytes") ) ), 0, wxLEFT, 5 );
00164     sizer->Add( bytes_text, 0, wxEXPAND|wxRIGHT, 5);
00165 
00166     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
00167     wxButton *ok_button = new wxButton( this, wxID_OK, wxU(_("OK") ) );
00168     ok_button->SetDefault();
00169     button_sizer->Add( ok_button );
00170     button_sizer->Add( new wxButton( this, wxID_CANCEL, wxU(_("Cancel") ) ) );
00171 
00172     panel_sizer->Add( sizer, 0, wxEXPAND | wxTOP|wxBOTTOM, 5 );
00173     panel_sizer->Add( button_sizer, 0, wxEXPAND | wxBOTTOM, 5 );
00174     panel_sizer->Layout();
00175     SetSizerAndFit( panel_sizer );
00176 }
00177 
00178 BookmarkEditDialog::~BookmarkEditDialog()
00179 {
00180 }
00181 void BookmarkEditDialog::OnOK( wxCommandEvent &event )
00182 {
00183     if( p_seekpoint->psz_name ) free( p_seekpoint->psz_name );
00184     p_seekpoint->psz_name = strdup( name_text->GetValue().mb_str() );
00185     p_seekpoint->i_byte_offset = atoi( bytes_text->GetValue().mb_str() );
00186     p_seekpoint->i_time_offset =  1000000 *
00187                                   atoll( time_text->GetValue().mb_str() ) ;
00188     EndModal( wxID_OK );
00189 }
00190 
00191 void BookmarkEditDialog::OnCancel( wxCommandEvent &event )
00192 {
00193     EndModal( wxID_CANCEL );
00194 }
00195 
00196 /*****************************************************************************
00197  * Constructor.
00198  *****************************************************************************/
00199 BookmarksDialog::BookmarksDialog( intf_thread_t *_p_intf, wxWindow *p_parent )
00200   : wxFrame( p_parent->GetParent() ? p_parent->GetParent() : p_parent,
00201              -1, wxU(_("Bookmarks")),
00202              !p_parent->GetParent() ? wxDefaultPosition :
00203                wxPoint( p_parent->GetParent()->GetRect().GetX(),
00204                         p_parent->GetParent()->GetRect().GetY() +
00205                         p_parent->GetParent()->GetRect().GetHeight() + 40 ),
00206              wxSize( 500, -1 ),
00207              wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
00208 {
00209     /* Initializations */
00210     p_intf = _p_intf;
00211     SetIcon( *p_intf->p_sys->p_icon );
00212 
00213     wxPanel *main_panel = new wxPanel( this, -1 );
00214     wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
00215 
00216     wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
00217 
00218     wxPanel *panel = new wxPanel( main_panel, -1 );
00219     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
00220     wxButton *button_add =
00221         new wxButton( panel, ButtonAdd_Event, wxU(_("Add")) );
00222     wxButton *button_del =
00223         new wxButton( panel, ButtonDel_Event, wxU(_("Remove")) );
00224     wxButton *button_clear =
00225         new wxButton( panel, ButtonClear_Event, wxU(_("Clear")) );
00226     wxButton *button_edit =
00227         new wxButton( panel, ButtonEdit_Event, wxU(_("Edit")) );
00228     wxButton *button_extract =
00229         new wxButton( panel, ButtonExtract_Event, wxU(_("Extract")) );
00230 
00231 #define ADD_TEXT "Adds a bookmark at the current position in the stream"
00232 #define REMOVE_TEXT "Removes the selected bookmarks"
00233 #define CLEAR_TEXT "Removes all the bookmarks for that stream"
00234 #define EDIT_TEXT "Edit the properties of a bookmark"
00235 #define EXTRACT_TEXT "If you select two or more bookmarks, this will " \
00236                "launch the streaming/transcoding wizard to allow you to " \
00237               "stream or save the part of the stream between these bookmarks"
00238     button_add->SetToolTip(  wxU(_( ADD_TEXT ) ) );
00239     button_del->SetToolTip(  wxU(_( REMOVE_TEXT ) ) );
00240     button_clear->SetToolTip(  wxU(_( CLEAR_TEXT ) ) );
00241     button_edit->SetToolTip(  wxU(_( EDIT_TEXT ) ) );
00242     button_extract->SetToolTip( wxU(_( EXTRACT_TEXT ) ) );
00243 
00244     panel_sizer->Add( button_add, 0, wxEXPAND );
00245     panel_sizer->Add( button_del, 0, wxEXPAND );
00246     panel_sizer->Add( button_clear, 0, wxEXPAND );
00247 
00248     panel_sizer->Add( button_edit, 0, wxEXPAND );
00249     panel_sizer->Add( 0, 0, 1 );
00250     panel_sizer->Add( button_extract, 0, wxEXPAND );
00251 
00252     panel->SetSizerAndFit( panel_sizer );
00253 
00254     list_ctrl = new wxListView( main_panel, -1,
00255                                 wxDefaultPosition, wxDefaultSize,
00256                                 wxLC_REPORT | wxSUNKEN_BORDER );
00257     list_ctrl->InsertColumn( 0, wxU(_("Description")) );
00258     list_ctrl->SetColumnWidth( 0, 240 );
00259     list_ctrl->InsertColumn( 1, wxU(_("Size offset")) );
00260     list_ctrl->InsertColumn( 2, wxU(_("Time offset")) );
00261 
00262     sizer->Add( panel, 0, wxEXPAND | wxALL, 1 );
00263     sizer->Add( list_ctrl, 1, wxEXPAND | wxALL, 1 );
00264     main_panel->SetSizer( sizer );
00265 
00266     main_sizer->Add( main_panel, 1, wxEXPAND );
00267     SetSizer( main_sizer );
00268 
00269     playlist_t *p_playlist =
00270         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
00271                                        FIND_ANYWHERE );
00272     if( p_playlist )
00273     {
00274        /* Some global changes happened -> Rebuild all */
00275        var_AddCallback( p_playlist, "playlist-current",
00276                         PlaylistChanged, this );
00277        vlc_object_release( p_playlist );
00278     }
00279 }
00280 
00281 BookmarksDialog::~BookmarksDialog()
00282 {
00283     playlist_t *p_playlist =
00284         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
00285                                        FIND_ANYWHERE );
00286     if( p_playlist )
00287     {
00288        var_DelCallback( p_playlist, "playlist-current",
00289                         PlaylistChanged, this );
00290        vlc_object_release( p_playlist );
00291     }
00292 }
00293 
00294 /*****************************************************************************
00295  * Private methods.
00296  *****************************************************************************/
00297 wxFrame *BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent )
00298 {
00299     return new class BookmarksDialog( p_intf, p_parent );
00300 }
00301 
00302 void BookmarksDialog::Update()
00303 {
00304     input_thread_t *p_input =
00305         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00306                                            FIND_ANYWHERE );
00307     if( !p_input ) return;
00308 
00309     seekpoint_t **pp_bookmarks;
00310     int i_bookmarks;
00311 
00312     list_ctrl->DeleteAllItems();
00313     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
00314                        &i_bookmarks ) != VLC_SUCCESS )
00315     {
00316         vlc_object_release( p_input );
00317         return;
00318     }
00319 
00320     for( int i = 0; i < i_bookmarks; i++ )
00321     {
00322         list_ctrl->InsertItem( i, wxL2U( pp_bookmarks[i]->psz_name ) );
00323         /* FIXME: see if we can use the 64 bits integer format string */
00324         list_ctrl->SetItem( i, 1, wxString::Format(wxT("%d"),
00325                             (int)(pp_bookmarks[i]->i_byte_offset) ) );
00326         list_ctrl->SetItem( i, 2, wxString::Format(wxT("%d"),
00327                             (int)(pp_bookmarks[i]->i_time_offset / 1000000) ) );
00328     }
00329 
00330     vlc_object_release( p_input );
00331 }
00332 
00333 bool BookmarksDialog::Show( bool show )
00334 {
00335     Update();
00336     return wxFrame::Show( show );
00337 }
00338 
00339 void BookmarksDialog::OnClose( wxCloseEvent& event )
00340 {
00341     Hide();
00342 }
00343 
00344 void BookmarksDialog::OnAdd( wxCommandEvent& event )
00345 {
00346     input_thread_t *p_input =
00347         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00348                                            FIND_ANYWHERE );
00349     if( !p_input ) return;
00350 
00351     seekpoint_t bookmark;
00352     vlc_value_t pos;
00353     bookmark.psz_name = NULL;
00354     bookmark.i_byte_offset = 0;
00355     bookmark.i_time_offset = 0;
00356 
00357     var_Get( p_input, "position", &pos );
00358     bookmark.psz_name = NULL;
00359     input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
00360     var_Get( p_input, "time", &pos );
00361     bookmark.i_time_offset = pos.i_time;
00362     input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
00363     vlc_object_release( p_input );
00364 
00365     Update();
00366 }
00367 
00368 void BookmarksDialog::OnDel( wxCommandEvent& event )
00369 {
00370     input_thread_t *p_input =
00371         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00372                                            FIND_ANYWHERE );
00373     if( !p_input ) return;
00374 
00375     int i_focused = list_ctrl->GetFocusedItem();
00376     if( i_focused >= 0 )
00377     {
00378         input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
00379     }
00380 
00381     vlc_object_release( p_input );
00382 
00383     Update();
00384 }
00385 
00386 void BookmarksDialog::OnClear( wxCommandEvent& event )
00387 {
00388     input_thread_t *p_input =
00389         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00390                                            FIND_ANYWHERE );
00391     if( !p_input ) return;
00392 
00393     input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
00394 
00395     vlc_object_release( p_input );
00396 
00397     Update();
00398 }
00399 
00400 void BookmarksDialog::OnExtract( wxCommandEvent& event )
00401 {
00402     long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
00403                                           wxLIST_STATE_SELECTED );
00404     long i_second = list_ctrl->GetNextItem( i_first, wxLIST_NEXT_ALL,
00405                                           wxLIST_STATE_SELECTED );
00406 
00407     if( i_first == -1 || i_second == -1 )
00408     {
00409         wxMessageBox( wxU(_("You must select two bookmarks") ),
00410                       wxU(_("Invalid selection") ), wxICON_WARNING | wxOK,
00411                       this );
00412         return;
00413     }
00414     input_thread_t *p_input =
00415         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00416                                            FIND_ANYWHERE );
00417     if( !p_input )
00418     {
00419         wxMessageBox( wxU(_("The stream must be playing or paused for "
00420                             "bookmarks to work" ) ), wxU(_("No input found")),
00421                             wxICON_WARNING | wxOK,
00422                             this );
00423         return;
00424     }
00425 
00426     seekpoint_t **pp_bookmarks;
00427     int i_bookmarks ;
00428 
00429     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
00430                        &i_bookmarks ) != VLC_SUCCESS )
00431     {
00432         vlc_object_release( p_input );
00433         return;
00434     }
00435 
00436     if( i_first < i_bookmarks && i_second <= i_bookmarks )
00437     {
00438         WizardDialog *p_wizard_dialog = new WizardDialog( p_intf, this,
00439                                p_input->input.p_item->psz_uri,
00440                                pp_bookmarks[i_first]->i_time_offset/1000000,
00441                                pp_bookmarks[i_second]->i_time_offset/1000000 );
00442         vlc_object_release( p_input );
00443         if( p_wizard_dialog )
00444         {
00445             p_wizard_dialog->Run();
00446             delete p_wizard_dialog;
00447         }
00448     }
00449     else
00450     {
00451         vlc_object_release( p_input );
00452     }
00453 }
00454 
00455 void BookmarksDialog::OnActivateItem( wxListEvent& event )
00456 {
00457     input_thread_t *p_input =
00458         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00459                                            FIND_ANYWHERE );
00460     if( !p_input ) return;
00461 
00462     input_Control( p_input, INPUT_SET_BOOKMARK, event.GetIndex() );
00463 
00464     vlc_object_release( p_input );
00465 }
00466 
00467 void BookmarksDialog::OnEdit( wxCommandEvent& event )
00468 {
00469     input_thread_t *p_old_input;
00470     input_thread_t *p_input =
00471         (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
00472                                            FIND_ANYWHERE );
00473     if( !p_input ) return;
00474 
00475 
00476     seekpoint_t **pp_bookmarks;
00477     int i_bookmarks;
00478 
00479     if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
00480                        &i_bookmarks ) != VLC_SUCCESS )
00481     {
00482         vlc_object_release( p_input );
00483         return;
00484     }
00485     p_old_input = p_input;
00486     vlc_object_release( p_input );
00487 
00488     long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
00489                                                wxLIST_STATE_SELECTED );
00490 
00491     if( i_first > -1 && i_first <= i_bookmarks )
00492     {
00493         BookmarkEditDialog *p_bmk_edit;
00494         p_bmk_edit = new BookmarkEditDialog( p_intf, this,
00495                                              pp_bookmarks[i_first]);
00496 
00497         if( p_bmk_edit->ShowModal() == wxID_OK )
00498         {
00499             p_input =(input_thread_t *)vlc_object_find( p_intf,
00500                             VLC_OBJECT_INPUT, FIND_ANYWHERE );
00501            if( !p_input )
00502            {
00503                 wxMessageBox( wxU( _("No input found. The stream must be "
00504                                   "playing or paused for bookmarks to work.") ),
00505                               wxU( _("No input") ), wxICON_WARNING | wxOK,
00506                               this );
00507                 return;
00508            }
00509            if( p_old_input != p_input )
00510            {
00511                 wxMessageBox( wxU( _("Input has changed, unable to save "
00512                                   "bookmark. Use \"pause\" while editing "
00513                                   "bookmarks to keep the same input.") ),
00514                               wxU( _("Input has changed ") ),
00515                               wxICON_WARNING | wxOK, this );
00516                 vlc_object_release( p_input );
00517                 return;
00518 
00519            }
00520            if( input_Control( p_input, INPUT_CHANGE_BOOKMARK,
00521                               p_bmk_edit->p_seekpoint, i_first ) !=
00522                VLC_SUCCESS )
00523            {
00524                vlc_object_release( p_input );
00525                return;
00526            }
00527            Update();
00528            vlc_object_release( p_input );
00529         }
00530     }
00531 }
00532 
00533 
00534 void BookmarksDialog::OnUpdate( wxCommandEvent &event )
00535 {
00536     Update();
00537 }
00538 
00539 /*****************************************************************************
00540  * PlaylistChanged: callback triggered by the intf-change playlist variable
00541  *  We don't rebuild the playlist directly here because we don't want the
00542  *  caller to block for a too long time.
00543  *****************************************************************************/
00544 static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
00545                             vlc_value_t oval, vlc_value_t nval, void *param )
00546 {
00547     class BookmarksDialog *p_dialog = (class BookmarksDialog *)param;
00548 
00549     wxCommandEvent bookmarks_event( wxEVT_BOOKMARKS, 0 );
00550     p_dialog->AddPendingEvent( bookmarks_event );
00551 
00552     return VLC_SUCCESS;
00553 }

Generated on Tue Dec 20 10:14:47 2005 for vlc-0.8.4a by  doxygen 1.4.2