menus.cpp 45.2 KB
Newer Older
1 2 3
/*****************************************************************************
 * menus.cpp : Qt menus
 *****************************************************************************
4
 * Copyright © 2006-2009 the VideoLAN team
5
 * $Id$
6
 *
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
7
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Jean-Philippe André <jpeg@videolan.org>
10 11 12 13
 *
 * 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
14
 * ( at your option ) any later version.
15 16 17 18 19 20 21 22 23 24 25
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

26 27 28 29
/** \todo
 * - Remove static currentGroup
 */

30 31 32 33
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

34
#include <vlc_intf_strings.h>
35
#include <vlc_services_discovery.h>
36
#include <vlc_aout.h>
37
#include <vlc_vout.h>
38

Clément Stenac's avatar
Clément Stenac committed
39
#include "menus.hpp"
40 41

#include "main_interface.hpp"    /* View modifications */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
42 43 44
#include "dialogs_provider.hpp"  /* Dialogs display */
#include "input_manager.hpp"     /* Input Management */
#include "recents.hpp"           /* Recent Items */
45
#include "actions_manager.hpp"
46
#include "extensions_manager.hpp"
Clément Stenac's avatar
Clément Stenac committed
47

48 49 50 51 52 53
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QActionGroup>
#include <QSignalMapper>
#include <QSystemTrayIcon>
Ludovic Fauvet's avatar
Ludovic Fauvet committed
54
#include <QList>
55

56 57 58 59 60 61 62 63 64 65 66 67 68 69
/*
  This file defines the main menus and the pop-up menu (right-click menu)
  and the systray menu (in that order in the file)

  There are 3 menus that have to be rebuilt everytime there are called:
  Audio, Video, Navigation
  3 functions are building those menus: AudioMenu, VideoMenu, NavigMenu
  and 3 functions associated are collecting the objects :
  InputAutoMenuBuilder, AudioAutoMenuBuilder, VideoAutoMenuBuilder.

  A QSignalMapper decides when to rebuild those menus cf MenuFunc in the .hpp
  Just before one of those menus are aboutToShow(), they are rebuild.
  */

70 71 72
#define STATIC_ENTRY "__static__"
#define ENTRY_ALWAYS_ENABLED "__ignore__"

73 74 75 76 77 78 79 80 81
enum
{
    ITEM_NORMAL,
    ITEM_CHECK,
    ITEM_RADIO
};

static QActionGroup *currentGroup;

Ludovic Fauvet's avatar
Ludovic Fauvet committed
82 83
QMenu *QVLCMenu::recentsMenu = NULL;

84 85 86 87 88
/****************************************************************************
 * Menu code helpers:
 ****************************************************************************
 * Add static entries to DP in menus
 ***************************************************************************/
89
void addDPStaticEntry( QMenu *menu,
90
                       const QString& text,
91
                       const char *icon,
92
                       const char *member,
93
                       const char *shortcut = NULL )
94
{
95
    QAction *action = NULL;
Rémi Duraffort's avatar
Rémi Duraffort committed
96
    if( !EMPTY_STR( icon ) )
97
    {
Rémi Duraffort's avatar
Rémi Duraffort committed
98
        if( !EMPTY_STR( shortcut ) )
99 100
            action = menu->addAction( QIcon( icon ), text, THEDP,
                                      member, qtr( shortcut ) );
101
        else
102
            action = menu->addAction( QIcon( icon ), text, THEDP, member );
103 104 105
    }
    else
    {
Rémi Duraffort's avatar
Rémi Duraffort committed
106
        if( !EMPTY_STR( shortcut ) )
107
            action = menu->addAction( text, THEDP, member, qtr( shortcut ) );
108
        else
109
            action = menu->addAction( text, THEDP, member );
110
    }
111
    action->setData( STATIC_ENTRY );
112
}
113

114 115 116
/***
 * Same for MIM
 ***/
117 118
QAction* addMIMStaticEntry( intf_thread_t *p_intf,
                            QMenu *menu,
119
                            const QString& text,
120 121 122
                            const char *icon,
                            const char *member,
                            bool bStatic = false )
