interface.cpp 45.4 KB
Newer Older
gbazin's avatar
   
gbazin committed
1
/*****************************************************************************
2
 * interface.cpp : wxWidgets plugin for vlc
gbazin's avatar
   
gbazin committed
3
 *****************************************************************************
4
 * Copyright (C) 2000-2006 the VideoLAN team
gbazin's avatar
gbazin committed
5
 * $Id$
gbazin's avatar
   
gbazin committed
6
 *
7
 * Authors: Gildas Bazin <gbazin@videolan.org>
gbazin's avatar
   
gbazin committed
8
9
10
11
12
 *
 * 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.
13
 *
gbazin's avatar
   
gbazin committed
14
15
16
17
18
19
20
 * 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
dionoea's avatar
dionoea committed
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
gbazin's avatar
   
gbazin committed
22
23
24
25
26
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
27
#include "interface.hpp"
28
#include "playlist_manager.hpp"
29
30
31
32
33
#include "extrapanel.hpp"
#include "timer.hpp"
#include "video.hpp"
#include <vlc_keys.h>

zorglub's avatar
zorglub committed
34
#include "vlc_charset.h"
gbazin's avatar
   
gbazin committed
35

zorglub's avatar
zorglub committed
36
37
#include <vlc_aout.h>
#include "vlc_charset.h"
gbazin's avatar
   
gbazin committed
38

zorglub's avatar
zorglub committed
39
#include <vlc_interface.h>
40

41
42
#include <wx/splitter.h>

43
44
#include <wx/utils.h>                             /* wxLaunchDefaultBrowser() */

gbazin's avatar
   
gbazin committed
45
46
47
48
/* include the toolbar graphics */
#include "bitmaps/play.xpm"
#include "bitmaps/pause.xpm"
#include "bitmaps/stop.xpm"
49
#include "bitmaps/prev.xpm"
gbazin's avatar
   
gbazin committed
50
#include "bitmaps/next.xpm"
51
#include "bitmaps/eject.xpm"
gbazin's avatar
   
gbazin committed
52
#include "bitmaps/slow.xpm"
53
#include "bitmaps/fast.xpm"
54
#include "bitmaps/playlist.xpm"
55
#include "bitmaps/playlist_small.xpm"
56
#include "bitmaps/speaker.xpm"
57
#include "bitmaps/speaker_mute.xpm"
gbazin's avatar
   
gbazin committed
58

59
60
#define TOOLBAR_BMP_WIDTH 16
#define TOOLBAR_BMP_HEIGHT 16
gbazin's avatar
   
gbazin committed
61

gbazin's avatar
   
gbazin committed
62
/* include the icon graphic */
Sam Hocevar's avatar
Sam Hocevar committed
63
#include "../../../share/vlc32x32.xpm"
64
/* include a small icon graphic for the systray icon */
65
#ifdef wxHAS_TASK_BAR_ICON
66
#include "../../../share/vlc16x16.xpm"
67
#endif
gbazin's avatar
   
gbazin committed
68

zorglub's avatar
zorglub committed
69
70
71
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
72
73
static int InteractCallback( vlc_object_t *, const char *, vlc_value_t,
                             vlc_value_t, void *);
zorglub's avatar
zorglub committed
74

gbazin's avatar
   
gbazin committed
75
76
77
/*****************************************************************************
 * Local class declarations.
 *****************************************************************************/
gbazin's avatar
   
gbazin committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class wxMenuExt: public wxMenu
{
public:
    /* Constructor */
    wxMenuExt( wxMenu* parentMenu, int id, const wxString& text,
                   const wxString& helpString, wxItemKind kind,
                   char *_psz_var, int _i_object_id, vlc_value_t _val,
                   int _i_val_type );

    virtual ~wxMenuExt() {};

    char *psz_var;
    int  i_val_type;
    int  i_object_id;
    vlc_value_t val;

private:

};
gbazin's avatar
   
gbazin committed
97

98
99
class wxVolCtrl;
class VLCVolCtrl : public wxControl
gbazin's avatar
   
gbazin committed
100
101
{
public:
102
103
    VLCVolCtrl( intf_thread_t *p_intf, wxWindow *p_parent );
    virtual ~VLCVolCtrl() {};
gbazin's avatar
   
gbazin committed
104

105
106
    virtual void OnPaint( wxPaintEvent &event );
    void OnChange( wxMouseEvent& event );
107
    void UpdateVolume();
gbazin's avatar
   
gbazin committed
108

109
  private:
110
    DECLARE_EVENT_TABLE()
gbazin's avatar
   
gbazin committed
111

112
113
    wxVolCtrl *gauge;
    int i_y_offset;
114
    vlc_bool_t b_mute;
gbazin's avatar
   
gbazin committed
115
116
117
    intf_thread_t *p_intf;
};

118
BEGIN_EVENT_TABLE(VLCVolCtrl, wxControl)
119
    EVT_PAINT(VLCVolCtrl::OnPaint)
120

gbazin's avatar
   
gbazin committed
121
    /* Mouse events */
122
    EVT_LEFT_UP(VLCVolCtrl::OnChange)
gbazin's avatar
   
gbazin committed
123
124
END_EVENT_TABLE()

