actions_manager.cpp 10.8 KB
Newer Older
1
/*****************************************************************************
Pere Orga's avatar
Pere Orga committed
2
 * actions_manager.cpp : Controller for the main interface
3
 ****************************************************************************
4
 * Copyright © 2009-2014 VideoLAN and VLC authors
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * $Id$
 *
 * Authors: Jean-Baptiste Kempf <jb@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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_vout.h>
#include <vlc_keys.h>
30
#include <vlc_renderer_discovery.h>
31 32

#include "actions_manager.hpp"
33 34 35 36

#include "dialogs_provider.hpp"      /* Opening Dialogs */
#include "input_manager.hpp"         /* THEMIM */
#include "main_interface.hpp"        /* Show playlist */
37
#include "components/controller.hpp" /* Toggle FSC controller width */
38
#include "components/extended_panels.hpp"
39
#include "menus.hpp"
40

41
ActionsManager::ActionsManager( intf_thread_t * _p_i )
42 43
    : p_intf( _p_i )
{ }
44 45 46

ActionsManager::~ActionsManager()
{
47
    foreach ( vlc_renderer_discovery_t* p_rd, m_rds )
48
        vlc_rd_release( p_rd );
49 50 51 52 53 54 55 56
}

void ActionsManager::doAction( int id_action )
{
    switch( id_action )
    {
        case PLAY_ACTION:
            play(); break;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
57 58 59
        case STOP_ACTION:
            THEMIM->stop(); break;
        case OPEN_ACTION:
60
            THEDP->openDialog(); break;
61
        case PREVIOUS_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
62
            THEMIM->prev(); break;
63
        case NEXT_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
64
            THEMIM->next(); break;
65
        case SLOWER_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
66
            THEMIM->getIM()->slower(); break;
67
        case FASTER_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
68
            THEMIM->getIM()->faster(); break;
69 70 71
        case FULLSCREEN_ACTION:
            fullscreen(); break;
        case EXTENDED_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
72
            THEDP->extendedDialog(); break;
73 74 75 76 77 78 79 80
        case PLAYLIST_ACTION:
            playlist(); break;
        case SNAPSHOT_ACTION:
            snapshot(); break;
        case RECORD_ACTION:
            record(); break;
        case FRAME_ACTION:
            frame(); break;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
81 82
        case ATOB_ACTION:
            THEMIM->getIM()->setAtoB(); break;
83
        case REVERSE_ACTION:
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
84
            THEMIM->getIM()->reverse(); break;
85
        case SKIP_BACK_ACTION:
86
            skipBackward();
87 88
            break;
        case SKIP_FW_ACTION:
89
            skipForward();
90
            break;
91 92
        case QUIT_ACTION:
            THEDP->quit();  break;
93
        case RANDOM_ACTION:
94
            THEMIM->toggleRandom(); break;
95 96
        case INFO_ACTION:
            THEDP->mediaInfoDialog(); break;
97 98
        case OPEN_SUB_ACTION:
            THEDP->loadSubtitlesFile(); break;
99 100 101 102
        case FULLWIDTH_ACTION:
            if( p_intf->p_sys->p_mi )
                p_intf->p_sys->p_mi->getFullscreenControllerWidget()->toggleFullwidth();
            break;
103
        default:
104
            msg_Warn( p_intf, "Action not supported: %i", id_action );
105 106 107 108 109 110
            break;
    }
}

void ActionsManager::play()
{
111
    if( THEPL->current.i_size == 0 && THEPL->items.i_size == 0 )
112 113 114 115 116 117 118 119 120
    {
        /* The playlist is empty, open a file requester */
        THEDP->openFileDialog();
        return;
    }
    THEMIM->togglePlayPause();
}

/**
121
 * TODO
122 123
 * This functions toggle the fullscreen mode
 * If there is no video, it should first activate Visualisations...
124
 * This has also to be fixed in enableVideo()
125 126 127
 */
void ActionsManager::fullscreen()
{
128
    bool fs = var_ToggleBool( THEPL, "fullscreen" );
129
    vout_thread_t *p_vout = THEMIM->getVout();
130 131
    if( p_vout)
    {
132
        var_SetBool( p_vout, "fullscreen", fs );
133 134 135 136 137 138
        vlc_object_release( p_vout );
    }
}