123
{
124
    QAction *action;
125 126
    if( strlen( icon ) > 0 )
    {
127
        action = menu->addAction( text, THEMIM,  member );
128 129 130 131
        action->setIcon( QIcon( icon ) );
    }
    else
    {
Rémi Duraffort's avatar
Rémi Duraffort committed
132
        action = menu->addAction( text, THEMIM, member );
133
    }
134
    action->setData( bStatic ? STATIC_ENTRY : ENTRY_ALWAYS_ENABLED );
135
    return action;
136 137
}

138 139 140 141 142
/**
 * @brief Enable all static entries, disable the others
 * @param enable if false, disable all entries
 */
void EnableStaticEntries( QMenu *menu, bool enable = true )
143
{
144
    if( !menu ) return;
145

Jean-Philippe Andre's avatar
Jean-Philippe Andre committed
146 147
    QList< QAction* > actions = menu->actions();
    for( int i = 0; i < actions.size(); ++i )
148
    {
149 150 151 152
        actions[i]->setEnabled( actions[i]->data().toString()
                                == ENTRY_ALWAYS_ENABLED ||
            /* Be careful here, because data("string").toBool is true */
            ( enable && (actions[i]->data().toString() == STATIC_ENTRY ) ) );
153 154 155
    }
}

156 157 158 159 160
/**
 * \return Number of static entries
 */
int DeleteNonStaticEntries( QMenu *menu )
{
161 162
    if( !menu ) return VLC_EGENERIC;

163
    int i_ret = 0;
164

Jean-Philippe Andre's avatar
Jean-Philippe Andre committed
165 166
    QList< QAction* > actions = menu->actions();
    for( int i = 0; i < actions.size(); ++i )
167
    {
168
        if( actions[i]->data().toString() != STATIC_ENTRY )
Jean-Philippe Andre's avatar
Jean-Philippe Andre committed
169
            delete actions[i];
170 171 172
        else
            i_ret++;
    }
173
    return i_ret;
174 175
}

176 177 178 179
/**
 * \return QAction associated to psz_var variable
 **/
static QAction * FindActionWithVar( QMenu *menu, const char *psz_var )
180
{
181 182
    QList< QAction* > actions = menu->actions();
    for( int i = 0; i < actions.size(); ++i )
183
    {
184 185
        if( actions[i]->data().toString() == psz_var )
            return actions[i];
186
    }
187
    return NULL;
188 189
}

190
/*****************************************************************************
191
 * Definitions of variables for the dynamic menus
192
 *****************************************************************************/
193
#define PUSH_VAR( var ) varnames.push_back( var ); \
194
    objects.push_back( VLC_OBJECT(p_object) )
195 196

#define PUSH_INPUTVAR( var ) varnames.push_back( var ); \
197
    objects.push_back( VLC_OBJECT(p_input) );
198 199

#define PUSH_SEPARATOR if( objects.size() != i_last_separator ) { \
200
    objects.push_back( 0 ); varnames.push_back( "" ); \
201
    i_last_separator = objects.size(); }
202

203
static int InputAutoMenuBuilder( input_thread_t *p_object,
204
        vector<vlc_object_t *> &objects,
205
        vector<const char *> &varnames )
