p( vlc.getInterfaces().getInterface( "wxwidgets" ).isBroken() ) = 1/2
authorClément Stenac <zorglub@videolan.org>
Wed, 2 Nov 2005 19:20:34 +0000 (19:20 +0000)
committerClément Stenac <zorglub@videolan.org>
Wed, 2 Nov 2005 19:20:34 +0000 (19:20 +0000)
aka : merge the big wx changes from branch

67 files changed:
include/vlc_interface.h
modules/gui/wxwidgets/Modules.am
modules/gui/wxwidgets/bitmaps/trash.xpm [new file with mode: 0644]
modules/gui/wxwidgets/bookmarks.cpp [deleted file]
modules/gui/wxwidgets/dialogs.cpp
modules/gui/wxwidgets/dialogs/bookmarks.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/bookmarks.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/fileinfo.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/fileinfo.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/iteminfo.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/iteminfo.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/messages.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/messages.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/open.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/open.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/playlist.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/playlist.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/preferences.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/preferences.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/preferences_widgets.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/preferences_widgets.h [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/streamout.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/streamout.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/subtitles.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/subtitles.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/updatevlc.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/updatevlc.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_panel.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_panel.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_slider_manager.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_slider_manager.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_stream.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_stream.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_streampanel.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_streampanel.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_wrapper.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/vlm/vlm_wrapper.hpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/wizard.cpp [new file with mode: 0644]
modules/gui/wxwidgets/dialogs/wizard.hpp [new file with mode: 0644]
modules/gui/wxwidgets/extrapanel.cpp
modules/gui/wxwidgets/extrapanel.hpp [new file with mode: 0644]
modules/gui/wxwidgets/fileinfo.cpp [deleted file]
modules/gui/wxwidgets/interface.cpp
modules/gui/wxwidgets/interface.hpp [new file with mode: 0644]
modules/gui/wxwidgets/iteminfo.cpp [deleted file]
modules/gui/wxwidgets/main_slider_manager.cpp [new file with mode: 0644]
modules/gui/wxwidgets/main_slider_manager.hpp [new file with mode: 0644]
modules/gui/wxwidgets/menus.cpp
modules/gui/wxwidgets/messages.cpp [deleted file]
modules/gui/wxwidgets/open.cpp [deleted file]
modules/gui/wxwidgets/playlist.cpp [deleted file]
modules/gui/wxwidgets/preferences.cpp [deleted file]
modules/gui/wxwidgets/preferences_widgets.cpp [deleted file]
modules/gui/wxwidgets/preferences_widgets.h [deleted file]
modules/gui/wxwidgets/slider_manager.cpp [new file with mode: 0644]
modules/gui/wxwidgets/slider_manager.hpp [new file with mode: 0644]
modules/gui/wxwidgets/streamout.cpp [deleted file]
modules/gui/wxwidgets/subtitles.cpp [deleted file]
modules/gui/wxwidgets/timer.cpp
modules/gui/wxwidgets/timer.hpp [new file with mode: 0644]
modules/gui/wxwidgets/updatevlc.cpp [deleted file]
modules/gui/wxwidgets/video.cpp
modules/gui/wxwidgets/video.hpp [new file with mode: 0644]
modules/gui/wxwidgets/wizard.cpp [deleted file]
modules/gui/wxwidgets/wxwidgets.cpp
modules/gui/wxwidgets/wxwidgets.h [deleted file]
modules/gui/wxwidgets/wxwidgets.hpp [new file with mode: 0644]

index 556c171..1ca1392 100644 (file)
@@ -158,6 +158,7 @@ VLC_EXPORT( void,              intf_Destroy,    ( intf_thread_t * ) );
 #define INTF_DIALOG_FILE_GENERIC 30
 
 #define INTF_DIALOG_UPDATEVLC   90
+#define INTF_DIALOG_VLM   91
 
 #define INTF_DIALOG_EXIT       99
 
index 7b4fb96..285f55d 100644 (file)
@@ -1,27 +1,33 @@
 SOURCES_wxwidgets = \
        wxwidgets.cpp \
-       wxwidgets.h \
-       interface.cpp \
-       extrapanel.cpp \
-       dialogs.cpp \
-       open.cpp \
-       streamout.cpp \
-       wizard.cpp \
        streamdata.h \
        streamdata.cpp \
-       messages.cpp \
-       playlist.cpp \
-       iteminfo.cpp \
+       interface.cpp \
+       extrapanel.cpp \
        menus.cpp \
-       preferences.cpp \
-       preferences_widgets.cpp \
-       preferences_widgets.h \
        timer.cpp \
-       fileinfo.cpp \
-       updatevlc.cpp \
-       subtitles.cpp \
-       bookmarks.cpp \
        video.cpp \
+       slider_manager.cpp \
+       main_slider_manager.cpp \
+       dialogs.cpp \
+       dialogs/open.cpp \
+       dialogs/streamout.cpp \
+       dialogs/wizard.cpp \
+       dialogs/messages.cpp \
+       dialogs/playlist.cpp \
+       dialogs/iteminfo.cpp \
+       dialogs/preferences.cpp \
+       dialogs/preferences_widgets.cpp \
+       dialogs/preferences_widgets.h \
+       dialogs/fileinfo.cpp \
+       dialogs/updatevlc.cpp \
+       dialogs/subtitles.cpp \
+       dialogs/bookmarks.cpp \
+       dialogs/vlm/vlm_slider_manager.cpp \
+       dialogs/vlm/vlm_stream.cpp \
+       dialogs/vlm/vlm_wrapper.cpp \
+       dialogs/vlm/vlm_streampanel.cpp \
+       dialogs/vlm/vlm_panel.cpp \
        $(NULL)
 
 EXTRA_DIST += \
@@ -53,4 +59,9 @@ EXTRA_DIST += \
        bitmaps/type_playlist.xpm \
        bitmaps/type_unknown.xpm \
        bitmaps/type_vfile.xpm \
-       bitmaps/video.xpm
+       bitmaps/video.xpm \
+       vlm/vlm_slider_manager.hpp \
+       vlm/vlm_stream.hpp \
+       vlm/vlm_wrapper.hpp \
+       vlm/vlm_streampanel.hpp \
+       vlm/vlm_panel.hpp
diff --git a/modules/gui/wxwidgets/bitmaps/trash.xpm b/modules/gui/wxwidgets/bitmaps/trash.xpm
new file mode 100644 (file)
index 0000000..a537702
--- /dev/null
@@ -0,0 +1,107 @@
+/* XPM */
+static char * trash_xpm[] = {
+"16 16 88 1",
+"      c None",
+".     c #2C2C2C",
+"+     c #6E6E6E",
+"@     c #555555",
+"#     c #161616",
+"$     c #626154",
+"%     c #6B6A5A",
+"&     c #A1A095",
+"*     c #9B9B98",
+"=     c #A4A49D",
+"-     c #A5A495",
+";     c #5C5C50",
+">     c #575649",
+",     c #616057",
+"'     c #D0CEBA",
+")     c #CCCBBD",
+"!     c #85847F",
+"~     c #4C4C48",
+"{     c #3D3C34",
+"]     c #7E7C6B",
+"^     c #B2B09E",
+"/     c #B2B097",
+"(     c #4D4C41",
+"_     c #616059",
+":     c #E0E0DB",
+"<     c #EBEBE4",
+"[     c #D8D7CD",
+"}     c #CCCBBC",
+"|     c #C0BEA8",
+"1     c #B8B69D",
+"2     c #C5C4AF",
+"3     c #AAA996",
+"4     c #414037",
+"5     c #4D4D42",
+"6     c #AAA99B",
+"7     c #D6D5CE",
+"8     c #EAE9E5",
+"9     c #E2E1DE",
+"0     c #D8D8CF",
+"a     c #BCBBAE",
+"b     c #9C9A89",
+"c     c #737262",
+"d     c #34332D",
+"e     c #000000",
+"f     c #41413C",
+"g     c #888882",
+"h     c #B3B2A8",
+"i     c #BCBCAE",
+"j     c #A3A18A",
+"k     c #8F8D7A",
+"l     c #606056",
+"m     c #353530",
+"n     c #676758",
+"o     c #59594F",
+"p     c #52524D",
+"q     c #3D3D38",
+"r     c #2A2A23",
+"s     c #2E2E26",
+"t     c #35352C",
+"u     c #3D3D32",
+"v     c #707060",
+"w     c #919184",
+"x     c #A0A098",
+"y     c #707066",
+"z     c #646458",
+"A     c #606051",
+"B     c #4D4D40",
+"C     c #4E4E40",
+"D     c #959587",
+"E     c #B9B9AC",
+"F     c #8E8E80",
+"G     c #787868",
+"H     c #7A7A67",
+"I     c #565648",
+"J     c #6E6E5D",
+"K     c #939385",
+"L     c #545445",
+"M     c #46463C",
+"N     c #868678",
+"O     c #B2B2A5",
+"P     c #8F8F82",
+"Q     c #787865",
+"R     c #515143",
+"S     c #39392F",
+"T     c #2F2F29",
+"U     c #30302A",
+"V     c #2C2C25",
+"W     c #272720",
+"                ",
+"                ",
+"      .+@#      ",
+"    $%&*=-;>    ",
+"   ,')!~{]^/(   ",
+"   _:<[}|1234   ",
+"   567890abcd   ",
+"   efghijklme   ",
+"   enopqrstue   ",
+"   evwxyzABCe   ",
+"   evDEFGHIIe   ",
+"   eJKEFGHILe   ",
+"   eMNOPGQRSe   ",
+"     eTUVWe     ",
+"                ",
+"                "};
diff --git a/modules/gui/wxwidgets/bookmarks.cpp b/modules/gui/wxwidgets/bookmarks.cpp
deleted file mode 100644 (file)
index 721bc4b..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-/*****************************************************************************
- * bookmarks.cpp : wxWindows plugin for vlc
- *****************************************************************************
- * Copyright (C) 2000-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <stdlib.h>                                      /* malloc(), free() */
-#include <errno.h>                                                 /* ENOMEM */
-#include <string.h>                                            /* strerror() */
-#include <stdio.h>
-
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
-
-#include "wxwidgets.h"
-#include <wx/dialog.h>
-
-/* Callback prototype */
-static int PlaylistChanged( vlc_object_t *, const char *,
-                            vlc_value_t, vlc_value_t, void * );
-
-/*****************************************************************************
- * Class declaration.
- *****************************************************************************/
-
-/* IDs for the controls and the menu commands */
-enum
-{
-    /* menu items */
-    ButtonAdd_Event = wxID_HIGHEST + 1,
-    ButtonDel_Event,
-    ButtonClear_Event,
-    ButtonExtract_Event,
-    ButtonEdit_Event
-};
-
-class BookmarksDialog: public wxFrame
-{
-public:
-    /* Constructor */
-    BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent );
-    virtual ~BookmarksDialog();
-
-    bool Show( bool );
-
-private:
-
-    void Update();
-
-    /* Event handlers (these functions should _not_ be virtual) */
-    void OnClose( wxCloseEvent& event );
-    void OnAdd( wxCommandEvent& event );
-    void OnDel( wxCommandEvent& event );
-    void OnClear( wxCommandEvent& event );
-    void OnActivateItem( wxListEvent& event );
-    void OnUpdate( wxCommandEvent &event );
-    void OnEdit( wxCommandEvent& event );
-    void OnExtract( wxCommandEvent& event );
-
-    DECLARE_EVENT_TABLE();
-
-    intf_thread_t *p_intf;
-    wxWindow *p_parent;
-
-    wxListView *list_ctrl;
-};
-
-/*****************************************************************************
- * Event Table.
- *****************************************************************************/
-
-DEFINE_LOCAL_EVENT_TYPE( wxEVT_BOOKMARKS );
-
-BEGIN_EVENT_TABLE(BookmarksDialog, wxFrame)
-    /* Hide the window when the user closes the window */
-    EVT_CLOSE(BookmarksDialog::OnClose )
-    EVT_BUTTON( ButtonAdd_Event, BookmarksDialog::OnAdd )
-    EVT_BUTTON( ButtonDel_Event, BookmarksDialog::OnDel )
-    EVT_BUTTON( ButtonClear_Event, BookmarksDialog::OnClear )
-    EVT_BUTTON( ButtonExtract_Event, BookmarksDialog::OnExtract )
-    EVT_BUTTON( ButtonEdit_Event, BookmarksDialog::OnEdit )
-
-    EVT_LIST_ITEM_ACTIVATED( -1, BookmarksDialog::OnActivateItem )
-
-    EVT_COMMAND( -1, wxEVT_BOOKMARKS, BookmarksDialog::OnUpdate )
-END_EVENT_TABLE()
-
-/* Declaration of class BookmarkEditDialog */
-class BookmarkEditDialog : public wxDialog
-{
-public:
-    /* Constructor */
-    BookmarkEditDialog( intf_thread_t *p_intf, wxWindow *p_parent,
-                  seekpoint_t *p_seekpoint );
-    virtual ~BookmarkEditDialog();
-    seekpoint_t *p_seekpoint;
-private:
-
-    wxTextCtrl *name_text, *time_text, *bytes_text;
-
-    void OnOK( wxCommandEvent& event);
-    void OnCancel( wxCommandEvent& event);
-
-    DECLARE_EVENT_TABLE();
-
-    intf_thread_t *p_intf;
-};
-
-BEGIN_EVENT_TABLE( BookmarkEditDialog, wxDialog)
-            EVT_BUTTON( wxID_OK, BookmarkEditDialog::OnOK)
-END_EVENT_TABLE()
-/****************************************************************************
- * BookmarkEditDialog
- ***************************************************************************/
-BookmarkEditDialog::BookmarkEditDialog( intf_thread_t *_p_intf,
-           wxWindow *_p_parent, seekpoint_t *_p_seekpoint ):wxDialog(
-            _p_parent, -1, wxU(_("Edit bookmark")), wxDefaultPosition,
-            wxDefaultSize, wxDEFAULT_FRAME_STYLE )
-{
-    /* Initializations */
-    p_intf = _p_intf;
-    p_seekpoint = _p_seekpoint;
-    SetIcon( *p_intf->p_sys->p_icon );
-
-    /* Create a panel to put everything in*/
-    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
-
-    wxFlexGridSizer * sizer = new wxFlexGridSizer( 2 , 3 , 1 );
-    name_text = new wxTextCtrl( this, -1, wxU( p_seekpoint->psz_name ?
-                                               p_seekpoint->psz_name : "" ),
-                                wxDefaultPosition, wxSize( 100, 20) );
-    time_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
-                                (int)(p_seekpoint->i_time_offset / 1000000) ),
-                                wxDefaultPosition, wxSize( 100, 20) );
-    bytes_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
-                                (int)p_seekpoint->i_byte_offset ),
-                                wxDefaultPosition, wxSize( 100, 20) );
-
-    sizer->Add( new wxStaticText( this, -1, wxU(_("Name") ) ), 0, wxLEFT, 5 );
-    sizer->Add( name_text, 0, wxEXPAND|wxRIGHT , 5 );
-    sizer->Add( new wxStaticText( this, -1, wxU(_("Time") ) ), 0, wxLEFT, 5 );
-    sizer->Add( time_text , 0, wxEXPAND|wxRIGHT , 5);
-    sizer->Add( new wxStaticText( this, -1, wxU(_("Bytes") ) ), 0, wxLEFT, 5 );
-    sizer->Add( bytes_text, 0, wxEXPAND|wxRIGHT, 5);
-
-    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
-    wxButton *ok_button = new wxButton( this, wxID_OK, wxU(_("OK") ) );
-    ok_button->SetDefault();
-    button_sizer->Add( ok_button );
-    button_sizer->Add( new wxButton( this, wxID_CANCEL, wxU(_("Cancel") ) ) );
-
-    panel_sizer->Add( sizer, 0, wxEXPAND | wxTOP|wxBOTTOM, 5 );
-    panel_sizer->Add( button_sizer, 0, wxEXPAND | wxBOTTOM, 5 );
-    panel_sizer->Layout();
-    SetSizerAndFit( panel_sizer );
-}
-
-BookmarkEditDialog::~BookmarkEditDialog()
-{
-}
-void BookmarkEditDialog::OnOK( wxCommandEvent &event )
-{
-    if( p_seekpoint->psz_name ) free( p_seekpoint->psz_name );
-    p_seekpoint->psz_name = strdup( name_text->GetValue().mb_str() );
-    p_seekpoint->i_byte_offset = atoi( bytes_text->GetValue().mb_str() );
-    p_seekpoint->i_time_offset =  1000000 *
-                                  atoll( time_text->GetValue().mb_str() ) ;
-    EndModal( wxID_OK );
-}
-
-void BookmarkEditDialog::OnCancel( wxCommandEvent &event )
-{
-    EndModal( wxID_CANCEL );
-}
-
-/*****************************************************************************
- * Constructor.
- *****************************************************************************/
-BookmarksDialog::BookmarksDialog( intf_thread_t *_p_intf, wxWindow *p_parent )
-  : wxFrame( p_parent->GetParent() ? p_parent->GetParent() : p_parent,
-             -1, wxU(_("Bookmarks")),
-             !p_parent->GetParent() ? wxDefaultPosition :
-               wxPoint( p_parent->GetParent()->GetRect().GetX(),
-                        p_parent->GetParent()->GetRect().GetY() +
-                        p_parent->GetParent()->GetRect().GetHeight() + 40 ),
-             wxSize( 500, -1 ),
-             wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
-{
-    /* Initializations */
-    p_intf = _p_intf;
-    SetIcon( *p_intf->p_sys->p_icon );
-
-    wxPanel *main_panel = new wxPanel( this, -1 );
-    wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
-
-    wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
-
-    wxPanel *panel = new wxPanel( main_panel, -1 );
-    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
-    wxButton *button_add =
-        new wxButton( panel, ButtonAdd_Event, wxU(_("Add")) );
-    wxButton *button_del =
-        new wxButton( panel, ButtonDel_Event, wxU(_("Remove")) );
-    wxButton *button_clear =
-        new wxButton( panel, ButtonClear_Event, wxU(_("Clear")) );
-    wxButton *button_edit =
-        new wxButton( panel, ButtonEdit_Event, wxU(_("Edit")) );
-    wxButton *button_extract =
-        new wxButton( panel, ButtonExtract_Event, wxU(_("Extract")) );
-
-#define ADD_TEXT "Adds a bookmark at the current position in the stream"
-#define REMOVE_TEXT "Removes the selected bookmarks"
-#define CLEAR_TEXT "Removes all the bookmarks for that stream"
-#define EDIT_TEXT "Edit the properties of a bookmark"
-#define EXTRACT_TEXT "If you select two or more bookmarks, this will " \
-               "launch the streaming/transcoding wizard to allow you to " \
-              "stream or save the part of the stream between these bookmarks"
-    button_add->SetToolTip(  wxU(_( ADD_TEXT ) ) );
-    button_del->SetToolTip(  wxU(_( REMOVE_TEXT ) ) );
-    button_clear->SetToolTip(  wxU(_( CLEAR_TEXT ) ) );
-    button_edit->SetToolTip(  wxU(_( EDIT_TEXT ) ) );
-    button_extract->SetToolTip( wxU(_( EXTRACT_TEXT ) ) );
-
-    panel_sizer->Add( button_add, 0, wxEXPAND );
-    panel_sizer->Add( button_del, 0, wxEXPAND );
-    panel_sizer->Add( button_clear, 0, wxEXPAND );
-
-    panel_sizer->Add( button_edit, 0, wxEXPAND );
-    panel_sizer->Add( 0, 0, 1 );
-    panel_sizer->Add( button_extract, 0, wxEXPAND );
-
-    panel->SetSizerAndFit( panel_sizer );
-
-    list_ctrl = new wxListView( main_panel, -1,
-                                wxDefaultPosition, wxDefaultSize,
-                                wxLC_REPORT | wxSUNKEN_BORDER );
-    list_ctrl->InsertColumn( 0, wxU(_("Description")) );
-    list_ctrl->SetColumnWidth( 0, 240 );
-    list_ctrl->InsertColumn( 1, wxU(_("Size offset")) );
-    list_ctrl->InsertColumn( 2, wxU(_("Time offset")) );
-
-    sizer->Add( panel, 0, wxEXPAND | wxALL, 1 );
-    sizer->Add( list_ctrl, 1, wxEXPAND | wxALL, 1 );
-    main_panel->SetSizer( sizer );
-
-    main_sizer->Add( main_panel, 1, wxEXPAND );
-    SetSizer( main_sizer );
-
-    playlist_t *p_playlist =
-        (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
-                                       FIND_ANYWHERE );
-    if( p_playlist )
-    {
-       /* Some global changes happened -> Rebuild all */
-       var_AddCallback( p_playlist, "playlist-current",
-                        PlaylistChanged, this );
-       vlc_object_release( p_playlist );
-    }
-}
-
-BookmarksDialog::~BookmarksDialog()
-{
-    playlist_t *p_playlist =
-        (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
-                                       FIND_ANYWHERE );
-    if( p_playlist )
-    {
-       var_DelCallback( p_playlist, "playlist-current",
-                        PlaylistChanged, this );
-       vlc_object_release( p_playlist );
-    }
-}
-
-/*****************************************************************************
- * Private methods.
- *****************************************************************************/
-wxFrame *BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent )
-{
-    return new class BookmarksDialog( p_intf, p_parent );
-}
-
-void BookmarksDialog::Update()
-{
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-    seekpoint_t **pp_bookmarks;
-    int i_bookmarks;
-
-    list_ctrl->DeleteAllItems();
-    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
-                       &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
-        return;
-    }
-
-    for( int i = 0; i < i_bookmarks; i++ )
-    {
-        list_ctrl->InsertItem( i, wxL2U( pp_bookmarks[i]->psz_name ) );
-        /* FIXME: see if we can use the 64 bits integer format string */
-        list_ctrl->SetItem( i, 1, wxString::Format(wxT("%d"),
-                            (int)(pp_bookmarks[i]->i_byte_offset) ) );
-        list_ctrl->SetItem( i, 2, wxString::Format(wxT("%d"),
-                            (int)(pp_bookmarks[i]->i_time_offset / 1000000) ) );
-    }
-
-    vlc_object_release( p_input );
-}
-
-bool BookmarksDialog::Show( bool show )
-{
-    Update();
-    return wxFrame::Show( show );
-}
-
-void BookmarksDialog::OnClose( wxCloseEvent& event )
-{
-    Hide();
-}
-
-void BookmarksDialog::OnAdd( wxCommandEvent& event )
-{
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-    seekpoint_t bookmark;
-    vlc_value_t pos;
-    bookmark.psz_name = NULL;
-    bookmark.i_byte_offset = 0;
-    bookmark.i_time_offset = 0;
-
-    var_Get( p_input, "position", &pos );
-    bookmark.psz_name = NULL;
-    input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
-    var_Get( p_input, "time", &pos );
-    bookmark.i_time_offset = pos.i_time;
-    input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
-    vlc_object_release( p_input );
-
-    Update();
-}
-
-void BookmarksDialog::OnDel( wxCommandEvent& event )
-{
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-    int i_focused = list_ctrl->GetFocusedItem();
-    if( i_focused >= 0 )
-    {
-        input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
-    }
-
-    vlc_object_release( p_input );
-
-    Update();
-}
-
-void BookmarksDialog::OnClear( wxCommandEvent& event )
-{
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-    input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
-
-    vlc_object_release( p_input );
-
-    Update();
-}
-
-void BookmarksDialog::OnExtract( wxCommandEvent& event )
-{
-    long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
-                                          wxLIST_STATE_SELECTED );
-    long i_second = list_ctrl->GetNextItem( i_first, wxLIST_NEXT_ALL,
-                                          wxLIST_STATE_SELECTED );
-
-    if( i_first == -1 || i_second == -1 )
-    {
-        wxMessageBox( wxU(_("You must select two bookmarks") ),
-                      wxU(_("Invalid selection") ), wxICON_WARNING | wxOK,
-                      this );
-        return;
-    }
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input )
-    {
-        wxMessageBox( wxU(_("The stream must be playing or paused for "
-                            "bookmarks to work" ) ), wxU(_("No input found")),
-                            wxICON_WARNING | wxOK,
-                            this );
-        return;
-    }
-
-    seekpoint_t **pp_bookmarks;
-    int i_bookmarks ;
-
-    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
-                       &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
-        return;
-    }
-
-    if( i_first < i_bookmarks && i_second <= i_bookmarks )
-    {
-        WizardDialog *p_wizard_dialog = new WizardDialog( p_intf, this,
-                               p_input->input.p_item->psz_uri,
-                               pp_bookmarks[i_first]->i_time_offset/1000000,
-                               pp_bookmarks[i_second]->i_time_offset/1000000 );
-        vlc_object_release( p_input );
-        if( p_wizard_dialog )
-        {
-            p_wizard_dialog->Run();
-            delete p_wizard_dialog;
-        }
-    }
-    else
-    {
-        vlc_object_release( p_input );
-    }
-}
-
-void BookmarksDialog::OnActivateItem( wxListEvent& event )
-{
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-    input_Control( p_input, INPUT_SET_BOOKMARK, event.GetIndex() );
-
-    vlc_object_release( p_input );
-}
-
-void BookmarksDialog::OnEdit( wxCommandEvent& event )
-{
-    input_thread_t *p_old_input;
-    input_thread_t *p_input =
-        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
-                                           FIND_ANYWHERE );
-    if( !p_input ) return;
-
-
-    seekpoint_t **pp_bookmarks;
-    int i_bookmarks;
-
-    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
-                       &i_bookmarks ) != VLC_SUCCESS )
-    {
-        vlc_object_release( p_input );
-        return;
-    }
-    p_old_input = p_input;
-    vlc_object_release( p_input );
-
-    long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
-                                               wxLIST_STATE_SELECTED );
-
-    if( i_first > -1 && i_first <= i_bookmarks )
-    {
-        BookmarkEditDialog *p_bmk_edit;
-        p_bmk_edit = new BookmarkEditDialog( p_intf, this,
-                                             pp_bookmarks[i_first]);
-
-        if( p_bmk_edit->ShowModal() == wxID_OK )
-        {
-            p_input =(input_thread_t *)vlc_object_find( p_intf,
-                            VLC_OBJECT_INPUT, FIND_ANYWHERE );
-           if( !p_input )
-           {
-                wxMessageBox( wxU( _("No input found. The stream must be "
-                                  "playing or paused for bookmarks to work.") ),
-                              wxU( _("No input") ), wxICON_WARNING | wxOK,
-                              this );
-                return;
-           }
-           if( p_old_input != p_input )
-           {
-                wxMessageBox( wxU( _("Input has changed, unable to save "
-                                  "bookmark. Use \"pause\" while editing "
-                                  "bookmarks to keep the same input.") ),
-                              wxU( _("Input has changed ") ),
-                              wxICON_WARNING | wxOK, this );
-                vlc_object_release( p_input );
-                return;
-
-           }
-           if( input_Control( p_input, INPUT_CHANGE_BOOKMARK,
-                              p_bmk_edit->p_seekpoint, i_first ) !=
-               VLC_SUCCESS )
-           {
-               vlc_object_release( p_input );
-               return;
-           }
-           Update();
-           vlc_object_release( p_input );
-        }
-    }
-}
-
-
-void BookmarksDialog::OnUpdate( wxCommandEvent &event )
-{
-    Update();
-}
-
-/*****************************************************************************
- * PlaylistChanged: callback triggered by the intf-change playlist variable
- *  We don't rebuild the playlist directly here because we don't want the
- *  caller to block for a too long time.
- *****************************************************************************/
-static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
-                            vlc_value_t oval, vlc_value_t nval, void *param )
-{
-    class BookmarksDialog *p_dialog = (class BookmarksDialog *)param;
-
-    wxCommandEvent bookmarks_event( wxEVT_BOOKMARKS, 0 );
-    p_dialog->AddPendingEvent( bookmarks_event );
-
-    return VLC_SUCCESS;
-}
index 23e9c1b..e9c602d 100644 (file)
 #include <vlc/vlc.h>
 #include <vlc/aout.h>
 #include <vlc/intf.h>
+
 #include "charset.h"
 
-#include "wxwidgets.h"
+#include "dialogs/vlm/vlm_panel.hpp"
+#include "dialogs/bookmarks.hpp"
+#include "dialogs/wizard.hpp"
+#include "dialogs/playlist.hpp"
+#include "dialogs/open.hpp"
+#include "dialogs/updatevlc.hpp"
+#include "dialogs/fileinfo.hpp"
+#include "dialogs/iteminfo.hpp"
+#include "dialogs/preferences.hpp"
+#include "dialogs/messages.hpp"
+#include "interface.hpp"
 
 /* include the icon graphic */
 #include "../../../share/vlc32x32.xpm"
@@ -52,6 +63,7 @@ private:
 
     /* Event handlers (these functions should _not_ be virtual) */
     void OnUpdateVLC( wxCommandEvent& event );
+    void OnVLM( wxCommandEvent& event );
     void OnExit( wxCommandEvent& event );
     void OnPlaylist( wxCommandEvent& event );
     void OnMessages( wxCommandEvent& event );
@@ -92,6 +104,7 @@ public:
     wxFrame             *p_bookmarks_dialog;
     wxFileDialog        *p_file_generic_dialog;
     UpdateVLC           *p_updatevlc_dialog;
+    VLMFrame            *p_vlm_dialog;
 };
 
 DEFINE_LOCAL_EVENT_TYPE( wxEVT_DIALOG );
@@ -131,6 +144,8 @@ BEGIN_EVENT_TABLE(DialogsProvider, wxFrame)
                 DialogsProvider::OnExitThread)
     EVT_COMMAND(INTF_DIALOG_UPDATEVLC, wxEVT_DIALOG,
                 DialogsProvider::OnUpdateVLC)
+    EVT_COMMAND(INTF_DIALOG_VLM, wxEVT_DIALOG,
+                DialogsProvider::OnVLM)
 END_EVENT_TABLE()
 
 wxWindow *CreateDialogsProvider( intf_thread_t *p_intf, wxWindow *p_parent )
@@ -157,6 +172,7 @@ DialogsProvider::DialogsProvider( intf_thread_t *_p_intf, wxWindow *p_parent )
     p_bookmarks_dialog = NULL;
     p_dir_dialog = NULL;
     p_updatevlc_dialog = NULL;
+    p_vlm_dialog = NULL;
 
     /* Give our interface a nice little icon */
     p_intf->p_sys->p_icon = new wxIcon( vlc_xpm );
@@ -191,7 +207,7 @@ DialogsProvider::DialogsProvider( intf_thread_t *_p_intf, wxWindow *p_parent )
     INIT( ID_PLAYLIST, p_playlist_dialog, new Playlist(p_intf,this), ShowPlaylist );
     INIT( ID_MESSAGES, p_messages_dialog, new Messages(p_intf,this), Show );
     INIT( ID_FILE_INFO, p_fileinfo_dialog, new FileInfo(p_intf,this), Show );
-    INIT( ID_BOOKMARKS, p_bookmarks_dialog, BookmarksDialog(p_intf,this), Show);
+    INIT( ID_BOOKMARKS, p_bookmarks_dialog, new BookmarksDialog(p_intf,this), Show);
 #undef INIT
 }
 
@@ -215,7 +231,7 @@ DialogsProvider::~DialogsProvider()
 
 #undef UPDATE
 
-       PopEventHandler(true);
+    PopEventHandler(true);
 
     /* Clean up */
     if( p_open_dialog )     delete p_open_dialog;
@@ -228,6 +244,7 @@ DialogsProvider::~DialogsProvider()
     if( p_wizard_dialog ) delete p_wizard_dialog;
     if( p_bookmarks_dialog ) delete p_bookmarks_dialog;
     if( p_updatevlc_dialog ) delete p_updatevlc_dialog;
+    if( p_vlm_dialog ) delete p_vlm_dialog;
 
 
     if( p_intf->p_sys->p_icon ) delete p_intf->p_sys->p_icon;
@@ -319,7 +336,7 @@ void DialogsProvider::OnBookmarks( wxCommandEvent& WXUNUSED(event) )
 {
     /* Show/hide the open dialog */
     if( !p_bookmarks_dialog )
-        p_bookmarks_dialog = BookmarksDialog( p_intf, this );
+        p_bookmarks_dialog = new BookmarksDialog( p_intf, this );
 
     if( p_bookmarks_dialog )
     {
@@ -502,3 +519,15 @@ void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
         p_updatevlc_dialog->Show( !p_updatevlc_dialog->IsShown() );
     }
 }