125
126
127
128
129
class Splitter : public wxSplitterWindow
{
public:
    Splitter( wxWindow *p_parent, intf_thread_t *_p_intf )
      : wxSplitterWindow( p_parent, -1, wxDefaultPosition, wxSize(0,0),
130
131
132
#if defined( __WXMSW__ )
                          wxCLIP_CHILDREN ),
#else
133
                          wxCLIP_CHILDREN | wxSP_3DSASH ),
134
#endif
135
        p_intf(_p_intf), b_video(0), i_delay(0)
136
137
    {
        SetSashSize( 0 );
138
139
140
141
142
143
144
145
146
147

        wxSize size = wxSize(-1, 150);
        wxPoint p = wxPoint(0,0);
        bool b_dummy;
        WindowSettings *ws = p_intf->p_sys->p_window_settings;
        ws->GetSettings( WindowSettings::ID_SMALL_PLAYLIST, b_dummy, p, size );

        i_width = size.GetWidth();
        i_sash_position = size.GetHeight();
        b_show_on_start = !!p.x;
148
149
    }

150
151
152
153
154
155
156
    virtual ~Splitter()
    {
        WindowSettings *ws = p_intf->p_sys->p_window_settings;
        ws->SetSettings( WindowSettings::ID_SMALL_PLAYLIST, true,
                         wxPoint(!!GetWindow2(),0),
                         wxSize(i_width, i_sash_position) );
    };
157
158
159

    virtual bool Split( wxWindow* window1, wxWindow* window2 )
    {
160
161
        SetSashSize( 0 );
        wxSize size = wxSize( i_width, i_sash_position );
162
163
        if( window2->GetSizer() ) window2->GetSizer()->SetMinSize( size );

164
165
166
167
        return wxSplitterWindow::SplitHorizontally( window1, window2,
                                                    -i_sash_position );
    }

168
169
170
171
172
173
    virtual bool Unsplit( wxWindow* window )
    {
        SetSashSize( 0 );
        return wxSplitterWindow::Unsplit( window );
    }

174
175
    bool ShowOnStart() { return b_show_on_start; }

176
177
178
179
180
private:
    DECLARE_EVENT_TABLE()

    void OnSize( wxSizeEvent &event )
    {
181
182
183
184
185
        /* If we display video, then resize the video window */
        if( GetWindow2() &&
            p_intf->p_sys->p_video_window && p_intf->p_sys->p_video_sizer &&
            p_intf->p_sys->p_video_sizer->GetMinSize() != wxSize(0,0) )
        {
186
187
188
            if( !b_video ) i_delay = mdate() + 1000000;
            b_video = VLC_TRUE;

189
190
191
            SetSashSize( -1 );

#if defined( __WXMSW__ )
192
            SetSashPosition( event.GetSize().GetHeight() - i_sash_position );
193
194
195
196
#else
            SetSashPosition( event.GetSize().GetHeight() -
                             i_sash_position - GetSashSize() );
#endif
197
198
199
200
201
        }
        else if( GetWindow2() && GetWindow1() && GetWindow1()->GetSizer() )
        {
            wxSize size = GetWindow1()->GetSizer()->GetMinSize();

202
203
204
            if( b_video ) i_delay = mdate() + 1000000;
            b_video = VLC_FALSE;

205
206
            if( event.GetSize().GetHeight() - size.GetHeight() )
            {
207
208
                SetSashSize( 0 );

209
210
                SetSashPosition( size.GetHeight() ? size.GetHeight() : 1 );

211
212
213
214
215
216
217
218
219
220
                if( i_delay < mdate() )
                {
                    i_sash_position = event.GetSize().GetHeight() -
                        size.GetHeight();
                    i_width = event.GetSize().GetWidth();

                    size = wxSize( i_width, i_sash_position );
                    if( GetWindow2()->GetSizer() )
                        GetWindow2()->GetSizer()->SetMinSize( size );
                }
221
222
223
            }
        }

224
225
226
227
228
229
        event.Skip();
    }

    void OnSashPosChanged( wxSplitterEvent &event )
    {
        if( !GetSize().GetHeight() ){ event.Skip(); return; }
230
231
232
233
234
235
236
237
238

        if( i_delay < mdate() )
        {
            i_sash_position = GetSize().GetHeight() - event.GetSashPosition();

            wxSize size = wxSize( i_width, i_sash_position );
            if( GetWindow2()->GetSizer() )
                GetWindow2()->GetSizer()->SetMinSize( size );
        }
239
240
241
242
243
        event.Skip();
    }

    intf_thread_t *p_intf;
    int i_sash_position;
244
    int i_width;
245
246
    vlc_bool_t b_video;
    mtime_t i_delay;
247
    vlc_bool_t b_show_on_start;
248
249
250
251
252
253
254
};

BEGIN_EVENT_TABLE(Splitter, wxSplitterWindow)
    EVT_SIZE( Splitter::OnSize )
    EVT_SPLITTER_SASH_POS_CHANGED(-1, Splitter::OnSashPosChanged)
END_EVENT_TABLE()

gbazin's avatar
   
gbazin committed
255
256
257
258
/*****************************************************************************
 * Event Table.
 *****************************************************************************/

gbazin's avatar
gbazin committed
259
260
DEFINE_LOCAL_EVENT_TYPE( wxEVT_INTF );

gbazin's avatar
   