206
{
207
    PUSH_VAR( "bookmark" );
208
    PUSH_VAR( "title" );
209
    PUSH_VAR( "chapter" );
210
    PUSH_VAR( "navigation" );
211
    PUSH_VAR( "program" );
212 213 214
    return VLC_SUCCESS;
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
215
static int VideoAutoMenuBuilder( vout_thread_t *p_object,
216
        input_thread_t *p_input,
217
        vector<vlc_object_t *> &objects,
218
        vector<const char *> &varnames )
219
{
220 221
    PUSH_INPUTVAR( "video-es" );
    PUSH_INPUTVAR( "spu-es" );
222 223
    PUSH_VAR( "fullscreen" );
    PUSH_VAR( "video-on-top" );
224
    PUSH_VAR( "video-wallpaper" );
225
#ifdef WIN32
226
    PUSH_VAR( "direct3d-desktop" );
227
#endif
228
    PUSH_VAR( "video-snapshot" );
229
    PUSH_VAR( "zoom" );
230
    PUSH_VAR( "autoscale" );
231 232
    PUSH_VAR( "aspect-ratio" );
    PUSH_VAR( "crop" );
233
    PUSH_VAR( "deinterlace" );
234
    PUSH_VAR( "deinterlace-mode" );
235
    PUSH_VAR( "postprocess" );
236

237 238 239
    return VLC_SUCCESS;
}

240
static int AudioAutoMenuBuilder( aout_instance_t *p_object,
241
        input_thread_t *p_input,
242
        vector<vlc_object_t *> &objects,
243
        vector<const char *> &varnames )
244
{
245
    PUSH_INPUTVAR( "audio-es" );
246
    PUSH_VAR( "audio-channels" );
247 248
    PUSH_VAR( "audio-device" );
    PUSH_VAR( "visual" );
249 250 251
    return VLC_SUCCESS;
}

252 253
/*****************************************************************************
 * All normal menus
254
 * Simple Code
255 256 257
 *****************************************************************************/

#define BAR_ADD( func, title ) { \
258
    QMenu *_menu = func; _menu->setTitle( title ); bar->addMenu( _menu ); }
259 260

#define BAR_DADD( func, title, id ) { \
261 262 263 264 265 266 267 268
    QMenu *_menu = func; _menu->setTitle( title ); bar->addMenu( _menu ); \
    MenuFunc *f = new MenuFunc( _menu, id ); \
    CONNECT( _menu, aboutToShow(), THEDP->menusUpdateMapper, map() ); \
    THEDP->menusUpdateMapper->setMapping( _menu, f ); }

#define ACT_ADD( _menu, val, title ) { \
    QAction *_action = new QAction( title, _menu ); _action->setData( val ); \
    _menu->addAction( _action ); }
269

270 271
#define ACT_ADDMENU( _menu, val, title ) { \
    QAction *_action = new QAction( title, _menu ); _action->setData( val ); \
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
272
    _action->setMenu( new QMenu( _menu ) ); _menu->addAction( _action ); }
273 274 275 276 277

#define ACT_ADDCHECK( _menu, val, title ) { \
    QAction *_action = new QAction( title, _menu ); _action->setData( val ); \
    _action->setCheckable( true ); _menu->addAction( _action ); }

278 279 280
/**
 * Main Menu Bar Creation
 **/
281
void QVLCMenu::createMenuBar( MainInterface *mi,
282
                              intf_thread_t *p_intf )