void ActionsManager::snapshot()
{
139
    vout_thread_t *p_vout = THEMIM->getVout();
140 141
    if( p_vout )
    {
142
        var_TriggerCallback( p_vout, "video-snapshot" );
143 144 145 146
        vlc_object_release( p_vout );
    }
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
147
void ActionsManager::playlist()
148
{
149 150
    if( p_intf->p_sys->p_mi )
        p_intf->p_sys->p_mi->togglePlaylist();
151 152 153 154 155 156 157 158
}

void ActionsManager::record()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
    {
        /* This method won't work fine if the stream can't be cut anywhere */
ivoire's avatar
ivoire committed
159
        var_ToggleBool( p_input, "record" );
160 161 162 163 164 165 166 167 168 169
#if 0
        else
        {
            /* 'record' access-filter is not loaded, we open Save dialog */
            input_item_t *p_item = input_GetItem( p_input );
            if( !p_item )
                return;

            char *psz = input_item_GetURI( p_item );
            if( psz )
170
                THEDP->streamingDialog( NULL, qfu(psz), true );
171 172 173 174 175 176 177 178 179
        }
#endif
    }
}

void ActionsManager::frame()
{
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
180
        var_TriggerCallback( p_input, "frame-next" );
181 182
}

183 184
void ActionsManager::toggleMuteAudio()
{
185
    playlist_MuteToggle( THEPL );
186 187 188 189
}

void ActionsManager::AudioUp()
{
190
    playlist_VolumeUp( THEPL, 1, NULL );
191 192 193 194
}

void ActionsManager::AudioDown()
{
195
    playlist_VolumeDown( THEPL, 1, NULL );
196
}
197

198 199
void ActionsManager::skipForward()
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
200 201 202
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        THEMIM->getIM()->jumpFwd();
203 204 205 206
}

void ActionsManager::skipBackward()
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
207 208 209
    input_thread_t *p_input = THEMIM->getInput();
    if( p_input )
        THEMIM->getIM()->jumpBwd();
210 211
}

212 213 214 215 216 217 218 219
void ActionsManager::PPaction( QAction *a )
{
    int i_q = -1;
    if( a != NULL )
        i_q = a->data().toInt();

    ExtVideo::setPostprocessing( p_intf, i_q );
}
220 221 222 223 224

bool ActionsManager::isItemSout( QVariant & m_obj, const char *psz_sout, bool as_output )
{
    if ( psz_sout == NULL )
        return false;
225
    if (!m_obj.canConvert<QVariantHash>())
226 227
        return false;

228
    QVariantHash hash = m_obj.value<QVariantHash>();
229 230 231
    QString renderer(psz_sout);
    if ( as_output && renderer.at(0) == '#' )
        renderer = renderer.right( renderer.length() - 1 );
232
    return QString::compare( hash["sout"].toString(), renderer, Qt::CaseInsensitive) == 0;
233 234
}

235 236
void ActionsManager::renderer_event_item_added(
    vlc_renderer_discovery_t *rd, vlc_renderer_item_t *p_item )
237
{
238 239
    intf_thread_t *p_intf = reinterpret_cast<intf_thread_t*>(rd->owner.sys);
    QAction *firstSeparator = NULL;
240

241
    foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
242
    {
243
        if (action->isSeparator())
244
        {
245 246
            firstSeparator = action;
            break;
247
        }
248 249 250 251
        QVariant v = action->data();
        if ( isItemSout( v, vlc_renderer_item_sout( p_item ), false ) )
            return; /* we already have this item */
    }
252

253 254 255 256
    QHash<QString,QVariant> itemData;
    itemData.insert("sout", vlc_renderer_item_sout( p_item ));
    itemData.insert("filter", vlc_renderer_item_demux_filter( p_item ));
    QVariant data(itemData);
257

258 259 260 261 262 263 264 265 266
    QAction *action = new QAction( vlc_renderer_item_flags(p_item) & VLC_RENDERER_CAN_VIDEO ? QIcon( ":/sidebar/movie" ) : QIcon( ":/sidebar/music" ),
                                   vlc_renderer_item_name(p_item), VLCMenuBar::rendererMenu );
    action->setCheckable(true);
    action->setData(data);
    if (firstSeparator != NULL)
    {
        VLCMenuBar::rendererMenu->insertAction( firstSeparator, action );
        VLCMenuBar::rendererGroup->addAction(action);
    }
267

268 269 270 271 272 273
    char *psz_renderer = var_InheritString( THEPL, "sout" );
    if ( psz_renderer != NULL )
    {
        if ( isItemSout( data, psz_renderer, true ) )
            action->setChecked( true );
        free( psz_renderer );
274 275 276
    }
}