gbazin committed
261
262
263
264
/* IDs for the controls and the menu commands */
enum
{
    /* menu items */
zorglub's avatar
zorglub committed
265
    MenuDummy_Event = wxID_HIGHEST + 1000,
gbazin's avatar
   
gbazin committed
266
    Exit_Event = wxID_HIGHEST,
gbazin's avatar
   
gbazin committed
267
    OpenFileSimple_Event,
zorglub's avatar
zorglub committed
268
    OpenAdv_Event,
gbazin's avatar
   
gbazin committed
269
    OpenFile_Event,
270
    OpenDir_Event,
gbazin's avatar
   
gbazin committed
271
272
    OpenDisc_Event,
    OpenNet_Event,
gbazin's avatar
gbazin committed
273
    OpenCapture_Event,
gbazin's avatar
   
gbazin committed
274
    OpenSat_Event,
zorglub's avatar
zorglub committed
275
    OpenOther_Event,
gbazin's avatar
   
gbazin committed
276
277
    EjectDisc_Event,

278
    Wizard_Event,
zorglub's avatar
zorglub committed
279

280
    Playlist_Event,
281
    PlaylistSmall_Event,
gbazin's avatar
   
gbazin committed
282
    Logs_Event,
283
    FileInfo_Event,
gbazin's avatar
   
gbazin committed
284
285

    Prefs_Event,
gbazin's avatar
gbazin committed
286
287
    Extended_Event,
    Bookmarks_Event,
gbazin's avatar
   
gbazin committed
288
    Skins_Event,
gbazin's avatar
   
gbazin committed
289
290
291
292

    StopStream_Event,
    PlayStream_Event,
    PrevStream_Event,
gbazin's avatar
   
gbazin committed
293
    NextStream_Event,
gbazin's avatar
   
gbazin committed
294
295
    SlowStream_Event,
    FastStream_Event,
gbazin's avatar
   
gbazin committed
296
297
298
299

    /* it is important for the id corresponding to the "About" command to have
     * this standard value as otherwise it won't be handled properly under Mac
     * (where it is special and put into the "Apple" menu) */
300
    About_Event = wxID_ABOUT,
301
302
    OnWebLink_Event,
    OnWebHelp_Event,
303
#ifdef UPDATE_CHECK
304
    UpdateVLC_Event,
305
#endif
306
    //VLM_Event,
307

308
    Iconize_Event,
gbazin's avatar
   
gbazin committed
309
310
};

311
312
DEFINE_LOCAL_EVENT_TYPE( wxEVT_INTERACTION );

gbazin's avatar
   
gbazin committed
313
314
315
316
BEGIN_EVENT_TABLE(Interface, wxFrame)
    /* Menu events */
    EVT_MENU(Exit_Event, Interface::OnExit)
    EVT_MENU(About_Event, Interface::OnAbout)
317
318
    EVT_MENU(OnWebLink_Event, Interface::OnWebLink)
    EVT_MENU(OnWebHelp_Event, Interface::OnWebHelp)
319
#ifdef UPDATE_CHECK
320
    EVT_MENU(UpdateVLC_Event, Interface::OnShowDialog)
321
#endif
322
    //EVT_MENU(VLM_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
323
324

    EVT_MENU(Playlist_Event, Interface::OnShowDialog)
325
    EVT_MENU(PlaylistSmall_Event, Interface::OnSmallPlaylist)
gbazin's avatar
   