Clément Stenac's avatar
Qt4:  
Clément Stenac committed
283
{
284 285 286
    /* QMainWindows->menuBar()
       gives the QProcess::destroyed timeout issue on Cleanlooks style with
       setDesktopAware set to false */
287
    QMenuBar *bar = mi->menuBar();
288

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
289
    BAR_ADD( FileMenu( p_intf, bar ), qtr( "&Media" ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
290

291
    /* Dynamic menus, rebuilt before being showed */
292
    BAR_DADD( NavigMenu( p_intf, bar ), qtr( "P&layback" ), 3 );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
293 294
    BAR_DADD( AudioMenu( p_intf, bar ), qtr( "&Audio" ), 1 );
    BAR_DADD( VideoMenu( p_intf, bar ), qtr( "&Video" ), 2 );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
295

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
296
    BAR_ADD( ToolsMenu( bar ), qtr( "&Tools" ) );
297
    BAR_ADD( ViewMenu( p_intf, mi ), qtr( "V&iew" ) );
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
298
    BAR_ADD( HelpMenu( bar ), qtr( "&Help" ) );
299
}
300 301
#undef BAR_ADD
#undef BAR_DADD
302 303

/**
304
 * Media ( File ) Menu
305 306
 * Opening, streaming and quit
 **/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
307
QMenu *QVLCMenu::FileMenu( intf_thread_t *p_intf, QWidget *parent )
308
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
309
    QMenu *menu = new QMenu( parent );
310

311
    addDPStaticEntry( menu, qtr( "&Open File..." ),
312
        ":/type/file-asym", SLOT( simpleOpenDialog() ), "Ctrl+O" );
313
    addDPStaticEntry( menu, qtr( "Advanced Open File..." ),
314
        ":/type/file-asym", SLOT( openFileDialog() ), "Ctrl+Shift+O" );
315
    addDPStaticEntry( menu, qtr( I_OPEN_FOLDER ),
316
        ":/type/folder-grey", SLOT( PLOpenDir() ), "Ctrl+F" );
317
    addDPStaticEntry( menu, qtr( "Open &Disc..." ),
318
        ":/type/disc", SLOT( openDiscDialog() ), "Ctrl+D" );
319
    addDPStaticEntry( menu, qtr( "Open &Network Stream..." ),
320
        ":/type/network", SLOT( openNetDialog() ), "Ctrl+N" );
321
    addDPStaticEntry( menu, qtr( "Open &Capture Device..." ),
322
        ":/type/capture-card", SLOT( openCaptureDialog() ),
323
        "Ctrl+C" );
324

325
    menu->addSeparator();
326
    addDPStaticEntry( menu, qtr( "Open &Location from clipboard" ),
327
                      NULL, SLOT( openUrlDialog() ), "Ctrl+V" );
328

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
329
    if( var_InheritBool( p_intf, "qt-recentplay" ) )
330 331 332 333 334
    {
        recentsMenu = new QMenu( qtr( "&Recent Media" ), menu );
        updateRecents( p_intf );
        menu->addMenu( recentsMenu );
    }
335
    menu->addSeparator();
336

337 338 339 340
    addDPStaticEntry( menu, qtr( I_PL_SAVE ), "", SLOT( saveAPlaylist() ),
        "Ctrl+Y" );
    menu->addSeparator();

341
#ifdef ENABLE_SOUT
342
    addDPStaticEntry( menu, qtr( "Conve&rt / Save..." ), "",
343
        SLOT( openAndTranscodingDialogs() ), "Ctrl+R" );
344
    addDPStaticEntry( menu, qtr( "&Streaming..." ),
345
        ":/menu/stream", SLOT( openAndStreamingDialogs() ),
346
        "Ctrl+S" );
347
    menu->addSeparator();
348
#endif
349

350
    addDPStaticEntry( menu, qtr( "&Quit" ) ,
351
        ":/menu/quit", SLOT( quit() ), "Ctrl+Q" );
352 353 354
    return menu;
}

355
/**
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
356
 * Tools, like Media Information, Preferences or Messages
357
 **/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
358
QMenu *QVLCMenu::ToolsMenu( QMenu *menu )
Clément Stenac's avatar
Clément Stenac committed
359
{
360
    addDPStaticEntry( menu, qtr( "&Effects and Filters"), ":/menu/settings",
361
            SLOT( extendedDialog() ), "Ctrl+E" );
362

363
    addDPStaticEntry( menu, qtr( "&Track Synchronization"), ":/menu/settings",
364 365
            SLOT( synchroDialog() ), "" );

366
    addDPStaticEntry( menu, qtr( I_MENU_INFO ) , ":/menu/info",
367
        SLOT( mediaInfoDialog() ), "Ctrl+I" );
368
    addDPStaticEntry( menu, qtr( I_MENU_CODECINFO ) ,
369
        ":/menu/info", SLOT( mediaCodecDialog() ), "Ctrl+J" );
370

371
    addDPStaticEntry( menu, qtr( I_MENU_BOOKMARK ),"",
372 373
                      SLOT( bookmarksDialog() ), "Ctrl+B" );
#ifdef ENABLE_VLM
374
    addDPStaticEntry( menu, qtr( I_MENU_VLM ), "", SLOT( vlmDialog() ),
375 376
        "Ctrl+W" );
#endif
377 378

    addDPStaticEntry( menu, qtr( I_MENU_MSG ),
379
        ":/menu/messages", SLOT( messagesDialog() ),
380 381
        "Ctrl+M" );

382 383
    addDPStaticEntry( menu, qtr( "Plu&gins and extensions" ),
        "", SLOT( pluginDialog() ) );
Clément Stenac's avatar
Clément Stenac committed
384 385
    menu->addSeparator();

386
    addDPStaticEntry( menu, qtr( "&Preferences" ),
387
        ":/menu/preferences", SLOT( prefsDialog() ), "Ctrl+P" );
388

Clément Stenac's avatar
Clément Stenac committed
389 390 391
    return menu;
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
392 393 394 395 396
QMenu *QVLCMenu::ToolsMenu( QWidget *parent )
{
    return ToolsMenu( new QMenu( parent ) );
}

397
/**
398
 * View Menu
399
 * Interface Modification
400
 **/
401
QMenu *QVLCMenu::ViewMenu( intf_thread_t *p_intf,
402 403
                            MainInterface *mi,
                            bool with_intf )
404
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
405 406
    QAction *action;

407 408 409 410
    assert( mi );

    QMenu *menu = new QMenu( qtr( "V&iew" ), mi );

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
411
    menu->addAction( QIcon( ":/menu/playlist_menu" ),
412 413 414
            qtr( "Play&list" ), mi,
            SLOT( togglePlaylist() ), qtr( "Ctrl+L" ) );

415 416 417 418
    /*menu->addSeparator();
    menu->addAction( qtr( "Undock from Interface" ), mi,
                     SLOT( undockPlaylist() ), qtr( "Ctrl+U" ) );*/

419 420
    menu->addSeparator();

421 422
    if( with_intf )
    {
423
        QMenu *intfmenu = InterfacesMenu( p_intf, menu );
424 425 426
        MenuFunc *f = new MenuFunc( intfmenu, 4 );
        CONNECT( intfmenu, aboutToShow(), THEDP->menusUpdateMapper, map() );
        THEDP->menusUpdateMapper->setMapping( intfmenu, f );
427 428
        menu->addSeparator();
    }
429

430
    /* Minimal View */
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
431
    action = menu->addAction( qtr( "Mi&nimal View" ) );
432
    action->setShortcut( qtr( "Ctrl+H" ) );
433
    action->setCheckable( true );
434
    action->setChecked( !with_intf &&
435
            (mi->getControlsVisibilityStatus() & CONTROLS_HIDDEN ) );
436

437 438
    CONNECT( action, triggered( bool ), mi, toggleMinimalView( bool ) );
    CONNECT( mi, minimalViewToggled( bool ), action, setChecked( bool ) );
439 440 441 442 443

    /* FullScreen View */
    action = menu->addAction( qtr( "&Fullscreen Interface" ), mi,
            SLOT( toggleFullScreen() ), QString( "F11" ) );
    action->setCheckable( true );
444 445 446
    action->setChecked( mi->isFullScreen() );
    CONNECT( mi, fullscreenInterfaceToggled( bool ),
             action, setChecked( bool ) );
447 448 449 450 451 452 453 454

    /* Advanced Controls */
    action = menu->addAction( qtr( "&Advanced Controls" ), mi,
            SLOT( toggleAdvanced() ) );
    action->setCheckable( true );
    if( mi->getControlsVisibilityStatus() & CONTROLS_ADVANCED )
        action->setChecked( true );

455 456 457 458 459 460 461 462
    if( with_intf )
    // I don't want to manage consistency between menus, so no popup-menu
    {
        action = menu->addAction( qtr( "Quit after Playback" ) );
        action->setCheckable( true );
        CONNECT( action, triggered( bool ), THEMIM, activatePlayQuit( bool ) );
    }

463
#if 0 /* For Visualisations. Not yet working */
464 465 466 467
    adv = menu->addAction( qtr( "Visualizations selector" ),
            mi, SLOT( visual() ) );
    adv->setCheckable( true );
    if( visual_selector_enabled ) adv->setChecked( true );
468
#endif
469

470
    menu->addSeparator();
471
    addDPStaticEntry( menu, qtr( "Customi&ze Interface..." ),
472
        ":/menu/preferences", SLOT( toolbarDialog() ) );
473
    menu->addSeparator();
474

475 476 477 478 479 480 481
    /* Extensions */
    menu->addSeparator();
    QMenu *extmenu = ExtensionsMenu( p_intf, menu );
    MenuFunc *f = new MenuFunc( menu, 5 );
    CONNECT( menu, aboutToShow(), THEDP->menusUpdateMapper, map() );
    THEDP->menusUpdateMapper->setMapping( menu, f );

482 483 484
    return menu;
}

485 486 487
/**
 * Interface Sub-Menu, to list extras interface and skins
 **/
488 489
QMenu *QVLCMenu::InterfacesMenu( intf_thread_t *p_intf, QMenu *current )
{
490
    vector<vlc_object_t *> objects;
491 492
    vector<const char *> varnames;
    varnames.push_back( "intf-add" );
493
    objects.push_back( VLC_OBJECT(p_intf) );
Clément Stenac's avatar
Qt4:  
Clément Stenac committed
494

495
    return Populate( p_intf, current, varnames, objects );
496 497
}

498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
/**
 * Extensions Sub-Menu
 * EXPERIMENTAL
 **/
QMenu *QVLCMenu::ExtensionsMenu( intf_thread_t *p_intf, QMenu *current )
{
    QMenu *extMenu = NULL;

    QAction *extAction = NULL;
    foreach( QAction *action, current->actions() )
    {
        if( action->text() == qtr( "&Extensions" ) )
        {
            extAction = action;
            break;
        }
    }

    ExtensionsManager *extMgr = ExtensionsManager::getInstance( p_intf );

    extMenu = new QMenu( qtr( "&Extensions" ) );
    if( extMgr->isLoaded() )
    {
        /* Let the ExtensionsManager build itself the menu */
        extMgr->menu( extMenu );
    }
    else
    {
        extMenu->addAction( qtr( "&Load extensions" ),
                            extMgr, SLOT( loadExtensions() ) );
    }

    if( extAction )
        extAction->setMenu( extMenu );
    else
        current->addMenu( extMenu );
}

536 537
/**
 * Main Audio Menu
538
 **/
539 540
QMenu *QVLCMenu::AudioMenu( intf_thread_t *p_intf, QMenu * current )
{
541
    vector<vlc_object_t *> objects;
542
    vector<const char *> varnames;
543
    aout_instance_t *p_aout;
544 545 546
    input_thread_t *p_input;

    if( current->isEmpty() )
547
    {
548 549 550
        ACT_ADDMENU( current, "audio-es", qtr( "Audio &Track" ) );
        ACT_ADDMENU( current, "audio-channels", qtr( "Audio &Channels" ) );
        ACT_ADDMENU( current, "audio-device", qtr( "Audio &Device" ) );
551
        current->addSeparator();
552

553
        ACT_ADDMENU( current, "visual", qtr( "&Visualizations" ) );
554 555
        current->addSeparator();

556
        QAction *action = current->addAction( qtr( "Increase Volume" ),
557
                ActionsManager::getInstance( p_intf ), SLOT( AudioUp() ) );
558
        action->setData( STATIC_ENTRY );
559 560
        action = current->addAction( qtr( "Decrease Volume" ),
                ActionsManager::getInstance( p_intf ), SLOT( AudioDown() ) );
561
        action->setData( STATIC_ENTRY );
562 563
        action = current->addAction( qtr( "Mute" ),
                ActionsManager::getInstance( p_intf ), SLOT( toggleMuteAudio() ) );
564
        action->setData( STATIC_ENTRY );
565 566
    }

567
    p_input = THEMIM->getInput();
568
    p_aout = THEMIM->getAout();
569
    EnableStaticEntries( current, ( p_aout != NULL ) );
570
    AudioAutoMenuBuilder( p_aout, p_input, objects, varnames );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
571
    if( p_aout )
572
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
573
        vlc_object_release( p_aout );
574
    }
575

576 577 578
    return Populate( p_intf, current, varnames, objects );
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
579 580 581 582 583
QMenu *QVLCMenu::AudioMenu( intf_thread_t *p_intf, QWidget *parent )
{
    return AudioMenu( p_intf, new QMenu( parent ) );
}

584 585 586 587
/**
 * Main Video Menu
 * Subtitles are part of Video.
 **/
588
QMenu *QVLCMenu::VideoMenu( intf_thread_t *p_intf, QMenu *current )
589
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
590
    vout_thread_t *p_vout;
591
    input_thread_t *p_input;
592
    vector<vlc_object_t *> objects;
593 594
    vector<const char *> varnames;

595
    if( current->isEmpty() )
596
    {
597
        ACT_ADDMENU( current, "video-es", qtr( "Video &Track" ) );
598 599 600 601 602

        QAction *action;
        QMenu *submenu = new QMenu( qtr( "&Subtitles Track" ), current );
        action = current->addMenu( submenu );
        action->setData( "spu-es" );
603
        addDPStaticEntry( submenu, qtr( "Open File..." ), "",
604
                          SLOT( loadSubtitlesFile() ) );
605
        submenu->addSeparator();
606
        current->addSeparator();
607

608 609
        ACT_ADDCHECK( current, "fullscreen", qtr( "&Fullscreen" ) );
        ACT_ADDCHECK( current, "video-on-top", qtr( "Always &On Top" ) );
610
        ACT_ADDCHECK( current, "video-wallpaper", qtr( "DirectX Wallpaper" ) );
611
#ifdef WIN32
612
        ACT_ADDCHECK( current, "direct3d-desktop", qtr( "Direct3D Desktop mode" ) );
613
#endif
614
        ACT_ADD( current, "video-snapshot", qtr( "Sna&pshot" ) );
615

616 617
        current->addSeparator();

618 619 620 621
        ACT_ADDMENU( current, "zoom", qtr( "&Zoom" ) );
        ACT_ADDCHECK( current, "autoscale", qtr( "Sca&le" ) );
        ACT_ADDMENU( current, "aspect-ratio", qtr( "&Aspect Ratio" ) );
        ACT_ADDMENU( current, "crop", qtr( "&Crop" ) );
622 623
        ACT_ADDMENU( current, "deinterlace", qtr( "&Deinterlace" ) );
        ACT_ADDMENU( current, "deinterlace-mode", qtr( "&Deinterlace mode" ) );
624
        ACT_ADDMENU( current, "postprocess", qtr( "&Post processing" ) );
625
    }
626

627 628
    p_input = THEMIM->getInput();

629
    p_vout = THEMIM->getVout();
630
    VideoAutoMenuBuilder( p_vout, p_input, objects, varnames );
631

632 633
    if( p_vout )
        vlc_object_release( p_vout );
634

635
    return Populate( p_intf, current, varnames, objects );
636 637
}

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
638 639 640 641 642
QMenu *QVLCMenu::VideoMenu( intf_thread_t *p_intf, QWidget *parent )
{
    return VideoMenu( p_intf, new QMenu( parent ) );
}