277 278 279 280 281 282
void ActionsManager::renderer_event_item_removed(
    vlc_renderer_discovery_t *rd, vlc_renderer_item_t *p_item )
{
    (void) rd; (void) p_item;
}

283 284
void ActionsManager::ScanRendererAction(bool checked)
{
285
    if (checked == !m_rds.empty())
286 287 288 289 290 291 292 293
        return; /* nothing changed */

    if (checked)
    {
        /* reset the list of renderers */
        foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
        {
            QVariant data = action->data();
294
            if (!data.canConvert<QVariantHash>())
295 296 297 298 299 300 301 302 303
                continue;
            VLCMenuBar::rendererMenu->removeAction(action);
            VLCMenuBar::rendererGroup->removeAction(action);
        }
        char *psz_renderer = var_InheritString( THEPL, "sout" );
        if ( psz_renderer == NULL || *psz_renderer == '\0' )
        {
            foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
            {
304
                if (!action->data().canConvert<QVariantHash>())
305 306 307 308 309 310 311 312 313 314 315 316 317 318
                    continue;
                if (!action->isSeparator())
                    action->setChecked(true);
                break;
            }
        }
        free( psz_renderer );

        /* SD subnodes */
        char **ppsz_longnames;
        char **ppsz_names;
        if( vlc_rd_get_names( THEPL, &ppsz_names, &ppsz_longnames ) != VLC_SUCCESS )
            return;

319 320 321 322 323 324 325
        struct vlc_renderer_discovery_owner owner =
        {
            p_intf,
            renderer_event_item_added,
            renderer_event_item_removed,
        };

326 327 328 329
        char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
        for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
        {
            msg_Dbg( p_intf, "starting renderer discovery service %s", *ppsz_longname );
330 331 332 333
            vlc_renderer_discovery_t* p_rd = vlc_rd_new( VLC_OBJECT(p_intf), *ppsz_name, &owner );
            if( !p_rd )
                msg_Err( p_intf, "Could not start renderer discovery services" );
            else
334
            {
335 336 337 338
                if ( vlc_rd_start( p_rd ) == VLC_SUCCESS )
                    m_rds.push_back( p_rd );
                else
                    vlc_rd_release( p_rd );
339
            }
340 341
            free( *ppsz_name );
            free( *ppsz_longname );
342 343 344 345 346 347
        }
        free( ppsz_names );
        free( ppsz_longnames );
    }
    else
    {
348
        foreach ( vlc_renderer_discovery_t* p_rd, m_rds )
349
            vlc_rd_release( p_rd );
350
        m_rds.clear();
351 352 353 354 355
    }
}

void ActionsManager::RendererSelected( QAction *selected )
{
356
    QString s_sout, s_demux_filter;
357
    QVariant data = selected->data();
358
    if (data.canConvert<QVariantHash>())
359
    {
360
        QVariantHash hash = data.value<QVariantHash>();
361
        s_sout.append('#');
362 363
        s_sout.append(hash["sout"].toString());
        s_demux_filter.append(hash["filter"].toString());
364 365 366
    }
    msg_Dbg( p_intf, "using sout: '%s'", s_sout.toUtf8().constData() );
    var_SetString( THEPL, "sout", s_sout.toUtf8().constData() );
367
    var_SetString( THEPL, "demux-filter", s_demux_filter.toUtf8().constData() );
368 369
}