gbazin committed
326
327
328
    EVT_MENU(Logs_Event, Interface::OnShowDialog)
    EVT_MENU(FileInfo_Event, Interface::OnShowDialog)
    EVT_MENU(Prefs_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
329

gbazin's avatar
   
gbazin committed
330
331
    EVT_MENU_OPEN(Interface::OnMenuOpen)

332
    EVT_MENU( Extended_Event, Interface::OnExtended )
zorglub's avatar
zorglub committed
333

334
    EVT_MENU( Bookmarks_Event, Interface::OnShowDialog)
zorglub's avatar
zorglub committed
335

gbazin's avatar
   
gbazin committed
336
#if defined( __WXMSW__ ) || defined( __WXMAC__ )
gbazin's avatar
   
gbazin committed
337
    EVT_CONTEXT_MENU(Interface::OnContextMenu2)
gbazin's avatar
   
gbazin committed
338
#endif
gbazin's avatar
   
gbazin committed
339
    EVT_RIGHT_UP(Interface::OnContextMenu)
gbazin's avatar
   
gbazin committed
340

gbazin's avatar
   
gbazin committed
341
    /* Toolbar events */
gbazin's avatar
   
gbazin committed
342
    EVT_MENU(OpenFileSimple_Event, Interface::OnShowDialog)
zorglub's avatar
zorglub committed
343
    EVT_MENU(OpenAdv_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
344
    EVT_MENU(OpenFile_Event, Interface::OnShowDialog)
345
    EVT_MENU(OpenDir_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
346
347
    EVT_MENU(OpenDisc_Event, Interface::OnShowDialog)
    EVT_MENU(OpenNet_Event, Interface::OnShowDialog)
gbazin's avatar
gbazin committed
348
    EVT_MENU(OpenCapture_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
349
    EVT_MENU(OpenSat_Event, Interface::OnShowDialog)
350
    EVT_MENU(Wizard_Event, Interface::OnShowDialog)
gbazin's avatar
   
gbazin committed
351
352
353
354
    EVT_MENU(StopStream_Event, Interface::OnStopStream)
    EVT_MENU(PlayStream_Event, Interface::OnPlayStream)
    EVT_MENU(PrevStream_Event, Interface::OnPrevStream)
    EVT_MENU(NextStream_Event, Interface::OnNextStream)
gbazin's avatar
   
gbazin committed
355
356
    EVT_MENU(SlowStream_Event, Interface::OnSlowStream)
    EVT_MENU(FastStream_Event, Interface::OnFastStream)
gbazin's avatar
   
gbazin committed
357

gbazin's avatar
gbazin committed
358
    /* Custom events */
359
360
    EVT_COMMAND(0, wxEVT_INTF, Interface::OnControlEvent)
    EVT_COMMAND(1, wxEVT_INTF, Interface::OnControlEvent)
361
362

    EVT_COMMAND( -1, wxEVT_INTERACTION, Interface::OnInteraction )
gbazin's avatar
   
gbazin committed
363
364
365
366
367
END_EVENT_TABLE()

/*****************************************************************************
 * Constructor.
 *****************************************************************************/
368
Interface::Interface( intf_thread_t *_p_intf, long style ):
gbazin's avatar
   
gbazin committed
369
    wxFrame( NULL, -1, wxT("VLC media player"),
370
             wxDefaultPosition, wxSize(700,100), style )
gbazin's avatar
   
gbazin committed
371
372
373
{
    /* Initializations */
    p_intf = _p_intf;
zorglub's avatar
zorglub committed
374
    b_extra = VLC_FALSE;
375
    extra_frame = 0;
376
    playlist_manager = 0;
377
    i_update_counter = 0;
gbazin's avatar
   
gbazin committed
378

zorglub's avatar
zorglub committed
379

gbazin's avatar
   
gbazin committed
380
    /* Give our interface a nice little icon */
Rafaël Carré's avatar
Rafaël Carré committed
381
    SetIcon( wxIcon( (const char**) vlc_xpm ) );
gbazin's avatar
   
gbazin committed
382

383
384
385
    /* Create a splitter window that will fill in the interface window.
     * We need a splitter bar in order to make the embedded playlist
     * resizable. */
386
    splitter = new Splitter( this, p_intf );
387
    main_sizer = new wxBoxSizer( wxVERTICAL );
388
    main_sizer->Add( splitter, 1, wxEXPAND );
389
    SetSizer( main_sizer );
390
391
392

    /* Create a main panel that will fill in the interface window */
    main_panel = new wxPanel( splitter, -1, wxPoint(0,0), wxSize(0,0),
393
                              wxCLIP_CHILDREN );
394
    main_panel->SetFocus();
gbazin's avatar
   
gbazin committed
395

396
397
398
#if defined(__WXGTK20__) && wxCHECK_VERSION(2,5,6)
    /* As ugly as your butt! Please remove when wxWidgets 2.6 fixed their
     * Accelerators bug. */
399
    main_panel->m_imData = 0;
400
    m_imData = 0;
401
#endif
402
403
404
405

    /* Create a sizer for the main frame */
    panel_sizer = new wxBoxSizer( wxVERTICAL );
    main_panel->SetSizer( panel_sizer );
zorglub's avatar
zorglub committed
406

407
408
409
    /* Put this in the splitter */
    splitter->Initialize( main_panel );

410
411
/* wxCocoa pretends to support this, but at least 2.6.x doesn't */
#ifndef __APPLE__
412
#ifdef wxHAS_TASK_BAR_ICON
413
414
    /* Systray integration */
    p_systray = NULL;
415
    if( config_GetInt( p_intf, "wx-systray" ) )
416
    {
417
        p_systray = new Systray( this, p_intf );
418
    }
419
#endif
420
#endif
421

gbazin's avatar
   
gbazin committed
422
423
424
425
426
427
    /* Creation of the menu bar */
    CreateOurMenuBar();

    /* Creation of the tool bar */
    CreateOurToolBar();

428
    /* Creation of the status bar
gbazin's avatar
   
gbazin committed
429
430
     * Helptext for menu items and toolbar tools will automatically get
     * displayed here. */
431
    int i_status_width[3] = {150, 55, -1};
gbazin's avatar
   
gbazin committed
432
433
434
435
    statusbar = CreateStatusBar( 3 );                            /* 2 fields */
    statusbar->SetStatusWidths( 3, i_status_width );
    statusbar->SetStatusText( wxString::Format(wxT("x%.2f"), 1.0), 1 );

436
    /* Get minimum window size to prevent user from glitching it */
437
    splitter->SetSizeHints( -1, 0 );
438
439
440
    panel_sizer->Layout(); panel_sizer->Fit( main_panel );
    main_sizer->Layout(); main_sizer->Fit( this );
    main_min_size = GetSize();
441
442
443
444
445
446
447
    /* FIXME HACK as far as i understan (i.e. not a lot) the toolbar
     * doesn't take the labels into account when it returns its size */

    if( config_GetInt(p_intf, "wx-labels") )
    {
        main_min_size.SetWidth(800);
    }
448
    splitter->SetSizeHints( -1, -1 );
449

gbazin's avatar
gbazin committed
450
    /* Video window */
451
    video_window = 0;
452
    if( config_GetInt( p_intf, "wx-embed" ) )
gbazin's avatar
gbazin committed
453
    {
454
455
        video_window = CreateVideoWindow( p_intf, main_panel );
        panel_sizer->Add( p_intf->p_sys->p_video_sizer, 1, wxEXPAND, 0 );
gbazin's avatar
gbazin committed
456
457
    }

458
459
460
    /* Creation of the input manager panel */
    input_manager = new InputManager( p_intf, this, main_panel );
    panel_sizer->Add( input_manager, 0, wxEXPAND , 0 );
461

gbazin's avatar
   
gbazin committed
462
    /* Layout everything */
463
    splitter->SetSizeHints( -1, 0 );
464
465
    panel_sizer->Layout(); panel_sizer->Fit( main_panel );
    main_sizer->Layout(); main_sizer->Fit( this );
466
    splitter->SetSizeHints( -1, -1 );
gbazin's avatar
   
gbazin committed
467

468
#if wxUSE_DRAG_AND_DROP
gbazin's avatar
   
gbazin committed
469
470
    /* Associate drop targets with the main interface */
    SetDropTarget( new DragAndDrop( p_intf ) );
gbazin's avatar
   
gbazin committed
471
#endif
472

473
    SetupHotkeys();
gbazin's avatar
   
gbazin committed
474
475
476

    /* Start timer */
    timer = new Timer( p_intf, this );
477

478
    /* Restore previous position / settings */
479
480
    WindowSettings *ws = p_intf->p_sys->p_window_settings;
    wxPoint p;
481
482
    wxSize s;
    bool b_shown;
483
484
485
486

    ws->SetScreen( wxSystemSettings::GetMetric( wxSYS_SCREEN_X ),
                   wxSystemSettings::GetMetric( wxSYS_SCREEN_Y ) );

487
    if( ws->GetSettings( WindowSettings::ID_MAIN, b_shown, p, s ) ) Move( p );
488
489

    /* Show extended GUI if requested */
490
491
492
493
    wxCommandEvent dummy;
    if( config_GetInt( p_intf, "wx-extended" ) ) OnExtended( dummy );

    SetIntfMinSize();
494

495
496
497
498
    var_Create( p_intf, "interaction", VLC_VAR_ADDRESS );
    var_AddCallback( p_intf, "interaction", InteractCallback, this );
    p_intf->b_interaction = VLC_TRUE;

499
500
    /* Show embedded playlist if requested */
    if( splitter->ShowOnStart() ) OnSmallPlaylist( dummy );
gbazin's avatar
   
gbazin committed
501
502
503
504
}

Interface::~Interface()
{
505
506
    WindowSettings *ws = p_intf->p_sys->p_window_settings;

507
508
509
510
511
    if( !IsIconized() )
    {
        ws->SetSettings( WindowSettings::ID_MAIN, true,
                         GetPosition(), GetSize() );
    }
512

513
    PopEventHandler(true);
514

515
516
    if( video_window ) delete video_window;

517
518
/* wxCocoa pretends to support this, but at least 2.6.x doesn't */
#ifndef __APPLE__
519
#ifdef wxHAS_TASK_BAR_ICON
520
    if( p_systray ) delete p_systray;
521
#endif
522
#endif
523

524
525
526
    p_intf->b_interaction = VLC_FALSE;
    var_DelCallback( p_intf, "interaction", InteractCallback, this );

527
    if( p_intf->p_sys->p_wxwindow ) delete p_intf->p_sys->p_wxwindow;
gbazin's avatar
   
gbazin committed
528

529

gbazin's avatar
   
gbazin committed
530
    /* Clean up */
gbazin's avatar
   
gbazin committed
531
    delete timer;
gbazin's avatar
   
gbazin committed
532
}
gbazin's avatar
   
gbazin committed
533

534
535
536
void Interface::Init()
{
    /* Misc init */
537
    SetupHotkeys();
538
539
}

540
541
542
void Interface::Update()
{
    /* Misc updates */
543
    if( !(i_update_counter % 10) ) ((VLCVolCtrl *)volctrl)->UpdateVolume();
544
545

    if( playlist_manager ) playlist_manager->Update();
546
547

    i_update_counter++;
548
549
}

550
void Interface::OnControlEvent( wxCommandEvent& event )
gbazin's avatar
gbazin committed
551
{
552
553
554
    switch( event.GetId() )
    {
    case 0:
555
556
        main_sizer->Layout();
        main_sizer->Fit( this );
557
558
559
560
561
562
563
564
565
        break;

    case 1:
        long i_style = GetWindowStyle();
        if( event.GetInt() ) i_style |= wxSTAY_ON_TOP;
        else i_style &= ~wxSTAY_ON_TOP;
        SetWindowStyle( i_style );
        break;
    }
gbazin's avatar
gbazin committed
566
567
}

gbazin's avatar
   
gbazin committed
568
569
570
571
572
/*****************************************************************************
 * Private methods.
 *****************************************************************************/
void Interface::CreateOurMenuBar()
{
573
    int minimal = config_GetInt( p_intf, "wx-minimal" );
574

gbazin's avatar
   
gbazin committed
575
    /* Create the "File" menu */
gbazin's avatar
   
gbazin committed
576
    wxMenu *file_menu = new wxMenu;
577
578
579

    if (!minimal)
    {
580
    file_menu->Append( OpenFileSimple_Event,
gbazin's avatar
gbazin committed
581
                       wxU(_("Quick &Open File...\tCtrl-O")) );
zorglub's avatar
zorglub committed
582
583

    file_menu->AppendSeparator();
gbazin's avatar
gbazin committed
584
    file_menu->Append( OpenFile_Event, wxU(_("Open &File...\tCtrl-F")) );
585
    file_menu->Append( OpenDir_Event, wxU(_("Open Dir&ectory...\tCtrl-E")) );
gbazin's avatar
gbazin committed
586
    file_menu->Append( OpenDisc_Event, wxU(_("Open &Disc...\tCtrl-D")) );
587
    file_menu->Append( OpenNet_Event,
gbazin's avatar
gbazin committed
588
589
                       wxU(_("Open &Network Stream...\tCtrl-N")) );
    file_menu->Append( OpenCapture_Event,
590
                       wxU(_("Open C&apture Device...\tCtrl-A")) );
zorglub's avatar
zorglub committed
591

gbazin's avatar
   
gbazin committed
592
    file_menu->AppendSeparator();
593
    file_menu->Append( Wizard_Event, wxU(_("&Wizard...\tCtrl-W")) );
gbazin's avatar
   
gbazin committed
594
    file_menu->AppendSeparator();
595
    }
gbazin's avatar
gbazin committed
596
    file_menu->Append( Exit_Event, wxU(_("E&xit\tCtrl-X")) );
gbazin's avatar
   
gbazin committed
597

gbazin's avatar
   
gbazin committed
598
    /* Create the "View" menu */
gbazin's avatar
   
gbazin committed
599
    wxMenu *view_menu = new wxMenu;
600
601
    if (!minimal)
    {
gbazin's avatar
gbazin committed
602
    view_menu->Append( Playlist_Event, wxU(_("&Playlist...\tCtrl-P")) );
603
    }
gbazin's avatar
gbazin committed
604
    view_menu->Append( Logs_Event, wxU(_("&Messages...\tCtrl-M")) );
605
    view_menu->Append( FileInfo_Event,
606
                       wxU(_("Stream and Media &Info...\tCtrl-I")) );
607
#if 0
608
    view_menu->Append( VLM_Event,
609
                       wxU(_("VLM Control...\tCtrl-V")) );
610
#endif
gbazin's avatar
   
gbazin committed
611

612
613
614
615
616
    /* Create the "Auto-generated" menus */
    p_settings_menu = SettingsMenu( p_intf, this );
    p_audio_menu = AudioMenu( p_intf, this );
    p_video_menu = VideoMenu( p_intf, this );
    p_navig_menu = NavigMenu( p_intf, this );
gbazin's avatar
   
gbazin committed
617

gbazin's avatar
   
gbazin committed
618
    /* Create the "Help" menu */
gbazin's avatar
   
gbazin committed
619
    wxMenu *help_menu = new wxMenu;
620
621
622
    help_menu->Append( OnWebLink_Event, wxU(_("VideoLAN's Website")) );
    help_menu->Append( OnWebHelp_Event, wxU(_("Online Help")) );
    help_menu->AppendSeparator();
zorglub's avatar
zorglub committed
623
    help_menu->Append( About_Event, wxU(_("About...")) );
624
#ifdef UPDATE_CHECK
625
    help_menu->AppendSeparator();
626
    help_menu->Append( UpdateVLC_Event, wxU(_("Check for Updates...")) );
627
#endif
gbazin's avatar
   
gbazin committed
628
629

    /* Append the freshly created menus to the menu bar... */
630
    wxMenuBar *menubar = new wxMenuBar();
gbazin's avatar
   
gbazin committed
631
    menubar->Append( file_menu, wxU(_("&File")) );
632
    menubar->Append( view_menu, wxU(_("V&iew")) );
gbazin's avatar
   
gbazin committed
633
    menubar->Append( p_settings_menu, wxU(_("&Settings")) );
gbazin's avatar
   
gbazin committed
634
635
    menubar->Append( p_audio_menu, wxU(_("&Audio")) );
    menubar->Append( p_video_menu, wxU(_("&Video")) );
gbazin's avatar
   
gbazin committed
636
    menubar->Append( p_navig_menu, wxU(_("&Navigation")) );
gbazin's avatar
   
gbazin committed
637
    menubar->Append( help_menu, wxU(_("&Help")) );
gbazin's avatar
   
gbazin committed
638
639
640
641

    /* Attach the menu bar to the frame */
    SetMenuBar( menubar );

642
643
    /* Find out size of menu bar */
    int i_size = 0;
644
    for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
645
646
647
    {
        int i_width, i_height;
        menubar->GetTextExtent( menubar->GetLabelTop(i), &i_width, &i_height );
648
649
        i_size += i_width +
#if defined(__WXGTK__)
650
            22 /* approximate margin */;
651
#else
652
#if (wxMAJOR_VERSION <= 2) && (wxMINOR_VERSION <= 5) && (wxRELEASE_NUMBER < 3)
653
            4 /* approximate margin */;
654
#else
655
            18 /* approximate margin */;
656
#endif
657
#endif
658
    }
659
660
661
662
663
664
665
666
667

/* Patch by zcot for menu wrapping */
#if defined(WIN32)
    /* Find out size of msw menu bar */
    i_size = 0;
    SIZE sizing;
    HDC hdc = GetDC( NULL );
    for( unsigned int i = 0; i < menubar->GetMenuCount(); i++ )
    {
zorglub's avatar
zorglub committed
668
669
        GetTextExtentPoint32( hdc, menubar->GetLabelTop(i).c_str(),
                                menubar->GetLabelTop(i).Length(), &sizing );
670
671
672

        // [ SM_CXDLGFRAME + pixels + textextent + pixels + SM_CXDLGFRAME ]
        i_size += sizing.cx + 2 + GetSystemMetrics( SM_CXDLGFRAME ) * 2;
673
674
    }
    ReleaseDC( NULL, hdc );
675
    i_size += GetSystemMetrics( SM_CXSIZEFRAME ) * 2 + 4;
676
677
678
#endif
/* End patch by zcot */

679
    panel_sizer->SetMinSize( i_size, -1 );
680

gbazin's avatar
   
gbazin committed
681
682
683
    /* Intercept all menu events in our custom event handler */
    PushEventHandler( new MenuEvtHandler( p_intf, this ) );

684
#if wxUSE_DRAG_AND_DROP
gbazin's avatar
   
gbazin committed
685
686
    /* Associate drop targets with the menubar */
    menubar->SetDropTarget( new DragAndDrop( p_intf ) );
gbazin's avatar
   
gbazin committed
687
#endif
gbazin's avatar
   
gbazin committed
688
689
690
691
}

void Interface::CreateOurToolBar()
{
692
#define HELP_OPEN N_("Open")
hartman's avatar
hartman committed
693
694
695
696
#define HELP_STOP N_("Stop")
#define HELP_PLAY N_("Play")
#define HELP_PAUSE N_("Pause")
#define HELP_PLO N_("Playlist")
697
#define HELP_SPLO N_("Embedded playlist")
gbazin's avatar
   
gbazin committed
698
699
#define HELP_PLP N_("Previous playlist item")
#define HELP_PLN N_("Next playlist item")
gbazin's avatar
   
gbazin committed
700
701
#define HELP_SLOW N_("Play slower")
#define HELP_FAST N_("Play faster")
gbazin's avatar
   
gbazin committed
702

703
704
705
706
707
#define LABEL_OPEN N_("Open")
#define LABEL_STOP N_("Stop")
#define LABEL_PLAY N_("Play")
#define LABEL_PAUSE N_("Pause")
#define LABEL_PLO N_("Playlist")
zorglub's avatar
zorglub committed
708
#define LABEL_SPLO N_("Embedded playlist")
709
710
711
712
#define LABEL_PLP N_("Previous")
#define LABEL_PLN N_("Next")
#define LABEL_SLOW N_("Slower")
#define LABEL_FAST N_("Faster")
713
    int minimal = config_GetInt( p_intf, "wx-minimal" );
714
    bool label = config_GetInt( p_intf, "wx-labels" );
715

gbazin's avatar
   
gbazin committed
716
717
    wxLogNull LogDummy; /* Hack to suppress annoying log message on the win32
                         * version because we don't include wx.rc */
gbazin's avatar
   
gbazin committed
718

719
    wxToolBar *toolbar =
720
721
        CreateToolBar( label?wxTB_HORIZONTAL | wxTB_FLAT |wxTB_TEXT:
                       wxTB_HORIZONTAL | wxTB_FLAT );
gbazin's avatar
   
gbazin committed
722

gbazin's avatar
   
gbazin committed
723
724
    toolbar->SetToolBitmapSize( wxSize(TOOLBAR_BMP_WIDTH,TOOLBAR_BMP_HEIGHT) );

725
726
    if (!minimal)
    {
727
    toolbar->AddTool( OpenFile_Event, wxU(LABEL_OPEN),
728
729
                      wxBitmap( eject_xpm ), wxU(_(HELP_OPEN)) );
    toolbar->AddSeparator();
730
    }
731

732
    wxToolBarToolBase *p_tool = toolbar->AddTool( PlayStream_Event, wxU(LABEL_PLAY),
733
                      wxBitmap( play_xpm ), wxU(_(HELP_PLAY)), wxITEM_CHECK );
734
735
    p_tool->SetClientData( p_tool );

736
737
    if (!minimal)
    {
738
    toolbar->AddTool( StopStream_Event, wxU(LABEL_STOP), wxBitmap( stop_xpm ),
739
                      wxU(_(HELP_STOP)) );
gbazin's avatar
   
gbazin committed
740
    toolbar->AddSeparator();
741

742
    toolbar->AddTool( PrevStream_Event, wxU(LABEL_PLP),
743
                      wxBitmap( prev_xpm ), wxU(_(HELP_PLP)) );
744
    toolbar->AddTool( SlowStream_Event, wxU(LABEL_SLOW),
745
                      wxBitmap( slow_xpm ), wxU(_(HELP_SLOW)) );
746
    toolbar->AddTool( FastStream_Event, wxU(LABEL_FAST),
747
                      wxBitmap( fast_xpm ), wxU(_(HELP_FAST)) );
748
    toolbar->AddTool( NextStream_Event, wxU(LABEL_PLN), wxBitmap( next_xpm ),
gbazin's avatar
   
gbazin committed
749
                      wxU(_(HELP_PLN)) );
750
    toolbar->AddSeparator();
751
    if( config_GetInt( p_intf, "wx-playlist-view" ) != 1 )
752
753
        toolbar->AddTool( Playlist_Event, wxU(LABEL_PLO),
                          wxBitmap( playlist_xpm ), wxU(_(HELP_PLO)) );
754
    if( config_GetInt( p_intf, "wx-playlist-view" ) >= 1 )
755
        toolbar->AddTool( PlaylistSmall_Event, wxU(LABEL_SPLO),
756
                          wxBitmap( playlist_small_xpm ), wxU(_(HELP_SPLO)) );
757
    }
gbazin's avatar
   
gbazin committed
758

759
    wxControl *p_dummy_ctrl =
760
        new wxControl( toolbar, -1, wxDefaultPosition,
761
                       wxSize(16, 16 ), wxBORDER_NONE );
762

763
    toolbar->AddControl( p_dummy_ctrl );
gbazin's avatar
   
gbazin committed
764

765
766
    volctrl = new VLCVolCtrl( p_intf, toolbar );
    toolbar->AddControl( volctrl );
767
768

    toolbar->Realize();
gbazin's avatar
   
gbazin committed
769

770
#if wxUSE_DRAG_AND_DROP
gbazin's avatar
   
gbazin committed
771
772
    /* Associate drop targets with the toolbar */
    toolbar->SetDropTarget( new DragAndDrop( p_intf ) );
gbazin's avatar
   
gbazin committed
773
#endif
gbazin's avatar
   
gbazin committed
774
775
}

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
static int ConvertHotkeyModifiers( int i_hotkey )
{
    int i_accel_flags = 0;
    if( i_hotkey & KEY_MODIFIER_ALT ) i_accel_flags |= wxACCEL_ALT;
    if( i_hotkey & KEY_MODIFIER_CTRL ) i_accel_flags |= wxACCEL_CTRL;
    if( i_hotkey & KEY_MODIFIER_SHIFT ) i_accel_flags |= wxACCEL_SHIFT;
    if( !i_accel_flags ) i_accel_flags = wxACCEL_NORMAL;
    return i_accel_flags;
}

static int ConvertHotkey( int i_hotkey )
{
    int i_key = i_hotkey & ~KEY_MODIFIER;
    if( i_key & KEY_ASCII ) return i_key & KEY_ASCII;
    else if( i_key & KEY_SPECIAL )
    {
        switch ( i_key )
        {
        case KEY_LEFT: return WXK_LEFT;
        case KEY_RIGHT: return WXK_RIGHT;
        case KEY_UP: return WXK_UP;
        case KEY_DOWN: return WXK_DOWN;
        case KEY_SPACE: return WXK_SPACE;
        case KEY_ENTER: return WXK_RETURN;
        case KEY_F1: return WXK_F1;
        case KEY_F2: return WXK_F2;
        case KEY_F3: return WXK_F3;
        case KEY_F4: return WXK_F4;
        case KEY_F5: return WXK_F5;
        case KEY_F6: return WXK_F6;
        case KEY_F7: return WXK_F7;
        case KEY_F8: return WXK_F8;
        case KEY_F9: return WXK_F9;
        case KEY_F10: return WXK_F10;
        case KEY_F11: return WXK_F11;
        case KEY_F12: return WXK_F12;
        case KEY_HOME: return WXK_HOME;
813
814
815
        case KEY_END: return WXK_END;
        case KEY_INSERT: return WXK_INSERT;
        case KEY_DELETE: return WXK_DELETE;
816
817
818
819
820
821
822
823
824
825
826
        case KEY_MENU: return WXK_MENU;
        case KEY_ESC: return WXK_ESCAPE;
        case KEY_PAGEUP: return WXK_PRIOR;
        case KEY_PAGEDOWN: return WXK_NEXT;
        case KEY_TAB: return WXK_TAB;
        case KEY_BACKSPACE: return WXK_BACK;
        }
    }
    return WXK_F24;
}

827
void Interface::SetupHotkeys()
828
{
829
    struct libvlc_int_t::hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys;
830
    int i_hotkeys;
831

832
833
834
835
836
837
    /* Count number of hoteys */
    for( i_hotkeys = 0; p_hotkeys[i_hotkeys].psz_action != NULL; i_hotkeys++ );

    p_intf->p_sys->i_first_hotkey_event = wxID_HIGHEST + 7000;
    p_intf->p_sys->i_hotkeys = i_hotkeys;

838
    wxAcceleratorEntry *p_entries = new wxAcceleratorEntry[i_hotkeys];
839
840

    /* Setup the hotkeys as accelerators */
841
    for( int i = 0; i < i_hotkeys; i++ )
842
    {
843
844
845
846
        int i_mod = ConvertHotkeyModifiers( p_hotkeys[i].i_key );
        int i_key = ConvertHotkey( p_hotkeys[i].i_key );

#ifdef WIN32
847
848
        if( !(p_hotkeys[i].i_key & KEY_SPECIAL) && i_mod )
            i_key = toupper(i_key);
849
850
851
#endif

        p_entries[i].Set( i_mod, i_key,
852
853
                          p_intf->p_sys->i_first_hotkey_event + i );
    }
zorglub's avatar
zorglub committed
854

855
    wxAcceleratorTable accel( i_hotkeys, p_entries );
zorglub's avatar
zorglub committed
856

857
858
859
860
861
862
863
864
    if( !accel.Ok() )
    {
        msg_Err( p_intf, "invalid accelerator table" );
    }
    else
    {
        SetAcceleratorTable( accel );
    }
865
866

    delete [] p_entries;
867
868
}

869
void Interface::SetIntfMinSize()
zorglub's avatar
zorglub committed
870
{
871
    wxSize ms = main_min_size;
zorglub's avatar
zorglub committed