643 644 645 646
/**
 * Navigation Menu
 * For DVD, MP4, MOV and other chapter based format
 **/
647
QMenu *QVLCMenu::NavigMenu( intf_thread_t *p_intf, QMenu *menu )
648
{
649
    QAction *action;
650

651 652 653 654 655 656
    QMenu *submenu = new QMenu( qtr( "&Bookmarks" ), menu );
    addDPStaticEntry( submenu, qtr( "Manage &bookmarks" ), "",
                      SLOT( bookmarksDialog() ) );
    submenu->addSeparator();
    action = menu->addMenu( submenu );
    action->setData( "bookmark" );
657

658 659 660 661
    ACT_ADDMENU( menu, "title", qtr( "T&itle" ) );
    ACT_ADDMENU( menu, "chapter", qtr( "&Chapter" ) );
    ACT_ADDMENU( menu, "navigation", qtr( "&Navigation" ) );
    ACT_ADDMENU( menu, "program", qtr( "&Program" ) );
662

663 664
    menu->addSeparator();
    PopupMenuPlaylistControlEntries( menu, p_intf );
665
    PopupMenuControlEntries( menu, p_intf );
666

667 668
    EnableStaticEntries( menu, ( THEMIM->getInput() != NULL ) );
    return RebuildNavigMenu( p_intf, menu );
669 670 671 672
}