+
+void DialogsProvider::OnVLM( wxCommandEvent& WXUNUSED(event) )
+{
+    /* Show/hide the file info window */
+    if( !p_vlm_dialog )
+        p_vlm_dialog = new VLMFrame( p_intf, this );
+
+    if( p_vlm_dialog )
+    {
+        p_vlm_dialog->Show( !p_vlm_dialog->IsShown() );
+    }
+}
diff --git a/modules/gui/wxwidgets/dialogs/bookmarks.cpp b/modules/gui/wxwidgets/dialogs/bookmarks.cpp
new file mode 100644 (file)
index 0000000..8e91d3e
--- /dev/null
@@ -0,0 +1,491 @@
+/*****************************************************************************
+ * bookmarks.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "dialogs/bookmarks.hpp"
+
+#include "wizard.hpp"
+
+/* Callback prototype */
+static int PlaylistChanged( vlc_object_t *, const char *,
+                            vlc_value_t, vlc_value_t, void * );
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    /* menu items */
+    ButtonAdd_Event = wxID_HIGHEST + 1,
+    ButtonDel_Event,
+    ButtonClear_Event,
+    ButtonExtract_Event,
+    ButtonEdit_Event
+};
+
+DEFINE_LOCAL_EVENT_TYPE( wxEVT_BOOKMARKS );
+
+BEGIN_EVENT_TABLE(BookmarksDialog, wxFrame)
+    /* Hide the window when the user closes the window */
+    EVT_CLOSE(BookmarksDialog::OnClose )
+    EVT_BUTTON( ButtonAdd_Event, BookmarksDialog::OnAdd )
+    EVT_BUTTON( ButtonDel_Event, BookmarksDialog::OnDel )
+    EVT_BUTTON( ButtonClear_Event, BookmarksDialog::OnClear )
+    EVT_BUTTON( ButtonExtract_Event, BookmarksDialog::OnExtract )
+    EVT_BUTTON( ButtonEdit_Event, BookmarksDialog::OnEdit )
+
+    EVT_LIST_ITEM_ACTIVATED( -1, BookmarksDialog::OnActivateItem )
+
+    EVT_COMMAND( -1, wxEVT_BOOKMARKS, BookmarksDialog::OnUpdate )
+END_EVENT_TABLE()
+
+BEGIN_EVENT_TABLE( BookmarkEditDialog, wxDialog)
+    EVT_BUTTON( wxID_OK, BookmarkEditDialog::OnOK)
+END_EVENT_TABLE()
+
+/****************************************************************************
+ * BookmarkEditDialog
+ ***************************************************************************/
+BookmarkEditDialog::BookmarkEditDialog( intf_thread_t *_p_intf,
+           wxWindow *_p_parent, seekpoint_t *_p_seekpoint ):wxDialog(
+            _p_parent, -1, wxU(_("Edit bookmark")), wxDefaultPosition,
+            wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    p_seekpoint = _p_seekpoint;
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    /* Create a panel to put everything in*/
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+
+    wxFlexGridSizer * sizer = new wxFlexGridSizer( 2 , 3 , 1 );
+    name_text = new wxTextCtrl( this, -1, wxU( p_seekpoint->psz_name ?
+                                               p_seekpoint->psz_name : "" ),
+                                wxDefaultPosition, wxSize( 100, 20) );
+    time_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
+                                (int)(p_seekpoint->i_time_offset / 1000000) ),
+                                wxDefaultPosition, wxSize( 100, 20) );
+    bytes_text = new wxTextCtrl( this, -1, wxString::Format(wxT("%d"),
+                                (int)p_seekpoint->i_byte_offset ),
+                                wxDefaultPosition, wxSize( 100, 20) );
+
+    sizer->Add( new wxStaticText( this, -1, wxU(_("Name") ) ), 0, wxLEFT, 5 );
+    sizer->Add( name_text, 0, wxEXPAND|wxRIGHT , 5 );
+    sizer->Add( new wxStaticText( this, -1, wxU(_("Time") ) ), 0, wxLEFT, 5 );
+    sizer->Add( time_text , 0, wxEXPAND|wxRIGHT , 5);
+    sizer->Add( new wxStaticText( this, -1, wxU(_("Bytes") ) ), 0, wxLEFT, 5 );
+    sizer->Add( bytes_text, 0, wxEXPAND|wxRIGHT, 5);
+
+    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+    wxButton *ok_button = new wxButton( this, wxID_OK, wxU(_("OK") ) );
+    ok_button->SetDefault();
+    button_sizer->Add( ok_button );
+    button_sizer->Add( new wxButton( this, wxID_CANCEL, wxU(_("Cancel") ) ) );
+
+    panel_sizer->Add( sizer, 0, wxEXPAND | wxTOP|wxBOTTOM, 5 );
+    panel_sizer->Add( button_sizer, 0, wxEXPAND | wxBOTTOM, 5 );
+    panel_sizer->Layout();
+    SetSizerAndFit( panel_sizer );
+}
+
+BookmarkEditDialog::~BookmarkEditDialog()
+{
+}
+void BookmarkEditDialog::OnOK( wxCommandEvent &event )
+{
+    if( p_seekpoint->psz_name ) free( p_seekpoint->psz_name );
+    p_seekpoint->psz_name = strdup( name_text->GetValue().mb_str() );
+    p_seekpoint->i_byte_offset = atoi( bytes_text->GetValue().mb_str() );
+    p_seekpoint->i_time_offset =  1000000 *
+                                  atoll( time_text->GetValue().mb_str() ) ;
+    EndModal( wxID_OK );
+}
+
+void BookmarkEditDialog::OnCancel( wxCommandEvent &event )
+{
+    EndModal( wxID_CANCEL );
+}
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+BookmarksDialog::BookmarksDialog( intf_thread_t *_p_intf, wxWindow *p_parent )
+  : wxFrame( p_parent->GetParent() ? p_parent->GetParent() : p_parent,
+             -1, wxU(_("Bookmarks")),
+             !p_parent->GetParent() ? wxDefaultPosition :
+               wxPoint( p_parent->GetParent()->GetRect().GetX(),
+                        p_parent->GetParent()->GetRect().GetY() +
+                        p_parent->GetParent()->GetRect().GetHeight() + 40 ),
+             wxSize( 500, -1 ),
+             wxDEFAULT_FRAME_STYLE | wxFRAME_FLOAT_ON_PARENT )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    wxPanel *main_panel = new wxPanel( this, -1 );
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxHORIZONTAL );
+
+    wxBoxSizer *sizer = new wxBoxSizer( wxHORIZONTAL );
+
+    wxPanel *panel = new wxPanel( main_panel, -1 );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    wxButton *button_add =
+        new wxButton( panel, ButtonAdd_Event, wxU(_("Add")) );
+    wxButton *button_del =
+        new wxButton( panel, ButtonDel_Event, wxU(_("Remove")) );
+    wxButton *button_clear =
+        new wxButton( panel, ButtonClear_Event, wxU(_("Clear")) );
+    wxButton *button_edit =
+        new wxButton( panel, ButtonEdit_Event, wxU(_("Edit")) );
+    wxButton *button_extract =
+        new wxButton( panel, ButtonExtract_Event, wxU(_("Extract")) );
+
+#define ADD_TEXT "Adds a bookmark at the current position in the stream"
+#define REMOVE_TEXT "Removes the selected bookmarks"
+#define CLEAR_TEXT "Removes all the bookmarks for that stream"
+#define EDIT_TEXT "Edit the properties of a bookmark"
+#define EXTRACT_TEXT "If you select two or more bookmarks, this will " \
+               "launch the streaming/transcoding wizard to allow you to " \
+              "stream or save the part of the stream between these bookmarks"
+    button_add->SetToolTip(  wxU(_( ADD_TEXT ) ) );
+    button_del->SetToolTip(  wxU(_( REMOVE_TEXT ) ) );
+    button_clear->SetToolTip(  wxU(_( CLEAR_TEXT ) ) );
+    button_edit->SetToolTip(  wxU(_( EDIT_TEXT ) ) );
+    button_extract->SetToolTip( wxU(_( EXTRACT_TEXT ) ) );
+
+    panel_sizer->Add( button_add, 0, wxEXPAND );
+    panel_sizer->Add( button_del, 0, wxEXPAND );
+    panel_sizer->Add( button_clear, 0, wxEXPAND );
+
+    panel_sizer->Add( button_edit, 0, wxEXPAND );
+    panel_sizer->Add( 0, 0, 1 );
+    panel_sizer->Add( button_extract, 0, wxEXPAND );
+
+    panel->SetSizerAndFit( panel_sizer );
+
+    list_ctrl = new wxListView( main_panel, -1,
+                                wxDefaultPosition, wxDefaultSize,
+                                wxLC_REPORT | wxSUNKEN_BORDER );
+    list_ctrl->InsertColumn( 0, wxU(_("Description")) );
+    list_ctrl->SetColumnWidth( 0, 240 );
+    list_ctrl->InsertColumn( 1, wxU(_("Size offset")) );
+    list_ctrl->InsertColumn( 2, wxU(_("Time offset")) );
+
+    sizer->Add( panel, 0, wxEXPAND | wxALL, 1 );
+    sizer->Add( list_ctrl, 1, wxEXPAND | wxALL, 1 );
+    main_panel->SetSizer( sizer );
+
+    main_sizer->Add( main_panel, 1, wxEXPAND );
+    SetSizer( main_sizer );
+
+    playlist_t *p_playlist =
+        (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                       FIND_ANYWHERE );
+    if( p_playlist )
+    {
+       /* Some global changes happened -> Rebuild all */
+       var_AddCallback( p_playlist, "playlist-current",
+                        PlaylistChanged, this );
+       vlc_object_release( p_playlist );
+    }
+}
+
+BookmarksDialog::~BookmarksDialog()
+{
+    playlist_t *p_playlist =
+        (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                       FIND_ANYWHERE );
+    if( p_playlist )
+    {
+       var_DelCallback( p_playlist, "playlist-current",
+                        PlaylistChanged, this );
+       vlc_object_release( p_playlist );
+    }
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+//wxFrame *BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent )
+//{
+//    return new class BookmarksDialog( p_intf, p_parent );
+//}
+
+void BookmarksDialog::Update()
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+    seekpoint_t **pp_bookmarks;
+    int i_bookmarks;
+
+    list_ctrl->DeleteAllItems();
+    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
+                       &i_bookmarks ) != VLC_SUCCESS )
+    {
+        vlc_object_release( p_input );
+        return;
+    }
+
+    for( int i = 0; i < i_bookmarks; i++ )
+    {
+        list_ctrl->InsertItem( i, wxL2U( pp_bookmarks[i]->psz_name ) );
+        /* FIXME: see if we can use the 64 bits integer format string */
+        list_ctrl->SetItem( i, 1, wxString::Format(wxT("%d"),
+                            (int)(pp_bookmarks[i]->i_byte_offset) ) );
+        list_ctrl->SetItem( i, 2, wxString::Format(wxT("%d"),
+                            (int)(pp_bookmarks[i]->i_time_offset / 1000000) ) );
+    }
+
+    vlc_object_release( p_input );
+}
+
+bool BookmarksDialog::Show( bool show )
+{
+    Update();
+    return wxFrame::Show( show );
+}
+
+void BookmarksDialog::OnClose( wxCloseEvent& event )
+{
+    Hide();
+}
+
+void BookmarksDialog::OnAdd( wxCommandEvent& event )
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+    seekpoint_t bookmark;
+    vlc_value_t pos;
+    bookmark.psz_name = NULL;
+    bookmark.i_byte_offset = 0;
+    bookmark.i_time_offset = 0;
+
+    var_Get( p_input, "position", &pos );
+    bookmark.psz_name = NULL;
+    input_Control( p_input, INPUT_GET_BYTE_POSITION, &bookmark.i_byte_offset );
+    var_Get( p_input, "time", &pos );
+    bookmark.i_time_offset = pos.i_time;
+    input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
+    vlc_object_release( p_input );
+
+    Update();
+}
+
+void BookmarksDialog::OnDel( wxCommandEvent& event )
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+    int i_focused = list_ctrl->GetFocusedItem();
+    if( i_focused >= 0 )
+    {
+        input_Control( p_input, INPUT_DEL_BOOKMARK, i_focused );
+    }
+
+    vlc_object_release( p_input );
+
+    Update();
+}
+
+void BookmarksDialog::OnClear( wxCommandEvent& event )
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+    input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
+
+    vlc_object_release( p_input );
+
+    Update();
+}
+
+void BookmarksDialog::OnExtract( wxCommandEvent& event )
+{
+    long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
+                                          wxLIST_STATE_SELECTED );
+    long i_second = list_ctrl->GetNextItem( i_first, wxLIST_NEXT_ALL,
+                                          wxLIST_STATE_SELECTED );
+
+    if( i_first == -1 || i_second == -1 )
+    {
+        wxMessageBox( wxU(_("You must select two bookmarks") ),
+                      wxU(_("Invalid selection") ), wxICON_WARNING | wxOK,
+                      this );
+        return;
+    }
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input )
+    {
+        wxMessageBox( wxU(_("The stream must be playing or paused for "
+                            "bookmarks to work" ) ), wxU(_("No input found")),
+                            wxICON_WARNING | wxOK,
+                            this );
+        return;
+    }
+
+    seekpoint_t **pp_bookmarks;
+    int i_bookmarks ;
+
+    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
+                       &i_bookmarks ) != VLC_SUCCESS )
+    {
+        vlc_object_release( p_input );
+        return;
+    }
+
+    if( i_first < i_bookmarks && i_second <= i_bookmarks )
+    {
+        WizardDialog *p_wizard_dialog = new WizardDialog( p_intf, this,
+                               p_input->input.p_item->psz_uri,
+                               pp_bookmarks[i_first]->i_time_offset/1000000,
+                               pp_bookmarks[i_second]->i_time_offset/1000000 );
+        vlc_object_release( p_input );
+        if( p_wizard_dialog )
+        {
+            p_wizard_dialog->Run();
+            delete p_wizard_dialog;
+        }
+    }
+    else
+    {
+        vlc_object_release( p_input );
+    }
+}
+
+void BookmarksDialog::OnActivateItem( wxListEvent& event )
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+    input_Control( p_input, INPUT_SET_BOOKMARK, event.GetIndex() );
+
+    vlc_object_release( p_input );
+}
+
+void BookmarksDialog::OnEdit( wxCommandEvent& event )
+{
+    input_thread_t *p_old_input;
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( !p_input ) return;
+
+
+    seekpoint_t **pp_bookmarks;
+    int i_bookmarks;
+
+    if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
+                       &i_bookmarks ) != VLC_SUCCESS )
+    {
+        vlc_object_release( p_input );
+        return;
+    }
+    p_old_input = p_input;
+    vlc_object_release( p_input );
+
+    long i_first = list_ctrl->GetNextItem( -1, wxLIST_NEXT_ALL,
+                                               wxLIST_STATE_SELECTED );
+
+    if( i_first > -1 && i_first <= i_bookmarks )
+    {
+        BookmarkEditDialog *p_bmk_edit;
+        p_bmk_edit = new BookmarkEditDialog( p_intf, this,
+                                             pp_bookmarks[i_first]);
+
+        if( p_bmk_edit->ShowModal() == wxID_OK )
+        {
+            p_input =(input_thread_t *)vlc_object_find( p_intf,
+                            VLC_OBJECT_INPUT, FIND_ANYWHERE );
+           if( !p_input )
+           {
+                wxMessageBox( wxU( _("No input found. The stream must be "
+                                  "playing or paused for bookmarks to work.") ),
+                              wxU( _("No input") ), wxICON_WARNING | wxOK,
+                              this );
+                return;
+           }
+           if( p_old_input != p_input )
+           {
+                wxMessageBox( wxU( _("Input has changed, unable to save "
+                                  "bookmark. Use \"pause\" while editing "
+                                  "bookmarks to keep the same input.") ),
+                              wxU( _("Input has changed ") ),
+                              wxICON_WARNING | wxOK, this );
+                vlc_object_release( p_input );
+                return;
+
+           }
+           if( input_Control( p_input, INPUT_CHANGE_BOOKMARK,
+                              p_bmk_edit->p_seekpoint, i_first ) !=
+               VLC_SUCCESS )
+           {
+               vlc_object_release( p_input );
+               return;
+           }
+           Update();
+           vlc_object_release( p_input );
+        }
+    }
+}
+
+
+void BookmarksDialog::OnUpdate( wxCommandEvent &event )
+{
+    Update();
+}
+
+/*****************************************************************************
+ * PlaylistChanged: callback triggered by the intf-change playlist variable
+ *  We don't rebuild the playlist directly here because we don't want the
+ *  caller to block for a too long time.
+ *****************************************************************************/
+static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
+                            vlc_value_t oval, vlc_value_t nval, void *param )
+{
+    class BookmarksDialog *p_dialog = (class BookmarksDialog *)param;
+
+    wxCommandEvent bookmarks_event( wxEVT_BOOKMARKS, 0 );
+    p_dialog->AddPendingEvent( bookmarks_event );
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/gui/wxwidgets/dialogs/bookmarks.hpp b/modules/gui/wxwidgets/dialogs/bookmarks.hpp
new file mode 100644 (file)
index 0000000..e65820b
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * bookmarks.hpp: Headers for the bookmarks window
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12670 2005-09-25 11:16:31Z zorglub $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_BOOKMARKS_H_
+#define _WXVLC_BOOKMARKS_H_
+
+#include "wxwidgets.hpp"
+
+namespace wxvlc
+{
+    class BookmarksDialog: public wxFrame
+    {
+    public:
+        /* Constructor */
+        BookmarksDialog( intf_thread_t *p_intf, wxWindow *p_parent );
+        virtual ~BookmarksDialog();
+
+        bool Show( bool );
+
+    private:
+        void Update();
+
+        /* Event handlers (these functions should _not_ be virtual) */
+        void OnClose( wxCloseEvent& event );
+        void OnAdd( wxCommandEvent& event );
+        void OnDel( wxCommandEvent& event );
+        void OnClear( wxCommandEvent& event );
+        void OnActivateItem( wxListEvent& event );
+        void OnUpdate( wxCommandEvent &event );
+        void OnEdit( wxCommandEvent& event );
+        void OnExtract( wxCommandEvent& event );
+
+        DECLARE_EVENT_TABLE();
+
+        intf_thread_t *p_intf;
+        wxWindow *p_parent;
+
+        wxListView *list_ctrl;
+    };
+
+    class BookmarkEditDialog : public wxDialog
+    {
+    public:
+        /* Constructor */
+        BookmarkEditDialog( intf_thread_t *p_intf, wxWindow *p_parent,
+                            seekpoint_t *p_seekpoint );
+        virtual ~BookmarkEditDialog();
+        seekpoint_t *p_seekpoint;
+    private:
+        wxTextCtrl *name_text, *time_text, *bytes_text;
+
+        void OnOK( wxCommandEvent& event);
+        void OnCancel( wxCommandEvent& event);
+
+        DECLARE_EVENT_TABLE();
+
+        intf_thread_t *p_intf;
+    };
+};
+
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/fileinfo.cpp b/modules/gui/wxwidgets/dialogs/fileinfo.cpp
new file mode 100644 (file)
index 0000000..dca9de9
--- /dev/null
@@ -0,0 +1,186 @@
+/*****************************************************************************
+ * fileinfo.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "dialogs/fileinfo.hpp"
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+static int ItemChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Close_Event
+};
+
+BEGIN_EVENT_TABLE(FileInfo, wxFrame)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, FileInfo::OnButtonClose)
+
+    /* Hide the window when the user closes the window */
+    EVT_CLOSE(FileInfo::OnClose)
+
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+FileInfo::FileInfo( intf_thread_t *_p_intf, wxWindow *p_parent ):
+    wxFrame( p_parent, -1, wxU(_("Stream and media info")), wxDefaultPosition,
+             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    playlist_t *p_playlist;
+
+    /* Initializations */
+    p_intf = _p_intf;
+    SetIcon( *p_intf->p_sys->p_icon );
+    SetAutoLayout( TRUE );
+
+    /* Create a panel to put everything in */
+    wxPanel *panel = new wxPanel( this, -1 );
+    panel->SetAutoLayout( TRUE );
+
+    fileinfo_tree =
+        new wxTreeCtrl( panel, -1, wxDefaultPosition, wxSize( 350, 350 ),
+                        wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxSUNKEN_BORDER );
+
+    fileinfo_root_label = wxT("");
+
+    /* Place everything in sizers */
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( fileinfo_tree, 1, wxEXPAND | wxALL, 5 );
+    panel_sizer->Layout();
+    panel->SetSizerAndFit( panel_sizer );
+    main_sizer->Add( panel, 1, wxEXPAND, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+
+    p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                FIND_ANYWHERE );
+
+    if( p_playlist )
+    {
+        var_AddCallback( p_playlist, "item-change", ItemChanged, this );
+        vlc_object_release( p_playlist );
+    }
+
+    b_need_update = VLC_TRUE;
+    UpdateFileInfo();
+}
+
+void FileInfo::UpdateFileInfo()
+{
+    input_thread_t *p_input =
+        (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+
+    if( !p_input || p_input->b_dead || !p_input->input.p_item->psz_name )
+    {
+        if( fileinfo_root )
+        {
+            fileinfo_root_label = wxT("");
+            fileinfo_tree->DeleteChildren( fileinfo_root );
+        }
+        if (p_input)
+        {
+            vlc_object_release(p_input);
+        }
+        return;
+    }
+
+    if( !fileinfo_root )
+    {
+        /* On linux, the first argument of wxTreeCtrl::AddRoot() can be
+         * retrieved with the GetItemText() method, but it doesn't work on
+         * Windows when the wxTR_HIDE_ROOT style is set. That's why we need to
+         * use the fileinfo_root_label variable... */
+        fileinfo_root =
+            fileinfo_tree->AddRoot( wxL2U(p_input->input.p_item->psz_name) );
+        fileinfo_root_label = wxL2U(p_input->input.p_item->psz_name);
+    }
+    else if( fileinfo_root_label == wxL2U(p_input->input.p_item->psz_name) &&
+             b_need_update == VLC_FALSE )
+    {
+        vlc_object_release(p_input);
+        return;
+    }
+
+    /* We rebuild the tree from scratch */
+    fileinfo_tree->DeleteChildren( fileinfo_root );
+    fileinfo_root_label = wxL2U(p_input->input.p_item->psz_name);
+
+    vlc_mutex_lock( &p_input->input.p_item->lock );
+    for( int i = 0; i < p_input->input.p_item->i_categories; i++ )
+    {
+        info_category_t *p_cat = p_input->input.p_item->pp_categories[i];
+
+        wxTreeItemId cat = fileinfo_tree->AppendItem( fileinfo_root,
+                                                      wxU(p_cat->psz_name) );
+        for( int j = 0; j < p_cat->i_infos; j++ )
+        {
+            info_t *p_info = p_cat->pp_infos[j];
+
+            if( p_info->psz_value[0] != 0 )
+            /* We only wanna show fields that have an actual value */
+            {
+                fileinfo_tree->AppendItem( cat, (wxString)wxU(p_info->psz_name)
+                                        + wxT(": ") + wxU(p_info->psz_value) );
+            }
+        }
+        fileinfo_tree->Expand( cat );
+    }
+    vlc_mutex_unlock( &p_input->input.p_item->lock );
+
+    b_need_update = VLC_FALSE;
+
+    vlc_object_release(p_input);
+    return;
+}
+
+FileInfo::~FileInfo()
+{
+}
+
+void FileInfo::OnButtonClose( wxCommandEvent& event )
+{
+    wxCloseEvent cevent;
+    OnClose(cevent);
+}
+
+void FileInfo::OnClose( wxCloseEvent& WXUNUSED(event) )
+{
+    Hide();
+}
+
+static int ItemChanged( vlc_object_t *p_this, const char *psz_var,
+                        vlc_value_t oldval, vlc_value_t newval, void *param )
+{
+    FileInfo *p_fileinfo = (FileInfo *)param;
+    p_fileinfo->b_need_update = VLC_TRUE;
+    return VLC_SUCCESS;
+}
diff --git a/modules/gui/wxwidgets/dialogs/fileinfo.hpp b/modules/gui/wxwidgets/dialogs/fileinfo.hpp
new file mode 100644 (file)
index 0000000..8f6feb1
--- /dev/null
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * fileinfo.hpp: private wxWindows interface description
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12502 2005-09-09 19:38:01Z gbazin $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_FILEINFO_H_
+#define _WXVLC_FILEINFO_H_
+
+#include "wxwidgets.hpp"
+
+#include <wx/treectrl.h>
+
+namespace wxvlc
+{
+    class FileInfo: public wxFrame
+    {
+    public:
+        /* Constructor */
+        FileInfo( intf_thread_t *p_intf, wxWindow *p_parent );
+        virtual ~FileInfo();
+        void UpdateFileInfo();
+
+        vlc_bool_t b_need_update;
+
+    private:
+        void OnButtonClose( wxCommandEvent& event );
+        void OnClose( wxCloseEvent& WXUNUSED(event) );
+
+        DECLARE_EVENT_TABLE();
+
+        intf_thread_t *p_intf;
+        wxTreeCtrl *fileinfo_tree;
+        wxTreeItemId fileinfo_root;
+        wxString fileinfo_root_label;
+    };
+};
+
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/iteminfo.cpp b/modules/gui/wxwidgets/dialogs/iteminfo.cpp
new file mode 100644 (file)
index 0000000..3e410eb
--- /dev/null
@@ -0,0 +1,204 @@
+/*****************************************************************************
+ * iteminfo.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Clément Stenac <zorglub@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "dialogs/iteminfo.hpp"
+#include <wx/combobox.h>
+#include <wx/statline.h>
+
+#ifndef wxRB_SINGLE
+#   define wxRB_SINGLE 0
+#endif
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Uri_Event,
+    Name_Event,
+    Enabled_Event,
+};
+
+BEGIN_EVENT_TABLE(ItemInfoDialog, wxDialog)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, ItemInfoDialog::OnOk)
+    EVT_BUTTON(wxID_CANCEL, ItemInfoDialog::OnCancel)
+
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+ItemInfoDialog::ItemInfoDialog( intf_thread_t *_p_intf,
+                                playlist_item_t *_p_item,
+                                wxWindow* _p_parent ):
+    wxDialog( _p_parent, -1, wxU(_("Playlist item info")),
+             wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    p_parent = _p_parent;
+    p_item = _p_item;
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    /* Create a panel to put everything in */
+    wxPanel *panel = new wxPanel( this, -1 );
+    panel->SetAutoLayout( TRUE );
+
+    /* Create the standard info panel */
+    wxPanel *info_panel = InfoPanel( panel );
+
+    /* Separation */
+    wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
+
+    /* Create the buttons */
+    wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
+    ok_button->SetDefault();
+    wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
+                                            wxU(_("Cancel")) );
+
+    /* Place everything in sizers */
+    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+    button_sizer->Add( ok_button, 0, wxALL, 5 );
+    button_sizer->Add( cancel_button, 0, wxALL, 5 );
+    button_sizer->Layout();
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( info_panel, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
+                      wxALL, 5 );
+    panel_sizer->Layout();
+    panel->SetSizerAndFit( panel_sizer );
+    main_sizer->Add( panel, 1, wxGROW, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+}
+
+ItemInfoDialog::~ItemInfoDialog()
+{
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+wxPanel *ItemInfoDialog::InfoPanel( wxWindow* parent )
+{
+    wxPanel *info_panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxDefaultSize );
+    info_panel->SetAutoLayout( TRUE );
+    wxBoxSizer *info_sizer = new wxBoxSizer( wxHORIZONTAL );
+
+    /* Create a box to surround the controls */
+    wxStaticBox *panel_box = new wxStaticBox( info_panel, -1,
+                                   wxU(_("Item Info")) );
+
+    wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( panel_box,
+                                                          wxVERTICAL );
+
+    wxFlexGridSizer *sizer = new wxFlexGridSizer(2,3,20);
+    /* URI Textbox */
+    wxStaticText *uri_label =
+           new wxStaticText( info_panel, -1, wxU(_("URI")) );
+
+    uri_text = new wxTextCtrl( info_panel, Uri_Event,
+        wxU(p_item->input.psz_uri), wxDefaultPosition, wxSize( 300, -1 ),
+        wxTE_PROCESS_ENTER );
+
+    sizer->Add( uri_label, 0 , wxALIGN_LEFT |wxALL , 5 );
+    sizer->Add( uri_text, 1 , wxALIGN_RIGHT | wxALL , 5 );
+
+    /* Name Textbox */
+    wxStaticText *name_label =
+           new wxStaticText(  info_panel, -1, wxU(_("Name")) );
+
+    name_text = new wxTextCtrl( info_panel, Uri_Event,
+        wxU(p_item->input.psz_name), wxDefaultPosition, wxSize( 300, -1 ),
+        wxTE_PROCESS_ENTER );
+
+    sizer->Add( name_label, 0 , wxALIGN_LEFT |wxALL , 5  );
+    sizer->Add( name_text, 1 , wxALIGN_RIGHT | wxALL , 5 );
+
+    /* Treeview */
+    info_tree = new wxTreeCtrl( info_panel, -1, wxDefaultPosition,
+                                wxSize(220,200),
+                                wxSUNKEN_BORDER |wxTR_HAS_BUTTONS |
+                                wxTR_HIDE_ROOT );
+
+    sizer->Layout();
+    box_sizer->Add( sizer, 0, wxEXPAND, 5 );
+    box_sizer->Add( info_tree, 0, wxEXPAND, 5 );
+    info_sizer->Add( box_sizer, 1, wxBOTTOM, 5 );
+
+    info_panel->SetSizer( info_sizer );
+    info_sizer->Layout();
+    info_sizer->SetSizeHints( info_panel );
+
+    UpdateInfo();
+
+    return info_panel;
+}
+
+void ItemInfoDialog::UpdateInfo()
+{
+    if( !info_root )
+    {
+       info_root = info_tree->AddRoot( wxU( p_item->input.psz_name) );
+    }
+
+    /* Rebuild the tree */
+    for( int i = 0; i< p_item->input.i_categories ; i++)
+    {
+        wxTreeItemId cat = info_tree->AppendItem( info_root,
+                            wxU( p_item->input.pp_categories[i]->psz_name) );
+
+        for( int j = 0 ; j < p_item->input.pp_categories[i]->i_infos ; j++ )
+        {
+           info_tree->AppendItem( cat , (wxString)
+               wxU(p_item->input.pp_categories[i]->pp_infos[j]->psz_name) +
+               wxT(": ") +
+               wxU(p_item->input.pp_categories[i]->pp_infos[j]->psz_value) );
+        }
+
+        info_tree->Expand( cat );
+    }
+}
+
+/*****************************************************************************
+ * Events methods.
+ *****************************************************************************/
+void ItemInfoDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
+{
+    vlc_mutex_lock( &p_item->input.lock );
+    p_item->input.psz_name = strdup( name_text->GetLineText(0).mb_str() );
+    p_item->input.psz_uri = strdup( uri_text->GetLineText(0).mb_str() );
+    vlc_mutex_unlock( &p_item->input.lock );
+    EndModal( wxID_OK );
+}
+
+void ItemInfoDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
+{
+    EndModal( wxID_CANCEL );
+}
diff --git a/modules/gui/wxwidgets/dialogs/iteminfo.hpp b/modules/gui/wxwidgets/dialogs/iteminfo.hpp
new file mode 100644 (file)
index 0000000..ca453a1
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * iteminfo.hpp: private wxWindows interface description
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12502 2005-09-09 19:38:01Z gbazin $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_ITEMINFO_H_
+#define _WXVLC_ITEMINFO_H_
+
+#include "wxwidgets.hpp"
+
+#include <wx/treectrl.h>
+
+namespace wxvlc
+{
+class ItemInfoDialog: public wxDialog
+{
+public:
+    /* Constructor */
+    ItemInfoDialog( intf_thread_t *p_intf, playlist_item_t *_p_item,
+                    wxWindow *p_parent );
+    virtual ~ItemInfoDialog();
+
+    wxArrayString GetOptions();
+
+private:
+    wxPanel *InfoPanel( wxWindow* parent );
+    wxPanel *GroupPanel( wxWindow* parent );
+
+    /* Event handlers (these functions should _not_ be virtual) */
+    void OnOk( wxCommandEvent& event );
+    void OnCancel( wxCommandEvent& event );
+
+    void UpdateInfo();
+
+    DECLARE_EVENT_TABLE();
+
+    intf_thread_t *p_intf;
+    playlist_item_t *p_item;
+    wxWindow *p_parent;
+
+    /* Controls for the iteminfo dialog box */
+    wxPanel *info_subpanel;
+    wxPanel *info_panel;
+
+    wxPanel *group_subpanel;
+    wxPanel *group_panel;
+
+    wxTextCtrl *uri_text;
+    wxTextCtrl *name_text;
+
+    wxTreeCtrl *info_tree;
+    wxTreeItemId info_root;
+
+};
+
+};
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/messages.cpp b/modules/gui/wxwidgets/dialogs/messages.cpp
new file mode 100644 (file)
index 0000000..5b0b12b
--- /dev/null
@@ -0,0 +1,216 @@
+/*****************************************************************************
+ * messages.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "dialogs/messages.hpp"
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Close_Event,
+    Clear_Event,
+    Save_Log_Event
+};
+
+BEGIN_EVENT_TABLE(Messages, wxFrame)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, Messages::OnButtonClose)
+    EVT_BUTTON(wxID_CLEAR, Messages::OnClear)
+    EVT_BUTTON(wxID_SAVEAS, Messages::OnSaveLog)
+
+    /* Special events : we don't want to destroy the window when the user
+     * clicks on (X) */
+    EVT_CLOSE(Messages::OnClose)
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+Messages::Messages( intf_thread_t *_p_intf, wxWindow *p_parent ):
+    wxFrame( p_parent, -1, wxU(_("Messages")), wxDefaultPosition,
+             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    b_verbose = VLC_FALSE;
+    SetIcon( *p_intf->p_sys->p_icon );
+    save_log_dialog = NULL;
+    b_verbose = VLC_FALSE;
+
+    /* Create a panel to put everything in */
+    wxPanel *messages_panel = new wxPanel( this, -1 );
+    messages_panel->SetAutoLayout( TRUE );
+
+    /* Create the textctrl and some text attributes */
+    textctrl = new wxTextCtrl( messages_panel, -1, wxT(""), wxDefaultPosition,
+        wxSize::wxSize( 400, 500 ), wxTE_MULTILINE | wxTE_READONLY |
+                                    wxTE_RICH | wxTE_NOHIDESEL );
+    info_attr = new wxTextAttr( wxColour::wxColour( 0, 128, 0 ) );
+    err_attr = new wxTextAttr( *wxRED );
+    warn_attr = new wxTextAttr( *wxBLUE );
+    dbg_attr = new wxTextAttr( *wxBLACK );
+
+    /* Create the OK button */
+    wxButton *ok_button = new wxButton( messages_panel, wxID_OK,
+                                        wxU(_("Close")));
+    ok_button->SetDefault();
+
+    /* Create the Clear button */
+    wxButton *clear_button = new wxButton( messages_panel, wxID_CLEAR,
+                                           wxU(_("Clear")));
+    clear_button->SetDefault();
+
+    /* Create the Save Log button */
+    wxButton *save_log_button = new wxButton( messages_panel, wxID_SAVEAS,
+                                              wxU(_("Save As...")));
+    save_log_button->SetDefault();
+
+    /* Place everything in sizers */
+    wxBoxSizer *buttons_sizer = new wxBoxSizer( wxHORIZONTAL );
+    buttons_sizer->Add( ok_button, 0, wxEXPAND |wxALIGN_LEFT| wxALL, 5 );
+    buttons_sizer->Add( clear_button, 0, wxEXPAND |wxALIGN_LEFT| wxALL, 5 );
+    buttons_sizer->Add( save_log_button, 0, wxEXPAND |wxALIGN_LEFT| wxALL, 5 );
+    buttons_sizer->Add( new wxPanel( this, -1 ), 1, wxALL, 5 );
+    buttons_sizer->Layout();
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( textctrl, 1, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( buttons_sizer, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Layout();
+    messages_panel->SetSizerAndFit( panel_sizer );
+    main_sizer->Add( messages_panel, 1, wxGROW, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+}
+
+Messages::~Messages()
+{
+    /* Clean up */
+    if( save_log_dialog ) delete save_log_dialog;
+
+    delete info_attr;
+    delete err_attr;
+    delete warn_attr;
+    delete dbg_attr;
+}
+
+bool Messages::Show( bool show )
+{
+    b_verbose = show;
+    return wxFrame::Show( show );
+}
+
+void Messages::UpdateLog()
+{
+    msg_subscription_t *p_sub = p_intf->p_sys->p_sub;
+    int i_start;
+
+    vlc_mutex_lock( p_sub->p_lock );
+    int i_stop = *p_sub->pi_stop;
+    vlc_mutex_unlock( p_sub->p_lock );
+
+
+    if( p_sub->i_start != i_stop )
+    {
+        textctrl->SetInsertionPointEnd();
+
+        for( i_start = p_sub->i_start;
+             i_start != i_stop;
+             i_start = (i_start+1) % VLC_MSG_QSIZE )
+        {
+
+            if( !b_verbose &&
+                VLC_MSG_ERR != p_sub->p_msg[i_start].i_type )
+                continue;
+
+            /* Append all messages to log window */
+            textctrl->SetDefaultStyle( *dbg_attr );
+            (*textctrl) << wxL2U(p_sub->p_msg[i_start].psz_module);
+
+            switch( p_sub->p_msg[i_start].i_type )
+            {
+            case VLC_MSG_INFO:
+                (*textctrl) << wxT(": ");
+                textctrl->SetDefaultStyle( *info_attr );
+                break;
+            case VLC_MSG_ERR:
+                (*textctrl) << wxT(" error: ");
+                textctrl->SetDefaultStyle( *err_attr );
+                break;
+            case VLC_MSG_WARN:
+                (*textctrl) << wxT(" warning: ");
+                textctrl->SetDefaultStyle( *warn_attr );
+                break;
+            case VLC_MSG_DBG:
+            default:
+                (*textctrl) << wxT(" debug: ");
+                break;
+            }
+
+            /* Add message */
+            (*textctrl) << wxL2U(p_sub->p_msg[i_start].psz_msg) << wxT("\n");
+        }
+
+        vlc_mutex_lock( p_sub->p_lock );
+        p_sub->i_start = i_start;
+        vlc_mutex_unlock( p_sub->p_lock );
+    }
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+void Messages::OnButtonClose( wxCommandEvent& WXUNUSED(event) )
+{
+    wxCloseEvent cevent;
+    OnClose(cevent);
+}
+
+void Messages::OnClose( wxCloseEvent& WXUNUSED(event) )
+{
+    Hide();
+}
+
+void Messages::OnClear( wxCommandEvent& WXUNUSED(event) )
+{
+    textctrl->Clear();
+}
+
+void Messages::OnSaveLog( wxCommandEvent& WXUNUSED(event) )
+{
+    if( save_log_dialog == NULL )
+        save_log_dialog = new wxFileDialog( this,
+            wxU(_("Save Messages As...")),
+            wxT(""), wxT("messages"), wxT("*"), wxSAVE | wxOVERWRITE_PROMPT );
+
+    if( save_log_dialog && save_log_dialog->ShowModal() == wxID_OK )
+    {
+        if( !textctrl->SaveFile( save_log_dialog->GetPath() ) )
+        {
+            // [FIX ME] should print an error message
+        }
+    }
+}
diff --git a/modules/gui/wxwidgets/dialogs/messages.hpp b/modules/gui/wxwidgets/dialogs/messages.hpp
new file mode 100644 (file)
index 0000000..7aa0be7
--- /dev/null
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * messages.hpp: Messages dialog
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12670 2005-09-25 11:16:31Z zorglub $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_MESSAGES_H_
+#define _WXVLC_MESSAGES_H_
+
+#include "wxwidgets.hpp"
+
+namespace wxvlc
+{
+    class Messages: public wxFrame
+    {
+    public:
+        /* Constructor */
+        Messages( intf_thread_t *p_intf, wxWindow *p_parent );
+        virtual ~Messages();
+        bool Show( bool show = TRUE );
+        void UpdateLog();
+
+    private:
+        /* Event handlers (these functions should _not_ be virtual) */
+        void OnButtonClose( wxCommandEvent& event );
+        void OnClose( wxCloseEvent& WXUNUSED(event) );
+        void OnClear( wxCommandEvent& event );
+        void OnSaveLog( wxCommandEvent& event );
+
+        DECLARE_EVENT_TABLE();
+
+        intf_thread_t *p_intf;
+        wxTextCtrl *textctrl;
+        wxTextAttr *info_attr;
+        wxTextAttr *err_attr;
+        wxTextAttr *warn_attr;
+        wxTextAttr *dbg_attr;
+
+        wxFileDialog *save_log_dialog;
+
+        vlc_bool_t b_verbose;
+    };
+};
+
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/open.cpp b/modules/gui/wxwidgets/dialogs/open.cpp
new file mode 100644 (file)
index 0000000..6a75bba
--- /dev/null
@@ -0,0 +1,1871 @@
+/*****************************************************************************
+ * open.cpp : Open dialog box
+ *****************************************************************************
+ * Copyright (C) 2000-2005 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "dialogs/open.hpp"
+#include "dialogs/streamout.hpp"
+#include "dialogs/preferences_widgets.h"
+#include "dialogs/subtitles.hpp"
+
+#include "charset.h"
+
+#ifdef HAVE_LIBCDIO
+#include <cdio/cdio.h>
+#include <cdio/cd_types.h>
+#include <cdio/logging.h>
+#endif /* HAVE_LIBCDIO */
+
+#ifdef HAVE_VCDINFO
+#include <libvcd/version.h>
+/* There was a bug in libvcdinfo <= 23 which prevented C++ compilation */
+#if LIBVCD_VERSION_NUM > 23
+#include <libvcd/info.h>
+#endif /* LIBVCD_VERSION_NUM > 23 */
+#endif /* HAVE_VCDINFO */
+
+#include <wx/combobox.h>
+#include <wx/statline.h>
+#include <wx/tokenzr.h>
+
+#include <vector>
+
+
+#ifndef wxRB_SINGLE
+#   define wxRB_SINGLE 0
+#endif
+
+#define SELECTION_DISC_TYPE_DVD_MENUS 0
+#define SELECTION_DISC_TYPE_DVD       1
+#define SELECTION_DISC_TYPE_VCD       2
+#define SELECTION_DISC_TYPE_CDDA      3
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Notebook_Event = wxID_HIGHEST,
+    MRL_Event,
+
+    FileBrowse_Event,
+    FileName_Event,
+
+    DiscType_Event,
+#ifdef HAVE_LIBCDIO
+    DiscProbe_Event,
+#endif
+    DiscDevice_Event,
+    DiscTitle_Event,
+    DiscChapter_Event,
+    DiscSub_Event,
+    DiscAudio_Event,
+
+    NetType_Event,
+    NetRadio1_Event, NetRadio2_Event, NetRadio3_Event, NetRadio4_Event,
+    NetPort1_Event, NetPort2_Event, NetPort3_Event,
+    NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
+    NetForceIPv6_Event, NetTimeshift_Event,
+
+    SubsFileEnable_Event,
+    SubsFileSettings_Event,
+
+    SoutEnable_Event,
+    SoutSettings_Event,
+
+    CachingEnable_Event,
+    CachingChange_Event,
+
+    AdvancedOptions_Event
+};
+
+BEGIN_EVENT_TABLE(OpenDialog, wxDialog)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, OpenDialog::OnOk)
+    EVT_BUTTON(wxID_CANCEL, OpenDialog::OnCancel)
+
+    EVT_NOTEBOOK_PAGE_CHANGED(Notebook_Event, OpenDialog::OnPageChange)
+
+    EVT_TEXT(MRL_Event, OpenDialog::OnMRLChange)
+
+    /* Events generated by the file panel */
+    EVT_TEXT(FileName_Event, OpenDialog::OnFilePanelChange)
+    EVT_BUTTON(FileBrowse_Event, OpenDialog::OnFileBrowse)
+
+    /* Events generated by the disc panel */
+    EVT_RADIOBOX(DiscType_Event, OpenDialog::OnDiscTypeChange)
+#ifdef HAVE_LIBCDIO
+    EVT_CHECKBOX(DiscProbe_Event, OpenDialog::OnDiscProbe)
+#endif
+    EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscDeviceChange)
+    EVT_TEXT(DiscDevice_Event, OpenDialog::OnDiscPanelChange)
+    EVT_TEXT(DiscTitle_Event, OpenDialog::OnDiscPanelChange)
+    EVT_SPINCTRL(DiscTitle_Event, OpenDialog::OnDiscPanelChangeSpin)
+    EVT_TEXT(DiscChapter_Event, OpenDialog::OnDiscPanelChange)
+    EVT_SPINCTRL(DiscChapter_Event, OpenDialog::OnDiscPanelChangeSpin)
+    EVT_TEXT(DiscSub_Event, OpenDialog::OnDiscPanelChange)
+    EVT_TEXT(DiscAudio_Event, OpenDialog::OnDiscPanelChange)
+    EVT_SPINCTRL(DiscSub_Event, OpenDialog::OnDiscPanelChangeSpin)
+
+    /* Events generated by the net panel */
+    EVT_RADIOBUTTON(NetRadio1_Event, OpenDialog::OnNetTypeChange)
+    EVT_RADIOBUTTON(NetRadio2_Event, OpenDialog::OnNetTypeChange)
+    EVT_RADIOBUTTON(NetRadio3_Event, OpenDialog::OnNetTypeChange)
+    EVT_RADIOBUTTON(NetRadio4_Event, OpenDialog::OnNetTypeChange)
+    EVT_TEXT(NetPort1_Event, OpenDialog::OnNetPanelChange)
+    EVT_SPINCTRL(NetPort1_Event, OpenDialog::OnNetPanelChangeSpin)
+    EVT_TEXT(NetPort2_Event, OpenDialog::OnNetPanelChange)
+    EVT_SPINCTRL(NetPort2_Event, OpenDialog::OnNetPanelChangeSpin)
+    EVT_TEXT(NetPort3_Event, OpenDialog::OnNetPanelChange)
+    EVT_SPINCTRL(NetPort3_Event, OpenDialog::OnNetPanelChangeSpin)
+    EVT_TEXT(NetAddr2_Event, OpenDialog::OnNetPanelChange)
+    EVT_TEXT(NetAddr3_Event, OpenDialog::OnNetPanelChange)
+    EVT_TEXT(NetAddr4_Event, OpenDialog::OnNetPanelChange)
+    EVT_CHECKBOX(NetForceIPv6_Event, OpenDialog::OnNetPanelChange)
+    EVT_CHECKBOX(NetTimeshift_Event, OpenDialog::OnNetPanelChange)
+
+    /* Events generated by the subtitle file buttons */
+    EVT_CHECKBOX(SubsFileEnable_Event, OpenDialog::OnSubsFileEnable)
+    EVT_BUTTON(SubsFileSettings_Event, OpenDialog::OnSubsFileSettings)
+
+    /* Events generated by the stream output buttons */
+    EVT_CHECKBOX(SoutEnable_Event, OpenDialog::OnSoutEnable)
+    EVT_BUTTON(SoutSettings_Event, OpenDialog::OnSoutSettings)
+
+    /* Events generated by the caching button */
+    EVT_CHECKBOX(CachingEnable_Event, OpenDialog::OnCachingEnable)
+    EVT_TEXT(CachingChange_Event, OpenDialog::OnCachingChange)
+    EVT_SPINCTRL(CachingChange_Event, OpenDialog::OnCachingChangeSpin)
+
+    /* Hide the window when the user closes the window */
+    EVT_CLOSE(OpenDialog::OnClose)
+
+END_EVENT_TABLE()
+
+#if 0
+/* Perhaps someday we'll figure out how to add media information to
+   "Stream-and-Media info" when no input thread hasn't been initialized.
+*/
+extern void MediaInsertCDDA( intf_thread_t *_p_intf,  CdIo_t *p_cdio,
+                 track_t i_last_track );
+#endif
+
+/*****************************************************************************
+ * AutoBuiltPanel.
+ *****************************************************************************/
+WX_DEFINE_ARRAY(ConfigControl *, ArrayOfConfigControls);
+
+class AutoBuiltPanel : public wxPanel
+{
+public:
+
+    AutoBuiltPanel() { }
+    AutoBuiltPanel( wxWindow *, OpenDialog *, intf_thread_t *,
+                    const module_t * );
+
+    virtual ~AutoBuiltPanel() {}
+
+    void UpdateAdvancedMRL();
+
+    wxString name;
+    ArrayOfConfigControls config_array;
+    ArrayOfConfigControls advanced_config_array;
+    wxComboBox *p_advanced_mrl_combo;
+
+private:
+    intf_thread_t *p_intf;
+    OpenDialog *p_open_dialog;
+
+    void OnAdvanced( wxCommandEvent& event );
+    wxDialog *p_advanced_dialog;
+
+    DECLARE_EVENT_TABLE();
+};
+
+BEGIN_EVENT_TABLE(AutoBuiltPanel, wxPanel)
+    EVT_BUTTON(AdvancedOptions_Event, AutoBuiltPanel::OnAdvanced)
+END_EVENT_TABLE()
+
+static void AutoBuildCallback( void *p_data )
+{
+    ((OpenDialog *)p_data)->UpdateMRL();
+}
+
+static void AutoBuildAdvancedCallback( void *p_data )
+{
+    ((AutoBuiltPanel *)p_data)->UpdateAdvancedMRL();
+}
+
+AutoBuiltPanel::AutoBuiltPanel( wxWindow *parent, OpenDialog *dialog,
+                                intf_thread_t *_p_intf,
+                                const module_t *p_module )
+  : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize ),
+    name( wxU(p_module->psz_object_name) ),
+    p_advanced_mrl_combo( NULL ),
+    p_intf( _p_intf ), p_open_dialog( dialog ), p_advanced_dialog( NULL )
+{
+    wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
+    module_config_t *p_item = p_module->p_config;
+    bool b_advanced = false;
+
+    if( p_item ) do
+    {
+        if( !(p_item->i_type & CONFIG_HINT) && p_item->b_advanced )
+            b_advanced = true;
+
+        if( p_item->i_type & CONFIG_HINT || p_item->b_advanced )
+            continue;
+
+        ConfigControl *control =
+            CreateConfigControl( VLC_OBJECT(p_intf), p_item, this );
+
+        config_array.Add( control );
+
+        /* Don't add items that were not recognized */
+        if( control == NULL ) continue;
+
+        control->SetUpdateCallback( AutoBuildCallback, (void *)dialog );
+
+        sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
+    }
+    while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+
+    if( b_advanced )
+    {
+        wxButton *button =
+            new wxButton( this, AdvancedOptions_Event,
+                          wxU(_("Advanced options...")) );
+        sizer->Add( button, 0, wxALL, 5 );
+
+        /* Build the advanced dialog */
+        p_advanced_dialog =
+            new wxDialog( this, -1, ((wxString)wxU(_("Advanced options"))) +
+                          wxT(" (") + wxU( p_module->psz_longname ) + wxT(")"),
+                          wxDefaultPosition, wxDefaultSize,
+                          wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER );
+
+        wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
+
+        /* Create MRL combobox */
+        wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
+        wxStaticBox *mrl_box =
+            new wxStaticBox( p_advanced_dialog, -1,
+                             wxU(_("Advanced options")) );
+        wxStaticBoxSizer *mrl_sizer =
+            new wxStaticBoxSizer( mrl_box, wxHORIZONTAL );
+        wxStaticText *mrl_label =
+            new wxStaticText( p_advanced_dialog, -1, wxU(_("Options:")) );
+        p_advanced_mrl_combo =
+            new wxComboBox( p_advanced_dialog, MRL_Event, wxT(""),
+                            wxDefaultPosition, wxDefaultSize );
+        mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
+        mrl_sizer->Add( p_advanced_mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
+        mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
+        sizer->Add( mrl_sizer_sizer, 0, wxEXPAND | wxALL, 2 );
+
+        /* Add advanced options to panel */
+        module_config_t *p_item = p_module->p_config;
+        if( p_item ) do
+        {
+            if( p_item->i_type & CONFIG_HINT || !p_item->b_advanced )
+                continue;
+
+            ConfigControl *control =
+                CreateConfigControl( VLC_OBJECT(p_intf), p_item,
+                                     p_advanced_dialog );
+
+            advanced_config_array.Add( control );
+
+            /* Don't add items that were not recognized */
+            if( control == NULL ) continue;
+
+            control->SetUpdateCallback( AutoBuildAdvancedCallback,
+                                        (void *)this );
+
+            sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
+        }
+        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+
+        /* Separation */
+        wxPanel *dummy_panel = new wxPanel( p_advanced_dialog, -1 );
+        sizer->Add( dummy_panel, 1 );
+        wxStaticLine *static_line =
+            new wxStaticLine( p_advanced_dialog, wxID_OK );
+        sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
+
+        /* Create buttons */
+        wxButton *ok_button =
+            new wxButton( p_advanced_dialog, wxID_OK, wxU(_("OK")) );
+        ok_button->SetDefault();
+        wxButton *cancel_button =
+            new wxButton( p_advanced_dialog, wxID_CANCEL, wxU(_("Cancel")) );
+        wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+        button_sizer->Add( ok_button, 0, wxALL, 5 );
+        button_sizer->Add( cancel_button, 0, wxALL, 5 );
+        button_sizer->Layout();
+        sizer->Add( button_sizer, 0, wxALL, 0 );
+
+        sizer->SetMinSize( 400, -1 );
+        p_advanced_dialog->SetSizerAndFit( sizer );
+    }
+
+    this->SetSizerAndFit( sizer );
+}
+
+void AutoBuiltPanel::OnAdvanced( wxCommandEvent& event )
+{
+    if( p_advanced_dialog->ShowModal() == wxID_OK )
+    {
+        UpdateAdvancedMRL();
+        p_open_dialog->UpdateMRL();
+    }
+}
+
+void AutoBuiltPanel::UpdateAdvancedMRL()
+{
+    wxString mrltemp;
+
+    for( int i = 0; i < (int)advanced_config_array.GetCount(); i++ )
+    {
+        ConfigControl *control = advanced_config_array.Item(i);
+
+        mrltemp += (i ? wxT(" :") : wxT(":"));
+
+        if( control->GetType() == CONFIG_ITEM_BOOL &&
+            !control->GetIntValue() ) mrltemp += wxT("no-");
+
+        mrltemp += control->GetName();
+
+        switch( control->GetType() )
+        {
+        case CONFIG_ITEM_STRING:
+        case CONFIG_ITEM_FILE:
+        case CONFIG_ITEM_DIRECTORY:
+        case CONFIG_ITEM_MODULE:
+            mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
+            break;
+        case CONFIG_ITEM_INTEGER:
+            mrltemp +=
+                wxString::Format( wxT("=%i"), control->GetIntValue() );
+            break;
+        case CONFIG_ITEM_FLOAT:
+            mrltemp +=
+                wxString::Format(wxT("=%f"), control->GetFloatValue());
+            break;
+        }
+    }
+
+    p_advanced_mrl_combo->SetValue( mrltemp );
+}
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
+                        int i_access_method, int i_arg ):
+      wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
+             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    OpenDialog( _p_intf, _p_parent, i_access_method, i_arg, OPEN_NORMAL );
+}
+
+OpenDialog::OpenDialog( intf_thread_t *_p_intf, wxWindow *_p_parent,
+                        int i_access_method, int i_arg, int _i_method ):
+      wxDialog( _p_parent, -1, wxU(_("Open...")), wxDefaultPosition,
+             wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    i_method = _i_method;
+    p_intf = _p_intf;
+    p_parent = _p_parent;
+    SetIcon( *p_intf->p_sys->p_icon );
+    file_dialog = NULL;
+    i_disc_type_selection = 0;
+    i_disc_title = 0;
+    i_open_arg = i_arg;
+
+    sout_dialog = NULL;
+    subsfile_dialog = NULL;
+    b_disc_device_changed = false;
+
+    /* Create a panel to put everything in */
+    wxPanel *panel = new wxPanel( this, -1 );
+    panel->SetAutoLayout( TRUE );
+
+    /* Create MRL combobox */
+    wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
+    wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
+                               wxU(_("Media Resource Locator (MRL)")) );
+    wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
+                                                        wxHORIZONTAL );
+    wxStaticText *mrl_label = new wxStaticText( panel, -1,
+                                                wxU(_("Open:")) );
+    mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
+                                wxPoint(20,25), wxSize(120, -1) );
+    mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
+        "the full MRL you want to open.\n""Alternatively, the field will be "
+        "filled automatically when you use the controls below.")) );
+
+    mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
+    mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
+    mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
+
+
+    /* Create Static Text */
+    wxStaticText *label = new wxStaticText( panel, -1,
+        wxU(_("Alternatively, you can build an MRL using one of the "
+              "following predefined targets:")) );
+
+    wxFlexGridSizer *common_opt_sizer = new wxFlexGridSizer( 5, 1, 20 );
+
+    if( i_method == OPEN_NORMAL )
+    {
+        /* Create Stream Output checkox */
+        sout_checkbox = new wxCheckBox( panel, SoutEnable_Event,
+                                         wxU(_("Stream output")) );
+        sout_checkbox->SetToolTip( wxU(_("Use VLC as a server of streams")) );
+        common_opt_sizer->Add( sout_checkbox, 0,
+                               wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+
+        sout_button = new wxButton( panel, SoutSettings_Event,
+                                    wxU(_("Settings...")) );
+        sout_button->Disable();
+
+        char *psz_sout = config_GetPsz( p_intf, "sout" );
+        if( psz_sout && *psz_sout )
+        {
+            sout_checkbox->SetValue(TRUE);
+            sout_button->Enable();
+            subsfile_mrl.Add( wxString(wxT("sout=")) + wxL2U(psz_sout) );
+        }
+        if( psz_sout ) free( psz_sout );
+
+        common_opt_sizer->Add( sout_button, 1, wxALIGN_LEFT |
+                               wxALIGN_CENTER_VERTICAL );
+
+        common_opt_sizer->Add( new wxPanel( this, -1 ), 1,
+                               wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    }
+
+    /* Create caching options */
+    caching_checkbox = new wxCheckBox( panel, CachingEnable_Event,
+                                       wxU(_("Caching")) );
+    caching_checkbox->SetToolTip( wxU(_("Change the default caching value "
+                                        "(in milliseconds)")) );
+    common_opt_sizer->Add( caching_checkbox, 0,
+                           wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    caching_value = new wxSpinCtrl( panel, CachingChange_Event );
+    caching_value->SetRange( 0, 1000000 );
+    caching_value->Disable();
+    common_opt_sizer->Add( caching_value, 0,
+                           wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+
+    /* Separation */
+    wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
+
+    /* Create the buttons */
+    wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
+    ok_button->SetDefault();
+    wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
+                                            wxU(_("Cancel")) );
+
+    /* Create notebook */
+    notebook = new wxNotebook( panel, Notebook_Event );
+
+#if (!wxCHECK_VERSION(2,5,0))
+    wxNotebookSizer *notebook_sizer = new wxNotebookSizer( notebook );
+#endif
+
+    notebook->AddPage( FilePanel( notebook ), wxU(_("File")),
+                       i_access_method == FILE_ACCESS );
+    notebook->AddPage( DiscPanel( notebook ), wxU(_("Disc")),
+                       i_access_method == DISC_ACCESS );
+    notebook->AddPage( NetPanel( notebook ), wxU(_("Network")),
+                       i_access_method == NET_ACCESS );
+
+    module_t *p_module = config_FindModule( VLC_OBJECT(p_intf), "v4l" );
+    if( p_module )
+    {
+        AutoBuiltPanel *autopanel =
+            new AutoBuiltPanel( notebook, this, p_intf, p_module );
+        input_tab_array.Add( autopanel );
+        notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
+                        p_module->psz_shortname : p_module->psz_object_name ),
+                           i_access_method == CAPTURE_ACCESS );
+    }
+
+    p_module = config_FindModule( VLC_OBJECT(p_intf), "pvr" );
+    if( p_module )
+    {
+        AutoBuiltPanel *autopanel =
+            new AutoBuiltPanel( notebook, this, p_intf, p_module );
+        input_tab_array.Add( autopanel );
+        notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
+                        p_module->psz_shortname : p_module->psz_object_name ),
+                           i_access_method == CAPTURE_ACCESS );
+    }
+
+    p_module = config_FindModule( VLC_OBJECT(p_intf), "dvb" );
+    if( p_module )
+    {
+        AutoBuiltPanel *autopanel =
+            new AutoBuiltPanel( notebook, this, p_intf, p_module );
+        input_tab_array.Add( autopanel );
+        notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
+                        p_module->psz_shortname : p_module->psz_object_name ),
+                           i_access_method == CAPTURE_ACCESS );
+    }
+
+    p_module = config_FindModule( VLC_OBJECT(p_intf), "dshow" );
+    if( p_module )
+    {
+        AutoBuiltPanel *autopanel =
+            new AutoBuiltPanel( notebook, this, p_intf, p_module );
+        input_tab_array.Add( autopanel );
+        notebook->AddPage( autopanel, wxU( p_module->psz_shortname ?
+                        p_module->psz_shortname : p_module->psz_object_name ),
+                           i_access_method == CAPTURE_ACCESS );
+    }
+
+    /* Update Disc panel */
+    wxCommandEvent dummy_event;
+    OnDiscTypeChange( dummy_event );
+
+    /* Update Net panel */
+    dummy_event.SetId( NetRadio1_Event );
+    OnNetTypeChange( dummy_event );
+
+    /* Update MRL */
+    wxNotebookEvent event( wxEVT_NULL, 0, i_access_method );
+    OnPageChange( event );
+
+    /* Place everything in sizers */
+    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+    button_sizer->Add( ok_button, 0, wxALL, 5 );
+    button_sizer->Add( cancel_button, 0, wxALL, 5 );
+    button_sizer->Layout();
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
+    panel_sizer->Add( label, 0, wxEXPAND | wxALL, 5 );
+#if (!wxCHECK_VERSION(2,5,0))
+    panel_sizer->Add( notebook_sizer, 1, wxEXPAND | wxALL, 5 );
+#else
+    panel_sizer->Add( notebook, 1, wxEXPAND | wxALL, 5 );
+#endif
+    panel_sizer->Add( common_opt_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
+    panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALL, 5 );
+    panel_sizer->Layout();
+    panel->SetSizerAndFit( panel_sizer );
+    main_sizer->Add( panel, 1, wxGROW, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+}
+
+OpenDialog::~OpenDialog()
+{
+    /* Clean up */
+    if( file_dialog ) delete file_dialog;
+    if( sout_dialog ) delete sout_dialog;
+    if( subsfile_dialog ) delete subsfile_dialog;
+}
+
+int OpenDialog::Show( int i_access_method, int i_arg )
+{
+    notebook->SetSelection( i_access_method );
+    int i_ret = wxDialog::Show();
+    Raise();
+    SetFocus();
+    i_open_arg = i_arg;
+    return i_ret;
+}
+
+int OpenDialog::Show()
+{
+    int i_ret = wxDialog::Show();
+    Raise();
+    SetFocus();
+    return i_ret;
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+wxPanel *OpenDialog::FilePanel( wxWindow* parent )
+{
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
+
+    /* Create browse file line */
+    wxBoxSizer *file_sizer = new wxBoxSizer( wxHORIZONTAL );
+
+    file_combo = new wxComboBox( panel, FileName_Event, wxT(""),
+                                 wxPoint(20,25), wxSize(200, -1) );
+    wxButton *browse_button = new wxButton( panel, FileBrowse_Event,
+                                            wxU(_("Browse...")) );
+    file_sizer->Add( file_combo, 1, wxALL, 5 );
+    file_sizer->Add( browse_button, 0, wxALL, 5 );
+
+    /* Create Subtitles File checkox */
+    wxFlexGridSizer *subsfile_sizer = new wxFlexGridSizer( 2, 1, 20 );
+    subsfile_checkbox = new wxCheckBox( panel, SubsFileEnable_Event,
+                                        wxU(_("Subtitle options")) );
+    subsfile_checkbox->SetToolTip( wxU(_("Force options for separate subtitle files.")) );
+    subsfile_sizer->Add( subsfile_checkbox, 0,
+                         wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subsfile_button = new wxButton( panel, SubsFileSettings_Event,
+                                    wxU(_("Settings...")) );
+    subsfile_button->Disable();
+
+    char *psz_subsfile = config_GetPsz( p_intf, "sub-file" );
+    if( psz_subsfile && *psz_subsfile )
+    {
+        subsfile_checkbox->SetValue(TRUE);
+        subsfile_button->Enable();
+        subsfile_mrl.Add( wxString(wxT("sub-file=")) + wxL2U(psz_subsfile) );
+    }
+    if( psz_subsfile ) free( psz_subsfile );
+
+    subsfile_sizer->Add( subsfile_button, 1,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    sizer->Add( file_sizer, 0, wxEXPAND | wxALL, 5 );
+    sizer->Add( subsfile_sizer, 0, wxEXPAND | wxALL, 5 );
+    panel->SetSizerAndFit( sizer );
+    return panel;
+}
+
+wxPanel *OpenDialog::DiscPanel( wxWindow* parent )
+{
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
+    wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 3, 20 );
+
+    static const wxString disc_type_array[] =
+    {
+        wxU(_("DVD (menus)")),
+        wxU(_("DVD")),
+        wxU(_("VCD")),
+        wxU(_("Audio CD")),
+    };
+
+    disc_type = new wxRadioBox( panel, DiscType_Event, wxU(_("Disc type")),
+                                wxDefaultPosition, wxDefaultSize,
+                                WXSIZEOF(disc_type_array), disc_type_array,
+                                WXSIZEOF(disc_type_array), wxRA_SPECIFY_COLS );
+
+#ifdef HAVE_LIBCDIO
+    disc_probe = new wxCheckBox( panel, DiscProbe_Event,
+                                 wxU(_("Probe Disc(s)")) );
+    disc_probe->SetToolTip( wxU(_("Probe for a DVD, VCD or audio CD. "
+"First try the Device name entered for the selected Disc type "
+"(DVD, DVD Menu, VCD, audio CD). If that doesn't find media, try any device "
+"for the Disc type.  If that doesn't work, then try looking for CD-ROMs or "
+"DVD drives. The Disc type, Device name, and some parameter ranges are set "
+"based on media we find.")) );
+#endif
+
+    sizer_row->Add( disc_type, i_disc_type_selection, wxEXPAND | wxALL, 5 );
+#ifdef HAVE_LIBCDIO
+    sizer_row->Add( disc_probe, 0, wxEXPAND | wxALL );
+#endif
+
+    wxStaticText *label = new wxStaticText( panel, -1, wxU(_("Device name")) );
+    disc_device = new wxTextCtrl( panel, DiscDevice_Event, wxT(""),
+                                  wxDefaultPosition, wxDefaultSize,
+                                  wxTE_PROCESS_ENTER);
+
+#ifdef WIN32
+    char psz_default_device[3] = {0};
+
+    /* find the drive_name for the first cdrom drive,
+     * which is probably "D:" and put the drive_name into
+     * psz_default_device... */
+    for( char drive_letter = 'A'; drive_letter <= 'Z'; ++drive_letter )
+    {
+        char drive_name[3] = {drive_letter, ':', 0};
+        UINT type = GetDriveTypeA( drive_name );
+        if( type == DRIVE_CDROM )
+        {
+            psz_default_device[0] = drive_letter;
+            psz_default_device[1] = ':';
+            break;
+        }
+    }
+
+
+    if( strlen(psz_default_device) > 0 )
+    {
+        if(disc_device)
+            disc_device->SetValue( wxL2U(psz_default_device) );
+    }
+#endif
+
+    sizer->Add( label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    sizer->Add( disc_device, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    disc_title_label = new wxStaticText( panel, -1, wxU(_("Title")) );
+    disc_title = new wxSpinCtrl( panel, DiscTitle_Event );
+    sizer->Add( disc_title_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    sizer->Add( disc_title, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    disc_chapter_label = new wxStaticText( panel, -1, wxU(_("Chapter")) );
+    disc_chapter = new wxSpinCtrl( panel, DiscChapter_Event );
+    sizer->Add( disc_chapter_label, 0,
+                wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    sizer->Add( disc_chapter, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    disc_sub_label = new wxStaticText( panel, -1, wxU(_("Subtitles track")) );
+    disc_sub = new wxSpinCtrl( panel, DiscSub_Event );
+    sizer->Add( disc_sub_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    sizer->Add( disc_sub, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    disc_sub->SetRange( -1, 255 );
+    i_disc_sub = config_GetInt( p_intf, "sub-track" );
+    disc_sub->SetValue( i_disc_sub );
+
+    disc_audio_label = new wxStaticText( panel, -1, wxU(_("Audio track")) );
+    disc_audio = new wxSpinCtrl( panel, DiscAudio_Event );
+    sizer->Add( disc_audio_label, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    sizer->Add( disc_audio, 1, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    disc_audio->SetRange( -1, 255 );
+    i_disc_audio = config_GetInt( p_intf, "audio-track" );
+    disc_audio->SetValue( i_disc_audio );
+
+    sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
+
+    panel->SetSizerAndFit( sizer_row );
+    return panel;
+}
+
+wxPanel *OpenDialog::NetPanel( wxWindow* parent )
+{
+    int i;
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxBoxSizer *sizer_row = new wxBoxSizer( wxVERTICAL );
+    wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );
+
+    static const wxString net_type_array[] =
+    {
+        wxU(_("UDP/RTP")),
+        wxU(_("UDP/RTP Multicast")),
+        wxU(_("HTTP/HTTPS/FTP/MMS")),
+        wxU(_("RTSP"))
+    };
+
+    for( i=0; i<4; i++ )
+    {
+        net_radios[i] = new wxRadioButton( panel, NetRadio1_Event + i,
+                                           net_type_array[i],
+                                           wxDefaultPosition, wxDefaultSize,
+                                           wxRB_SINGLE );
+
+        net_subpanels[i] = new wxPanel( panel, -1,
+                                        wxDefaultPosition, wxDefaultSize );
+    }
+
+    /* Timeshift */
+    net_timeshift  = new wxCheckBox( panel, NetTimeshift_Event,
+                                     wxU(_("Allow timeshifting")) );
+
+    /* UDP/RTP row */
+    wxFlexGridSizer *subpanel_sizer;
+    wxStaticText *label;
+    i_net_ports[0] = config_GetInt( p_intf, "server-port" );
+    subpanel_sizer = new wxFlexGridSizer( 3, 1, 20 );
+    label = new wxStaticText( net_subpanels[0], -1, wxU(_("Port")) );
+    net_ports[0] = new wxSpinCtrl( net_subpanels[0], NetPort1_Event,
+                                   wxString::Format(wxT("%d"), i_net_ports[0]),
+                                   wxDefaultPosition, wxDefaultSize,
+                                   wxSP_ARROW_KEYS,
+                                   0, 65535, i_net_ports[0] );
+
+    subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( net_ports[0], 1,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    net_ipv6 = new wxCheckBox( net_subpanels[0], NetForceIPv6_Event,
+                               wxU(_("Force IPv6")));
+    subpanel_sizer->Add( net_ipv6, 0,
+                         wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    net_subpanels[0]->SetSizerAndFit( subpanel_sizer );
+    net_radios[0]->SetValue( TRUE );
+
+    /* UDP/RTP Multicast row */
+    subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
+    label = new wxStaticText( net_subpanels[1], -1, wxU(_("Address")) );
+    net_addrs[1] = new wxTextCtrl( net_subpanels[1], NetAddr2_Event, wxT(""),
+                                   wxDefaultPosition, wxDefaultSize,
+                                   wxTE_PROCESS_ENTER);
+    subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( net_addrs[1], 1,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    label = new wxStaticText( net_subpanels[1], -1, wxU(_("Port")) );
+    i_net_ports[1] = i_net_ports[0];
+    net_ports[1] = new wxSpinCtrl( net_subpanels[1], NetPort2_Event,
+                                   wxString::Format(wxT("%d"), i_net_ports[1]),
+                                   wxDefaultPosition, wxDefaultSize,
+                                   wxSP_ARROW_KEYS,
+                                   0, 65535, i_net_ports[1] );
+
+    subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( net_ports[1], 1,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    net_subpanels[1]->SetSizerAndFit( subpanel_sizer );
+
+    /* HTTP and RTSP rows */
+    for( i=2; i<4; i++ )
+    {
+        subpanel_sizer = new wxFlexGridSizer( 2, 1, 20 );
+        label = new wxStaticText( net_subpanels[i], -1, wxU(_("URL")) );
+        net_addrs[i] = new wxTextCtrl( net_subpanels[i], NetAddr1_Event + i,
+                                       (i == 2) ? wxT("") : wxT("rtsp://"),
+                                       wxDefaultPosition, wxSize( 200, -1 ),
+                                       wxTE_PROCESS_ENTER);
+        subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+        subpanel_sizer->Add( net_addrs[i], 1,
+                             wxEXPAND | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+        net_subpanels[i]->SetSizerAndFit( subpanel_sizer );
+    }
+
+    /* Stuff everything into the main panel */
+    for( i=0; i<4; i++ )
+    {
+        sizer->Add( net_radios[i], 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
+                    wxALL, 5 );
+        sizer->Add( net_subpanels[i], 1, wxEXPAND | wxALIGN_LEFT |
+                    wxALIGN_CENTER_VERTICAL | wxALL, 5  );
+    }
+    sizer->Add( net_timeshift, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
+                wxALL, 5 );
+
+    sizer_row->Add( sizer, 0, wxEXPAND | wxALL, 5 );
+
+    panel->SetSizerAndFit( sizer_row );
+    return panel;
+}
+
+void OpenDialog::UpdateMRL()
+{
+    UpdateMRL( i_current_access_method );
+}
+
+void OpenDialog::UpdateMRL( int i_access_method )
+{
+    wxString mrltemp, caching_name;
+
+    i_current_access_method = i_access_method;
+
+    switch( i_access_method )
+    {
+    case FILE_ACCESS:
+        mrltemp = file_combo->GetValue();
+        caching_name = wxT("file-caching");
+        break;
+
+    case DISC_ACCESS:
+        i_disc_type_selection = disc_type->GetSelection();
+
+        switch ( i_disc_type_selection )
+        {
+        case 0: /* DVD with menus */
+        case 1: /* DVD without menus */
+            disc_device->SetToolTip( wxU(_("Name of DVD device "
+            "to read from.")) );
+            if( i_disc_type_selection == 0 )
+            {
+                mrltemp = wxT("dvd://") + disc_device->GetValue();
+                caching_name = wxT("dvdnav-caching");
+            }
+            else
+            {
+                mrltemp = wxT("dvdsimple://") + disc_device->GetValue();
+                caching_name = wxT("dvdread-caching");
+            }
+
+            if( i_disc_title > 0 )
+            {
+                mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
+
+                if( i_disc_chapter > 0 )
+                    mrltemp += wxString::Format( wxT(":%d"), i_disc_chapter );
+            }
+
+            if( i_disc_sub >= 0 )
+                mrltemp += wxString::Format( wxT("  :sub-track=%d"),
+                                             i_disc_sub );
+            if( i_disc_audio >= 0 )
+                mrltemp += wxString::Format( wxT("  :audio-track=%d"),
+                                             i_disc_audio );
+            break;
+
+        case 2:  /* VCD of some sort */
+#ifdef HAVE_VCDX
+            disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
+            "to read Video CD from. If this field is left empty, we will scan "
+            "for a CD-ROM with a VCD in it.")) );
+            mrltemp = wxT("vcdx://") + disc_device->GetValue();
+            if( i_disc_title > 0 )
+                mrltemp += wxString::Format( wxT("@%c%d"),
+                                  config_GetInt( p_intf, "vcdx-PBC"  )
+                                  ? 'P' : 'E', i_disc_title );
+#else
+            disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
+            "to read Video CD from.")) );
+            mrltemp = wxT("vcd://") + disc_device->GetValue();
+            if( i_disc_title > 0 )
+                mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
+#endif
+
+            if( i_disc_sub >= 0 )
+                mrltemp += wxString::Format( wxT("  :sub-track=%d"),
+                                             i_disc_sub );
+
+            if( i_disc_audio >= 0 )
+                mrltemp += wxString::Format( wxT("  :audio-track=%d"),
+                                             i_disc_audio );
+            caching_name = wxT("vcd-caching");
+            break;
+
+        case 3: /* CD-DA */
+#ifdef HAVE_CDDAX
+            disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
+            "to read audio CD from. If this field is left empty, we will scan "
+            "for a CD-ROM with an audio CD in it." )) );
+            mrltemp = wxT("cddax://")
+#else
+            disc_device->SetToolTip( wxU(_("Name of CD-ROM device "
+            "to read audio CD from." )) );
+            mrltemp = wxT("cdda://")
+#endif
+              + disc_device->GetValue();
+            if( i_disc_title > 0 )
+                mrltemp += wxString::Format( wxT("@%d"), i_disc_title );
+
+            caching_name = wxT("cdda-caching");
+            break;
+
+        default:
+            msg_Err( p_intf, "invalid selection (%d)",
+                     disc_type->GetSelection() );
+        }
+
+        break;
+
+    case NET_ACCESS:
+        switch( i_net_type )
+        {
+        case 0:
+            mrltemp = wxT("udp://@");
+            if ( net_ipv6->GetValue() )
+            {
+                mrltemp += wxT("[::]");
+            }
+            if( i_net_ports[0] !=
+                config_GetInt( p_intf, "server-port" ) )
+            {
+                mrltemp += wxString::Format( wxT(":%d"), i_net_ports[0] );
+            }
+
+            caching_name = wxT("udp-caching");
+            break;
+
+        case 1:
+            mrltemp = wxT("udp://@");
+            if ((net_addrs[1]->GetLineText(0).Find (':') != -1)
+                && (net_addrs[1]->GetLineText(0)[0u] != '['))
+            {
+                /* automatically adds '[' and ']' to IPv6 addresses */
+                mrltemp += wxT("[") + net_addrs[1]->GetLineText(0)
+                         + wxT("]");
+            }
+            else
+            {
+                mrltemp += net_addrs[1]->GetLineText(0);
+            }
+            if( i_net_ports[1] != config_GetInt( p_intf, "server-port" ) )
+            {
+                mrltemp += wxString::Format( wxT(":%d"), i_net_ports[1] );
+            }
+
+            caching_name = wxT("udp-caching");
+            break;
+
+        case 2:
+            /* http access */
+            if( net_addrs[2]->GetLineText(0).Find(wxT("://")) == -1 )
+                mrltemp = wxT("http://");
+
+            mrltemp += net_addrs[2]->GetLineText(0);
+
+            caching_name = wxT("http-caching");
+            break;
+
+        case 3:
+            /* RTSP access */
+            if( net_addrs[3]->GetLineText(0).Find(wxT("rtsp://")) != 0 )
+            {
+                mrltemp = wxT("rtsp://");
+            }
+            mrltemp += net_addrs[3]->GetLineText(0);
+
+            caching_name = wxT("rtsp-caching");
+            break;
+        }
+        if( net_timeshift->IsEnabled() && net_timeshift->IsChecked() )
+            mrltemp += wxT(" :access-filter=timeshift");
+        break;
+
+    default:
+        {
+            int i_item = i_access_method - MAX_ACCESS;
+
+            if( i_item < 0 || i_item >= (int)input_tab_array.GetCount() )
+                break;
+
+            AutoBuiltPanel *input_panel = input_tab_array.Item( i_item );
+
+            mrltemp = input_panel->name + wxT("://");
+
+            for( int i=0; i < (int)input_panel->config_array.GetCount(); i++ )
+            {
+                ConfigControl *control = input_panel->config_array.Item(i);
+
+                mrltemp += wxT(" :");
+
+                if( control->GetType() == CONFIG_ITEM_BOOL &&
+                    !control->GetIntValue() ) mrltemp += wxT("no-");
+
+                mrltemp += control->GetName();
+
+                switch( control->GetType() )
+                {
+                case CONFIG_ITEM_STRING:
+                case CONFIG_ITEM_FILE:
+                case CONFIG_ITEM_DIRECTORY:
+                case CONFIG_ITEM_MODULE:
+                    mrltemp += wxT("=\"") + control->GetPszValue() + wxT("\"");
+                    break;
+                case CONFIG_ITEM_INTEGER:
+                    mrltemp +=
+                        wxString::Format( wxT("=%i"), control->GetIntValue() );
+                    break;
+                case CONFIG_ITEM_FLOAT:
+                    mrltemp +=
+                        wxString::Format(wxT("=%f"), control->GetFloatValue());
+                    break;
+                }
+            }
+
+            if( input_panel->p_advanced_mrl_combo &&
+                input_panel->p_advanced_mrl_combo->GetValue() )
+            {
+                mrltemp += wxT(" ") +
+                    input_panel->p_advanced_mrl_combo->GetValue();
+            }
+        }
+        break;
+    }
+
+    if( caching_name.size() )
+    {
+        if( caching_value->IsEnabled() )
+        {
+            mrltemp += wxT("  :") + caching_name +
+                wxString::Format( wxT("=%d"), i_caching );
+        }
+        else
+        {
+            int i_value = config_GetInt( p_intf, caching_name.mb_str() );
+            caching_value->SetValue( i_value );
+        }
+    }
+
+    mrl_combo->SetValue( mrltemp );
+}
+
+/*****************************************************************************
+ * Events methods.
+ *****************************************************************************/
+void OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
+{
+    mrl = SeparateEntries( mrl_combo->GetValue() );
+    mrl_combo->Append( mrl_combo->GetValue() );
+    if( mrl_combo->GetCount() > 10 ) mrl_combo->Delete( 0 );
+    mrl_combo->SetSelection( mrl_combo->GetCount() - 1 );
+
+    if( i_method == OPEN_STREAM )
+    {
+        if( IsModal() ) EndModal( wxID_OK );
+        Hide();
+        return;
+    }
+
+    /* Update the playlist */
+    playlist_t *p_playlist =
+        (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                       FIND_ANYWHERE );
+    if( p_playlist == NULL ) return;
+
+    for( int i = 0; i < (int)mrl.GetCount(); i++ )
+    {
+        vlc_bool_t b_start = !i && i_open_arg;
+        playlist_item_t *p_item;
+        char *psz_utf8;
+
+        psz_utf8 = wxFromLocale( mrl[i] );
+        p_item = playlist_ItemNew( p_intf, psz_utf8, psz_utf8 );
+        wxLocaleFree( psz_utf8 );
+
+        /* Insert options */
+        while( i + 1 < (int)mrl.GetCount() &&
+               ((const char *)mrl[i + 1].mb_str())[0] == ':' )
+        {
+            psz_utf8 = wxFromLocale( mrl[i + 1] );
+            playlist_ItemAddOption( p_item, psz_utf8 );
+            wxLocaleFree( psz_utf8 );
+            i++;
+        }
+
+        /* Get the options from the subtitles dialog */
+        if( subsfile_checkbox->IsChecked() && subsfile_mrl.GetCount() )
+        {
+            for( int j = 0; j < (int)subsfile_mrl.GetCount(); j++ )
+            {
+                psz_utf8 = wxFromLocale( subsfile_mrl[j] );
+                playlist_ItemAddOption( p_item, psz_utf8 );
+                wxLocaleFree( psz_utf8 );
+            }
+        }
+
+        /* Get the options from the stream output dialog */
+        if( sout_checkbox->IsChecked() && sout_mrl.GetCount() )
+        {
+            for( int j = 0; j < (int)sout_mrl.GetCount(); j++ )
+            {
+                psz_utf8 = wxFromLocale( sout_mrl[j] );
+                playlist_ItemAddOption( p_item, psz_utf8 );
+                wxLocaleFree( psz_utf8 );
+            }
+        }
+
+        playlist_AddItem( p_playlist, p_item, PLAYLIST_APPEND, PLAYLIST_END );
+
+        if( b_start )
+        {
+            playlist_Control( p_playlist, PLAYLIST_ITEMPLAY, p_item );
+        }
+    }
+
+    vlc_object_release( p_playlist );
+
+    Hide();
+
+    if( IsModal() ) EndModal( wxID_OK );
+}
+
+void OpenDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
+{
+    wxCloseEvent cevent;
+    OnClose(cevent);
+}
+
+void OpenDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
+{
+    Hide();
+
+    if( IsModal() ) EndModal( wxID_CANCEL );
+}
+
+void OpenDialog::OnPageChange( wxNotebookEvent& event )
+{
+    UpdateMRL( event.GetSelection() );
+}
+
+void OpenDialog::OnMRLChange( wxCommandEvent& event )
+{
+    //mrl = SeparateEntries( event.GetString() );
+}
+
+/*****************************************************************************
+ * File panel event methods.
+ *****************************************************************************/
+void OpenDialog::OnFilePanelChange( wxCommandEvent& WXUNUSED(event) )
+{
+    UpdateMRL( FILE_ACCESS );
+}
+
+void OpenDialog::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
+{
+    if( file_dialog == NULL )
+        file_dialog = new wxFileDialog( this, wxU(_("Open File")),
+            wxT(""), wxT(""), wxT("*"), wxOPEN | wxMULTIPLE );
+
+    if( file_dialog && file_dialog->ShowModal() == wxID_OK )
+    {
+        wxArrayString paths;
+        wxString path;
+
+        file_dialog->GetPaths( paths );
+
+        for( size_t i = 0; i < paths.GetCount(); i++ )
+        {
+            if( paths[i].Find( wxT(' ') ) >= 0 )
+                path += wxT("\"") + paths[i] + wxT("\" ");
+            else
+                path += paths[i] + wxT(" ");
+        }
+
+        file_combo->SetValue( path );
+        file_combo->Append( path );
+        if( file_combo->GetCount() > 10 ) file_combo->Delete( 0 );
+        UpdateMRL( FILE_ACCESS );
+    }
+}
+
+/*****************************************************************************
+ * Disc panel event methods.
+ *****************************************************************************/
+void OpenDialog::OnDiscPanelChangeSpin( wxSpinEvent& event )
+{
+    wxCommandEvent cevent;
+    cevent.SetId(event.GetId());
+    cevent.SetInt(event.GetPosition());
+    OnDiscPanelChange(cevent);
+}
+
+void OpenDialog::OnDiscPanelChange( wxCommandEvent& event )
+{
+    if( event.GetId() == DiscTitle_Event ) i_disc_title = event.GetInt();
+    if( event.GetId() == DiscChapter_Event ) i_disc_chapter = event.GetInt();
+    if( event.GetId() == DiscSub_Event ) i_disc_sub = event.GetInt();
+    if( event.GetId() == DiscAudio_Event ) i_disc_audio = event.GetInt();
+
+    UpdateMRL( DISC_ACCESS );
+}
+
+void OpenDialog::OnDiscDeviceChange( wxCommandEvent& event )
+{
+    char *psz_device;
+
+    switch( disc_type->GetSelection() )
+    {
+        case 3:
+            psz_device = config_GetPsz( p_intf, "cd-audio" );
+            break;
+
+        case 2:
+            psz_device = config_GetPsz( p_intf, "vcd" );
+            break;
+
+        default:
+            psz_device = config_GetPsz( p_intf, "dvd" );
+            break;
+    }
+
+    if ( !psz_device ) psz_device = "";
+
+    if( disc_device->GetValue().Cmp( wxL2U( psz_device ) ) )
+    {
+        b_disc_device_changed = true;
+    }
+
+    UpdateMRL( DISC_ACCESS );
+}
+
+#ifdef HAVE_LIBCDIO
+
+/* Return true if *psz_drive is a drive with a DVD in it. A more complete
+   check would see if the media looks like a *playable* DVD. This should
+   go into libcdio.
+ */
+static bool IsDVD(const char *psz_drive)
+{
+  CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_UNKNOWN);
+  if (p_cdio)
+  {
+      discmode_t discmode = cdio_get_discmode(p_cdio);
+      cdio_destroy(p_cdio);
+      return cdio_is_discmode_dvd(discmode);
+  }
+  return false;
+}
+
+
+/* Return a device that has a DVD in it. The caller needs to free
+   the returned string.
+*/
+static char * ProbeDVD(const wxChar *device)
+{
+        /*
+  char **ppsz_cd_drives;
+  const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
+  char *psz_device = (char *) tmp_buf;
+
+  if( IsDVD(psz_device) )
+  {
+      return strdup(psz_device);
+  }
+
+  ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);
+  if( ppsz_cd_drives )
+  {
+      char **c;
+      for( c = ppsz_cd_drives; *c != NULL; c++ )
+      {
+      if( IsDVD(*c) )
+      {
+          char *psz_drive = strdup(*c);
+          cdio_free_device_list(ppsz_cd_drives);
+          return strdup(psz_drive);
+          }
+      }
+      cdio_free_device_list(ppsz_cd_drives);
+  }*/
+  return NULL;
+}
+
+
+static char * ProbeDevice(char **ppsz_search_devices, cdio_fs_anal_t mask,
+              bool b_any)
+{
+    char **ppsz_devices;
+
+    if( ppsz_search_devices && !ppsz_search_devices[0] )
+        ppsz_search_devices = NULL;
+
+    /* Start out trying the device that has been entered so far. */
+    ppsz_devices = cdio_get_devices_with_cap(ppsz_search_devices, mask,
+                         b_any);
+
+    if (ppsz_devices && *ppsz_devices)
+    {
+        char *psz_device = strdup(*ppsz_devices);
+        cdio_free_device_list(ppsz_devices);
+        return psz_device;
+    }
+
+    /* If there was no device specified on the first try, then give up
+       now. Otherwise accept any CD-ROM in the class (e.g. VCD or DVD).
+    */
+    if( !ppsz_search_devices ) return NULL;
+
+    ppsz_devices = cdio_get_devices_with_cap(NULL, mask, true);
+
+    if (ppsz_devices && *ppsz_devices)
+    {
+        char *psz_device = strdup(*ppsz_devices);
+        cdio_free_device_list(ppsz_devices);
+        return psz_device;
+    }
+
+    return NULL;
+}
+
+
+/* Return a device that has a CD-DA in it. The caller needs to free
+   the returned string.
+*/
+static char * ProbeCDDA(const wxChar *device)
+{
+        /*
+   char *ppsz_device[2];
+   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
+   char *psz_device = (char *) tmp_buf;
+   ppsz_device[0] = (device && *device) ? psz_device : NULL;
+   ppsz_device[1] = NULL;
+   return ProbeDevice(ppsz_device, CDIO_FS_AUDIO, false);
+   */ return NULL;
+}
+
+/* Return a device that has a VCD in it. The caller needs to free
+   the returned string.
+*/
+static char * ProbeVCD(const wxChar *device)
+{/*
+   char *ppsz_device[2];
+   const wxWX2MBbuf tmp_buf = wxConvCurrent->cWX2MB(device);
+   char *psz_device = (char *) tmp_buf;
+   ppsz_device[0] = (device && *device) ? psz_device : NULL;
+   ppsz_device[1] = NULL;
+   return ProbeDevice(ppsz_device,
+                      (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD
+                       |CDIO_FS_UNKNOWN), true);
+                       */ return NULL;
+}
+
+
+/*
+   Probe (find anywhere) a CD-DA, VCD, or a DVD.
+   First try the device name that may have been entered for the "disc type"
+   selected. If that doesn't work we try any device for the disc type.
+   If that doesn't work, try looking for CD-ROMs or DVD drives. the
+   disc type, device name and paramter ranges are set to whatever we find.
+*/
+void OpenDialog::OnDiscProbe( wxCommandEvent& WXUNUSED(event) )
+{
+    wxCommandEvent dummy_event;
+    char *psz_device = NULL;
+    bool b_probed_DVD = false;
+    bool b_probed_VCD = false;
+    const int i_selection = disc_type->GetSelection();
+
+    /* Reduce verbosity of cdio errors. */
+    cdio_loglevel_default = CDIO_LOG_ERROR;
+
+ retry:
+    switch( disc_type->GetSelection() )
+    {
+
+    case SELECTION_DISC_TYPE_DVD_MENUS:
+    case SELECTION_DISC_TYPE_DVD:
+      /* If not a DVD then try for a VCD. If VCD fails it will
+         try for a CD-DA. */
+      if (!psz_device) psz_device = ProbeDVD(disc_device->GetValue());
+      if (!psz_device)
+      {
+          b_probed_DVD = true;
+          disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
+          OnDiscTypeChange( dummy_event );
+          goto retry;
+      }
+      disc_device->SetValue( wxL2U(psz_device) );
+      break;
+
+    case SELECTION_DISC_TYPE_VCD:  /* VCD probe of some sort */
+      if(!psz_device) psz_device = ProbeVCD(disc_device->GetValue());
+      if( psz_device  )
+      {
+#ifdef HAVE_VCDX
+#if LIBVCD_VERSION_NUM > 23
+      vcdinfo_obj_t *p_vcdinfo;
+
+          /* Set LID or entry range accurately if possible. */
+      if( vcdinfo_open(&p_vcdinfo, &psz_device, DRIVER_DEVICE,
+                NULL) == VCDINFO_OPEN_VCD)
+      {
+          if (config_GetInt( p_intf, "vcdx-PBC"  ))
+          {
+          /* Set largest LID. */;
+          disc_title->SetRange( 0, vcdinfo_get_num_LIDs(p_vcdinfo) );
+
+          }
+          else
+          {
+          /* Set largest Entry */
+          disc_title->SetRange( 0,
+                    vcdinfo_get_num_entries(p_vcdinfo)-1 );
+          }
+          vcdinfo_close(p_vcdinfo);
+      }
+#endif /* LIBVCD_VERSION_NUM > 23 */
+          disc_device->SetValue( wxL2U(psz_device) );
+#else
+          CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
+          disc_device->SetValue( wxL2U(psz_device) );
+
+          /* Set track range accurately if possible. */
+          if (p_cdio)
+          {
+              track_t i_last_track = cdio_get_last_track_num(p_cdio);
+              disc_title->SetRange( 0, i_last_track-1 );
+          }
+          cdio_destroy(p_cdio);
+#endif
+          break;
+      }
+
+      b_probed_VCD = true;
+
+      /* Not a VCD. Try for a DVD unless we've been there before. */
+      if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
+      {
+          disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
+          OnDiscTypeChange( dummy_event );
+          goto retry;
+      }
+      b_probed_DVD = true;
+
+      /* Couldn't find a VCD or DVD. See if we can find a CD-DA. */
+      psz_device = ProbeCDDA(disc_device->GetValue());
+      if( psz_device  )
+      {
+          disc_type->SetSelection(SELECTION_DISC_TYPE_CDDA);
+          OnDiscTypeChange( dummy_event );
+          goto retry;
+      }
+
+      /* Couldn't find a VCD, DVD or CD-DA. Null out the Device name and
+     set to original selection.
+       */
+      disc_device->SetValue( wxL2U("") );
+      disc_type->SetSelection(i_selection);
+      OnDiscTypeChange( dummy_event );
+      break;
+
+    case SELECTION_DISC_TYPE_CDDA:
+      if(!psz_device) psz_device = ProbeCDDA(disc_device->GetValue());
+      if( psz_device  )
+      {
+          CdIo_t *p_cdio = cdio_open (psz_device, DRIVER_UNKNOWN);
+          disc_device->SetValue( wxL2U(psz_device) );
+          if (p_cdio)
+          {
+              track_t i_last_track = cdio_get_last_track_num(p_cdio);
+              disc_title->SetRange( 0, i_last_track );
+#if 0
+          MediaInsertCDDA( p_intf,  p_cdio, i_last_track );
+#endif
+          }
+          cdio_destroy(p_cdio);
+          break;
+      }
+
+      /* Not a CD-DA. Try for a DVD unless we've been there before. */
+      if( !b_probed_DVD && (psz_device = ProbeDVD(disc_device->GetValue())) )
+      {
+          disc_type->SetSelection(SELECTION_DISC_TYPE_DVD_MENUS);
+          OnDiscTypeChange( dummy_event );
+          goto retry;
+      }
+
+      /* Couldn't find a CD-DA or DVD. See if we can find a VCD, unless
+         we've tried that before. */
+      if (!b_probed_VCD) psz_device = ProbeVCD(disc_device->GetValue());
+      if( psz_device  )
+      {
+          disc_type->SetSelection(SELECTION_DISC_TYPE_VCD);
+          OnDiscTypeChange( dummy_event );
+          goto retry;
+      }
+      disc_device->SetValue( wxL2U("") );
+      break;
+
+    default:
+        msg_Err( p_intf, "invalid Disc type selection (%d)",
+                 disc_type->GetSelection() );
+        break;
+    }
+
+    free(psz_device);
+    disc_probe->SetValue(FALSE);
+
+    UpdateMRL( DISC_ACCESS );
+}
+#endif /* HAVE_LIBCDIO */
+
+void OpenDialog::OnDiscTypeChange( wxCommandEvent& WXUNUSED(event) )
+{
+    char *psz_device = NULL;
+
+    switch( disc_type->GetSelection() )
+    {
+
+    case SELECTION_DISC_TYPE_DVD_MENUS:
+    case SELECTION_DISC_TYPE_DVD:
+        disc_sub->Enable(); disc_sub_label->Enable();
+        disc_audio->Enable(); disc_audio_label->Enable();
+        disc_chapter->Enable(); disc_chapter_label->Enable();
+        disc_title_label->SetLabel ( wxU(_("Title")) );
+        psz_device = config_GetPsz( p_intf, "dvd" );
+        if( !b_disc_device_changed )
+        {
+            if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
+            else disc_device->SetValue( wxT("") );
+        }
+        disc_title->SetRange( 0, 255 );
+        disc_sub->SetRange( -1, 31 );  // up to 32 subtitles -1: no subtitle
+        disc_audio->SetRange( 0, 7 );  // up to 8 audio channels
+        disc_chapter->SetRange( 0, 255 );
+        disc_title->SetToolTip( wxU(_("Title number.")) );
+        disc_sub->SetToolTip( wxU(_(
+          "DVD's can have up to 32 subtitles numbered 0..31. "
+          "Note this is not the same thing as a subtitle name e.g. 'en'. "
+          "If a value -1 is used, no subtitle will be shown." )) );
+        disc_audio->SetToolTip( wxU(_("Audio track number. "
+          "DVD's can have up to 8 audio tracks numbered 0..7."
+        )) );
+        break;
+
+    case SELECTION_DISC_TYPE_VCD:
+        disc_sub->Enable(); disc_sub_label->Enable();
+        disc_audio->Enable(); disc_audio_label->Enable();
+        disc_chapter->Disable(); disc_chapter_label->Disable();
+        psz_device = config_GetPsz( p_intf, "vcd" );
+        if( !b_disc_device_changed )
+        {
+            if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
+            else disc_device->SetValue( wxT("") );
+        }
+
+#ifdef HAVE_VCDX
+        if (config_GetInt( p_intf, "vcdx-PBC"  ))
+        {
+          disc_title_label->SetLabel ( wxT("Playback LID") );
+          disc_title->SetToolTip( wxU(_(
+          "Playback control (PBC) usually starts with number 1." )) );
+        }
+        else
+        {
+          disc_title_label->SetLabel ( wxT("Entry") );
+          disc_title->SetToolTip( wxU(_(
+          "The first entry (the beginning of the first MPEG track) is 0." )) );
+        }
+
+#else
+        disc_title_label->SetLabel ( wxU(_("Track")) );
+        disc_title->SetToolTip( wxU(_("Track number.")) );
+#endif
+        disc_title->SetRange( 0, 99 );  // only 100 tracks allowed on VCDs
+        disc_sub->SetRange( -1, 3 );    // up to 4 subtitles -1 = no subtitle
+        disc_audio->SetRange( 0, 1 );   // up to 2 audio tracks
+        disc_sub->SetToolTip( wxU(_(
+          "SVCD's can have up to 4 subtitles numbered 0..3. "
+          "If a value -1 is used, no subtitle will be shown." )) );
+        disc_audio->SetToolTip( wxU(_("Audio track number. "
+          "VCD's can have up to 2 audio tracks numbered 0 or 1. "
+        )) );
+        break;
+
+    case SELECTION_DISC_TYPE_CDDA:
+        disc_sub->Disable(); disc_sub_label->Disable();
+        disc_chapter->Disable(); disc_chapter_label->Disable();
+        disc_audio->Disable(); disc_audio_label->Disable();
+        disc_title_label->SetLabel ( wxU(_("Track")) );
+#ifdef HAVE_CDDAX
+        disc_title->SetToolTip( wxU(_(
+        "Audio CDs can have up to 100 tracks, the first track is usually 1. "
+        "If 0 is given, then all tracks are played.")) );
+#else
+        disc_title->SetToolTip( wxU(_(
+        "Audio CDs can have up to 100 tracks, the first track is usually 1."
+        )) );
+#endif
+        psz_device = config_GetPsz( p_intf, "cd-audio" );
+        if( !b_disc_device_changed )
+        {
+            if( psz_device ) disc_device->SetValue( wxL2U(psz_device) );
+            else disc_device->SetValue( wxT("") );
+        }
+
+        /* There are at most 100 tracks in a CD-DA */
+        disc_title->SetRange( 0, 100 );
+        break;
+
+    default:
+        msg_Err( p_intf, "invalid Disc type selection (%d)",
+                 disc_type->GetSelection() );
+        break;
+    }
+
+    disc_title->SetValue( 0 ); i_disc_title = 0;
+    disc_chapter->SetValue( 0 ); i_disc_chapter = 0;
+
+    if( psz_device ) free( psz_device );
+
+    UpdateMRL( DISC_ACCESS );
+}
+
+/*****************************************************************************
+ * Net panel event methods.
+ *****************************************************************************/
+void OpenDialog::OnNetPanelChangeSpin( wxSpinEvent& event )
+{
+    wxCommandEvent cevent;
+    cevent.SetId(event.GetId());
+    cevent.SetInt(event.GetPosition());
+    OnNetPanelChange(cevent);
+}
+
+void OpenDialog::OnNetPanelChange( wxCommandEvent& event )
+{
+    if( event.GetId() >= NetPort1_Event && event.GetId() <= NetPort3_Event )
+    {
+        i_net_ports[event.GetId() - NetPort1_Event] = event.GetInt();
+    }
+
+    UpdateMRL( NET_ACCESS );
+}
+
+void OpenDialog::OnNetTypeChange( wxCommandEvent& event )
+{
+    int i;
+
+    i_net_type = event.GetId() - NetRadio1_Event;
+
+    for(i=0; i<4; i++)
+    {
+        net_radios[i]->SetValue( event.GetId() == (NetRadio1_Event+i) );
+        net_subpanels[i]->Enable( event.GetId() == (NetRadio1_Event+i) );
+    }
+    /* UDP Unicast or multicast -> timeshift */
+    if( i_net_type == 0 || i_net_type == 1 )
+        net_timeshift->Enable();
+    else
+        net_timeshift->Disable();
+
+    UpdateMRL( NET_ACCESS );
+}
+
+/*****************************************************************************
+ * Subtitles file event methods.
+ *****************************************************************************/
+void OpenDialog::OnSubsFileEnable( wxCommandEvent& event )
+{
+    subsfile_button->Enable( event.GetInt() != 0 );
+}
+
+void OpenDialog::OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) )
+{
+    /* Show/hide the open dialog */
+    if( subsfile_dialog == NULL )
+        subsfile_dialog = new SubsFileDialog( p_intf, this );
+
+    if( subsfile_dialog && subsfile_dialog->ShowModal() == wxID_OK )
+    {
+        subsfile_mrl.Empty();
+        subsfile_mrl.Add( wxString(wxT("sub-file=")) +
+                          subsfile_dialog->file_combo->GetValue() );
+        if( subsfile_dialog->encoding_combo )
+        {
+            subsfile_mrl.Add( wxString(wxT("subsdec-encoding=")) +
+                              subsfile_dialog->encoding_combo->GetValue() );
+        }
+        if( subsfile_dialog->align_combo )
+        {
+            subsfile_mrl.Add( wxString::Format(wxT("subsdec-align=%i"),
+                              (int)subsfile_dialog->align_combo->GetClientData(
+                              subsfile_dialog->align_combo->GetSelection()) ) );
+        }
+        if( subsfile_dialog->size_combo )
+        {
+            subsfile_mrl.Add( wxString::Format( wxT("freetype-rel-fontsize=%i"),
+                              (int)subsfile_dialog->size_combo->GetClientData(
+                              subsfile_dialog->size_combo->GetSelection()) ) );
+        }
+        subsfile_mrl.Add( wxString::Format( wxT("sub-fps=%i"),
+                          subsfile_dialog->fps_spinctrl->GetValue() ) );
+        subsfile_mrl.Add( wxString::Format( wxT("sub-delay=%i"),
+                          subsfile_dialog->delay_spinctrl->GetValue() ) );
+    }
+}
+
+/*****************************************************************************
+ * Stream output event methods.
+ *****************************************************************************/
+void OpenDialog::OnSoutEnable( wxCommandEvent& event )
+{
+    sout_button->Enable( event.GetInt() != 0 );
+}
+
+void OpenDialog::OnSoutSettings( wxCommandEvent& WXUNUSED(event) )
+{
+    /* Show/hide the open dialog */
+    if( sout_dialog == NULL )
+        sout_dialog = new SoutDialog( p_intf, this );
+
+    if( sout_dialog && sout_dialog->ShowModal() == wxID_OK )
+    {
+        sout_mrl = sout_dialog->GetOptions();
+    }
+}
+
+/*****************************************************************************
+ * Caching event methods.
+ *****************************************************************************/
+void OpenDialog::OnCachingEnable( wxCommandEvent& event )
+{
+    caching_value->Enable( event.GetInt() != 0 );
+    i_caching = caching_value->GetValue();
+    UpdateMRL();
+}
+
+void OpenDialog::OnCachingChangeSpin( wxSpinEvent& event )
+{
+    wxCommandEvent cevent;
+    OnCachingChange(cevent);
+}
+
+void OpenDialog::OnCachingChange( wxCommandEvent& event )
+{
+    i_caching = event.GetInt();
+    UpdateMRL();
+}
+
+/*****************************************************************************
+ * Utility functions.
+ *****************************************************************************/
+wxArrayString SeparateEntries( wxString entries )
+{
+    vlc_bool_t b_quotes_mode = VLC_FALSE;
+
+    wxArrayString entries_array;
+    wxString entry;
+
+    wxStringTokenizer token( entries, wxT(" \t\r\n\""), wxTOKEN_RET_DELIMS );
+
+    while( token.HasMoreTokens() )
+    {
+        entry += token.GetNextToken();
+
+        if( entry.IsEmpty() ) continue;
+
+        if( !b_quotes_mode && entry.Last() == wxT('\"') )
+        {
+            /* Enters quotes mode */
+            entry.RemoveLast();
+            b_quotes_mode = VLC_TRUE;
+        }
+        else if( b_quotes_mode && entry.Last() == wxT('\"') )
+        {
+            /* Finished the quotes mode */
+            entry.RemoveLast();
+            b_quotes_mode = VLC_FALSE;
+        }
+        else if( !b_quotes_mode && entry.Last() != wxT('\"') )
+        {
+            /* we found a non-quoted standalone string */
+            if( token.HasMoreTokens() ||
+                entry.Last() == wxT(' ') || entry.Last() == wxT('\t') ||
+                entry.Last() == wxT('\r') || entry.Last() == wxT('\n') )
+                entry.RemoveLast();
+            if( !entry.IsEmpty() ) entries_array.Add( entry );
+            entry.Empty();
+        }
+        else
+        {;}
+    }
+
+    if( !entry.IsEmpty() ) entries_array.Add( entry );
+
+    return entries_array;
+}
diff --git a/modules/gui/wxwidgets/dialogs/open.hpp b/modules/gui/wxwidgets/dialogs/open.hpp
new file mode 100644 (file)
index 0000000..14b02e6
--- /dev/null
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * open.hpp: Headers for the Open dialog
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12670 2005-09-25 11:16:31Z zorglub $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_OPEN_H_
+#define _WXVLC_OPEN_H_
+
+#include "wxwidgets.hpp"
+
+#include <wx/spinctrl.h>
+
+class AutoBuiltPanel;
+namespace wxvlc
+{
+    class SubsFileDialog;
+    class SoutDialog;
+    WX_DEFINE_ARRAY(AutoBuiltPanel *, ArrayOfAutoBuiltPanel);
+
+    class OpenDialog: public wxDialog
+    {
+
+public:
+    /* Constructor */
+    OpenDialog( intf_thread_t *p_intf, wxWindow *p_parent,
+                int i_access_method, int i_arg = 0  );
+
+    /* Extended Contructor */
+    OpenDialog( intf_thread_t *p_intf, wxWindow *p_parent,
+                int i_access_method, int i_arg = 0 , int _i_method = 0 );
+    virtual ~OpenDialog();
+
+    int Show();
+    int Show( int i_access_method, int i_arg = 0 );
+
+    void UpdateMRL();
+    void UpdateMRL( int i_access_method );
+
+    wxArrayString mrl;
+
+private:
+    wxPanel *FilePanel( wxWindow* parent );
+    wxPanel *DiscPanel( wxWindow* parent );
+    wxPanel *NetPanel( wxWindow* parent );
+
+    ArrayOfAutoBuiltPanel input_tab_array;
+
+    /* Event handlers (these functions should _not_ be virtual) */
+    void OnOk( wxCommandEvent& event );
+    void OnCancel( wxCommandEvent& event );
+    void OnClose( wxCloseEvent& event );
+
+    void OnPageChange( wxNotebookEvent& event );
+    void OnMRLChange( wxCommandEvent& event );
+
+    /* Event handlers for the file page */
+    void OnFilePanelChange( wxCommandEvent& event );
+    void OnFileBrowse( wxCommandEvent& event );
+
+    /* Event handlers for the disc page */
+    void OnDiscPanelChangeSpin( wxSpinEvent& event );
+    void OnDiscPanelChange( wxCommandEvent& event );
+    void OnDiscTypeChange( wxCommandEvent& event );
+#ifdef HAVE_LIBCDIO
+    void OnDiscProbe( wxCommandEvent& event );
+#endif
+    void OnDiscDeviceChange( wxCommandEvent& event );
+
+    /* Event handlers for the net page */
+    void OnNetPanelChangeSpin( wxSpinEvent& event );
+    void OnNetPanelChange( wxCommandEvent& event );
+    void OnNetTypeChange( wxCommandEvent& event );
+
+    /* Event handlers for the stream output */
+    void OnSubsFileEnable( wxCommandEvent& event );
+    void OnSubsFileSettings( wxCommandEvent& WXUNUSED(event) );
+
+    /* Event handlers for the stream output */
+    void OnSoutEnable( wxCommandEvent& event );
+    void OnSoutSettings( wxCommandEvent& WXUNUSED(event) );
+
+    /* Event handlers for the caching option */
+    void OnCachingEnable( wxCommandEvent& event );
+    void OnCachingChange( wxCommandEvent& event );
+    void OnCachingChangeSpin( wxSpinEvent& event );
+
+    DECLARE_EVENT_TABLE();
+
+    intf_thread_t *p_intf;
+    wxWindow *p_parent;
+    int i_current_access_method;
+    int i_disc_type_selection;
+
+    int i_method; /* Normal or for the stream dialog ? */
+    int i_open_arg;
+
+    wxComboBox *mrl_combo;
+    wxNotebook *notebook;
+
+    /* Controls for the file panel */
+    wxComboBox *file_combo;
+    wxFileDialog *file_dialog;
+
+    /* Controls for the disc panel */
+    wxRadioBox *disc_type;
+    wxCheckBox *disc_probe;
+    wxTextCtrl *disc_device;
+    wxSpinCtrl *disc_title; int i_disc_title;
+    wxSpinCtrl *disc_chapter; int i_disc_chapter;
+    wxSpinCtrl *disc_sub; int i_disc_sub;
+    wxSpinCtrl *disc_audio; int i_disc_audio;
+
+    /* The media equivalent name for a DVD names. For example,
+     * "Title", is "Track" for a CD-DA */
+    wxStaticText *disc_title_label;
+    wxStaticText *disc_chapter_label;
+    wxStaticText *disc_sub_label;
+    wxStaticText *disc_audio_label;
+
+    /* Indicates if the disc device control was modified */
+    bool b_disc_device_changed;
+
+    /* Controls for the net panel */
+    wxRadioBox *net_type;
+    int i_net_type;
+    wxPanel *net_subpanels[4];
+    wxRadioButton *net_radios[4];
+    wxSpinCtrl *net_ports[4];
+    int        i_net_ports[4];
+    wxTextCtrl *net_addrs[4];
+    wxCheckBox *net_timeshift;
+    wxCheckBox *net_ipv6;
+
+    /* Controls for the subtitles file */
+    wxButton *subsfile_button;
+    wxCheckBox *subsfile_checkbox;
+    SubsFileDialog *subsfile_dialog;
+    wxArrayString subsfile_mrl;
+
+    /* Controls for the stream output */
+    wxButton *sout_button;
+    wxCheckBox *sout_checkbox;
+    SoutDialog *sout_dialog;
+    wxArrayString sout_mrl;
+
+    /* Controls for the caching options */
+    wxCheckBox *caching_checkbox;
+    wxSpinCtrl *caching_value;
+    int i_caching;
+};
+
+};
+
+enum
+{
+    FILE_ACCESS = 0,
+    DISC_ACCESS,
+    NET_ACCESS,
+
+    /* Auto-built panels */
+    CAPTURE_ACCESS
+};
+#define MAX_ACCESS CAPTURE_ACCESS
+
+
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/playlist.cpp b/modules/gui/wxwidgets/dialogs/playlist.cpp
new file mode 100644 (file)
index 0000000..c0bc252
--- /dev/null
@@ -0,0 +1,1534 @@
+/*****************************************************************************
+ * playlist.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2005 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
+ *          Clément Stenac <zorglub@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/OR MODIFy
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "dialogs/playlist.hpp"
+#include "dialogs/iteminfo.hpp"
+#include "interface.hpp" // Needed for D&D - TODO: Split
+
+#include "bitmaps/shuffle.xpm"
+#include "bitmaps/repeat.xpm"
+#include "bitmaps/loop.xpm"
+
+#include "bitmaps/type_unknown.xpm"
+#include "bitmaps/type_afile.xpm"
+#include "bitmaps/type_vfile.xpm"
+#include "bitmaps/type_net.xpm"
+#include "bitmaps/type_card.xpm"
+#include "bitmaps/type_disc.xpm"
+#include "bitmaps/type_cdda.xpm"
+#include "bitmaps/type_directory.xpm"
+#include "bitmaps/type_playlist.xpm"
+#include "bitmaps/type_node.xpm"
+
+#include <wx/dynarray.h>
+#include <wx/imaglist.h>
+
+#define HELP_SHUFFLE N_( "Shuffle" )
+#define HELP_LOOP N_( "Repeat All" )
+#define HELP_REPEAT N_( "Repeat One" )
+
+namespace wxvlc {
+/* Callback prototype */
+static int PlaylistChanged( vlc_object_t *, const char *,
+                            vlc_value_t, vlc_value_t, void * );
+static int PlaylistNext( vlc_object_t *, const char *,
+                         vlc_value_t, vlc_value_t, void * );
+static int ItemChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
+                      vlc_value_t oval, vlc_value_t nval, void *param );
+static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
+                      vlc_value_t oval, vlc_value_t nval, void *param );
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    /* menu items */
+    AddFile_Event = 1,
+    AddDir_Event,
+    AddMRL_Event,
+    Close_Event,
+    Open_Event,
+    Save_Event,
+
+    SortTitle_Event,
+    RSortTitle_Event,
+    Randomize_Event,
+
+    DeleteSelection_Event,
+    Random_Event,
+    Loop_Event,
+    Repeat_Event,
+
+    PopupPlay_Event,
+    PopupPlayThis_Event,
+    PopupPreparse_Event,
+    PopupSort_Event,
+    PopupDel_Event,
+    PopupInfo_Event,
+
+    SearchText_Event,
+    Search_Event,
+
+    /* controls */
+    TreeCtrl_Event,
+
+    Browse_Event,  /* For export playlist */
+
+    /* custom events */
+    UpdateItem_Event,
+    AppendItem_Event,
+    RemoveItem_Event,
+
+    MenuDummy_Event = wxID_HIGHEST + 999,
+
+    FirstView_Event = wxID_HIGHEST + 1000,
+    LastView_Event = wxID_HIGHEST + 1100,
+
+    FirstSD_Event = wxID_HIGHEST + 2000,
+    LastSD_Event = wxID_HIGHEST + 2100,
+};
+
+DEFINE_LOCAL_EVENT_TYPE( wxEVT_PLAYLIST );
+
+BEGIN_EVENT_TABLE(Playlist, wxFrame)
+    EVT_SIZE(Playlist::OnSize)
+
+    /* Menu events */
+    EVT_MENU(AddFile_Event, Playlist::OnAddFile)
+    EVT_MENU(AddDir_Event, Playlist::OnAddDir)
+    EVT_MENU(AddMRL_Event, Playlist::OnAddMRL)
+    EVT_MENU(Close_Event, Playlist::OnMenuClose)
+    EVT_MENU(Open_Event, Playlist::OnOpen)
+    EVT_MENU(Save_Event, Playlist::OnSave)
+
+    EVT_MENU(SortTitle_Event, Playlist::OnSort)
+    EVT_MENU(RSortTitle_Event, Playlist::OnSort)
+
+    EVT_MENU(Randomize_Event, Playlist::OnSort)
+
+    EVT_MENU(DeleteSelection_Event, Playlist::OnDeleteSelection)
+
+    EVT_MENU_OPEN( Playlist::OnMenuOpen )
+    EVT_MENU( -1, Playlist::OnMenuEvent )
+
+    EVT_TOOL(Random_Event, Playlist::OnRandom)
+    EVT_TOOL(Repeat_Event, Playlist::OnRepeat)
+    EVT_TOOL(Loop_Event, Playlist::OnLoop)
+
+    /* Popup events */
+    EVT_MENU( PopupPlay_Event, Playlist::OnPopupPlay)
+    EVT_MENU( PopupPlayThis_Event, Playlist::OnPopupPlay)
+    EVT_MENU( PopupPreparse_Event, Playlist::OnPopupPreparse)
+    EVT_MENU( PopupSort_Event, Playlist::OnPopupSort)
+    EVT_MENU( PopupDel_Event, Playlist::OnPopupDel)
+    EVT_MENU( PopupInfo_Event, Playlist::OnPopupInfo)
+
+    /* Tree control events */
+    EVT_TREE_ITEM_ACTIVATED( TreeCtrl_Event, Playlist::OnActivateItem )
+    EVT_TREE_KEY_DOWN( -1, Playlist::OnKeyDown )
+
+    EVT_CONTEXT_MENU( Playlist::OnPopup )
+
+    /* Button events */
+    EVT_BUTTON( Search_Event, Playlist::OnSearch)
+    EVT_BUTTON( Save_Event, Playlist::OnSave)
+
+    /*EVT_TEXT( SearchText_Event, Playlist::OnSearchTextChange )*/
+    EVT_TEXT_ENTER( SearchText_Event, Playlist::OnSearch )
+
+    /* Custom events */
+    EVT_COMMAND(-1, wxEVT_PLAYLIST, Playlist::OnPlaylistEvent)
+
+    /* Special events : we don't want to destroy the window when the user
+     * clicks on (X) */
+    EVT_CLOSE(Playlist::OnClose)
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * PlaylistItem class
+ ****************************************************************************/
+class PlaylistItem : public wxTreeItemData
+{
+public:
+    PlaylistItem( playlist_item_t *p_item ) : wxTreeItemData()
+    {
+        i_id = p_item->input.i_id;
+    }
+protected:
+    int i_id;
+friend class Playlist;
+};
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+Playlist::Playlist( intf_thread_t *_p_intf, wxWindow *p_parent ):
+    wxFrame( p_parent, -1, wxU(_("Playlist")), wxDefaultPosition,
+             wxSize(500,300), wxDEFAULT_FRAME_STYLE )
+{
+    vlc_value_t val;
+
+    /* Initializations */
+    p_intf = _p_intf;
+    pp_sds = NULL;
+    i_update_counter = 0;
+    i_sort_mode = MODE_NONE;
+    b_need_update = VLC_FALSE;
+    i_items_to_append = 0;
+    p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
+                                                FIND_ANYWHERE );
+    if( p_playlist == NULL ) return;
+
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    p_view_menu = NULL;
+    p_sd_menu = SDMenu();
+
+    i_current_view = VIEW_CATEGORY;
+    b_changed_view = VLC_FALSE;
+
+    i_title_sorted = 0;
+    i_group_sorted = 0;
+    i_duration_sorted = 0;
+
+    var_Create( p_intf, "random", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Create( p_intf, "loop", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+    var_Create( p_intf, "repeat", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );;
+
+    /* Create our "Manage" menu */
+    wxMenu *manage_menu = new wxMenu;
+    manage_menu->Append( AddFile_Event, wxU(_("&Simple Add File...")) );
+    manage_menu->Append( AddDir_Event, wxU(_("Add &Directory...")) );
+    manage_menu->Append( AddMRL_Event, wxU(_("&Add MRL...")) );
+    manage_menu->AppendSeparator();
+    manage_menu->Append( MenuDummy_Event, wxU(_("Services discovery")),
+                         p_sd_menu );
+    manage_menu->AppendSeparator();
+    manage_menu->Append( Open_Event, wxU(_("&Open Playlist...")) );
+    manage_menu->Append( Save_Event, wxU(_("&Save Playlist...")) );
+    manage_menu->AppendSeparator();
+    manage_menu->Append( Close_Event, wxU(_("&Close")) );
+
+    /* Create our "Sort" menu */
+    wxMenu *sort_menu = new wxMenu;
+    sort_menu->Append( SortTitle_Event, wxU(_("Sort by &title")) );
+    sort_menu->Append( RSortTitle_Event, wxU(_("&Reverse sort by title")) );
+    sort_menu->AppendSeparator();
+    sort_menu->Append( Randomize_Event, wxU(_("&Shuffle Playlist")) );
+
+    /* Create our "Selection" menu */
+    wxMenu *selection_menu = new wxMenu;
+    selection_menu->Append( DeleteSelection_Event, wxU(_("D&elete")) );
+
+    /* Create our "View" menu */
+    ViewMenu();
+
+    /* Append the freshly created menus to the menu bar */
+    wxMenuBar *menubar = new wxMenuBar();
+    menubar->Append( manage_menu, wxU(_("&Manage")) );
+    menubar->Append( sort_menu, wxU(_("S&ort")) );
+    menubar->Append( selection_menu, wxU(_("&Selection")) );
+    menubar->Append( p_view_menu, wxU(_("&View items") ) );
+
+    /* Attach the menu bar to the frame */
+    SetMenuBar( menubar );
+
+    /* Create the popup menu */
+    node_popup = new wxMenu;
+    node_popup->Append( PopupPlay_Event, wxU(_("Play")) );
+    node_popup->Append( PopupPlayThis_Event, wxU(_("Play this branch")) );
+    node_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
+    node_popup->Append( PopupSort_Event, wxU(_("Sort this branch")) );
+    node_popup->Append( PopupDel_Event, wxU(_("Delete")) );
+    node_popup->Append( PopupInfo_Event, wxU(_("Info")) );
+
+    item_popup = new wxMenu;
+    item_popup->Append( PopupPlay_Event, wxU(_("Play")) );
+    item_popup->Append( PopupPreparse_Event, wxU(_("Preparse")) );
+    item_popup->Append( PopupDel_Event, wxU(_("Delete")) );
+    item_popup->Append( PopupInfo_Event, wxU(_("Info")) );
+
+    /* Create a panel to put everything in */
+    wxPanel *playlist_panel = new wxPanel( this, -1 );
+    playlist_panel->SetAutoLayout( TRUE );
+
+    /* Create the toolbar */
+    wxToolBar *toolbar =
+        CreateToolBar( wxTB_HORIZONTAL | wxTB_FLAT );
+
+    /* Create the random tool */
+    toolbar->AddTool( Random_Event, wxT(""), wxBitmap(shuffle_on_xpm),
+                       wxBitmap(shuffle_on_xpm), wxITEM_CHECK,
+                       wxU(_(HELP_SHUFFLE) ) );
+    var_Get( p_intf, "random", &val );
+    toolbar->ToggleTool( Random_Event, val.b_bool );
+
+    /* Create the Loop tool */
+    toolbar->AddTool( Loop_Event, wxT(""), wxBitmap( loop_xpm),
+                      wxBitmap( loop_xpm), wxITEM_CHECK,
+                      wxU(_(HELP_LOOP )  ) );
+    var_Get( p_intf, "loop", &val );
+    toolbar->ToggleTool( Loop_Event, val.b_bool );
+
+    /* Create the Repeat one checkbox */
+    toolbar->AddTool( Repeat_Event, wxT(""), wxBitmap( repeat_xpm),
+                      wxBitmap( repeat_xpm), wxITEM_CHECK,
+                      wxU(_(HELP_REPEAT )  ) );
+    var_Get( p_intf, "repeat", &val );
+    toolbar->ToggleTool( Repeat_Event, val.b_bool ) ;
+
+    /* Create the Search Textbox */
+    search_text = new wxTextCtrl( toolbar, SearchText_Event, wxT(""),
+                                  wxDefaultPosition, wxSize(100, -1),
+                                  wxTE_PROCESS_ENTER);
+
+    /* Create the search button */
+    search_button = new wxButton( toolbar , Search_Event, wxU(_("Search")) );
+
+    toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
+                         wxSize(16, 16), wxBORDER_NONE ) );
+    toolbar->AddControl( search_text );
+    toolbar->AddControl( new wxControl( toolbar, -1, wxDefaultPosition,
+                         wxSize(5, 5), wxBORDER_NONE ) );
+    toolbar->AddControl( search_button );
+    search_button->SetDefault();
+    toolbar->Realize();
+
+    /* Create the tree */
+    treectrl = new wxTreeCtrl( playlist_panel, TreeCtrl_Event,
+                               wxDefaultPosition, wxDefaultSize,
+                               wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT|
+                               wxTR_NO_LINES |
+                               wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS |
+                               wxTR_MULTIPLE | wxTR_EXTENDED );
+
+    /* Create image list */
+    wxImageList *p_images = new wxImageList( 16 , 16, TRUE );
+
+    /* FIXME: absolutely needs to be in the right order FIXME */
+    p_images->Add( wxIcon( type_unknown_xpm ) );
+    p_images->Add( wxIcon( type_afile_xpm ) );
+    p_images->Add( wxIcon( type_vfile_xpm ) );
+    p_images->Add( wxIcon( type_directory_xpm ) );
+    p_images->Add( wxIcon( type_disc_xpm ) );
+    p_images->Add( wxIcon( type_cdda_xpm ) );
+    p_images->Add( wxIcon( type_card_xpm ) );
+    p_images->Add( wxIcon( type_net_xpm ) );
+    p_images->Add( wxIcon( type_playlist_xpm ) );
+    p_images->Add( wxIcon( type_node_xpm ) );
+    treectrl->AssignImageList( p_images );
+
+    treectrl->AddRoot( wxU(_("root" )), -1, -1, NULL );
+
+    /* Reduce font size */
+    wxFont font= treectrl->GetFont();
+    font.SetPointSize(9);
+    treectrl->SetFont( font );
+
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( treectrl, 1, wxEXPAND | wxALL, 5 );
+    panel_sizer->Layout();
+
+    playlist_panel->SetSizerAndFit( panel_sizer );
+
+    int pi_widths[1] =  { -1 };
+    statusbar = CreateStatusBar( 1 );
+    statusbar->SetStatusWidths( 1, pi_widths );
+
+#if wxUSE_DRAG_AND_DROP
+    /* Associate drop targets with the playlist */
+    SetDropTarget( new DragAndDrop( p_intf, VLC_TRUE ) );
+#endif
+
+    i_saved_id = -1;
+
+
+    /* We want to be noticed of playlist changes */
+
+    /* Some global changes happened -> Rebuild all */
+    var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
+
+    /* We went to the next item */
+    var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
+
+    /* One item has been updated */
+    var_AddCallback( p_playlist, "item-change", ItemChanged, this );
+
+    var_AddCallback( p_playlist, "item-append", ItemAppended, this );
+    var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
+
+    /* Update the playlist */
+    Rebuild( VLC_TRUE );
+
+}
+
+Playlist::~Playlist()
+{
+    if( pp_sds != NULL ) free( pp_sds );
+
+    if( p_playlist == NULL ) return;
+
+    var_DelCallback( p_playlist, "item-change", ItemChanged, this );
+    var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
+    var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
+    var_DelCallback( p_playlist, "item-append", ItemAppended, this );
+    var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
+    vlc_object_release( p_playlist );
+}
+
+/**********************************************************************
+ * Update functions
+ **********************************************************************/
+
+/* Update a node */
+void Playlist::UpdateNode( playlist_item_t *p_node, wxTreeItemId node )
+{
+    wxTreeItemIdValue cookie;
+    wxTreeItemId child;
+    for( int i = 0; i< p_node->i_children ; i++ )
+    {
+        if( i == 0 )
+        {
+            child = treectrl->GetFirstChild( node, cookie);
+        }
+        else
+        {
+            child = treectrl->GetNextChild( node, cookie );
+        }
+
+        if( !child.IsOk() )
+        {
+            /* Not enough children */
+            CreateNode( p_node->pp_children[i], node );
+            /* Keep the tree pointer up to date */
+            child = treectrl->GetNextChild( node, cookie );
+        }
+    }
+    treectrl->SetItemImage( node, p_node->input.i_type );
+
+}
+
+/* Creates the node p_node as last child of parent */
+void Playlist::CreateNode( playlist_item_t *p_node, wxTreeItemId parent )
+{
+    wxTreeItemId node =
+        treectrl->AppendItem( parent, wxL2U( p_node->input.psz_name ),
+                              -1,-1, new PlaylistItem( p_node ) );
+    treectrl->SetItemImage( node, p_node->input.i_type );
+
+    UpdateNodeChildren( p_node, node );
+}
+
+/* Update all children (recursively) of this node */
+void Playlist::UpdateNodeChildren( playlist_item_t *p_node,
+                                   wxTreeItemId node )
+{
+
+    for( int i = 0; i< p_node->i_children ; i++ )
+    {
+        /* Append the item */
+        if( p_node->pp_children[i]->i_children == -1 )
+        {
+            wxTreeItemId item =
+                treectrl->AppendItem( node,
+                    wxL2U( p_node->pp_children[i]->input.psz_name ), -1,-1,
+                           new PlaylistItem( p_node->pp_children[i]) );
+
+            UpdateTreeItem( item );
+        }
+        else
+        {
+            CreateNode( p_node->pp_children[i], node );
+        }
+    }
+}
+
+/* Update an item in the tree */
+void Playlist::UpdateTreeItem( wxTreeItemId item )
+{
+    if( ! item.IsOk() ) return;
+
+    wxTreeItemData *p_data = treectrl->GetItemData( item );
+    if( !p_data ) return;
+
+    LockPlaylist( p_intf->p_sys, p_playlist );
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
+                                          ((PlaylistItem *)p_data)->i_id );
+    if( !p_item )
+    {
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+        return;
+    }
+
+    wxString msg;
+    wxString duration = wxU( "" );
+    char *psz_author = vlc_input_item_GetInfo( &p_item->input,
+                                                     _("Meta-information"),
+                                                     _("Artist"));
+    if( !psz_author )
+    {
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+        return;
+    }
+
+    char psz_duration[MSTRTIME_MAX_SIZE];
+    mtime_t dur = p_item->input.i_duration;
+
+    if( dur != -1 )
+    {
+        secstotimestr( psz_duration, dur/1000000 );
+        duration.Append( wxU( " ( " ) +  wxString( wxU( psz_duration ) ) +
+                         wxU( " )" ) );
+    }
+
+    if( !strcmp( psz_author, "" ) || p_item->input.b_fixed_name == VLC_TRUE )
+    {
+        msg = wxString( wxU( p_item->input.psz_name ) ) + duration;
+    }
+    else
+    {
+        msg = wxString(wxU( psz_author )) + wxT(" - ") +
+                    wxString(wxU(p_item->input.psz_name)) + duration;
+    }
+    free( psz_author );
+    treectrl->SetItemText( item , msg );
+    treectrl->SetItemImage( item, p_item->input.i_type );
+
+    if( p_playlist->status.p_item == p_item )
+    {
+        treectrl->SetItemBold( item, true );
+        while( treectrl->GetItemParent( item ).IsOk() )
+        {
+            item = treectrl->GetItemParent( item );
+            treectrl->Expand( item );
+        }
+    }
+    else
+    {
+        treectrl->SetItemBold( item, false );
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+/* Process a AppendIt em request */
+void Playlist::AppendItem( wxCommandEvent& event )
+{
+    playlist_add_t *p_add = (playlist_add_t *)event.GetClientData();
+    playlist_item_t *p_item = NULL;
+    wxTreeItemId item, node;
+
+    i_items_to_append--;
+
+    /* No need to do anything if the playlist is going to be rebuilt */
+    if( b_need_update ) return;
+
+    if( p_add->i_view != i_current_view ) goto update;
+
+    node = FindItem( treectrl->GetRootItem(), p_add->i_node );
+    if( !node.IsOk() ) goto update;
+
+    p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
+    if( !p_item ) goto update;
+
+    item = FindItem( treectrl->GetRootItem(), p_add->i_item );
+    if( item.IsOk() ) goto update;
+
+    item = treectrl->AppendItem( node,
+                                 wxL2U( p_item->input.psz_name ), -1,-1,
+                                 new PlaylistItem( p_item ) );
+    treectrl->SetItemImage( item, p_item->input.i_type );
+
+    if( item.IsOk() && p_item->i_children == -1 )
+    {
+        UpdateTreeItem( item );
+    }
+
+update:
+    int i_count = CountItems( treectrl->GetRootItem());
+    if( i_count != p_playlist->i_size )
+    {
+        statusbar->SetStatusText( wxString::Format( wxU(_(
+                                  "%i items in playlist (%i not shown)")),
+                                  p_playlist->i_size,
+                                  p_playlist->i_size - i_count ) );
+        if( !b_changed_view )
+        {
+            i_current_view = VIEW_CATEGORY;
+            b_changed_view = VLC_TRUE;
+            b_need_update = VLC_TRUE;
+        }
+    }
+    else
+    {
+        statusbar->SetStatusText( wxString::Format( wxU(_(
+                                  "%i items in playlist")),
+                                  p_playlist->i_size ), 0 );
+    }
+
+    return;
+}
+
+/* Process a updateitem request */
+void Playlist::UpdateItem( int i )
+{
+    if( i < 0 ) return; /* Sanity check */
+
+    wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
+
+    if( item.IsOk() )
+    {
+        UpdateTreeItem( item );
+    }
+}
+
+void Playlist::RemoveItem( int i )
+{
+    if( i <= 0 ) return; /* Sanity check */
+    if( i == i_saved_id ) i_saved_id = -1;
+
+    wxTreeItemId item = FindItem( treectrl->GetRootItem(), i );
+
+    if( item.IsOk() )
+    {
+        treectrl->Delete( item );
+    }
+}
+
+
+/**********************************************************************
+ * Search functions (internal)
+ **********************************************************************/
+
+/* Find a wxItem from a playlist id */
+wxTreeItemId Playlist::FindItem( wxTreeItemId root, int i_id )
+{
+    wxTreeItemIdValue cookie;
+    PlaylistItem *p_wxcurrent;
+    wxTreeItemId search;
+    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+    wxTreeItemId child;
+
+    p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( root );
+
+    if( i_id < 0 )
+    {
+        wxTreeItemId dummy;
+        return dummy;
+    }
+    if( i_saved_id == i_id )
+    {
+        return saved_tree_item;
+    }
+
+    if( !p_wxcurrent )
+    {
+        wxTreeItemId dummy;
+        return dummy;
+    }
+
+    if( p_wxcurrent->i_id == i_id )
+    {
+        i_saved_id = i_id;
+        saved_tree_item = root;
+        return root;
+    }
+
+    while( item.IsOk() )
+    {
+        p_wxcurrent = (PlaylistItem *)treectrl->GetItemData( item );
+        if( p_wxcurrent->i_id == i_id )
+        {
+            i_saved_id = i_id;
+            saved_tree_item = item;
+            return item;
+        }
+        if( treectrl->ItemHasChildren( item ) )
+        {
+            wxTreeItemId search = FindItem( item, i_id );
+            if( search.IsOk() )
+            {
+                i_saved_id = i_id;
+                saved_tree_item = search;
+                return search;
+            }
+        }
+        item = treectrl->GetNextChild( root, cookie );
+    }
+    /* Not found */
+    wxTreeItemId dummy;
+    return dummy;
+}
+
+int Playlist::CountItems( wxTreeItemId root )
+{
+    wxTreeItemIdValue cookie;
+    int count = 0;
+    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+
+    while( item.IsOk() )
+    {
+        if( treectrl->ItemHasChildren( item ) )
+        {
+            count += CountItems( item );
+        }
+        else
+        {
+            playlist_item_t *p_item;
+            LockPlaylist( p_intf->p_sys, p_playlist );
+            p_item = playlist_ItemGetById( p_playlist, ((PlaylistItem *)treectrl->GetItemData( item ))->i_id );
+            if( p_item && p_item->i_children == -1 )
+                count++;
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+        }
+        item = treectrl->GetNextChild( root, cookie );
+    }
+    return count;
+}
+
+/* Find a wxItem from a name (from current) */
+wxTreeItemId Playlist::FindItemByName( wxTreeItemId root, wxString search_string, wxTreeItemId current, vlc_bool_t *pb_current_found )
+{
+    wxTreeItemIdValue cookie;
+    wxTreeItemId search;
+    wxTreeItemId item = treectrl->GetFirstChild( root, cookie );
+    wxTreeItemId child;
+
+    while( item.IsOk() )
+    {
+        if( treectrl->GetItemText( item).Lower().Contains(
+                                                 search_string.Lower() ) )
+        {
+            if( !current.IsOk() || *pb_current_found == VLC_TRUE )
+            {
+                return item;
+            }
+            else if( current.IsOk() && item == current )
+            {
+                *pb_current_found = VLC_TRUE;
+            }
+        }
+        if( treectrl->ItemHasChildren( item ) )
+        {
+            wxTreeItemId search = FindItemByName( item, search_string, current,
+                                                  pb_current_found );
+            if( search.IsOk() )
+            {
+                return search;
+            }
+        }
+        item = treectrl->GetNextChild( root, cookie);
+    }
+    /* Not found */
+    wxTreeItemId dummy;
+    return dummy;
+}
+
+/**********************************************************************
+ * Rebuild the playlist
+ **********************************************************************/
+void Playlist::Rebuild( vlc_bool_t b_root )
+{
+    playlist_view_t *p_view;
+
+    i_items_to_append = 0;
+
+    /* We can remove the callbacks before locking, anyway, we won't
+     * miss anything */
+    if( b_root )
+    {
+        var_DelCallback( p_playlist, "item-change", ItemChanged, this );
+        var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
+        var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
+        var_DelCallback( p_playlist, "item-append", ItemAppended, this );
+        var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
+
+        /* ...and rebuild it */
+        LockPlaylist( p_intf->p_sys, p_playlist );
+    }
+    i_saved_id = -1;
+
+    p_view = playlist_ViewFind( p_playlist, i_current_view ); /* FIXME */
+
+    /* HACK we should really get new*/
+    treectrl->DeleteAllItems();
+    treectrl->AddRoot( wxU(_("root" )), -1, -1,
+                         new PlaylistItem( p_view->p_root) );
+
+    wxTreeItemId root = treectrl->GetRootItem();
+    UpdateNode( p_view->p_root, root );
+
+    int i_count = CountItems( treectrl->GetRootItem() );
+
+    if( i_count < p_playlist->i_size && !b_changed_view )
+    {
+        i_current_view = VIEW_CATEGORY;
+        b_changed_view = VLC_TRUE;
+        Rebuild( VLC_FALSE );
+    }
+    else if( i_count != p_playlist->i_size )
+    {
+        statusbar->SetStatusText( wxString::Format( wxU(_(
+                                  "%i items in playlist (%i not shown)")),
+                                  p_playlist->i_size,
+                                  p_playlist->i_size - i_count ) );
+    }
+    else
+    {
+        statusbar->SetStatusText( wxString::Format( wxU(_(
+                                  "%i items in playlist")),
+                                  p_playlist->i_size ), 0 );
+    }
+
+    if( b_root )
+    {
+        /* Put callbacks back online */
+        var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
+        var_AddCallback( p_playlist, "playlist-current", PlaylistNext, this );
+        var_AddCallback( p_playlist, "item-change", ItemChanged, this );
+        var_AddCallback( p_playlist, "item-append", ItemAppended, this );
+        var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
+
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+    }
+}
+
+
+
+void Playlist::ShowPlaylist( bool show )
+{
+    if( show ) Rebuild( VLC_TRUE );
+    Show( show );
+}
+
+/* This function is called on a regular basis */
+void Playlist::UpdatePlaylist()
+{
+    i_update_counter++;
+
+    /* If the playlist isn't show there's no need to update it */
+    if( !IsShown() ) return;
+
+    if( this->b_need_update )
+    {
+        this->b_need_update = VLC_FALSE;
+        Rebuild( VLC_TRUE );
+    }
+
+    /* Updating the playing status every 0.5s is enough */
+    if( i_update_counter % 5 ) return;
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+void Playlist::DeleteTreeItem( wxTreeItemId item )
+{
+   PlaylistItem *p_wxitem;
+   playlist_item_t *p_item;
+   p_wxitem = (PlaylistItem *)treectrl->GetItemData( item );
+
+   LockPlaylist( p_intf->p_sys, p_playlist );
+   p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+
+   if( !p_item )
+   {
+       UnlockPlaylist( p_intf->p_sys, p_playlist );
+       return;
+   }
+
+   if( p_item->i_children == -1 ) DeleteItem( p_item->input.i_id );
+   else DeleteNode( p_item );
+
+   RemoveItem( item );
+   UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+void Playlist::DeleteItem( int item_id )
+{
+    playlist_LockDelete( p_playlist, item_id );
+}
+
+void Playlist::DeleteNode( playlist_item_t *p_item )
+{
+    playlist_NodeDelete( p_playlist, p_item, VLC_TRUE , VLC_FALSE );
+}
+
+void Playlist::OnMenuClose( wxCommandEvent& event )
+{
+    wxCloseEvent cevent;
+    OnClose(cevent);
+}
+
+void Playlist::OnClose( wxCloseEvent& WXUNUSED(event) )
+{
+    Hide();
+}
+
+void Playlist::OnSave( wxCommandEvent& WXUNUSED(event) )
+{
+    struct {
+        char *psz_desc;
+        char *psz_filter;
+        char *psz_module;
+    } formats[] = {{ _("M3U file"), "*.m3u", "export-m3u" }};
+
+    wxString filter = wxT("");
+
+    if( p_playlist->i_size == 0 )
+    {
+        wxMessageBox( wxU(_("Playlist is empty") ), wxU(_("Can't save")),
+                      wxICON_WARNING | wxOK, this );
+        return;
+    }
+
+    for( unsigned int i = 0; i < sizeof(formats)/sizeof(formats[0]); i++)
+    {
+        filter.Append( wxU(formats[i].psz_desc) );
+        filter.Append( wxT("|") );
+        filter.Append( wxU(formats[i].psz_filter) );
+        filter.Append( wxT("|") );
+    }
+    wxFileDialog dialog( this, wxU(_("Save playlist")),
+                         wxT(""), wxT(""), filter, wxSAVE );
+
+    if( dialog.ShowModal() == wxID_OK )
+    {
+        if( dialog.GetPath().mb_str() )
+        {
+            playlist_Export( p_playlist, dialog.GetPath().mb_str(),
+                             formats[dialog.GetFilterIndex()].psz_module );
+        }
+    }
+
+}
+
+void Playlist::OnOpen( wxCommandEvent& WXUNUSED(event) )
+{
+    wxFileDialog dialog( this, wxU(_("Open playlist")), wxT(""), wxT(""),
+        wxT("All playlists|*.pls;*.m3u;*.asx;*.b4s|M3U files|*.m3u"), wxOPEN );
+
+    if( dialog.ShowModal() == wxID_OK )
+    {
+        playlist_Import( p_playlist, dialog.GetPath().mb_str() );
+    }
+}
+
+void Playlist::OnAddFile( wxCommandEvent& WXUNUSED(event) )
+{
+    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE_SIMPLE, 0, 0 );
+
+}
+
+void Playlist::OnAddDir( wxCommandEvent& WXUNUSED(event) )
+{
+    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_DIRECTORY, 0, 0 );
+
+}
+
+void Playlist::OnAddMRL( wxCommandEvent& WXUNUSED(event) )
+{
+    p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_FILE, 0, 0 );
+
+}
+
+/********************************************************************
+ * Sorting functions
+ ********************************************************************/
+void Playlist::OnSort( wxCommandEvent& event )
+{
+    PlaylistItem *p_wxitem;
+    p_wxitem = (PlaylistItem *)treectrl->GetItemData( treectrl->GetRootItem() );
+
+    LockPlaylist( p_intf->p_sys, p_playlist );
+    switch( event.GetId() )
+    {
+        case SortTitle_Event:
+            playlist_RecursiveNodeSort( p_playlist,
+                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
+                            SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
+            break;
+        case RSortTitle_Event:
+            playlist_RecursiveNodeSort( p_playlist,
+                            playlist_ItemGetById( p_playlist, p_wxitem->i_id ),
+                            SORT_TITLE_NODES_FIRST, ORDER_REVERSE );
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+
+    Rebuild( VLC_TRUE );
+}
+
+/**********************************************************************
+ * Search functions (user)
+ **********************************************************************/
+/*void Playlist::OnSearchTextChange( wxCommandEvent& WXUNUSED(event) )
+{
+   search_button->SetDefault();
+}*/
+
+void Playlist::OnSearch( wxCommandEvent& WXUNUSED(event) )
+{
+    wxString search_string = search_text->GetValue();
+
+    vlc_bool_t pb_found = VLC_FALSE;
+
+    wxTreeItemId found =
+     FindItemByName( treectrl->GetRootItem(), search_string,
+                     search_current, &pb_found );
+
+    if( !found.IsOk() )
+    {
+        wxTreeItemId dummy;
+        search_current = dummy;
+        found =  FindItemByName( treectrl->GetRootItem(), search_string,
+                                 search_current, &pb_found );
+    }
+
+    if( found.IsOk() )
+    {
+        search_current = found;
+        treectrl->EnsureVisible( found );
+        treectrl->SelectItem( found, true );
+    }
+}
+
+/**********************************************************************
+ * Selection functions
+ **********************************************************************/
+void Playlist::RecursiveDeleteSelection(  wxTreeItemId root )
+{
+    wxTreeItemIdValue cookie;
+    wxTreeItemId child = treectrl->GetFirstChild( root, cookie );
+    while( child.IsOk() )
+    {
+        if( treectrl->ItemHasChildren( child ) )
+        {
+            RecursiveDeleteSelection( child );
+            if( treectrl->IsSelected(child ) ) DeleteTreeItem( child );
+        }
+        else if( treectrl->IsSelected( child ) )
+            DeleteTreeItem( child );
+        child = treectrl->GetNextChild( root, cookie );
+    }
+}
+
+void Playlist::OnDeleteSelection( wxCommandEvent& WXUNUSED(event) )
+{
+    RecursiveDeleteSelection( treectrl->GetRootItem() );
+}
+
+/**********************************************************************
+ * Playlist mode functions
+ **********************************************************************/
+void Playlist::OnRandom( wxCommandEvent& event )
+{
+    vlc_value_t val;
+    val.b_bool = event.IsChecked();
+    var_Set( p_playlist, "random", val);
+}
+
+void Playlist::OnLoop( wxCommandEvent& event )
+{
+    vlc_value_t val;
+    val.b_bool = event.IsChecked();
+    var_Set( p_playlist, "loop", val);
+}
+
+void Playlist::OnRepeat( wxCommandEvent& event )
+{
+    vlc_value_t val;
+    val.b_bool = event.IsChecked();
+    var_Set( p_playlist, "repeat", val);
+}
+
+/********************************************************************
+ * Event
+ ********************************************************************/
+void Playlist::OnActivateItem( wxTreeEvent& event )
+{
+    playlist_item_t *p_item,*p_node,*p_item2,*p_node2;
+
+    PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
+                                                            event.GetItem() );
+    wxTreeItemId parent = treectrl->GetItemParent( event.GetItem() );
+
+    PlaylistItem *p_wxparent = (PlaylistItem *)treectrl->GetItemData( parent );
+
+    LockPlaylist( p_intf->p_sys, p_playlist );
+
+    if( !( p_wxitem && p_wxparent ) )
+    {
+        UnlockPlaylist( p_intf->p_sys, p_playlist );
+        return;
+    }
+
+    p_item2 = playlist_ItemGetById(p_playlist, p_wxitem->i_id);
+    p_node2 = playlist_ItemGetById(p_playlist, p_wxparent->i_id);
+    if( p_item2 && p_item2->i_children == -1 )
+    {
+        p_node = p_node2;
+        p_item = p_item2;
+    }
+    else
+    {
+        p_node = p_item2;
+        if( p_node && p_node->i_children > 0 &&
+            p_node->pp_children[0]->i_children == -1)
+        {
+            p_item = p_node->pp_children[0];
+        }
+        else
+        {
+            p_item = NULL;
+        }
+    }
+
+    playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, i_current_view,
+                      p_node, p_item );
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+void Playlist::OnKeyDown( wxTreeEvent& event )
+{
+    long keycode = event.GetKeyCode();
+    /* Delete selected items */
+    if( keycode == WXK_BACK || keycode == WXK_DELETE )
+    {
+        /* We send a dummy event */
+        OnDeleteSelection( event );
+    }
+    else
+    {
+        event.Skip();
+    }
+}
+
+void Playlist::OnEnDis( wxCommandEvent& event )
+{
+    msg_Warn( p_intf, "not implemented" );
+}
+
+/**********************************************************************
+ * Menu
+ **********************************************************************/
+
+void Playlist::OnMenuOpen( wxMenuEvent& event)
+{
+#if defined( __WXMSW__ )
+#   define GetEventObject GetMenu
+#endif
+
+    if( event.GetEventObject() == p_view_menu )
+    {
+        p_view_menu = ViewMenu();
+    }
+#if defined( __WXMSW__ )
+#   undef GetEventObject
+#endif
+}
+
+void Playlist::OnMenuEvent( wxCommandEvent& event )
+{
+    if( event.GetId() < FirstView_Event )
+    {
+        event.Skip();
+        return;
+    }
+    else if( event.GetId() < LastView_Event )
+    {
+
+        int i_new_view = event.GetId() - FirstView_Event;
+
+        playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_new_view );
+
+        if( p_view != NULL )
+        {
+            b_changed_view = VLC_TRUE;
+            i_current_view = i_new_view;
+            playlist_ViewUpdate( p_playlist, i_new_view );
+            Rebuild( VLC_TRUE );
+            return;
+        }
+        else if( i_new_view >= VIEW_FIRST_SORTED &&
+                 i_new_view <= VIEW_LAST_SORTED )
+        {
+            b_changed_view = VLC_TRUE;
+            playlist_ViewInsert( p_playlist, i_new_view, "View" );
+            playlist_ViewUpdate( p_playlist, i_new_view );
+
+            i_current_view = i_new_view;
+
+            Rebuild( VLC_TRUE );
+        }
+    }
+    else if( event.GetId() >= FirstSD_Event && event.GetId() < LastSD_Event )
+    {
+        if( !playlist_IsServicesDiscoveryLoaded( p_playlist,
+                                pp_sds[event.GetId() - FirstSD_Event] ) )
+        {
+            playlist_ServicesDiscoveryAdd( p_playlist,
+                            pp_sds[event.GetId() - FirstSD_Event] );
+        }
+        else
+        {
+            //wxMutexGuiLeave();
+            playlist_ServicesDiscoveryRemove( p_playlist,
+                            pp_sds[event.GetId() - FirstSD_Event] );
+            //wxMutexGuiEnter();
+        }
+    }
+}
+
+wxMenu * Playlist::ViewMenu()
+{
+    if( !p_view_menu )
+    {
+        p_view_menu = new wxMenu;
+    }
+    else
+    {
+        wxMenuItemList::Node *node = p_view_menu->GetMenuItems().GetFirst();
+        for( ; node; )
+        {
+            wxMenuItem *item = node->GetData();
+            node = node->GetNext();
+            p_view_menu->Delete( item );
+        }
+    }
+
+    /* FIXME : have a list of "should have" views */
+    p_view_menu->Append( FirstView_Event + VIEW_CATEGORY,
+                           wxU(_("Normal") ) );
+    p_view_menu->Append( FirstView_Event + VIEW_S_AUTHOR,
+                           wxU(_("Sorted by artist") ) );
+    p_view_menu->Append( FirstView_Event + VIEW_S_ALBUM,
+                           wxU(_("Sorted by Album") ) );
+
+    return p_view_menu;
+}
+
+wxMenu *Playlist::SDMenu()
+{
+    p_sd_menu = new wxMenu;
+
+    vlc_list_t *p_list = vlc_list_find( p_playlist, VLC_OBJECT_MODULE,
+                                        FIND_ANYWHERE );
+
+    int i_number = 0;
+    for( int i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
+            i_number++;
+    }
+    if( i_number ) pp_sds = (char **)calloc( i_number, sizeof(void *) );
+
+    i_number = 0;
+    for( int i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        module_t * p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !strcmp( p_parser->psz_capability, "services_discovery" ) )
+        {
+            p_sd_menu->AppendCheckItem( FirstSD_Event + i_number ,
+                wxU( p_parser->psz_longname ? p_parser->psz_longname :
+                     (p_parser->psz_shortname ?
+                      p_parser->psz_shortname : p_parser->psz_object_name) ) );
+
+            if( playlist_IsServicesDiscoveryLoaded( p_playlist,
+                                    p_parser->psz_object_name ) )
+            {
+                p_sd_menu->Check( FirstSD_Event + i_number, TRUE );
+            }
+
+            pp_sds[i_number++] = p_parser->psz_object_name;
+        }
+    }
+    vlc_list_release( p_list );
+    return p_sd_menu;
+}
+
+
+/*****************************************************************************
+ * Popup management functions
+ *****************************************************************************/
+void Playlist::OnPopup( wxContextMenuEvent& event )
+{
+    wxPoint pt = event.GetPosition();
+    playlist_item_t *p_item;
+
+    i_wx_popup_item = treectrl->HitTest( ScreenToClient( pt ) );
+    if( i_wx_popup_item.IsOk() )
+    {
+        PlaylistItem *p_wxitem = (PlaylistItem *)treectrl->GetItemData(
+                                                            i_wx_popup_item );
+        PlaylistItem *p_wxparent= (PlaylistItem *)treectrl->GetItemData(
+                                  treectrl->GetItemParent( i_wx_popup_item ) );
+        i_popup_item = p_wxitem->i_id;
+        i_popup_parent = p_wxparent->i_id;
+        treectrl->SelectItem( i_wx_popup_item );
+
+        LockPlaylist( p_intf->p_sys, p_playlist );
+        p_item = playlist_ItemGetById( p_playlist, i_popup_item );
+
+        if( !p_item )
+        {
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+            return;
+        }
+        if( p_item->i_children == -1 )
+        {
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+            Playlist::PopupMenu( item_popup,
+                                 ScreenToClient( wxGetMousePosition() ) );
+        }
+        else
+        {
+            UnlockPlaylist( p_intf->p_sys, p_playlist );
+            Playlist::PopupMenu( node_popup,
+                                 ScreenToClient( wxGetMousePosition() ) );
+        }
+    }
+}
+
+void Playlist::OnPopupPlay( wxCommandEvent& event )
+{
+    playlist_item_t *p_popup_item, *p_popup_parent;
+    LockPlaylist( p_intf->p_sys, p_playlist );
+    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    p_popup_parent = playlist_ItemGetById( p_playlist, i_popup_parent );
+    if( p_popup_item != NULL )
+    {
+        if( p_popup_item->i_children > -1 )
+        {
+            if( event.GetId() == PopupPlay_Event &&
+                p_popup_item->i_children > 0 )
+            {
+                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+                                  i_current_view, p_popup_item,
+                                  p_popup_item->pp_children[0] );
+            }
+            else
+            {
+                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+                                  i_current_view, p_popup_item, NULL );
+            }
+        }
+        else
+        {
+            if( event.GetId() == PopupPlay_Event )
+            {
+                playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+                                  i_current_view, p_popup_parent,
+                                  p_popup_item );
+            }
+        }
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+void Playlist::OnPopupPreparse( wxCommandEvent& event )
+{
+    Preparse();
+}
+
+void Playlist::Preparse()
+{
+    playlist_item_t *p_popup_item;
+    LockPlaylist( p_intf->p_sys, p_playlist );
+    p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+
+    if( p_popup_item != NULL )
+    {
+        if( p_popup_item->i_children == -1 )
+        {
+            playlist_PreparseEnqueue( p_playlist, &p_popup_item->input );
+        }
+        else
+        {
+            int i = 0;
+            playlist_item_t *p_parent = p_popup_item;
+            for( i = 0; i< p_parent->i_children ; i++ )
+            {
+                wxMenuEvent dummy;
+                i_wx_popup_item = FindItem( treectrl->GetRootItem(),
+                                         p_parent->pp_children[i]->input.i_id );
+                i_popup_item = p_parent->pp_children[i]->input.i_id;
+                Preparse();
+            }
+        }
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+void Playlist::OnPopupDel( wxCommandEvent& event )
+{
+    DeleteTreeItem( i_wx_popup_item );
+}
+
+void Playlist::OnPopupSort( wxCommandEvent& event )
+{
+    PlaylistItem *p_wxitem;
+    playlist_item_t *p_item;
+
+    p_wxitem = (PlaylistItem *)treectrl->GetItemData( i_wx_popup_item );
+    LockPlaylist( p_intf->p_sys, p_playlist );
+
+    p_item = playlist_ItemGetById( p_playlist, p_wxitem->i_id );
+    if( p_item->i_children >= 0 )
+    {
+        playlist_RecursiveNodeSort( p_playlist, p_item,
+                                    SORT_TITLE_NODES_FIRST, ORDER_NORMAL );
+
+        treectrl->DeleteChildren( i_wx_popup_item );
+        i_saved_id = -1;
+        UpdateNodeChildren( p_item, i_wx_popup_item );
+
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+void Playlist::OnPopupInfo( wxCommandEvent& event )
+{
+    LockPlaylist( p_intf->p_sys, p_playlist );
+    playlist_item_t *p_popup_item = playlist_ItemGetById( p_playlist, i_popup_item );
+    if( p_popup_item )
+    {
+        iteminfo_dialog = new ItemInfoDialog( p_intf, p_popup_item, this );
+        if( iteminfo_dialog->ShowModal() == wxID_OK )
+        {
+            UpdateItem( i_wx_popup_item );
+        }
+        delete iteminfo_dialog;
+    }
+    UnlockPlaylist( p_intf->p_sys, p_playlist );
+}
+
+
+/*****************************************************************************
+ * Custom events management
+ *****************************************************************************/
+void Playlist::OnPlaylistEvent( wxCommandEvent& event )
+{
+    switch( event.GetId() )
+    {
+        case UpdateItem_Event:
+            UpdateItem( event.GetInt() );
+            break;
+        case AppendItem_Event:
+            AppendItem( event );
+            break;
+        case RemoveItem_Event:
+            RemoveItem( event.GetInt() );
+            break;
+    }
+}
+
+/*****************************************************************************
+ * PlaylistChanged: callback triggered by the intf-change playlist variable
+ *  We don't rebuild the playlist directly here because we don't want the
+ *  caller to block for a too long time.
+ *****************************************************************************/
+static int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable,
+                            vlc_value_t oval, vlc_value_t nval, void *param )
+{
+    Playlist *p_playlist_dialog = (Playlist *)param;
+    p_playlist_dialog->b_need_update = VLC_TRUE;
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * Next: callback triggered by the playlist-current playlist variable
+ *****************************************************************************/
+static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable,
+                         vlc_value_t oval, vlc_value_t nval, void *param )
+{
+    Playlist *p_playlist_dialog = (Playlist *)param;
+
+    wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
+    event.SetInt( oval.i_int );
+    p_playlist_dialog->AddPendingEvent( event );
+    event.SetInt( nval.i_int );
+    p_playlist_dialog->AddPendingEvent( event );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * ItemChanged: callback triggered by the item-change playlist variable
+ *****************************************************************************/
+static int ItemChanged( vlc_object_t *p_this, const char *psz_variable,
+                        vlc_value_t old_val, vlc_value_t new_val, void *param )
+{
+    Playlist *p_playlist_dialog = (Playlist *)param;
+
+    wxCommandEvent event( wxEVT_PLAYLIST, UpdateItem_Event );
+    event.SetInt( new_val.i_int );
+    p_playlist_dialog->AddPendingEvent( event );
+
+    return 0;
+}
+static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
+                        vlc_value_t old_val, vlc_value_t new_val, void *param )
+{
+    Playlist *p_playlist_dialog = (Playlist *)param;
+
+    wxCommandEvent event( wxEVT_PLAYLIST, RemoveItem_Event );
+    event.SetInt( new_val.i_int );
+    p_playlist_dialog->AddPendingEvent( event );
+
+    return 0;
+}
+
+static int ItemAppended( vlc_object_t *p_this, const char *psz_variable,
+                         vlc_value_t oval, vlc_value_t nval, void *param )
+{
+    Playlist *p_playlist_dialog = (Playlist *)param;
+
+    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));
+    memcpy( p_add, nval.p_address, sizeof( playlist_add_t ) );
+
+    if( p_playlist_dialog->i_items_to_append++ > 50 )
+    {
+        /* Too many items waiting to be added, it will be quicker to rebuild
+         * the whole playlist */
+        p_playlist_dialog->b_need_update = VLC_TRUE;
+        return VLC_SUCCESS;
+    }
+
+    wxCommandEvent event( wxEVT_PLAYLIST, AppendItem_Event );
+    event.SetClientData( (void *)p_add );
+    p_playlist_dialog->AddPendingEvent( event );
+
+    return VLC_SUCCESS;
+}
+}
diff --git a/modules/gui/wxwidgets/dialogs/playlist.hpp b/modules/gui/wxwidgets/dialogs/playlist.hpp
new file mode 100644 (file)
index 0000000..81a6555
--- /dev/null
@@ -0,0 +1,176 @@
+/*****************************************************************************
+ * playlist.hpp: Header for the playlist
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12502 2005-09-09 19:38:01Z gbazin $
+ *
+ * Authors: Clément Stenac <zorglub@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_PLAYLIST_H_
+#define _WXVLC_PLAYLIST_H_
+
+#include "wxwidgets.hpp"
+
+#include <wx/treectrl.h>
+
+#define MODE_NONE 0
+#define MODE_GROUP 1
+#define MODE_AUTHOR 2
+#define MODE_TITLE 3
+
+#define OPEN_NORMAL 0
+#define OPEN_STREAM 1
+
+namespace wxvlc
+{
+class ItemInfoDialog;
+class NewGroup;
+class ExportPlaylist;
+
+/* Playlist */
+class Playlist: public wxFrame
+{
+public:
+    /* Constructor */
+    Playlist( intf_thread_t *p_intf, wxWindow *p_parent );
+    virtual ~Playlist();
+
+    void UpdatePlaylist();
+    void ShowPlaylist( bool show );
+    void UpdateItem( int );
+    void AppendItem( wxCommandEvent& );
+
+    bool b_need_update;
+    int  i_items_to_append;
+
+private:
+    void RemoveItem( int );
+    void DeleteTreeItem( wxTreeItemId );
+    void DeleteItem( int item );
+    void DeleteNode( playlist_item_t *node );
+
+    void RecursiveDeleteSelection( wxTreeItemId );
+
+    /* Event handlers (these functions should _not_ be virtual) */
+
+    /* Menu Handlers */
+    void OnAddFile( wxCommandEvent& event );
+    void OnAddDir( wxCommandEvent& event );
+    void OnAddMRL( wxCommandEvent& event );
+    void OnMenuClose( wxCommandEvent& event );
+    void OnClose( wxCloseEvent& WXUNUSED(event) );
+
+    void OnDeleteSelection( wxCommandEvent& event );
+
+    void OnOpen( wxCommandEvent& event );
+    void OnSave( wxCommandEvent& event );
+
+    /* Search (user) */
+    void OnSearch( wxCommandEvent& event );
+    /*void OnSearchTextChange( wxCommandEvent& event );*/
+    wxTextCtrl *search_text;
+    wxButton *search_button;
+    wxTreeItemId search_current;
+
+    void OnEnDis( wxCommandEvent& event );
+
+    /* Sort */
+    int i_sort_mode;
+    void OnSort( wxCommandEvent& event );
+    int i_title_sorted;
+    int i_group_sorted;
+    int i_duration_sorted;
+
+    /* Dynamic menus */
+    void OnMenuEvent( wxCommandEvent& event );
+    void OnMenuOpen( wxMenuEvent& event );
+    wxMenu *p_view_menu;
+    wxMenu *p_sd_menu;
+    wxMenu *ViewMenu();
+    wxMenu *SDMenu();
+
+    void OnUp( wxCommandEvent& event);
+    void OnDown( wxCommandEvent& event);
+
+    void OnRandom( wxCommandEvent& event );
+    void OnRepeat( wxCommandEvent& event );
+    void OnLoop ( wxCommandEvent& event );
+
+    void OnActivateItem( wxTreeEvent& event );
+    void OnKeyDown( wxTreeEvent& event );
+    void OnNewGroup( wxCommandEvent& event );
+
+    /* Popup  */
+    wxMenu *item_popup;
+    wxMenu *node_popup;
+    wxTreeItemId i_wx_popup_item;
+    int i_popup_item;
+    int i_popup_parent;
+    void OnPopup( wxContextMenuEvent& event );
+    void OnPopupPlay( wxCommandEvent& event );
+    void OnPopupPreparse( wxCommandEvent& event );
+    void OnPopupSort( wxCommandEvent& event );
+    void OnPopupDel( wxCommandEvent& event );
+    void OnPopupEna( wxCommandEvent& event );
+    void OnPopupInfo( wxCommandEvent& event );
+    void Rebuild( vlc_bool_t );
+
+    void Preparse();
+
+    /* Update */
+    void UpdateNode( playlist_item_t*, wxTreeItemId );
+    void UpdateNodeChildren( playlist_item_t*, wxTreeItemId );
+    void CreateNode( playlist_item_t*, wxTreeItemId );
+    void UpdateTreeItem( wxTreeItemId );
+
+    /* Search (internal) */
+    int CountItems( wxTreeItemId);
+    wxTreeItemId FindItem( wxTreeItemId, int );
+    wxTreeItemId FindItemByName( wxTreeItemId, wxString,
+                                 wxTreeItemId, vlc_bool_t *);
+
+    wxTreeItemId saved_tree_item;
+    int i_saved_id;
+
+    playlist_t *p_playlist;
+
+
+    /* Custom events */
+    void OnPlaylistEvent( wxCommandEvent& event );
+
+    DECLARE_EVENT_TABLE();
+
+
+    /* Global widgets */
+    wxStatusBar *statusbar;
+    ItemInfoDialog *iteminfo_dialog;
+
+    int i_update_counter;
+
+    intf_thread_t *p_intf;
+    wxTreeCtrl *treectrl;
+    int i_current_view;
+    vlc_bool_t b_changed_view;
+    char **pp_sds;
+
+
+};
+
+} // end of wxvlc namespace
+
+#endif
diff --git a/modules/gui/wxwidgets/dialogs/preferences.cpp b/modules/gui/wxwidgets/dialogs/preferences.cpp
new file mode 100644 (file)
index 0000000..e723eed
--- /dev/null
@@ -0,0 +1,1114 @@
+/*****************************************************************************
+ * preferences.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+
+#include "dialogs/preferences.hpp"
+#include <vlc_config_cat.h>
+#include "dialogs/preferences_widgets.h"
+
+#include <wx/combobox.h>
+#include <wx/statline.h>
+#include <wx/clntdata.h>
+#include <wx/dynarray.h>
+#include <wx/imaglist.h>
+#include <wx/treectrl.h>
+
+#include "bitmaps/type_net.xpm"
+#include "bitmaps/codec.xpm"
+#include "bitmaps/video.xpm"
+#include "bitmaps/type_playlist.xpm"
+#include "bitmaps/advanced.xpm"
+#include "bitmaps/intf.xpm"
+#include "bitmaps/audio.xpm"
+
+#ifndef wxRB_SINGLE
+#   define wxRB_SINGLE 0
+#endif
+
+#define TYPE_CATEGORY 0
+#define TYPE_CATSUBCAT 1  /* Category with embedded subcategory */
+#define TYPE_SUBCATEGORY 2
+#define TYPE_MODULE 3
+
+/*****************************************************************************
+ * Classes declarations.
+ *****************************************************************************/
+class ConfigTreeData;
+class PrefsTreeCtrl : public wxTreeCtrl
+{
+public:
+
+    PrefsTreeCtrl() { }
+    PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
+                   PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
+    virtual ~PrefsTreeCtrl();
+
+    void ApplyChanges();
+    void CleanChanges();
+
+private:
+    /* Event handlers (these functions should _not_ be virtual) */
+    void OnSelectTreeItem( wxTreeEvent& event );
+    void OnAdvanced( wxCommandEvent& event );
+
+    ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
+
+    DECLARE_EVENT_TABLE()
+
+    intf_thread_t *p_intf;
+    PrefsDialog *p_prefs_dialog;
+    wxBoxSizer *p_sizer;
+    wxWindow *p_parent;
+    vlc_bool_t b_advanced;
+
+    wxTreeItemId root_item;
+    wxTreeItemId plugins_item;
+};
+
+WX_DEFINE_ARRAY(ConfigControl *, ArrayOfConfigControls);
+
+class PrefsPanel : public wxPanel
+{
+public:
+
+    PrefsPanel() { }
+    PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
+                PrefsDialog *, ConfigTreeData* );
+    virtual ~PrefsPanel() {}
+
+    void ApplyChanges();
+    void SwitchAdvanced( vlc_bool_t );
+
+private:
+    intf_thread_t *p_intf;
+    PrefsDialog *p_prefs_dialog;
+
+    vlc_bool_t b_advanced;
+
+    wxStaticText *hidden_text;
+    wxBoxSizer *config_sizer;
+    wxScrolledWindow *config_window;
+
+    ArrayOfConfigControls config_array;
+};
+
+class ConfigTreeData : public wxTreeItemData
+{
+public:
+
+    ConfigTreeData() { b_submodule = 0; panel = NULL; psz_name = NULL;
+                       psz_help = NULL; }
+    virtual ~ConfigTreeData() {
+                                 if( panel ) delete panel;
+                                 if( psz_name ) free( psz_name );
+                                 if( psz_help ) free( psz_help );
+                              };
+
+    vlc_bool_t b_submodule;
+
+    PrefsPanel *panel;
+    wxBoxSizer *sizer;
+
+    int i_object_id;
+    int i_subcat_id;
+    int i_type;
+    char *psz_name;
+    char *psz_help;
+};
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Notebook_Event = wxID_HIGHEST,
+    MRL_Event,
+    ResetAll_Event,
+    Advanced_Event,
+};
+
+BEGIN_EVENT_TABLE(PrefsDialog, wxFrame)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
+    EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
+    EVT_BUTTON(wxID_SAVE, PrefsDialog::OnSave)
+    EVT_BUTTON(ResetAll_Event, PrefsDialog::OnResetAll)
+    EVT_CHECKBOX(Advanced_Event, PrefsDialog::OnAdvanced)
+
+    /* Don't destroy the window when the user closes it */
+    EVT_CLOSE(PrefsDialog::OnClose)
+END_EVENT_TABLE()
+
+// menu and control ids
+enum
+{
+    PrefsTree_Ctrl = wxID_HIGHEST
+};
+
+BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
+    EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
+    EVT_COMMAND(Advanced_Event, wxEVT_USER_FIRST, PrefsTreeCtrl::OnAdvanced)
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, wxWindow *p_parent)
+  :  wxFrame( p_parent, -1, wxU(_("Preferences")), wxDefaultPosition,
+              wxSize(700,450), wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    /* Create a panel to put everything in */
+    wxPanel *panel = new wxPanel( this, -1 );
+    panel->SetAutoLayout( TRUE );
+
+    /* Create the preferences tree control */
+    wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
+    prefs_tree =
+        new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
+
+    /* Separation */
+    wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
+
+    /* Create the buttons */
+    wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
+    ok_button->SetDefault();
+    wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
+                                            wxU(_("Cancel")) );
+    wxButton *save_button = new wxButton( panel, wxID_SAVE, wxU(_("Save")) );
+    wxButton *reset_button = new wxButton( panel, ResetAll_Event,
+                                           wxU(_("Reset All")) );
+
+    wxPanel *dummy_panel = new wxPanel( this, -1 );
+    wxCheckBox *advanced_checkbox =
+        new wxCheckBox( panel, Advanced_Event, wxU(_("Advanced options")) );
+
+    if( config_GetInt( p_intf, "advanced" ) )
+    {
+        advanced_checkbox->SetValue(TRUE);
+        wxCommandEvent dummy_event;
+        dummy_event.SetInt(TRUE);
+        OnAdvanced( dummy_event );
+    }
+
+    /* Place everything in sizers */
+    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+    button_sizer->Add( ok_button, 0, wxALL, 5 );
+    button_sizer->Add( cancel_button, 0, wxALL, 5 );
+    button_sizer->Add( save_button, 0, wxALL, 5 );
+    button_sizer->Add( reset_button, 0, wxALL, 5 );
+    button_sizer->Add( dummy_panel, 1, wxALL, 5 );
+    button_sizer->Add( advanced_checkbox, 0, wxALL | wxALIGN_RIGHT |
+                       wxALIGN_CENTER_VERTICAL, 0 );
+    button_sizer->Layout();
+
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
+                      wxALL | wxEXPAND, 5 );
+    panel_sizer->Layout();
+    panel->SetSizer( panel_sizer );
+    main_sizer->Add( panel, 1, wxEXPAND, 0 );
+    main_sizer->Layout();
+    SetSizer( main_sizer );
+}
+
+PrefsDialog::~PrefsDialog()
+{
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * Events methods.
+ *****************************************************************************/
+void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
+{
+    prefs_tree->ApplyChanges();
+    this->Hide();
+    prefs_tree->CleanChanges();
+}
+
+void PrefsDialog::OnClose( wxCloseEvent& WXUNUSED(event) )
+{
+    wxCommandEvent cevent;
+    OnCancel(cevent);
+}
+
+void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
+{
+    this->Hide();
+    prefs_tree->CleanChanges();
+}
+
+void PrefsDialog::OnSave( wxCommandEvent& WXUNUSED(event) )
+{
+    prefs_tree->ApplyChanges();
+    config_SaveConfigFile( p_intf, NULL );
+    this->Hide();
+}
+
+void PrefsDialog::OnResetAll( wxCommandEvent& WXUNUSED(event) )
+{
+    wxMessageDialog dlg( this,
+        wxU(_("Beware this will reset your VLC media player preferences.\n"
+              "Are you sure you want to continue?")),
+        wxU(_("Reset Preferences")), wxYES_NO|wxNO_DEFAULT|wxCENTRE );
+
+    if ( dlg.ShowModal() == wxID_YES )
+    {
+        /* TODO: need to reset all the controls */
+        config_ResetAll( p_intf );
+        prefs_tree->CleanChanges();
+        config_SaveConfigFile( p_intf, NULL );
+    }
+}
+
+void PrefsDialog::OnAdvanced( wxCommandEvent& event )
+{
+    wxCommandEvent newevent( wxEVT_USER_FIRST, Advanced_Event );
+    newevent.SetInt( event.GetInt() );
+
+    prefs_tree->AddPendingEvent( newevent );
+}
+
+/*****************************************************************************
+ * PrefsTreeCtrl class definition.
+ *****************************************************************************/
+PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
+                              PrefsDialog *_p_prefs_dialog,
+                              wxBoxSizer *_p_sizer )
+  : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxSize(200,-1),
+                wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
+                wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
+                wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
+{
+    vlc_list_t      *p_list = NULL;;
+    module_t        *p_module;
+    module_config_t *p_item;
+    int i_index, i_image=0;
+
+    /* Initializations */
+    p_intf = _p_intf;
+    p_prefs_dialog = _p_prefs_dialog;
+    p_sizer = _p_sizer;
+    p_parent = _p_parent;
+    b_advanced = VLC_FALSE;
+
+    root_item = AddRoot( wxT("") );
+    wxASSERT_MSG(root_item.IsOk(), wxT("Could not add root item"));
+
+    wxImageList *p_images = new wxImageList( 16,16,TRUE );
+    p_images->Add( wxIcon( audio_xpm ) );
+    p_images->Add( wxIcon( video_xpm ) );
+    p_images->Add( wxIcon( codec_xpm ) );
+    p_images->Add( wxIcon( type_net_xpm ) );
+    p_images->Add( wxIcon( advanced_xpm ) );
+    p_images->Add( wxIcon( type_playlist_xpm ) );
+    p_images->Add( wxIcon( intf_xpm ) );
+    AssignImageList( p_images );
+
+    /* List the plugins */
+    p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    if( !p_list ) return;
+
+    /* Build the categories list */
+    for( i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        p_module = (module_t *)p_list->p_values[i_index].p_object;
+        if( !strcmp( p_module->psz_object_name, "main" ) )
+            break;
+    }
+    if( i_index < p_list->i_count )
+    {
+        wxTreeItemId current_item;
+        char *psz_help;
+        /* We found the main module */
+
+        /* Enumerate config categories and store a reference so we can
+         * generate their config panel them when it is asked by the user. */
+        p_item = p_module->p_config;
+
+        if( p_item ) do
+        {
+            ConfigTreeData *config_data;
+            switch( p_item->i_type )
+            {
+            case CONFIG_CATEGORY:
+                config_data = new ConfigTreeData;
+                config_data->psz_name = strdup( config_CategoryNameGet(
+                                                            p_item->i_value ) );
+                psz_help = config_CategoryHelpGet( p_item->i_value );
+                if( psz_help )
+                {
+                    config_data->psz_help = wraptext( strdup( psz_help ),
+                                                      72 , 1 );
+                }
+                else
+                {
+                    config_data->psz_help = NULL;
+                }
+                config_data->i_type = TYPE_CATEGORY;
+                config_data->i_object_id = p_item->i_value;
+
+                /* Add the category to the tree */
+                switch( p_item->i_value )
+                {
+                    case CAT_AUDIO:
+                        i_image = 0; break;
+                    case CAT_VIDEO:
+                        i_image = 1; break;
+                    case CAT_INPUT:
+                        i_image = 2; break;
+                    case CAT_SOUT:
+                        i_image = 3; break;
+                    case CAT_ADVANCED:
+                        i_image = 4; break;
+                    case CAT_PLAYLIST:
+                        i_image = 5; break;
+                    case CAT_INTERFACE:
+                        i_image = 6; break;
+                }
+                current_item = AppendItem( root_item,
+                                           wxU( config_data->psz_name ),
+                                           i_image, -1, config_data );
+
+                break;
+            case CONFIG_SUBCATEGORY:
+                if( p_item->i_value == SUBCAT_VIDEO_GENERAL ||
+                    p_item->i_value == SUBCAT_AUDIO_GENERAL )
+                {
+                    ConfigTreeData *cd = (ConfigTreeData *)
+                                            GetItemData( current_item );
+                    cd->i_type = TYPE_CATSUBCAT;
+                    cd->i_subcat_id = p_item->i_value;
+                    if( cd->psz_name ) free( cd->psz_name );
+                    cd->psz_name = strdup(  config_CategoryNameGet(
+                                                      p_item->i_value ) );
+                    if( cd->psz_help ) free( cd->psz_help );
+                    char *psz_help = config_CategoryHelpGet( p_item->i_value );
+                    if( psz_help )
+                    {
+                        cd->psz_help = wraptext( strdup( psz_help ),72 ,
+                                                 1 );
+                    }
+                    else
+                    {
+                        cd->psz_help = NULL;
+                    }
+                    continue;
+                }
+
+                config_data = new ConfigTreeData;
+
+                config_data->psz_name = strdup(  config_CategoryNameGet(
+                                                           p_item->i_value ) );
+                psz_help = config_CategoryHelpGet( p_item->i_value );
+                if( psz_help )
+                {
+                    config_data->psz_help = wraptext( strdup( psz_help ) ,
+                                                      72 , 1 );
+                }
+                else
+                {
+                    config_data->psz_help = NULL;
+                }
+                config_data->i_type = TYPE_SUBCATEGORY;
+                config_data->i_object_id = p_item->i_value;
+                /* WXMSW doesn't know image -1 ... FIXME */
+                #ifdef __WXMSW__
+                switch( p_item->i_value / 100 )
+                {
+                    case CAT_AUDIO:
+                        i_image = 0; break;
+                    case CAT_VIDEO:
+                        i_image = 1; break;
+                    case CAT_INPUT:
+                        i_image = 2; break;
+                    case CAT_SOUT:
+                        i_image = 3; break;
+                    case CAT_ADVANCED:
+                        i_image = 4; break;
+                    case CAT_PLAYLIST:
+                        i_image = 5; break;
+                    case CAT_INTERFACE:
+                        i_image = 6; break;
+                }
+                #else
+                i_image = -1;
+                #endif
+                AppendItem( current_item, wxU( config_data->psz_name ),
+                            i_image, -1, config_data );
+                break;
+            }
+        }
+        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+
+    }
+
+
+    /*
+     * Build a tree of all the plugins
+     */
+    for( i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        int i_category = -1;
+        int i_subcategory = -1;
+        int i_options = 0;
+
+        p_module = (module_t *)p_list->p_values[i_index].p_object;
+
+        /* Exclude the main module */
+        if( !strcmp( p_module->psz_object_name, "main" ) )
+            continue;
+
+        /* Exclude empty plugins (submodules don't have config options, they
+         * are stored in the parent module) */
+        if( p_module->b_submodule )
+              continue;
+//            p_item = ((module_t *)p_module->p_parent)->p_config;
+        else
+            p_item = p_module->p_config;
+
+
+        if( !p_item ) continue;
+        do
+        {
+            if( p_item->i_type == CONFIG_CATEGORY )
+            {
+                i_category = p_item->i_value;
+            }
+            else if( p_item->i_type == CONFIG_SUBCATEGORY )
+            {
+                i_subcategory = p_item->i_value;
+            }
+            if( p_item->i_type & CONFIG_ITEM )
+                i_options ++;
+            if( i_options > 0 && i_category >= 0 && i_subcategory >= 0 )
+            {
+                break;
+            }
+        }
+        while( p_item->i_type != CONFIG_HINT_END && p_item++ );
+
+        if( !i_options ) continue;
+
+        /* Find the right category item */
+        wxTreeItemIdValue cookie;
+        vlc_bool_t b_found = VLC_FALSE;
+
+        wxTreeItemId category_item = GetFirstChild( root_item , cookie);
+        while( category_item.IsOk() )
+        {
+            ConfigTreeData *config_data =
+                    (ConfigTreeData *)GetItemData( category_item );
+            if( config_data->i_object_id == i_category )
+            {
+                b_found = VLC_TRUE;
+                break;
+            }
+            category_item = GetNextChild( root_item, cookie );
+        }
+
+        if( !b_found ) continue;
+
+        /* Find subcategory item */
+        b_found = VLC_FALSE;
+        //cookie = -1;
+        wxTreeItemId subcategory_item = GetFirstChild( category_item, cookie );
+        while( subcategory_item.IsOk() )
+        {
+            ConfigTreeData *config_data =
+                    (ConfigTreeData *)GetItemData( subcategory_item );
+            if( config_data->i_object_id == i_subcategory )
+            {
+                b_found = VLC_TRUE;
+                break;
+            }
+            subcategory_item = GetNextChild( category_item, cookie );
+        }
+        if( !b_found )
+        {
+            subcategory_item = category_item;
+        }
+
+        /* Add the plugin to the tree */
+        ConfigTreeData *config_data = new ConfigTreeData;
+        config_data->b_submodule = p_module->b_submodule;
+        config_data->i_type = TYPE_MODULE;
+        config_data->i_object_id = p_module->b_submodule ?
+            ((module_t *)p_module->p_parent)->i_object_id :
+            p_module->i_object_id;
+        config_data->psz_help = NULL;
+
+        /* WXMSW doesn't know image -1 ... FIXME */
+        #ifdef __WXMSW__
+        switch( i_subcategory / 100 )
+        {
+            case CAT_AUDIO:
+                i_image = 0; break;
+            case CAT_VIDEO:
+                i_image = 1; break;
+            case CAT_INPUT:
+                i_image = 2; break;
+            case CAT_SOUT:
+                i_image = 3; break;
+            case CAT_ADVANCED:
+                i_image = 4; break;
+            case CAT_PLAYLIST:
+                i_image = 5; break;
+            case CAT_INTERFACE:
+                i_image = 6; break;
+        }
+        #else
+        i_image = -1;
+        #endif
+        AppendItem( subcategory_item, wxU( p_module->psz_shortname ?
+                       p_module->psz_shortname : p_module->psz_object_name )
+                                    , i_image, -1,
+                    config_data );
+    }
+
+    /* Sort all this mess */
+    wxTreeItemIdValue cookie; 
+    size_t i_child_index;
+    wxTreeItemId capability_item = GetFirstChild( root_item, cookie);
+    for( i_child_index = 0;
+         (capability_item.IsOk() && 
+          //(i_child_index < GetChildrenCount( plugins_item, FALSE )));
+          (i_child_index < GetChildrenCount( root_item, FALSE )));
+         i_child_index++ )
+    {
+        SortChildren( capability_item );
+        //capability_item = GetNextChild( plugins_item, cookie );
+        capability_item = GetNextChild( root_item, cookie );
+    }
+
+    /* Clean-up everything */
+    vlc_list_release( p_list );
+
+    p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
+    p_sizer->Layout();
+
+    /* Update Tree Ctrl */
+#ifndef WIN32 /* Workaround a bug in win32 implementation */
+    SelectItem( GetFirstChild( root_item, cookie ) );
+#endif
+
+    //cannot expand hidden root item
+    //Expand( root_item );
+}
+
+PrefsTreeCtrl::~PrefsTreeCtrl(){
+}
+
+void PrefsTreeCtrl::ApplyChanges()
+{
+    wxTreeItemIdValue cookie, cookie2, cookie3;
+    ConfigTreeData *config_data;
+
+    wxTreeItemId category = GetFirstChild( root_item, cookie );
+    while( category.IsOk() )
+    {
+        wxTreeItemId subcategory = GetFirstChild( category, cookie2 );
+        while( subcategory.IsOk() )
+        {
+            wxTreeItemId module = GetFirstChild( subcategory, cookie3 );
+            while( module.IsOk() )
+            {
+                config_data = (ConfigTreeData *)GetItemData( module );
+                if( config_data && config_data->panel )
+                {
+                    config_data->panel->ApplyChanges();
+                }
+                module = GetNextChild( subcategory, cookie3 );
+            }
+            config_data = (ConfigTreeData *)GetItemData( subcategory );
+            if( config_data && config_data->panel )
+            {
+                config_data->panel->ApplyChanges();
+            }
+            subcategory = GetNextChild( category, cookie2 );
+        }
+        config_data = (ConfigTreeData *)GetItemData( category );
+        if( config_data && config_data->panel )
+        {
+            config_data->panel->ApplyChanges();
+        }
+        category = GetNextChild( root_item, cookie );
+    }
+}
+
+void PrefsTreeCtrl::CleanChanges()
+{
+    wxTreeItemIdValue cookie, cookie2, cookie3;
+    ConfigTreeData *config_data;
+
+    config_data = !GetSelection() ? NULL :
+        FindModuleConfig( (ConfigTreeData *)GetItemData( GetSelection() ) );
+    if( config_data  )
+    {
+        config_data->panel->Hide();
+#if (wxCHECK_VERSION(2,5,0))
+        p_sizer->Detach( config_data->panel );
+#else
+        p_sizer->Remove( config_data->panel );
+#endif
+    }
+
+    wxTreeItemId category = GetFirstChild( root_item, cookie );
+    while( category.IsOk() )
+    {
+        wxTreeItemId subcategory = GetFirstChild( category, cookie2 );
+        while( subcategory.IsOk() )
+        {
+            wxTreeItemId module = GetFirstChild( subcategory, cookie3 );
+            while( module.IsOk() )
+            {
+                config_data = (ConfigTreeData *)GetItemData( module );
+                if( config_data && config_data->panel )
+                {
+                    delete config_data->panel;
+                    config_data->panel = NULL;
+                }
+                module = GetNextChild( subcategory, cookie3 );
+            }
+            config_data = (ConfigTreeData *)GetItemData( subcategory );
+            if( config_data && config_data->panel )
+            {
+                delete config_data->panel;
+                config_data->panel = NULL;
+            }
+            subcategory = GetNextChild( category, cookie2 );
+        }
+        config_data = (ConfigTreeData *)GetItemData( category );
+        if( config_data && config_data->panel )
+        {
+            delete config_data->panel;
+            config_data->panel = NULL;
+        }
+        category = GetNextChild( root_item, cookie );
+    }
+
+    if( GetSelection() )
+    {
+        wxTreeEvent event;
+        OnSelectTreeItem( event );
+    }
+}
+
+ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
+{
+    /* We need this complexity because submodules don't have their own config
+     * options. They use the parent module ones. */
+
+    if( !config_data || !config_data->b_submodule )
+    {
+        return config_data;
+    }
+
+    wxTreeItemIdValue cookie, cookie2, cookie3;
+    ConfigTreeData *config_new;
+    wxTreeItemId category = GetFirstChild( root_item, cookie );
+    while( category.IsOk() )
+    {
+        wxTreeItemId subcategory = GetFirstChild( category, cookie2 );
+        while( subcategory.IsOk() )
+        {
+            wxTreeItemId module = GetFirstChild( subcategory, cookie3 );
+            while( module.IsOk() )
+            {
+                config_new = (ConfigTreeData *)GetItemData( module );
+                if( config_new && !config_new->b_submodule &&
+                    config_new->i_object_id == config_data->i_object_id )
+                {
+                    return config_new;
+                }
+                module = GetNextChild( subcategory, cookie3 );
+            }
+            subcategory = GetNextChild( category, cookie2 );
+        }
+        category = GetNextChild( root_item, cookie );
+    }
+
+    /* Found nothing */
+    return NULL;
+}
+
+void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
+{
+    ConfigTreeData *config_data = NULL;
+
+    if( event.GetOldItem() )
+        config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
+                                        event.GetOldItem() ) );
+    if( config_data && config_data->panel )
+    {
+        config_data->panel->Hide();
+#if (wxCHECK_VERSION(2,5,0))
+        p_sizer->Detach( config_data->panel );
+#else
+        p_sizer->Remove( config_data->panel );
+#endif
+    }
+
+    /* Don't use event.GetItem() because we also send fake events */
+    config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
+                                    GetSelection() ) );
+    if( config_data )
+    {
+        if( !config_data->panel )
+        {
+            /* The panel hasn't been created yet. Let's do it. */
+            config_data->panel =
+                new PrefsPanel( p_parent, p_intf, p_prefs_dialog,
+                                config_data );
+            config_data->panel->SwitchAdvanced( b_advanced );
+        }
+        else
+        {
+            config_data->panel->SwitchAdvanced( b_advanced );
+            config_data->panel->Show();
+        }
+
+        p_sizer->Add( config_data->panel, 3, wxEXPAND | wxALL, 0 );
+        p_sizer->Layout();
+    }
+}
+
+void PrefsTreeCtrl::OnAdvanced( wxCommandEvent& event )
+{
+    b_advanced = event.GetInt();
+
+    ConfigTreeData *config_data = !GetSelection() ? NULL :
+        FindModuleConfig( (ConfigTreeData *)GetItemData( GetSelection() ) );
+    if( config_data  )
+    {
+        config_data->panel->Hide();
+#if (wxCHECK_VERSION(2,5,0))
+        p_sizer->Detach( config_data->panel );
+#else
+        p_sizer->Remove( config_data->panel );
+#endif
+    }
+
+    if( GetSelection() )
+    {
+        wxTreeEvent event;
+        OnSelectTreeItem( event );
+    }
+}
+
+/*****************************************************************************
+ * PrefsPanel class definition.
+ *****************************************************************************/
+PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
+                        PrefsDialog *_p_prefs_dialog,
+                        ConfigTreeData *config_data )
+  :  wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize )
+{
+    module_config_t *p_item;
+    vlc_list_t *p_list = NULL;;
+
+    wxStaticText *label;
+    wxStaticText *help;
+    wxArrayString array;
+
+    module_t *p_module = NULL;
+
+    /* Initializations */
+    p_intf = _p_intf;
+    p_prefs_dialog =_p_prefs_dialog,
+
+    b_advanced = VLC_TRUE;
+    SetAutoLayout( TRUE );
+    Hide();
+
+    wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
+
+
+    if( config_data->i_type == TYPE_CATEGORY )
+    {
+        label = new wxStaticText( this, -1,wxU(_( config_data->psz_name )));
+        wxFont heading_font = label->GetFont();
+        heading_font.SetPointSize( heading_font.GetPointSize() + 5 );
+        label->SetFont( heading_font );
+        sizer->Add( label, 0, wxEXPAND | wxLEFT, 10 );
+        sizer->Add( new wxStaticLine( this, 0 ), 0,
+                    wxEXPAND | wxLEFT | wxRIGHT, 2 );
+
+        hidden_text = NULL;
+        help = new wxStaticText( this, -1, wxU(_( config_data->psz_help ) ) );
+        sizer->Add( help ,0 ,wxEXPAND | wxALL, 5 );
+
+        config_sizer = NULL; config_window = NULL;
+    }
+    else
+    {
+        /* Get a pointer to the module */
+        if( config_data->i_type == TYPE_MODULE )
+        {
+            p_module = (module_t *)vlc_object_get( p_intf,
+                                                   config_data->i_object_id );
+        }
+        else
+        {
+            /* List the plugins */
+            int i_index;
+            vlc_bool_t b_found = VLC_FALSE;
+            p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+            if( !p_list ) return;
+
+            for( i_index = 0; i_index < p_list->i_count; i_index++ )
+            {
+                p_module = (module_t *)p_list->p_values[i_index].p_object;
+                if( !strcmp( p_module->psz_object_name, "main" ) )
+                {
+                    b_found = VLC_TRUE;
+                    break;
+                }
+            }
+            if( !p_module && !b_found )
+            {
+                msg_Warn( p_intf, "ohoh, unable to find main module" );
+                return;
+            }
+        }
+
+        if( p_module->i_object_type != VLC_OBJECT_MODULE )
+        {
+            /* 0OOoo something went really bad */
+            return;
+        }
+
+        /* Enumerate config options and add corresponding config boxes
+         * (submodules don't have config options, they are stored in the
+         *  parent module) */
+        if( p_module->b_submodule )
+            p_item = ((module_t *)p_module->p_parent)->p_config;
+        else
+            p_item = p_module->p_config;
+
+        /* Find the category if it has been specified */
+        if( config_data->i_type == TYPE_SUBCATEGORY ||
+            config_data->i_type == TYPE_CATSUBCAT )
+        {
+            do
+            {
+                if( p_item->i_type == CONFIG_SUBCATEGORY &&
+                    ( config_data->i_type == TYPE_SUBCATEGORY &&
+                      p_item->i_value == config_data->i_object_id ) ||
+                    ( config_data->i_type == TYPE_CATSUBCAT &&
+                      p_item->i_value == config_data->i_subcat_id ) )
+                {
+                    break;
+                }
+                if( p_item->i_type == CONFIG_HINT_END )
+                    break;
+            } while( p_item++ );
+        }
+
+        /* Add a head title to the panel */
+        char *psz_head;
+        if( config_data->i_type == TYPE_SUBCATEGORY ||
+            config_data->i_type == TYPE_CATSUBCAT )
+        {
+            psz_head = config_data->psz_name;
+            p_item++;
+        }
+        else
+        {
+            psz_head = p_module->psz_longname;
+        }
+
+        label = new wxStaticText( this, -1,
+                      wxU(_( psz_head ? psz_head : _("Unknown") ) ) );
+        wxFont heading_font = label->GetFont();
+        heading_font.SetPointSize( heading_font.GetPointSize() + 5 );
+        label->SetFont( heading_font );
+        sizer->Add( label, 0, wxEXPAND | wxLEFT, 10 );
+        sizer->Add( new wxStaticLine( this, 0 ), 0,
+                    wxEXPAND | wxLEFT | wxRIGHT, 2 );
+
+        /* Now put all the config options into a scrolled window */
+        config_sizer = new wxBoxSizer( wxVERTICAL );
+        config_window = new wxScrolledWindow( this, -1, wxDefaultPosition,
+            wxDefaultSize, wxBORDER_NONE | wxHSCROLL | wxVSCROLL );
+        config_window->SetAutoLayout( TRUE );
+        config_window->SetScrollRate( 5, 5 );
+
+        if( p_item ) do
+        {
+            /* If a category has been specified, check we finished the job */
+            if( ( ( config_data->i_type == TYPE_SUBCATEGORY &&
+                    p_item->i_value != config_data->i_object_id ) ||
+                  ( config_data->i_type == TYPE_CATSUBCAT  &&
+                    p_item->i_value != config_data->i_subcat_id ) ) &&
+                (p_item->i_type == CONFIG_CATEGORY ||
+                  p_item->i_type == CONFIG_SUBCATEGORY ) )
+                break;
+
+            ConfigControl *control =
+                CreateConfigControl( VLC_OBJECT(p_intf),
+                                     p_item, config_window );
+
+            /* Don't add items that were not recognized */
+            if( control == NULL ) continue;
+
+            /* Add the config data to our array so we can keep a trace of it */
+            config_array.Add( control );
+
+            config_sizer->Add( control, 0, wxEXPAND | wxALL, 2 );
+        }
+        while( !( p_item->i_type == CONFIG_HINT_END ||
+               ( ( config_data->i_type == TYPE_SUBCATEGORY ||
+                   config_data->i_type == TYPE_CATSUBCAT ) &&
+                 ( p_item->i_type == CONFIG_CATEGORY ||
+                   p_item->i_type == CONFIG_SUBCATEGORY ) ) ) && p_item++ );
+
+
+        config_sizer->Layout();
+        config_window->SetSizer( config_sizer );
+        sizer->Add( config_window, 1, wxEXPAND | wxALL, 5 );
+        hidden_text = new wxStaticText( this, -1,
+                        wxU( _( "Some options are available but hidden. " \
+                                "Check \"Advanced options\" to see them." ) ) );
+        sizer->Add( hidden_text );
+
+        /* And at last put a useful help string if available */
+        if( config_data->psz_help && *config_data->psz_help )
+        {
+            sizer->Add( new wxStaticLine( this, 0 ), 0,
+                        wxEXPAND | wxLEFT | wxRIGHT, 2 );
+            help = new wxStaticText( this, -1, wxU(_(config_data->psz_help)),
+                                     wxDefaultPosition, wxDefaultSize,
+                                     wxALIGN_LEFT,
+                                     wxT("") );
+            sizer->Add( help ,0 ,wxEXPAND | wxALL, 5 );
+        }
+
+        if( config_data->i_type == TYPE_MODULE )
+        {
+            vlc_object_release( p_module );
+        }
+        else
+        {
+            vlc_list_release( p_list );
+        }
+    }
+    sizer->Layout();
+    SetSizer( sizer );
+    Show();
+}
+
+void PrefsPanel::ApplyChanges()
+{
+    vlc_value_t val;
+
+    for( size_t i = 0; i < config_array.GetCount(); i++ )
+    {
+        ConfigControl *control = config_array.Item(i);
+
+        switch( control->GetType() )
+        {
+        case CONFIG_ITEM_STRING:
+        case CONFIG_ITEM_FILE:
+        case CONFIG_ITEM_DIRECTORY:
+        case CONFIG_ITEM_MODULE:
+        case CONFIG_ITEM_MODULE_CAT:
+        case CONFIG_ITEM_MODULE_LIST:
+        case CONFIG_ITEM_MODULE_LIST_CAT:
+            config_PutPsz( p_intf, control->GetName().mb_str(),
+                           control->GetPszValue().mb_str() );
+            break;
+        case CONFIG_ITEM_KEY:
+            /* So you don't need to restart to have the changes take effect */
+            val.i_int = control->GetIntValue();
+            var_Set( p_intf->p_vlc, control->GetName().mb_str(), val );
+        case CONFIG_ITEM_INTEGER:
+        case CONFIG_ITEM_BOOL:
+            config_PutInt( p_intf, control->GetName().mb_str(),
+                           control->GetIntValue() );
+            break;
+        case CONFIG_ITEM_FLOAT:
+            config_PutFloat( p_intf, control->GetName().mb_str(),
+                             control->GetFloatValue() );
+            break;
+        }
+    }
+}
+
+void PrefsPanel::SwitchAdvanced( vlc_bool_t b_new_advanced )
+{
+    bool hidden = false;
+
+    if( b_advanced == b_new_advanced )
+    {
+        goto hide;
+    }
+
+    if( config_sizer && config_window )
+    {
+        b_advanced = b_new_advanced;
+
+        for( size_t i = 0; i < config_array.GetCount(); i++ )
+        {
+            ConfigControl *control = config_array.Item(i);
+            if( control->IsAdvanced() )
+            {
+                if( !b_advanced ) hidden = true;
+                control->Show( b_advanced );
+                config_sizer->Show( control, b_advanced );
+            }
+        }
+
+        config_sizer->Layout();
+        config_window->FitInside();
+        config_window->Refresh();
+    }
+hide:
+    if( hidden && hidden_text )
+    {
+        hidden_text->Show( true );
+        config_sizer->Show( hidden_text, true );
+    }
+    else if ( hidden_text )
+    {
+        hidden_text->Show( false );
+        config_sizer->Show( hidden_text, false );
+    }
+    return;
+}
diff --git a/modules/gui/wxwidgets/dialogs/preferences.hpp b/modules/gui/wxwidgets/dialogs/preferences.hpp
new file mode 100644 (file)
index 0000000..a7f6a15
--- /dev/null
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * preferences.hpp : Headers for the preference dialog
+ *****************************************************************************
+ * Copyright (C) 1999-2005 the VideoLAN team
+ * $Id: wxwidgets.h 12670 2005-09-25 11:16:31Z zorglub $
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef _WXVLC_PREFERENCES_H_
+#define _WXVLC_PREFERENCES_H_
+
+#include "wxwidgets.hpp"
+
+class PrefsTreeCtrl;
+class PrefsPanel;
+
+namespace wxvlc
+{
+    /** This class is the preferences window
+     *  It includes a preferences panel (right part)
+     *  and the PrefsTreeCtrl (left part)
+     */
+    class PrefsDialog: public wxFrame
+    {
+    public:
+        /** Constructor */
+        PrefsDialog( intf_thread_t *p_intf, wxWindow *p_parent );
+        virtual ~PrefsDialog();
+
+    private:
+        wxPanel *PrefsPanel( wxWindow* parent );
+
+        /* Event handlers (these functions should _not_ be virtual) */
+        void OnOk( wxCommandEvent& event );
+        void OnCancel( wxCommandEvent& event );
+        void OnSave( wxCommandEvent& event );
+        void OnResetAll( wxCommandEvent& event );
+        void OnAdvanced( wxCommandEvent& event );
+        void OnClose( wxCloseEvent& event );
+
+        DECLARE_EVENT_TABLE();
+
+        intf_thread_t *p_intf;
+
+        PrefsTreeCtrl *prefs_tree;
+    };
+
+};
+
+#endif
+
diff --git a/modules/gui/wxwidgets/dialogs/preferences_widgets.cpp b/modules/gui/wxwidgets/dialogs/preferences_widgets.cpp
new file mode 100644 (file)
index 0000000..aea6352
--- /dev/null
@@ -0,0 +1,981 @@
+/*****************************************************************************
+ * preferences_widgets.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *          Sigmund Augdal Helberg <dnumgis@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "wxwidgets.hpp"
+#include "preferences_widgets.h"
+#include <vlc_keys.h>
+#include <vlc_config_cat.h>
+
+#include <wx/statline.h>
+#include <wx/spinctrl.h>
+
+/*****************************************************************************
+ * CreateConfigControl wrapper
+ *****************************************************************************/
+ConfigControl *CreateConfigControl( vlc_object_t *p_this,
+                                    module_config_t *p_item, wxWindow *parent )
+{
+    ConfigControl *p_control = NULL;
+
+    /*Skip deprecated options */
+    if( p_item->psz_current )
+    {
+        return NULL;
+    }
+
+    switch( p_item->i_type )
+    {
+    case CONFIG_ITEM_MODULE:
+        p_control = new ModuleConfigControl( p_this, p_item, parent );
+        break;
+    case CONFIG_ITEM_MODULE_CAT:
+        p_control = new ModuleCatConfigControl( p_this, p_item, parent );
+        break;
+    case CONFIG_ITEM_MODULE_LIST_CAT:
+        p_control = new ModuleListCatConfigControl( p_this, p_item, parent );
+        break;
+
+    case CONFIG_ITEM_STRING:
+        if( !p_item->i_list )
+        {
+            p_control = new StringConfigControl( p_this, p_item, parent );
+        }
+        else
+        {
+            p_control = new StringListConfigControl( p_this, p_item, parent );
+        }
+        break;
+
+    case CONFIG_ITEM_FILE:
+    case CONFIG_ITEM_DIRECTORY:
+        p_control = new FileConfigControl( p_this, p_item, parent );
+        break;
+
+    case CONFIG_ITEM_INTEGER:
+        if( p_item->i_list )
+        {
+            p_control = new IntegerListConfigControl( p_this, p_item, parent );
+        }
+        else if( p_item->i_min != 0 || p_item->i_max != 0 )
+        {
+            p_control = new RangedIntConfigControl( p_this, p_item, parent );
+        }
+        else
+        {
+            p_control = new IntegerConfigControl( p_this, p_item, parent );
+        }
+        break;
+
+    case CONFIG_ITEM_KEY:
+        p_control = new KeyConfigControl( p_this, p_item, parent );
+        break;
+
+    case CONFIG_ITEM_FLOAT:
+        p_control = new FloatConfigControl( p_this, p_item, parent );
+        break;
+
+    case CONFIG_ITEM_BOOL:
+        p_control = new BoolConfigControl( p_this, p_item, parent );
+        break;
+
+    case CONFIG_SECTION:
+        p_control = new SectionConfigControl( p_this, p_item, parent );
+        break;
+
+    default:
+        break;
+    }
+
+    return p_control;
+}
+
+/*****************************************************************************
+ * ConfigControl implementation
+ *****************************************************************************/
+ConfigControl::ConfigControl( vlc_object_t *_p_this,
+                              module_config_t *p_item, wxWindow *parent )
+  : wxPanel( parent ), p_this( _p_this ),
+    pf_update_callback( NULL ), p_update_data( NULL ),
+    name( wxU(p_item->psz_name) ), i_type( p_item->i_type ),
+    b_advanced( p_item->b_advanced )
+
+{
+    sizer = new wxBoxSizer( wxHORIZONTAL );
+}
+
+ConfigControl::~ConfigControl()
+{
+}
+
+wxSizer *ConfigControl::Sizer()
+{
+    return sizer;
+}
+
+wxString ConfigControl::GetName()
+{
+    return name;
+}
+
+int ConfigControl::GetType()
+{
+    return i_type;
+}
+
+vlc_bool_t ConfigControl::IsAdvanced()
+{
+    return b_advanced;
+}
+
+void ConfigControl::SetUpdateCallback( void (*p_callback)( void * ),
+                                             void *p_data )
+{
+    pf_update_callback = p_callback;
+    p_update_data = p_data;
+}
+
+void ConfigControl::OnUpdate( wxCommandEvent& WXUNUSED(event) )
+{
+    if( pf_update_callback )
+    {
+        pf_update_callback( p_update_data );
+    }
+}
+
+void ConfigControl::OnUpdateScroll( wxScrollEvent& WXUNUSED(event) )
+{
+    wxCommandEvent cevent;
+    OnUpdate(cevent);
+}
+
+
+/*****************************************************************************
+ * KeyConfigControl implementation
+ *****************************************************************************/
+wxString *KeyConfigControl::m_keysList = NULL;
+
+KeyConfigControl::KeyConfigControl( vlc_object_t *p_this,
+                                    module_config_t *p_item, wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    // Number of keys descriptions
+    unsigned int i_keys = sizeof(vlc_keys)/sizeof(key_descriptor_t);
+
+    // Init the keys decriptions array
+    if( m_keysList == NULL )
+    {
+        m_keysList = new wxString[i_keys];
+        for( unsigned int i = 0; i < i_keys; i++ )
+        {
+            m_keysList[i] = wxU(vlc_keys[i].psz_key_string);
+        }
+    }
+
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    alt = new wxCheckBox( this, -1, wxU(_("Alt")) );
+    alt->SetValue( p_item->i_value & KEY_MODIFIER_ALT );
+    ctrl = new wxCheckBox( this, -1, wxU(_("Ctrl")) );
+    ctrl->SetValue( p_item->i_value & KEY_MODIFIER_CTRL );
+    shift = new wxCheckBox( this, -1, wxU(_("Shift")) );
+    shift->SetValue( p_item->i_value & KEY_MODIFIER_SHIFT );
+    combo = new wxComboBox( this, -1, wxT(""), wxDefaultPosition,
+                            wxDefaultSize, i_keys, m_keysList,
+                            wxCB_READONLY );
+    for( unsigned int i = 0; i < i_keys; i++ )
+    {
+        combo->SetClientData( i, (void*)vlc_keys[i].i_key_code );
+        if( (unsigned int)vlc_keys[i].i_key_code ==
+            ( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ) )
+        {
+            combo->SetSelection( i );
+            combo->SetValue( wxU(_(vlc_keys[i].psz_key_string)) );
+        }
+    }
+
+    sizer->Add( label, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
+    sizer->Add( alt,   1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
+    sizer->Add( ctrl,  1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
+    sizer->Add( shift, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
+    sizer->Add( combo, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+KeyConfigControl::~KeyConfigControl()
+{
+    if( m_keysList )
+    {
+        delete[] m_keysList;
+        m_keysList = NULL;
+    }
+}
+
+int KeyConfigControl::GetIntValue()
+{
+    int result = 0;
+    if( alt->IsChecked() )
+    {
+        result |= KEY_MODIFIER_ALT;
+    }
+    if( ctrl->IsChecked() )
+    {
+        result |= KEY_MODIFIER_CTRL;
+    }
+    if( shift->IsChecked() )
+    {
+        result |= KEY_MODIFIER_SHIFT;
+    }
+    int selected = combo->GetSelection();
+    if( selected != -1 )
+    {
+        result |= (int)combo->GetClientData( selected );
+    }
+    return result;
+}
+
+/*****************************************************************************
+ * ModuleConfigControl implementation
+ *****************************************************************************/
+ModuleConfigControl::ModuleConfigControl( vlc_object_t *p_this,
+                                          module_config_t *p_item,
+                                          wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    vlc_list_t *p_list;
+    module_t *p_parser;
+
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    combo = new wxComboBox( this, -1, wxL2U(p_item->psz_value),
+                            wxDefaultPosition, wxDefaultSize,
+                            0, NULL, wxCB_READONLY | wxCB_SORT );
+
+    /* build a list of available modules */
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    combo->Append( wxU(_("Default")), (void *)NULL );
+    combo->SetSelection( 0 );
+    for( int i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )
+        {
+            combo->Append( wxU(p_parser->psz_longname),
+                           p_parser->psz_object_name );
+            if( p_item->psz_value && !strcmp(p_item->psz_value,
+                                             p_parser->psz_object_name) )
+                combo->SetValue( wxU(p_parser->psz_longname) );
+        }
+    }
+    vlc_list_release( p_list );
+
+    combo->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+ModuleCatConfigControl::~ModuleCatConfigControl()
+{
+    ;
+}
+
+wxString ModuleCatConfigControl::GetPszValue()
+{
+    return wxU( (char *)combo->GetClientData( combo->GetSelection() ));
+}
+
+/*****************************************************************************
+ * ModuleCatConfigControl implementation
+ *****************************************************************************/
+ModuleCatConfigControl::ModuleCatConfigControl( vlc_object_t *p_this,
+                                                module_config_t *p_item,
+                                                wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    vlc_list_t *p_list;
+    module_t *p_parser;
+
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    combo = new wxComboBox( this, -1, wxL2U(p_item->psz_value),
+                            wxDefaultPosition, wxDefaultSize,
+                            0, NULL, wxCB_READONLY | wxCB_SORT );
+
+    combo->Append( wxU(_("Default")), (void *)NULL );
+    combo->SetSelection( 0 );
+
+    /* build a list of available modules */
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    for(  int i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !strcmp( p_parser->psz_object_name, "main" ) )
+              continue;
+
+        module_config_t *p_config = p_parser->p_config;
+        if( p_config ) do
+        {
+            /* Hack: required subcategory is stored in i_min */
+            if( p_config->i_type == CONFIG_SUBCATEGORY &&
+                p_config->i_value == p_item->i_min )
+            {
+                combo->Append( wxU(p_parser->psz_longname),
+                                   p_parser->psz_object_name );
+                if( p_item->psz_value && !strcmp(p_item->psz_value,
+                                        p_parser->psz_object_name) )
+                combo->SetValue( wxU(p_parser->psz_longname) );
+            }
+        } while( p_config->i_type != CONFIG_HINT_END && p_config++ );
+    }
+    vlc_list_release( p_list );
+
+    combo->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+ModuleConfigControl::~ModuleConfigControl()
+{
+    ;
+}
+
+wxString ModuleConfigControl::GetPszValue()
+{
+    return wxU( (char *)combo->GetClientData( combo->GetSelection() ));
+}
+
+
+/*****************************************************************************
+ * ModuleListCatonfigControl implementation
+ *****************************************************************************/
+BEGIN_EVENT_TABLE(ModuleListCatConfigControl, wxPanel)
+    EVT_CHECKBOX( wxID_HIGHEST , ModuleListCatConfigControl::OnUpdate )
+END_EVENT_TABLE()
+
+
+ModuleListCatConfigControl::ModuleListCatConfigControl( vlc_object_t *p_this,
+                                                     module_config_t *p_item,
+                                                     wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    vlc_list_t *p_list;
+    module_t *p_parser;
+
+    delete sizer;
+    sizer = new wxBoxSizer( wxVERTICAL );
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    sizer->Add( label );
+
+    text = new wxTextCtrl( this, -1, wxU(p_item->psz_value),
+                           wxDefaultPosition,wxSize( 300, 20 ) );
+
+
+    /* build a list of available modules */
+    p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    for(  int i_index = 0; i_index < p_list->i_count; i_index++ )
+    {
+        p_parser = (module_t *)p_list->p_values[i_index].p_object ;
+
+        if( !strcmp( p_parser->psz_object_name, "main" ) )
+              continue;
+
+        module_config_t *p_config = p_parser->p_config;
+        if( p_config ) do
+        {
+            /* Hack: required subcategory is stored in i_min */
+            if( p_config->i_type == CONFIG_SUBCATEGORY &&
+                p_config->i_value == p_item->i_min )
+            {
+                moduleCheckBox *mc = new moduleCheckBox;
+                mc->checkbox = new wxCheckBox( this, wxID_HIGHEST,
+                                               wxU(p_parser->psz_longname));
+                mc->psz_module = strdup( p_parser->psz_object_name );
+                pp_checkboxes.push_back( mc );
+
+                if( p_item->psz_value &&
+                    strstr( p_item->psz_value, p_parser->psz_object_name ) )
+                {
+                    mc->checkbox->SetValue( true );
+                }
+                sizer->Add( mc->checkbox );
+            }
+        } while( p_config->i_type != CONFIG_HINT_END && p_config++ );
+    }
+    vlc_list_release( p_list );
+
+    text->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add(text, 0, wxEXPAND|wxALL, 5 );
+
+    sizer->Add (new wxStaticText( this, -1, wxU( vlc_wraptext( _("Select modules that you want. To get more advanced control, you can also modify the resulting chain by yourself") , 72, 1 ) ) ) );
+
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+ModuleListCatConfigControl::~ModuleListCatConfigControl()
+{
+    ;
+}
+
+wxString ModuleListCatConfigControl::GetPszValue()
+{
+    return text->GetValue() ;
+}
+
+void  ModuleListCatConfigControl::OnUpdate( wxCommandEvent &event )
+{
+    bool b_waschecked = false;
+    wxString newtext =  text->GetValue();
+
+    for( unsigned int i = 0 ; i< pp_checkboxes.size() ; i++ )
+    {
+        b_waschecked = newtext.Find( wxU(pp_checkboxes[i]->psz_module)) != -1 ;
+        /* For some reasons, ^^ doesn't compile :( */
+        if( (pp_checkboxes[i]->checkbox->IsChecked() && ! b_waschecked )||
+            (! pp_checkboxes[i]->checkbox->IsChecked() && b_waschecked) )
+        {
+            if( b_waschecked )
+            {
+                /* Maybe not the clest solution */
+                if( ! newtext.Replace(wxString(wxT(":"))
+                                      +wxU(pp_checkboxes[i]->psz_module),
+                                      wxT("")))
+                {
+                    if( ! newtext.Replace(wxString(wxU(pp_checkboxes[i]->psz_module))
+                                           + wxT(":"),wxT("")))
+            {
+                        newtext.Replace(wxU(pp_checkboxes[i]->psz_module),wxU(""));
+                    }
+                }
+            }
+            else
+            {
+                if( newtext.Len() == 0 )
+                {
+                    newtext = wxU(pp_checkboxes[i]->psz_module);
+                }
+                else
+                {
+                    newtext += wxU( ":" );
+                    newtext += wxU(pp_checkboxes[i]->psz_module);
+                }
+            }
+        }
+    }
+    text->SetValue( newtext );
+}
+
+/*****************************************************************************
+ * StringConfigControl implementation
+ *****************************************************************************/
+StringConfigControl::StringConfigControl( vlc_object_t *p_this,
+                                          module_config_t *p_item,
+                                          wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    textctrl = new wxTextCtrl( this, -1,
+                               wxL2U(p_item->psz_value),
+                               wxDefaultPosition,
+                               wxDefaultSize,
+                               wxTE_PROCESS_ENTER);
+    textctrl->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( textctrl, 1, wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+StringConfigControl::~StringConfigControl()
+{
+    ;
+}
+
+wxString StringConfigControl::GetPszValue()
+{
+    return textctrl->GetValue();
+}
+
+BEGIN_EVENT_TABLE(StringConfigControl, wxPanel)
+    /* Text events */
+    EVT_TEXT(-1, StringConfigControl::OnUpdate)
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * StringListConfigControl implementation
+ *****************************************************************************/
+StringListConfigControl::StringListConfigControl( vlc_object_t *p_this,
+                                                  module_config_t *p_item,
+                                                  wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    psz_default_value = p_item->psz_value;
+    if( psz_default_value ) psz_default_value = strdup( psz_default_value );
+
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    combo = new wxComboBox( this, -1, wxT(""),
+                            wxDefaultPosition, wxDefaultSize,
+                            0, NULL, wxCB_READONLY );
+    UpdateCombo( p_item );
+
+    combo->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+
+    for( int i = 0; i < p_item->i_action; i++ )
+    {
+        wxButton *button =
+            new wxButton( this, wxID_HIGHEST+i,
+                          wxU(p_item->ppsz_action_text[i]) );
+        sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+    }
+
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+StringListConfigControl::~StringListConfigControl()
+{
+    if( psz_default_value ) free( psz_default_value );
+}
+
+void StringListConfigControl::UpdateCombo( module_config_t *p_item )
+{
+    vlc_bool_t b_found = VLC_FALSE;
+    int i_index;
+
+    /* build a list of available options */
+    for( i_index = 0; i_index < p_item->i_list; i_index++ )
+    {
+        combo->Append( ( p_item->ppsz_list_text &&
+                         p_item->ppsz_list_text[i_index] ) ?
+                       wxU(p_item->ppsz_list_text[i_index]) :
+                       wxL2U(p_item->ppsz_list[i_index]) );
+        combo->SetClientData( i_index, (void *)p_item->ppsz_list[i_index] );
+        if( ( p_item->psz_value &&
+              !strcmp( p_item->psz_value, p_item->ppsz_list[i_index] ) ) ||
+             ( !p_item->psz_value && !*p_item->ppsz_list[i_index] ) )
+        {
+            combo->SetSelection( i_index );
+            combo->SetValue( ( p_item->ppsz_list_text &&
+                               p_item->ppsz_list_text[i_index] ) ?
+                             wxU(p_item->ppsz_list_text[i_index]) :
+                             wxL2U(p_item->ppsz_list[i_index]) );
+            b_found = VLC_TRUE;
+        }
+    }
+
+    if( p_item->psz_value && !b_found )
+    {
+        /* Add custom entry to list */
+        combo->Append( wxL2U(p_item->psz_value) );
+        combo->SetClientData( i_index, (void *)psz_default_value );
+        combo->SetSelection( i_index );
+        combo->SetValue( wxL2U(p_item->psz_value) );
+    }
+}
+
+BEGIN_EVENT_TABLE(StringListConfigControl, wxPanel)
+    /* Button events */
+    EVT_BUTTON(-1, StringListConfigControl::OnAction)
+
+    /* Text events */
+    EVT_TEXT(-1, StringListConfigControl::OnUpdate)
+END_EVENT_TABLE()
+
+void StringListConfigControl::OnAction( wxCommandEvent& event )
+{
+    int i_action = event.GetId() - wxID_HIGHEST;
+
+    module_config_t *p_item = config_FindConfig( p_this, GetName().mb_str() );
+    if( !p_item ) return;
+
+    if( i_action < 0 || i_action >= p_item->i_action ) return;
+
+    vlc_value_t val;
+    wxString value = GetPszValue();
+    *((const char **)&val.psz_string) = value.mb_str();
+    p_item->ppf_action[i_action]( p_this, GetName().mb_str(), val, val, 0 );
+
+    if( p_item->b_dirty )
+    {
+        combo->Clear();
+        UpdateCombo( p_item );
+        p_item->b_dirty = VLC_FALSE;
+    }
+}
+
+wxString StringListConfigControl::GetPszValue()
+{
+    int selected = combo->GetSelection();
+    if( selected != -1 )
+    {
+        return wxL2U((char *)combo->GetClientData( selected ));
+    }
+    return wxString();
+}
+
+/*****************************************************************************
+ * FileConfigControl implementation
+ *****************************************************************************/
+FileConfigControl::FileConfigControl( vlc_object_t *p_this,
+                                      module_config_t *p_item,
+                                      wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    directory = p_item->i_type == CONFIG_ITEM_DIRECTORY;
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    textctrl = new wxTextCtrl( this, -1,
+                               wxL2U(p_item->psz_value),
+                               wxDefaultPosition,
+                               wxDefaultSize,
+                               wxTE_PROCESS_ENTER);
+    textctrl->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( textctrl, 1, wxALL, 5 );
+    browse = new wxButton( this, wxID_HIGHEST, wxU(_("Browse...")) );
+    sizer->Add( browse, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+BEGIN_EVENT_TABLE(FileConfigControl, wxPanel)
+    /* Button events */
+    EVT_BUTTON(wxID_HIGHEST, FileConfigControl::OnBrowse)
+END_EVENT_TABLE()
+
+void FileConfigControl::OnBrowse( wxCommandEvent& event )
+{
+    if( directory )
+    {
+        wxDirDialog dialog( this, wxU(_("Choose directory")) );
+
+        if( dialog.ShowModal() == wxID_OK )
+        {
+            textctrl->SetValue( dialog.GetPath() );
+        }
+    }
+    else
+    {
+        wxFileDialog dialog( this, wxU(_("Choose file")),
+                             wxT(""), wxT(""), wxT("*.*"),
+#if defined( __WXMSW__ )
+                             wxOPEN
+#else
+                             wxOPEN | wxSAVE
+#endif
+                           );
+        if( dialog.ShowModal() == wxID_OK )
+        {
+            textctrl->SetValue( dialog.GetPath() );
+        }
+    }
+}
+
+FileConfigControl::~FileConfigControl()
+{
+    ;
+}
+
+wxString FileConfigControl::GetPszValue()
+{
+    return textctrl->GetValue();
+}
+
+/*****************************************************************************
+ * IntegerConfigControl implementation
+ *****************************************************************************/
+BEGIN_EVENT_TABLE(IntegerConfigControl, wxPanel)
+    EVT_TEXT(-1, IntegerConfigControl::OnUpdate)
+    EVT_COMMAND_SCROLL(-1, IntegerConfigControl::OnUpdateScroll)
+END_EVENT_TABLE()
+
+IntegerConfigControl::IntegerConfigControl( vlc_object_t *p_this,
+                                            module_config_t *p_item,
+                                            wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    spin = new wxSpinCtrl( this, -1,
+                           wxString::Format(wxT("%d"),
+                                            p_item->i_value),
+                           wxDefaultPosition, wxDefaultSize,
+                           wxSP_ARROW_KEYS,
+                           -100000000, 100000000, p_item->i_value);
+    spin->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+    i_value = p_item->i_value;
+}
+
+IntegerConfigControl::~IntegerConfigControl()
+{
+    ;
+}
+
+int IntegerConfigControl::GetIntValue()
+{
+    /* We avoid using GetValue because of a recursion bug with wxSpinCtrl with
+     * wxGTK. */
+    return i_value; //spin->GetValue();
+}
+
+void IntegerConfigControl::OnUpdate( wxCommandEvent &event )
+{
+    i_value = event.GetInt();
+    ConfigControl::OnUpdate( event );
+}
+void IntegerConfigControl::OnUpdateScroll( wxScrollEvent &event )
+{
+    wxCommandEvent cevent;
+    cevent.SetInt(event.GetPosition());
+    OnUpdate(cevent);
+}
+
+/*****************************************************************************
+ * IntegerListConfigControl implementation
+ *****************************************************************************/
+IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *p_this,
+                                                    module_config_t *p_item,
+                                                    wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    combo = new wxComboBox( this, -1, wxT(""),
+                            wxDefaultPosition, wxDefaultSize,
+                            0, NULL, wxCB_READONLY );
+
+    UpdateCombo( p_item );
+
+    combo->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+IntegerListConfigControl::~IntegerListConfigControl()
+{
+}
+
+void IntegerListConfigControl::UpdateCombo( module_config_t *p_item )
+{
+    /* build a list of available options */
+    for( int i_index = 0; i_index < p_item->i_list; i_index++ )
+    {
+        if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
+        {
+            combo->Append( wxU(p_item->ppsz_list_text[i_index]) );
+        }
+        else
+        {
+            combo->Append( wxString::Format(wxT("%i"),
+                                            p_item->pi_list[i_index]) );
+        }
+        combo->SetClientData( i_index, (void *)p_item->pi_list[i_index] );
+        if( p_item->i_value == p_item->pi_list[i_index] )
+        {
+            combo->SetSelection( i_index );
+            if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
+            {
+                combo->SetValue( wxU(p_item->ppsz_list_text[i_index]) );
+            }
+            else
+            {
+                combo->SetValue( wxString::Format(wxT("%i"),
+                                                  p_item->pi_list[i_index]) );
+            }
+        }
+    }
+}
+
+BEGIN_EVENT_TABLE(IntegerListConfigControl, wxPanel)
+    /* Button events */
+    EVT_BUTTON(-1, IntegerListConfigControl::OnAction)
+
+    /* Update events */
+    EVT_TEXT(-1, IntegerListConfigControl::OnUpdate)
+END_EVENT_TABLE()
+
+void IntegerListConfigControl::OnAction( wxCommandEvent& event )
+{
+    int i_action = event.GetId() - wxID_HIGHEST;
+
+    module_config_t *p_item;
+    p_item = config_FindConfig( p_this, GetName().mb_str() );
+    if( !p_item ) return;
+
+    if( i_action < 0 || i_action >= p_item->i_action ) return;
+
+    vlc_value_t val;
+    val.i_int = GetIntValue();
+    p_item->ppf_action[i_action]( p_this, GetName().mb_str(), val, val, 0 );
+
+    if( p_item->b_dirty )
+    {
+        combo->Clear();
+        UpdateCombo( p_item );
+        p_item->b_dirty = VLC_FALSE;
+    }
+}
+
+int IntegerListConfigControl::GetIntValue()
+{
+    int selected = combo->GetSelection();
+    if( selected != -1 )
+    {
+        return (int)combo->GetClientData( selected );
+    }
+    return -1;
+}
+
+/*****************************************************************************
+ * RangedIntConfigControl implementation
+ *****************************************************************************/
+BEGIN_EVENT_TABLE(RangedIntConfigControl, wxPanel)
+    EVT_COMMAND_SCROLL(-1, RangedIntConfigControl::OnUpdateScroll)
+END_EVENT_TABLE()
+
+RangedIntConfigControl::RangedIntConfigControl( vlc_object_t *p_this,
+                                                module_config_t *p_item,
+                                                wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    slider = new wxSlider( this, -1, p_item->i_value, p_item->i_min,
+                           p_item->i_max, wxDefaultPosition, wxDefaultSize,
+                           wxSL_LABELS | wxSL_HORIZONTAL );
+    slider->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+RangedIntConfigControl::~RangedIntConfigControl()
+{
+    ;
+}
+
+int RangedIntConfigControl::GetIntValue()
+{
+    return slider->GetValue();
+}
+
+
+/*****************************************************************************
+ * FloatConfigControl implementation
+ *****************************************************************************/
+BEGIN_EVENT_TABLE(FloatConfigControl, wxPanel)
+    EVT_TEXT(-1, FloatConfigControl::OnUpdate)
+END_EVENT_TABLE()
+
+FloatConfigControl::FloatConfigControl( vlc_object_t *p_this,
+                                        module_config_t *p_item,
+                                        wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    label = new wxStaticText(this, -1, wxU(p_item->psz_text));
+    textctrl = new wxTextCtrl( this, -1,
+                               wxString::Format(wxT("%f"),
+                                                p_item->f_value),
+                               wxDefaultPosition, wxDefaultSize,
+                               wxTE_PROCESS_ENTER );
+    textctrl->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+    sizer->Add( textctrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+FloatConfigControl::~FloatConfigControl()
+{
+    ;
+}
+
+float FloatConfigControl::GetFloatValue()
+{
+    float f_value;
+    if( (wxSscanf(textctrl->GetValue(), wxT("%f"), &f_value) == 1) )
+        return f_value;
+    else return 0.0;
+}
+
+/*****************************************************************************
+ * BoolConfigControl implementation
+ *****************************************************************************/
+BEGIN_EVENT_TABLE(BoolConfigControl, wxPanel)
+    EVT_CHECKBOX(-1, BoolConfigControl::OnUpdate)
+END_EVENT_TABLE()
+
+BoolConfigControl::BoolConfigControl( vlc_object_t *p_this,
+                                      module_config_t *p_item,
+                                      wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    checkbox = new wxCheckBox( this, -1, wxU(p_item->psz_text) );
+    if( p_item->i_value ) checkbox->SetValue(TRUE);
+    checkbox->SetToolTip( wxU(p_item->psz_longtext) );
+    sizer->Add( checkbox, 0, wxALL, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+BoolConfigControl::~BoolConfigControl()
+{
+    ;
+}
+
+int BoolConfigControl::GetIntValue()
+{
+    if( checkbox->IsChecked() ) return 1;
+    else return 0;
+}
+
+/*****************************************************************************
+ * SectionConfigControl implementation
+ *****************************************************************************/
+SectionConfigControl::SectionConfigControl( vlc_object_t *p_this,
+                                            module_config_t *p_item,
+                                            wxWindow *parent )
+  : ConfigControl( p_this, p_item, parent )
+{
+    delete sizer;
+    sizer = new wxBoxSizer( wxVERTICAL );
+    sizer->Add( new wxStaticText( this, -1, wxU( p_item->psz_text ) ) );
+    sizer->Add( new wxStaticLine( this, -1 ), 0, wxEXPAND, 5 );
+    sizer->Layout();
+    this->SetSizerAndFit( sizer );
+}
+
+SectionConfigControl::~SectionConfigControl()
+{
+    ;
+}
diff --git a/modules/gui/wxwidgets/dialogs/preferences_widgets.h b/modules/gui/wxwidgets/dialogs/preferences_widgets.h
new file mode 100644 (file)
index 0000000..2f10e2f
--- /dev/null
@@ -0,0 +1,236 @@
+/*****************************************************************************
+ * preferences_widgets.h : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2003 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Sigmund Augdal Helberg <dnumgis@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <vector>
+
+class ConfigControl: public wxPanel
+{
+public:
+    ConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~ConfigControl();
+    wxSizer *Sizer();
+
+    virtual int GetIntValue() {return 0;}
+    virtual float GetFloatValue() {return 0;}
+    virtual wxString GetPszValue() {return wxString();}
+
+    wxString GetName();
+    int GetType();
+    vlc_bool_t IsAdvanced();
+
+    void SetUpdateCallback( void (*)( void * ), void * );
+
+protected:
+    wxBoxSizer *sizer;
+    wxStaticText *label;
+    vlc_object_t *p_this;
+
+    void (*pf_update_callback)( void * );
+    void *p_update_data;
+
+    void OnUpdate( wxCommandEvent& event );
+    void OnUpdateScroll( wxScrollEvent& event );
+
+private:
+    wxString name;
+    int i_type;
+    vlc_bool_t b_advanced;
+};
+
+ConfigControl *CreateConfigControl( vlc_object_t *,
+                                    module_config_t *, wxWindow * );
+
+class KeyConfigControl: public ConfigControl
+{
+public:
+    KeyConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~KeyConfigControl();
+    virtual int GetIntValue();
+private:
+    wxCheckBox *alt;
+    wxCheckBox *ctrl;
+    wxCheckBox *shift;
+    wxComboBox *combo;
+    // Array of key descriptions, for the ComboBox
+    static wxString *m_keysList;
+};
+
+class ModuleConfigControl: public ConfigControl
+{
+public:
+    ModuleConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~ModuleConfigControl();
+    virtual wxString GetPszValue();
+private:
+    wxComboBox *combo;
+};
+
+struct moduleCheckBox {
+    wxCheckBox *checkbox;
+    char *psz_module;
+};
+
+class ModuleCatConfigControl: public ConfigControl
+{
+public:
+    ModuleCatConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~ModuleCatConfigControl();
+    virtual wxString GetPszValue();
+private:
+    wxComboBox *combo;
+};
+
+
+class ModuleListCatConfigControl: public ConfigControl
+{
+public:
+    ModuleListCatConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~ModuleListCatConfigControl();
+    virtual wxString GetPszValue();
+private:
+    std::vector<moduleCheckBox *> pp_checkboxes;
+
+    void OnUpdate( wxCommandEvent& );
+
+    wxTextCtrl *text;
+    DECLARE_EVENT_TABLE()
+};
+
+;
+
+class StringConfigControl: public ConfigControl
+{
+public:
+    StringConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~StringConfigControl();
+    virtual wxString GetPszValue();
+private:
+    wxTextCtrl *textctrl;
+
+    DECLARE_EVENT_TABLE()
+};
+
+class StringListConfigControl: public ConfigControl
+{
+public:
+    StringListConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~StringListConfigControl();
+    virtual wxString GetPszValue();
+private:
+    wxComboBox *combo;
+    char *psz_default_value;
+    void UpdateCombo( module_config_t *p_item );
+
+    void OnAction( wxCommandEvent& );
+
+    DECLARE_EVENT_TABLE()
+};
+
+class FileConfigControl: public ConfigControl
+{
+public:
+    FileConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~FileConfigControl();
+    void OnBrowse( wxCommandEvent& );
+    virtual wxString GetPszValue();
+private:
+    wxTextCtrl *textctrl;
+    wxButton *browse;
+    bool directory;
+
+    DECLARE_EVENT_TABLE()
+};
+
+class IntegerConfigControl: public ConfigControl
+{
+public:
+    IntegerConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~IntegerConfigControl();
+    virtual int GetIntValue();
+private:
+    wxSpinCtrl *spin;
+    int i_value;
+
+    void OnUpdate( wxCommandEvent& event );
+    void OnUpdateScroll( wxScrollEvent& event );
+
+    DECLARE_EVENT_TABLE()
+};
+
+class IntegerListConfigControl: public ConfigControl
+{
+public:
+    IntegerListConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~IntegerListConfigControl();
+    virtual int GetIntValue();
+private:
+    wxComboBox *combo;
+    void UpdateCombo( module_config_t *p_item );
+
+    void OnAction( wxCommandEvent& );
+
+    DECLARE_EVENT_TABLE()
+};
+
+class RangedIntConfigControl: public ConfigControl
+{
+public:
+    RangedIntConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~RangedIntConfigControl();
+    virtual int GetIntValue();
+private:
+    wxSlider *slider;
+
+    DECLARE_EVENT_TABLE()
+};
+
+class FloatConfigControl: public ConfigControl
+{
+public:
+    FloatConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~FloatConfigControl();
+    virtual float GetFloatValue();
+private:
+    wxTextCtrl *textctrl;
+
+    DECLARE_EVENT_TABLE()
+};
+
+class BoolConfigControl: public ConfigControl
+{
+public:
+    BoolConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~BoolConfigControl();
+    virtual int GetIntValue();
+private:
+    wxCheckBox *checkbox;
+
+    DECLARE_EVENT_TABLE()
+};
+
+class SectionConfigControl: public ConfigControl
+{
+public:
+    SectionConfigControl( vlc_object_t *, module_config_t *, wxWindow * );
+    ~SectionConfigControl();
+};
diff --git a/modules/gui/wxwidgets/dialogs/streamout.cpp b/modules/gui/wxwidgets/dialogs/streamout.cpp
new file mode 100644 (file)
index 0000000..891875d
--- /dev/null
@@ -0,0 +1,1087 @@
+/*****************************************************************************
+ * streamout.cpp : wxWindows plugin for vlc
+ *****************************************************************************
+ * Copyright (C) 2000-2004 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include "dialogs/streamout.hpp"
+
+#include <wx/spinctrl.h>
+#include <wx/combobox.h>
+#include <wx/statline.h>
+
+#include "streamdata.h"
+
+#ifndef wxRB_SINGLE
+#   define wxRB_SINGLE 0
+#endif
+
+/*****************************************************************************
+ * Event Table.
+ *****************************************************************************/
+
+/* IDs for the controls and the menu commands */
+enum
+{
+    Notebook_Event = wxID_HIGHEST,
+    MRL_Event,
+
+    FileBrowse_Event,
+    FileName_Event,
+    FileDump_Event,
+
+    AccessType1_Event, AccessType2_Event, AccessType3_Event,
+    AccessType4_Event, AccessType5_Event, AccessType6_Event,
+    NetPort1_Event, NetPort2_Event, NetPort3_Event, NetPort4_Event,
+    NetAddr1_Event, NetAddr2_Event, NetAddr3_Event, NetAddr4_Event,
+
+    EncapsulationRadio1_Event, EncapsulationRadio2_Event,
+    EncapsulationRadio3_Event, EncapsulationRadio4_Event,
+    EncapsulationRadio5_Event, EncapsulationRadio6_Event,
+    EncapsulationRadio7_Event, EncapsulationRadio8_Event,
+    EncapsulationRadio9_Event, EncapsulationRadio10_Event,
+
+    VideoTranscEnable_Event, VideoTranscCodec_Event, VideoTranscBitrate_Event,
+    VideoTranscScale_Event,
+    AudioTranscEnable_Event, AudioTranscCodec_Event, AudioTranscBitrate_Event,
+    AudioTranscChans_Event,
+    SubtitlesTranscEnable_Event, SubtitlesTranscCodec_Event,
+    SubtitlesOverlayEnable_Event,
+
+    SAPMisc_Event, AnnounceGroup_Event, AnnounceAddr_Event,
+    SoutAll_Event
+};
+
+BEGIN_EVENT_TABLE(SoutDialog, wxDialog)
+    /* Button events */
+    EVT_BUTTON(wxID_OK, SoutDialog::OnOk)
+    EVT_BUTTON(wxID_CANCEL, SoutDialog::OnCancel)
+
+    /* Events generated by the access output panel */
+    EVT_CHECKBOX(AccessType1_Event, SoutDialog::OnAccessTypeChange)
+    EVT_CHECKBOX(AccessType2_Event, SoutDialog::OnAccessTypeChange)
+    EVT_CHECKBOX(AccessType3_Event, SoutDialog::OnAccessTypeChange)
+    EVT_CHECKBOX(AccessType4_Event, SoutDialog::OnAccessTypeChange)
+    EVT_CHECKBOX(AccessType5_Event, SoutDialog::OnAccessTypeChange)
+    EVT_CHECKBOX(AccessType6_Event, SoutDialog::OnAccessTypeChange)
+    EVT_TEXT(FileName_Event, SoutDialog::OnFileChange)
+    EVT_BUTTON(FileBrowse_Event, SoutDialog::OnFileBrowse)
+    EVT_CHECKBOX(FileDump_Event, SoutDialog::OnFileDump)
+
+    EVT_TEXT(NetPort1_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetAddr1_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetPort2_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetAddr2_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetPort3_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetAddr3_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetPort4_Event, SoutDialog::OnNetChange)
+    EVT_TEXT(NetAddr4_Event, SoutDialog::OnNetChange)
+
+    /* Events generated by the encapsulation panel */
+    EVT_RADIOBUTTON(EncapsulationRadio1_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio2_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio3_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio4_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio5_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio6_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio7_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio8_Event,
+                    SoutDialog::OnEncapsulationChange)
+    EVT_RADIOBUTTON(EncapsulationRadio9_Event,
+                    SoutDialog::OnEncapsulationChange)
+
+    /* Events generated by the transcoding panel */
+    EVT_CHECKBOX(VideoTranscEnable_Event, SoutDialog::OnTranscodingEnable)
+    EVT_CHECKBOX(AudioTranscEnable_Event, SoutDialog::OnTranscodingEnable)
+    EVT_CHECKBOX(SubtitlesTranscEnable_Event, SoutDialog::OnTranscodingEnable)
+    EVT_CHECKBOX(SubtitlesOverlayEnable_Event, SoutDialog::OnTranscodingEnable)
+    EVT_COMBOBOX(VideoTranscCodec_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(VideoTranscCodec_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(AudioTranscCodec_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(AudioTranscCodec_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(VideoTranscBitrate_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(VideoTranscBitrate_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(AudioTranscBitrate_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(AudioTranscBitrate_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(VideoTranscScale_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(VideoTranscScale_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(AudioTranscChans_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(AudioTranscChans_Event, SoutDialog::OnTranscodingChange)
+    EVT_COMBOBOX(SubtitlesTranscCodec_Event, SoutDialog::OnTranscodingChange)
+    EVT_TEXT(SubtitlesTranscCodec_Event, SoutDialog::OnTranscodingChange)
+
+    /* Events generated by the misc panel */
+    EVT_CHECKBOX(SAPMisc_Event, SoutDialog::OnSAPMiscChange)
+    EVT_TEXT(AnnounceGroup_Event, SoutDialog::OnAnnounceGroupChange)
+    EVT_TEXT(AnnounceAddr_Event, SoutDialog::OnAnnounceAddrChange)
+    EVT_CHECKBOX(SoutAll_Event, SoutDialog::OnAnnounceGroupChange)
+
+END_EVENT_TABLE()
+
+/*****************************************************************************
+ * Constructor.
+ *****************************************************************************/
+SoutDialog::SoutDialog( intf_thread_t *_p_intf, wxWindow* _p_parent ):
+    wxDialog( _p_parent, -1, wxU(_("Stream output")),
+             wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+{
+    /* Initializations */
+    p_intf = _p_intf;
+    p_parent = _p_parent;
+    SetIcon( *p_intf->p_sys->p_icon );
+
+    /* Create a panel to put everything in */
+    wxPanel *panel = new wxPanel( this, -1 );
+    panel->SetAutoLayout( TRUE );
+
+    /* Create MRL combobox */
+    wxBoxSizer *mrl_sizer_sizer = new wxBoxSizer( wxHORIZONTAL );
+    wxStaticBox *mrl_box = new wxStaticBox( panel, -1,
+                               wxU(_("Stream output MRL")) );
+    wxStaticBoxSizer *mrl_sizer = new wxStaticBoxSizer( mrl_box,
+                                                        wxHORIZONTAL );
+    wxStaticText *mrl_label = new wxStaticText( panel, -1,
+                                                wxU(_("Destination Target:")));
+    mrl_combo = new wxComboBox( panel, MRL_Event, wxT(""),
+                                wxPoint(20,25), wxSize(120, -1) );
+    mrl_combo->SetToolTip( wxU(_("You can use this field directly by typing "
+        "the full MRL you want to open.\n""Alternatively, the field will be "
+        "filled automatically when you use the controls below")) );
+
+    mrl_sizer->Add( mrl_label, 0, wxALL | wxALIGN_CENTER, 5 );
+    mrl_sizer->Add( mrl_combo, 1, wxALL | wxALIGN_CENTER, 5 );
+    mrl_sizer_sizer->Add( mrl_sizer, 1, wxEXPAND | wxALL, 5 );
+
+    /* Create the output encapsulation panel */
+    encapsulation_panel = EncapsulationPanel( panel );
+
+    /* Create the access output panel */
+    access_panel = AccessPanel( panel );
+
+    /* Create the transcoding panel */
+    transcoding_panel = TranscodingPanel( panel );
+
+    /* Create the Misc panel */
+    misc_panel = MiscPanel( panel );
+
+    /* Create the buttons */
+    wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
+    ok_button->SetDefault();
+    wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
+                                            wxU(_("Cancel")) );
+
+    /* Place everything in sizers */
+    wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
+    button_sizer->Add( ok_button, 0, wxALL, 5 );
+    button_sizer->Add( cancel_button, 0, wxALL, 5 );
+    button_sizer->Layout();
+    wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
+    wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
+    panel_sizer->Add( mrl_sizer_sizer, 0, wxEXPAND, 5 );
+    panel_sizer->Add( access_panel, 1, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( encapsulation_panel, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( transcoding_panel, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( misc_panel, 0, wxEXPAND | wxALL, 5 );
+    panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
+                      wxALL, 5 );
+    panel_sizer->Layout();
+    panel->SetSizerAndFit( panel_sizer );
+    main_sizer->Add( panel, 1, wxGROW, 0 );
+    main_sizer->Layout();
+    SetSizerAndFit( main_sizer );
+}
+
+SoutDialog::~SoutDialog()
+{
+}
+
+wxArrayString SoutDialog::GetOptions()
+{
+   return SeparateEntries( mrl_combo->GetValue() );
+}
+
+/*****************************************************************************
+ * Private methods.
+ *****************************************************************************/
+void SoutDialog::UpdateMRL()
+{
+    /* Check the demux dump option */
+    if( dump_checkbox->IsChecked() )
+    {
+        wxString dumpfile;
+
+        if( file_combo->GetValue().size() )
+            dumpfile = wxT(" :demuxdump-file=\"") +
+                       file_combo->GetValue() + wxT("\"");
+        mrl_combo->SetValue( wxT(":demux=dump") + dumpfile );
+
+        return;
+    }
+
+    /* Let's start with the transcode options */
+    wxString transcode;
+    if( video_transc_checkbox->IsChecked() ||
+        audio_transc_checkbox->IsChecked() ||
+        subtitles_transc_checkbox->IsChecked() ||
+        subtitles_overlay_checkbox->IsChecked() )
+    {
+        transcode = wxT("transcode{");
+        if( video_transc_checkbox->IsChecked() )
+        {
+            transcode += wxT("vcodec=") + video_codec_combo->GetValue();
+            transcode += wxT(",vb=") + video_bitrate_combo->GetValue();
+            transcode += wxT(",scale=") + video_scale_combo->GetValue();
+            if( audio_transc_checkbox->IsChecked() ||
+                subtitles_transc_checkbox->IsChecked() ||
+                subtitles_overlay_checkbox->IsChecked() )
+                transcode += wxT(",");
+        }
+        if( audio_transc_checkbox->IsChecked() )
+        {
+            transcode += wxT("acodec=") + audio_codec_combo->GetValue();
+            transcode += wxT(",ab=") + audio_bitrate_combo->GetValue();
+            transcode += wxT(",channels=") + audio_channels_combo->GetValue();
+            if( subtitles_transc_checkbox->IsChecked() ||
+                subtitles_overlay_checkbox->IsChecked() )
+                transcode += wxT(",");
+        }
+        if( subtitles_transc_checkbox->IsChecked() )
+        {
+            transcode += wxT("scodec=") + subtitles_codec_combo->GetValue();
+        }
+        if( subtitles_overlay_checkbox->IsChecked() )
+        {
+            transcode += wxT("soverlay");
+        }
+        transcode += wxT("}");
+    }
+
+    /* Encapsulation */
+    wxString encapsulation;
+    switch( i_encapsulation_type )
+    {
+    case PS_ENCAPSULATION:
+        encapsulation = wxT("ps");
+        break;
+    case MPEG1_ENCAPSULATION:
+        encapsulation = wxT("mpeg1");
+        break;
+    case AVI_ENCAPSULATION:
+        encapsulation = wxT("avi");
+        break;
+    case OGG_ENCAPSULATION:
+        encapsulation = wxT("ogg");
+        break;
+    case RAW_ENCAPSULATION:
+        encapsulation = wxT("raw");
+        break;
+    case MP4_ENCAPSULATION:
+        encapsulation = wxT("mp4");
+        break;
+    case MOV_ENCAPSULATION:
+        encapsulation = wxT("mov");
+        break;
+    case ASF_ENCAPSULATION:
+        encapsulation = wxT("asf");
+        break;
+    case WAV_ENCAPSULATION:
+        encapsulation = wxT("wav");
+        break;
+    case TS_ENCAPSULATION:
+    default:
+        encapsulation = wxT("ts");
+        break;
+    }
+
+    /* Now continue with the duplicate option */
+    wxString dup_opts;
+    if( access_checkboxes[PLAY_ACCESS_OUT]->IsChecked() )
+    {
+        dup_opts += wxT("dst=display");
+    }
+    if( access_checkboxes[FILE_ACCESS_OUT]->IsChecked() )
+    {
+        if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
+        dup_opts += wxT("dst=std{access=file,mux=");
+        dup_opts += encapsulation + wxT(",url=\"");
+        dup_opts += file_combo->GetValue() + wxT("\"}");
+    }
+    if( access_checkboxes[HTTP_ACCESS_OUT]->IsChecked() )
+    {
+        if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
+        dup_opts += wxT("dst=std{access=http,mux=");
+        dup_opts += encapsulation + wxT(",url=");
+        dup_opts += net_addrs[HTTP_ACCESS_OUT]->GetLineText(0);
+        dup_opts += wxString::Format( wxT(":%d"),
+                                      net_ports[HTTP_ACCESS_OUT]->GetValue() );
+        dup_opts += wxT("}");
+    }
+    if( access_checkboxes[MMSH_ACCESS_OUT]->IsChecked() )
+    {
+        if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
+        dup_opts += wxT("dst=std{access=mmsh,mux=");
+        dup_opts += encapsulation;
+        if( i_encapsulation_type == ASF_ENCAPSULATION ) dup_opts += wxT("h");
+        dup_opts += wxT(",url=");
+        dup_opts += net_addrs[MMSH_ACCESS_OUT]->GetLineText(0);
+        dup_opts += wxString::Format( wxT(":%d"),
+                                      net_ports[MMSH_ACCESS_OUT]->GetValue() );
+        dup_opts += wxT("}");
+    }
+    if( access_checkboxes[RTP_ACCESS_OUT]->IsChecked() )
+    {
+        if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
+        dup_opts += wxT("dst=std{access=rtp,mux=");
+        dup_opts += encapsulation + wxT(",url=");
+
+        wxString rtp_addr = net_addrs[RTP_ACCESS_OUT]->GetLineText(0);
+        if ((rtp_addr[0u] != '[') && (rtp_addr.Find(':') != -1))
+        {
+            dup_opts += wxT ("[") + rtp_addr + wxT ("]");
+        }
+        else
+        {
+            dup_opts += rtp_addr;
+        }
+        dup_opts += wxString::Format( wxT(":%d"),
+                                      net_ports[RTP_ACCESS_OUT]->GetValue() );
+
+        /* SAP if RTP */
+        if( sap_checkbox->IsChecked() )
+        {
+            dup_opts += wxT(",sap");
+            if( ! announce_group->GetLineText(0).IsEmpty() )
+            {
+                dup_opts += wxT(",group=\"");
+                dup_opts += announce_group->GetLineText(0);
+                dup_opts += wxT("\"");
+            }
+            if( ! announce_addr->GetLineText(0).IsEmpty() )
+            {
+                dup_opts += wxT(",name=\"");
+                dup_opts += announce_addr->GetLineText(0);
+                dup_opts += wxT("\"");
+            }
+        }
+
+        dup_opts += wxT("}");
+    }
+
+    if( access_checkboxes[UDP_ACCESS_OUT]->IsChecked() )
+    {
+        if( !dup_opts.IsEmpty() ) dup_opts += wxT(",");
+        dup_opts += wxT("dst=std{access=udp,mux=");
+        dup_opts += encapsulation + wxT(",url=");
+
+        wxString udp_addr = net_addrs[UDP_ACCESS_OUT]->GetLineText(0);
+        if ((udp_addr[0u] != '[') && (udp_addr.Find(':') != -1))
+        {
+            dup_opts += wxT ("[") + udp_addr + wxT ("]");
+        }
+        else
+        {
+            dup_opts += udp_addr;
+        }
+        dup_opts += wxString::Format( wxT(":%d"),
+                                      net_ports[UDP_ACCESS_OUT]->GetValue() );
+
+        /* SAP if UDP */
+        if( sap_checkbox->IsChecked() )
+        {
+            dup_opts += wxT(",sap");
+            if( ! announce_group->GetLineText(0).IsEmpty() )
+            {
+                dup_opts += wxT(",group=\"");
+                dup_opts += announce_group->GetLineText(0);
+                dup_opts += wxT("\"");
+            }
+            if( ! announce_addr->GetLineText(0).IsEmpty() )
+            {
+                dup_opts += wxT(",name=\"");
+                dup_opts += announce_addr->GetLineText(0);
+                dup_opts += wxT("\"");
+            }
+        }
+
+        dup_opts += wxT("}");
+    }
+
+    wxString duplicate;
+    if( !dup_opts.IsEmpty() )
+    {
+        if( !transcode.IsEmpty() ) duplicate = wxT(":");
+        duplicate += wxT("duplicate{") + dup_opts + wxT("}");
+    }
+
+    wxString misc;
+    if( (!transcode.IsEmpty() || !duplicate.IsEmpty()) &&
+        sout_all_checkbox->IsChecked() )
+    {
+        misc = wxT(" :sout-all");
+    }
+
+    if( !transcode.IsEmpty() || !duplicate.IsEmpty() )
+        mrl_combo->SetValue( wxT(":sout=#") + transcode + duplicate + misc );
+    else
+        mrl_combo->SetValue( wxT("") );
+}
+
+wxPanel *SoutDialog::AccessPanel( wxWindow* parent )
+{
+    int i;
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxStaticBox *panel_box = new wxStaticBox( panel, -1,
+                                              wxU(_("Output methods")) );
+    wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
+                                                          wxVERTICAL );
+
+    /*wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 4, 20 );*/
+    wxFlexGridSizer *sizer = new wxFlexGridSizer( 2, 0, 20 );
+    static const wxString access_output_array[] =
+    {
+        wxU(_("Play locally")),
+        wxU(_("File")),
+        wxU(_("HTTP")),
+        wxU(_("MMSH")),
+        wxU(_("RTP")),
+        wxU(_("UDP")),
+    };
+
+    for( i=0; i < ACCESS_OUT_NUM; i++ )
+    {
+        access_checkboxes[i] = new wxCheckBox( panel, AccessType1_Event + i,
+                                               access_output_array[i] );
+        access_subpanels[i] = new wxPanel( panel, -1 );
+    }
+
+    /* Play locally row */
+    wxFlexGridSizer *subpanel_sizer;
+    wxStaticText *label;
+    label = new wxStaticText( access_subpanels[0], -1, wxT("") );
+    subpanel_sizer = new wxFlexGridSizer( 1, 1, 20 );
+    subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    access_subpanels[0]->SetSizerAndFit( subpanel_sizer );
+    access_subpanels[0]->Hide();
+
+    /* File row */
+    /*subpanel_sizer = new wxFlexGridSizer( 3, 2, 20 );*/
+    subpanel_sizer = new wxFlexGridSizer( 4, 1, 10);
+    label = new wxStaticText( access_subpanels[1], -1, wxU(_("Filename")) );
+    file_combo = new wxComboBox( access_subpanels[1], FileName_Event, wxT(""),
+                                 wxPoint(20,25), wxSize(200, -1) );
+    wxButton *browse_button = new wxButton( access_subpanels[1],
+                                  FileBrowse_Event, wxU(_("Browse...")) );
+    subpanel_sizer->Add( label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( file_combo, 1,
+                         wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( browse_button, 0,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    /*subpanel_sizer->Add( new wxPanel(access_subpanels[1], -1), 0,*/
+    /*                     wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );*/
+    dump_checkbox = new wxCheckBox( access_subpanels[1], FileDump_Event,
+                                    wxU(_("Dump raw input")) );
+    subpanel_sizer->Add( dump_checkbox, 0,
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxTOP, 5 );
+
+    access_subpanels[1]->SetSizerAndFit( subpanel_sizer );
+
+    /* Net rows */
+    for( i = HTTP_ACCESS_OUT; i < ACCESS_OUT_NUM; i++ )
+    {
+        subpanel_sizer = new wxFlexGridSizer( 4, 1, 20 );
+        label = new wxStaticText( access_subpanels[i], -1, wxU(_("Address")) );
+        net_addrs[i] = new wxTextCtrl( access_subpanels[i],
+                                   NetAddr1_Event + i - HTTP_ACCESS_OUT,
+                                   wxT(""), wxDefaultPosition,
+                                   wxSize( 200, -1 ), wxTE_PROCESS_ENTER);
+        subpanel_sizer->Add( label, 0,
+                             wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+        subpanel_sizer->Add( net_addrs[i], 1, wxEXPAND |
+                             wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+        int val = config_GetInt( p_intf, "server-port" );
+        label = new wxStaticText( access_subpanels[i], -1, wxU(_("Port")) );
+        net_ports[i] = new wxSpinCtrl( access_subpanels[i],
+                                   NetPort1_Event + i - HTTP_ACCESS_OUT,
+                                   wxString::Format(wxT("%d"), val),
+                                   wxDefaultPosition, wxDefaultSize,
+                                   wxSP_ARROW_KEYS,
+                                   0, 65535, val );
+
+        subpanel_sizer->Add( label, 0,
+                             wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+        subpanel_sizer->Add( net_ports[i], 0,
+                             wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+        access_subpanels[i]->SetSizerAndFit( subpanel_sizer );
+    }
+
+
+    /* Stuff everything into the main panel */
+    for( i=1; i < ACCESS_OUT_NUM; i++ )
+    {
+        sizer->Add( access_checkboxes[i], 0,
+                    wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
+        sizer->Add( access_subpanels[i], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL
+                    | wxALIGN_LEFT  | wxALL, 5 );
+    }
+
+    panel_sizer->Add( access_checkboxes[0], 0,
+                      wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL  | wxALL, 5 );
+    panel_sizer->Add( sizer, 1, wxEXPAND | wxTOP, 3 );
+
+    panel->SetSizerAndFit( panel_sizer );
+
+    /* Update access type panel */
+    for( i=1; i < ACCESS_OUT_NUM; i++ )
+    {
+        access_subpanels[i]->Disable();
+    }
+
+    return panel;
+}
+
+wxPanel *SoutDialog::MiscPanel( wxWindow* parent )
+{
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxStaticBox *panel_box = new wxStaticBox( panel, -1,
+                                   wxU(_("Miscellaneous options")) );
+    wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
+                                                          wxVERTICAL );
+
+    /* Announce Row */
+    misc_subpanels[ANN_MISC_SOUT] = new wxPanel( panel, -1 );
+    misc_subpanels[TTL_MISC_SOUT] = new wxPanel( panel, -1 );
+    wxFlexGridSizer *subpanel_sizer = new wxFlexGridSizer( 3, 4, 20 );
+    wxFlexGridSizer *subpanel_sub_sizer = new wxFlexGridSizer( 5, 4, 20 );
+    wxFlexGridSizer *subpanel2_sizer = new wxFlexGridSizer( 3, 4, 20 );
+
+    sap_checkbox = new wxCheckBox( misc_subpanels[ANN_MISC_SOUT],SAPMisc_Event,
+                                   wxU(_("SAP announce")) );
+    wxStaticText *label_g = new wxStaticText( misc_subpanels[ANN_MISC_SOUT], -1,
+                                            wxU(_("Group name")) );
+    announce_group = new wxTextCtrl( misc_subpanels[ANN_MISC_SOUT],
+                                    AnnounceGroup_Event,
+                                    wxT(""), wxDefaultPosition,
+                                    wxSize( 100, -1 ), wxTE_PROCESS_ENTER);
+
+    wxStaticText *label = new wxStaticText( misc_subpanels[ANN_MISC_SOUT], -1,
+                                            wxU(_("Channel name")) );
+    announce_addr = new wxTextCtrl( misc_subpanels[ANN_MISC_SOUT],
+                                    AnnounceAddr_Event,
+                                    wxT(""), wxDefaultPosition,
+                                    wxSize( 100, -1 ), wxTE_PROCESS_ENTER);
+
+    wxStaticText *ttl_label = new wxStaticText( misc_subpanels[TTL_MISC_SOUT], -1,
+                        wxU(_("Time-To-Live (TTL)")) );
+    ttl_spin = new wxSpinCtrl( misc_subpanels[TTL_MISC_SOUT], -1, wxEmptyString, wxDefaultPosition, wxDefaultSize,
+                   0, 1, 255, config_GetInt( p_intf, "ttl" ) );
+
+    subpanel_sizer->Add( sap_checkbox, 0,
+                         wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sub_sizer->Add( label_g, 0, wxALIGN_RIGHT |
+                             wxALIGN_CENTER_VERTICAL );
+    subpanel_sub_sizer->Add( announce_group, 1, wxEXPAND |
+                             wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sub_sizer->Add( label, 0, wxALIGN_RIGHT |
+                             wxALIGN_CENTER_VERTICAL );
+    subpanel_sub_sizer->Add( announce_addr, 1, wxEXPAND |
+                             wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+    subpanel_sizer->Add( subpanel_sub_sizer, 1, wxEXPAND |
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    sout_all_checkbox = new wxCheckBox( misc_subpanels[TTL_MISC_SOUT],
+                    SoutAll_Event, wxU(_("Select all elementary streams")) );
+    subpanel2_sizer->Add( sout_all_checkbox, 1,
+                      wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxLEFT, 5 );
+    subpanel2_sizer->Add( ttl_label, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    subpanel2_sizer->Add( ttl_spin, 0, wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+
+    misc_subpanels[ANN_MISC_SOUT]->SetSizerAndFit( subpanel_sizer );
+    misc_subpanels[TTL_MISC_SOUT]->SetSizerAndFit( subpanel2_sizer );
+
+    /* Stuff everything into the main panel */
+    panel_sizer->Add( misc_subpanels[ANN_MISC_SOUT], 1,
+                      wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxLEFT, 5 );
+
+    panel_sizer->Add( misc_subpanels[TTL_MISC_SOUT], 1,
+                      wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 5 );
+
+
+    panel->SetSizerAndFit( panel_sizer );
+
+    /* Update misc panel */
+    misc_subpanels[ANN_MISC_SOUT]->Disable();
+    announce_group->Disable();
+    announce_addr->Disable();
+
+    return panel;
+}
+
+wxPanel *SoutDialog::EncapsulationPanel( wxWindow* parent )
+{
+    unsigned int i;
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxStaticBox *panel_box = new wxStaticBox( panel, -1,
+                                              wxU(_("Encapsulation Method")) );
+    wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
+                                                          wxHORIZONTAL );
+
+    static const wxString encapsulation_array[] =
+    {
+        wxT("MPEG TS"),
+        wxT("MPEG PS"),
+        wxT("MPEG 1"),
+        wxT("Ogg"),
+        wxT("ASF"),
+        wxT("MP4"),
+        wxT("MOV"),
+        wxT("WAV"),
+        wxT("Raw")
+    };
+
+    /* Stuff everything into the main panel */
+    for( i = 0; i < WXSIZEOF(encapsulation_array); i++ )
+    {
+        encapsulation_radios[i] =
+            new wxRadioButton( panel, EncapsulationRadio1_Event + i,
+                               encapsulation_array[i] );
+        panel_sizer->Add( encapsulation_radios[i], 0,
+                          wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL |
+                          wxALL, 4 );
+    }
+    /* Hide avi one */
+    for( i = WXSIZEOF(encapsulation_array); i < ENCAPS_NUM; i++ )
+    {
+        encapsulation_radios[i] =
+            new wxRadioButton( panel, EncapsulationRadio1_Event + i, wxT("") );
+        encapsulation_radios[i]->Hide();
+    }
+
+    panel->SetSizerAndFit( panel_sizer );
+
+    /* Update encapsulation panel */
+    encapsulation_radios[TS_ENCAPSULATION]->SetValue(true);
+    i_encapsulation_type = TS_ENCAPSULATION;
+
+    return panel;
+}
+
+wxPanel *SoutDialog::TranscodingPanel( wxWindow* parent )
+{
+    wxPanel *panel = new wxPanel( parent, -1, wxDefaultPosition,
+                                  wxSize(200, 200) );
+
+    wxStaticBox *panel_box = new wxStaticBox( panel, -1,
+                                              wxU(_("Transcoding options")) );
+    wxStaticBoxSizer *panel_sizer = new wxStaticBoxSizer( panel_box,
+                                                          wxVERTICAL );
+
+    /* Create video transcoding checkox */
+    static const wxString wxvcodecs_array[] =
+    {
+        wxT("mp1v"),
+        wxT("mp2v"),
+        wxT("mp4v"),
+        wxT("DIV1"),
+        wxT("DIV2"),
+        wxT("DIV3"),
+        wxT("H263"),
+        wxT("h264"),
+        wxT("WMV1"),
+        wxT("WMV2"),
+        wxT("MJPG"),
+        wxT("theo")
+    };
+    /*
+    static const wxString vbitrates_array[] =
+    {
+            wxT("3072"),
+            wxT("2048"),
+            wxT("1024"),
+            wxT("768"),
+            wxT("512"),
+            wxT("384"),
+            wxT("256"),
+            wxT("192"),
+            wxT("128"),
+            wxT("96"),
+            wxT("64"),
+            wxT("32"),
+            wxT("16")
+    };
+*/
+    static const wxString vscales_array[] =
+    {
+            wxT("0.25"),
+            wxT("0.5"),
+            wxT("0.75"),
+            wxT("1"),
+            wxT("1.25"),
+            wxT("1.5"),
+            wxT("1.75"),
+            wxT("2")
+    };
+
+    wxFlexGridSizer *video_sizer = new wxFlexGridSizer( 6, 1, 20 );
+#if defined( __WXMSW__ )
+    wxFlexGridSizer *video_sub_sizer = new wxFlexGridSizer( 4, 5, 20 );
+#else
+    wxFlexGridSizer *video_sub_sizer = new wxFlexGridSizer( 2, 5, 20 );
+#endif
+    video_transc_checkbox =
+        new wxCheckBox( panel, VideoTranscEnable_Event, wxU(_("Video codec")));
+    video_codec_combo =
+        new wxComboBox( panel, VideoTranscCodec_Event, wxvcodecs_array[2],
+                        wxPoint(20,25), wxDefaultSize,
+                        WXSIZEOF(wxvcodecs_array),
+                        wxvcodecs_array, wxCB_READONLY );
+    video_codec_combo->SetSelection(2);
+    wxStaticText *bitrate_label =
+        new wxStaticText( panel, -1, wxU(_("Bitrate (kb/s)")));
+    video_bitrate_combo =
+        new wxComboBox( panel, VideoTranscBitrate_Event, wxT("1024"),
+                        wxPoint(20,25), wxDefaultSize,
+                        WXSIZEOF(vbitrates_array), vbitrates_array );
+    wxStaticText *scale_label =
+        new wxStaticText( panel, -1, wxU(_("Scale")));
+    video_scale_combo =
+        new wxComboBox( panel, VideoTranscScale_Event, wxT("1"),
+                        wxPoint(20,25), wxDefaultSize,
+                        WXSIZEOF(vscales_array), vscales_array );
+    video_sizer->Add( video_transc_checkbox, 0,
+                      wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sizer->Add( video_codec_combo, 1,
+                      wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sub_sizer->Add( bitrate_label, 0,
+                      wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sub_sizer->Add( video_bitrate_combo, 1,
+                      wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sub_sizer->Add( scale_label, 0,
+                      wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sub_sizer->Add( video_scale_combo, 1,
+                      wxEXPAND | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL );
+    video_sizer->Add( video_sub_sizer, 1, wxEXPAND |
+                         wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL );
+
+    /* Create audio transcoding checkox */
+    static const wxString wxacodecs_array[] =
+    {
+        wxT("mpga"),
+        wxT("mp2a"),
+        wxT("mp3"),
+        wxT("mp4a"),
+        wxT("a52"),
+        wxT("vorb"),
+        wxT("flac"),
+        wxT("spx"),
+        wxT("s16l"),
+        wxT("fl32")
+    };
+    static const wxString achannels_array[] =
+    {