QMenu *QVLCMenu::RebuildNavigMenu( intf_thread_t *p_intf, QMenu *menu )
{
673
    /* */
674 675 676 677
    input_thread_t *p_object;
    vector<vlc_object_t *> objects;
    vector<const char *> varnames;

678
    /* Get the input and hold it */
679
    p_object = THEMIM->getInput();
680

681
    InputAutoMenuBuilder( p_object, objects, varnames );
682

683 684
    menu->addSeparator();

685
    /* Title and so on */
686 687 688 689
    PUSH_VAR( "prev-title" );
    PUSH_VAR( "next-title" );
    PUSH_VAR( "prev-chapter" );
    PUSH_VAR( "next-chapter" );
690

691
    EnableStaticEntries( menu, (p_object != NULL ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
692
    return Populate( p_intf, menu, varnames, objects );
693
}
694

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
695 696 697 698 699
QMenu *QVLCMenu::NavigMenu( intf_thread_t *p_intf, QWidget *parent )
{
    return NavigMenu( p_intf, new QMenu( parent ) );
}

700
/**
701
 * Service Discovery SubMenu
702
 **/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
703
QMenu *QVLCMenu::SDMenu( intf_thread_t *p_intf, QWidget *parent )
Clément Stenac's avatar
Clément Stenac committed
704
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
705
    QMenu *menu = new QMenu( parent );
706
    menu->setTitle( qtr( I_PL_SD ) );
707

708
    char **ppsz_longnames;
709
    char **ppsz_names = vlc_sd_GetNames( p_intf, &ppsz_longnames );
710 711 712
    if( !ppsz_names )
        return menu;

713 714
    char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
    for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
Clément Stenac's avatar
Clément Stenac committed
715
    {
716
        if( !strcmp( *ppsz_name, "podcast" ) )
717
        {
Christophe Mutricy's avatar
Christophe Mutricy committed
718
            QAction *b = new QAction( qtr( "Configure podcasts..." ), menu );
719 720 721 722
            //b->setEnabled( a->isChecked() );
            menu->addAction( b );
            CONNECT( b, triggered(), THEDP, podcastConfigureDialog() );
        }
723 724
        free( *ppsz_name );
        free( *ppsz_longname );
Clément Stenac's avatar
Clément Stenac committed
725
    }
726 727
    free( ppsz_names );
    free( ppsz_longnames );
Clément Stenac's avatar
Clément Stenac committed
728 729
    return menu;
}
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
730

731 732 733
/**
 * Help/About Menu
**/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
734
QMenu *QVLCMenu::HelpMenu( QWidget *parent )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
735
{
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
736
    QMenu *menu = new QMenu( parent );
737
    addDPStaticEntry( menu, qtr( "&Help..." ) ,
738
        ":/menu/help", SLOT( helpDialog() ), "F1" );
739
#ifdef UPDATE_CHECK
740 741
    addDPStaticEntry( menu, qtr( "Check for &Updates..." ) , "",
                      SLOT( updateDialog() ) );
742
#endif
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
743
    menu->addSeparator();
744
    addDPStaticEntry( menu, qtr( I_MENU_ABOUT ), ":/menu/info",
745
            SLOT( aboutDialog() ), "Shift+F1" );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
746 747 748
    return menu;
}

749
/*****************************************************************************
750
 * Popup menus - Right Click menus                                           *
751
 *****************************************************************************/
752 753
#define POPUP_BOILERPLATE \
    unsigned int i_last_separator = 0; \
754
    vector<vlc_object_t *> objects; \
755 756 757 758 759 760 761
    vector<const char *> varnames; \
    input_thread_t *p_input = THEMIM->getInput();

#define CREATE_POPUP \
    Populate( p_intf, menu, varnames, objects ); \
    p_intf->p_sys->p_popup_menu = menu; \
    menu->popup( QCursor::pos() ); \
762
    p_intf->p_sys->p_popup_menu = NULL; \
763
    i_last_separator = 0;
764

765
void QVLCMenu::PopupPlayEntries( QMenu *menu,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
766 767 768
                                        intf_thread_t *p_intf,
                                        input_thread_t *p_input )
{
769 770 771
    QAction *action;

    /* Play or Pause action and icon */
772 773
    if( !p_input || var_GetInteger( p_input, "state" ) != PLAYING_S )
    {
774
        action = menu->addAction( qtr( "Play" ),
775
                ActionsManager::getInstance( p_intf ), SLOT( play() ) );
776
        action->setIcon( QIcon( ":/menu/play" ) );
777 778
    }
    else
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
779
    {
780
         addMIMStaticEntry( p_intf, menu, qtr( "Pause" ),
781
                    ":/menu/pause", SLOT( togglePlayPause() ) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed