input_manager.cpp 24.9 KB
Newer Older
zorglub's avatar
zorglub committed
1
2
3
/*****************************************************************************
 * input_manager.cpp : Manage an input and interact with its GUI elements
 ****************************************************************************
4
 * Copyright (C) 2006-2008 the VideoLAN team
5
 * $Id$
zorglub's avatar
zorglub committed
6
7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Ilkka Ollakka  <ileoo@videolan.org>
9
 *          Jean-Baptiste <jb@videolan.org>
zorglub's avatar
zorglub committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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.
 *****************************************************************************/
25

26
27
28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
zorglub's avatar
zorglub committed
29
30

#include "input_manager.hpp"
31
32

#include <QApplication>
zorglub's avatar
zorglub committed
33

34
35
static int ItemChanged( vlc_object_t *, const char *,
                        vlc_value_t, vlc_value_t, void * );
36
static int PLItemChanged( vlc_object_t *, const char *,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
37
                        vlc_value_t, vlc_value_t, void * );
38
39
static int VolumeChanged( vlc_object_t *, const char *,
                        vlc_value_t, vlc_value_t, void * );
40

Laurent Aimar's avatar
Laurent Aimar committed
41
42
43
44
static int InputEvent( vlc_object_t *, const char *,
                       vlc_value_t, vlc_value_t, void * );


45
46
/**********************************************************************
 * InputManager implementation
47
48
49
 **********************************************************************
 * The Input Manager can be the main one around the playlist
 * But can also be used for VLM dialog or similar
50
51
 **********************************************************************/

zorglub's avatar
zorglub committed
52
53
54
InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) :
                           QObject( parent ), p_intf( _p_intf )
{
55
    i_old_playing_status = END_S;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
56
    oldName      = "";
57
58
59
60
    artUrl       = "";
    p_input      = NULL;
    i_rate       = 0;
    i_input_id   = 0;
61
    b_video      = false;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
62
63
64
    timeA        = 0;
    timeB        = 0;

zorglub's avatar
zorglub committed
65
66
67
68
}

InputManager::~InputManager()
{
69
    delInput();
zorglub's avatar
zorglub committed
70
71
}

72
73
/* Define the Input used.
   Add the callbacks on input
74
   p_input is held once here */
zorglub's avatar
zorglub committed
75
76
void InputManager::setInput( input_thread_t *_p_input )
{
77
    delInput();
zorglub's avatar
zorglub committed
78
    p_input = _p_input;
79
    if( p_input && !( p_input->b_dead || !vlc_object_alive (p_input) ) )
80
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
81
        msg_Dbg( p_intf, "IM: Setting an input" );
82
        vlc_object_hold( p_input );
83
        emit statusChanged( PLAYING_S );
84
        UpdateName();
85
        UpdateArt();
86
        UpdateTeletext();
87
        UpdateNavigation();
88
        UpdateVout();
89
        addCallbacks();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
90
91
92
93
        i_input_id = input_GetItem( p_input )->i_id;
    }
    else
    {
94
95
        p_input = NULL;
        i_input_id = 0;
96
        emit rateChanged( INPUT_RATE_DEFAULT );
97
98
    }
}
99

100
101
102
/* delete Input if it ever existed.
   Delete the callbacls on input
   p_input is released once here */
103
104
void InputManager::delInput()
{
105
    if( !p_input ) return;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
106
    msg_Dbg( p_intf, "IM: Deleting the input" );
107
108
109
110
111
112
113
114
115
116

    delCallbacks();
    i_old_playing_status = END_S;
    i_input_id           = 0;
    oldName              = "";
    artUrl               = "";
    b_video              = false;
    timeA                = 0;
    timeB                = 0;

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
117
118
119
    vlc_object_release( p_input );
    p_input = NULL;

120
121
122
123
124
125
126
127
    emit positionUpdated( -1.0, 0 ,0 );
    emit rateChanged( INPUT_RATE_DEFAULT ); /* TODO: Do we want this ? */
    emit nameChanged( "" );
    emit chapterChanged( 0 );
    emit titleChanged( 0 );
    emit statusChanged( END_S );

    emit teletextPossible( false );
128
    emit AtoBchanged( false, false );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
129
    emit voutChanged( false );
130
    emit voutListChanged( NULL, 0 );
131

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
132
133
134
135
    /* Reset all InfoPanels but stats */
    emit artChanged( NULL );
    emit infoChanged( NULL );
    emit metaChanged( NULL );
zorglub's avatar
zorglub committed
136
137
}

138
/* Convert the event from the callbacks in actions */
139
140
void InputManager::customEvent( QEvent *event )
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
141
    int i_type = event->type();
142
    IMEvent *ple = static_cast<IMEvent *>(event);
143

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
144
145
146
147
    if ( i_type != PositionUpdate_Type &&
         i_type != ItemChanged_Type &&
         i_type != ItemRateChanged_Type &&
         i_type != ItemTitleChanged_Type &&
Laurent Aimar's avatar
Laurent Aimar committed
148
         i_type != ItemEsChanged_Type &&
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
149
150
151
         i_type != ItemTeletextChanged_Type &&
         i_type != ItemStateChanged_Type &&
         i_type != StatisticsUpdate_Type &&
Laurent Aimar's avatar
Laurent Aimar committed
152
         i_type != InterfaceVoutUpdate_Type &&
153
154
         i_type != MetaChanged_Type &&
         i_type != NameChanged_Type &&
155
         i_type != InfoChanged_Type &&
156
         i_type != SynchroChanged_Type &&
157
         i_type != CachingEvent_Type &&
158
159
         i_type != BookmarksChanged_Type &&
         i_type != InterfaceAoutUpdate_Type )
160
        return;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
161

162
163
    if( !hasInput() ) return;

164
165
166
    if( i_type == CachingEvent_Type )
        UpdateCaching();

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
167
168
    if( ( i_type != PositionUpdate_Type  &&
          i_type != ItemRateChanged_Type &&
Laurent Aimar's avatar
Laurent Aimar committed
169
          i_type != ItemEsChanged_Type &&
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
170
171
172
          i_type != ItemTeletextChanged_Type &&
          i_type != ItemStateChanged_Type &&
          i_type != StatisticsUpdate_Type &&
Laurent Aimar's avatar
Laurent Aimar committed
173
          i_type != InterfaceVoutUpdate_Type &&
174
175
          i_type != MetaChanged_Type &&
          i_type != NameChanged_Type &&
176
          i_type != InfoChanged_Type &&
177
          i_type != SynchroChanged_Type &&
178
179
          i_type != BookmarksChanged_Type &&
          i_type != InterfaceAoutUpdate_Type
180
181
        )
        && ( i_input_id != ple->i_id ) )
182
        return;
183

184
#ifndef NDEBUG
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
185
186
187
    if( i_type != PositionUpdate_Type &&
        i_type != StatisticsUpdate_Type )
        msg_Dbg( p_intf, "New Event: type %i", i_type );
188
#endif
189

190
    /* Actions */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
191
    switch( i_type )
192
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
193
    case PositionUpdate_Type:
194
        UpdatePosition();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
195
        break;
196
197
198
    case StatisticsUpdate_Type:
        UpdateStats();
        break;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
199
    case ItemChanged_Type:
200
        UpdateStatus();
201
202
203
204
205
206
207
208
209
210
211
212
        // UpdateName();
        // UpdateArt();
        break;
    case ItemStateChanged_Type:
        // TODO: Fusion with above state
        UpdateStatus();
        // UpdateName();
        // UpdateNavigation(); This shouldn't be useful now
        // UpdateTeletext(); Same
        break;
    case NameChanged_Type:
        UpdateName();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
213
        break;
Laurent Aimar's avatar
Laurent Aimar committed
214
    case MetaChanged_Type:
215
        UpdateMeta();
216
        UpdateName(); /* Needed for NowPlaying */
217
        UpdateArt(); /* Art is part of meta in the core */
Laurent Aimar's avatar
Laurent Aimar committed
218
        break;
219
    case InfoChanged_Type:
220
        UpdateInfo();
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
221
222
        break;
    case ItemTitleChanged_Type:
223
        UpdateNavigation();
224
        UpdateName(); /* Display the name of the Chapter, if exists */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
225
        break;
226
227
228
    case ItemRateChanged_Type:
        UpdateRate();
        break;
Laurent Aimar's avatar
Laurent Aimar committed
229
    case ItemEsChanged_Type:
230
        // We don't do anything. Why ?
231
        break;
232
233
234
    case ItemTeletextChanged_Type:
        UpdateTeletext();
        break;
235
236
237
    case InterfaceVoutUpdate_Type:
        UpdateVout();
        break;
238
239
240
    case SynchroChanged_Type:
        emit synchroChanged();
        break;
241
242
243
    case CachingEvent_Type:
        UpdateCaching();
        break;
244
245
246
    case BookmarksChanged_Type:
        emit bookmarksChanged();
        break;
247
248
249
    case InterfaceAoutUpdate_Type:
        UpdateAout();
        break;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
250
251
    default:
        msg_Warn( p_intf, "This shouldn't happen: %i", i_type );
252
    }
253
}
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* Add the callbacks on Input. Self explanatory */
inline void InputManager::addCallbacks()
{
    var_AddCallback( p_input, "intf-event", InputEvent, this );
}

/* Delete the callbacks on Input. Self explanatory */
inline void InputManager::delCallbacks()
{
    var_DelCallback( p_input, "intf-event", InputEvent, this );
}

/* Static callbacks for IM */
static int ItemChanged( vlc_object_t *p_this, const char *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *param )
{
    InputManager *im = (InputManager*)param;

    IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
    QApplication::postEvent( im, static_cast<QEvent*>(event) );
    return VLC_SUCCESS;
}

static int InputEvent( vlc_object_t *p_this, const char *,
                       vlc_value_t, vlc_value_t newval, void *param )
{
    InputManager *im = (InputManager*)param;
    IMEvent *event;

    switch( newval.i_int )
    {
    case INPUT_EVENT_STATE:
        event = new IMEvent( ItemStateChanged_Type, 0 );
        break;
    case INPUT_EVENT_RATE:
        event = new IMEvent( ItemRateChanged_Type, 0 );
        break;
    case INPUT_EVENT_TIMES:
        event = new IMEvent( PositionUpdate_Type, 0 );
        break;

    case INPUT_EVENT_TITLE:
    case INPUT_EVENT_CHAPTER:
        event = new IMEvent( ItemTitleChanged_Type, 0 );
        break;

    case INPUT_EVENT_ES:
        event = new IMEvent( ItemEsChanged_Type, 0 );
        break;
    case INPUT_EVENT_TELETEXT:
        event = new IMEvent( ItemTeletextChanged_Type, 0 );
        break;

308
309
310
311
    case INPUT_EVENT_STATISTICS:
        event = new IMEvent( StatisticsUpdate_Type, 0 );
        break;

312
313
314
    case INPUT_EVENT_VOUT:
        event = new IMEvent( InterfaceVoutUpdate_Type, 0 );
        break;
315
316
    case INPUT_EVENT_AOUT:
        event = new IMEvent( InterfaceAoutUpdate_Type, 0 );
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
        break;

    case INPUT_EVENT_ITEM_META: /* Codec MetaData + Art */
        event = new IMEvent( MetaChanged_Type, 0 );
        break;
    case INPUT_EVENT_ITEM_INFO: /* Codec Info */
        event = new IMEvent( InfoChanged_Type, 0 );
        break;
    case INPUT_EVENT_ITEM_NAME:
        event = new IMEvent( NameChanged_Type, 0 );
        break;

    case INPUT_EVENT_AUDIO_DELAY:
    case INPUT_EVENT_SUBTITLE_DELAY:
        event = new IMEvent( SynchroChanged_Type, 0 );
        break;

    case INPUT_EVENT_CACHE:
        event = new IMEvent( CachingEvent_Type, 0 );
        break;

    case INPUT_EVENT_BOOKMARK:
        event = new IMEvent( BookmarksChanged_Type, 0 );
        break;

    case INPUT_EVENT_RECORD:
        /* This happens when a recording starts. What do we do then?
           Display a red light? */
        /* event = new IMEvent( RecordingEvent_Type, 0 );
        break; */

    case INPUT_EVENT_PROGRAM:
        /* This is for PID changes */
        /* event = new IMEvent( ProgramChanged_Type, 0 );
        break; */
    case INPUT_EVENT_SIGNAL:
        /* This is for capture-card signals */
        /* event = new IMEvent( SignalChanged_Type, 0 );
        break; */
    default:
        event = NULL;
        break;
    }

    if( event )
        QApplication::postEvent( im, static_cast<QEvent*>(event) );
    return VLC_SUCCESS;
}
365
void InputManager::UpdatePosition()
366
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
367
368
369
370
371
372
373
    /* Update position */
    int i_length, i_time; /* Int is enough, since we store seconds */
    float f_pos;
    i_length = var_GetTime(  p_input , "length" ) / 1000000;
    i_time = var_GetTime(  p_input , "time") / 1000000;
    f_pos = var_GetFloat(  p_input , "position" );
    emit positionUpdated( f_pos, i_time, i_length );
374
375
}

376
void InputManager::UpdateNavigation()
377
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
378
379
    /* Update navigation status */
    vlc_value_t val; val.i_int = 0;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
380

381
382
    if( hasInput() )
        var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
383

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
384
385
    if( val.i_int > 0 )
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
386
        emit titleChanged( true );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
387
        /* p_input != NULL since val.i_int != 0 */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
388
389
        val.i_int = 0;
        var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
390
        emit chapterChanged( (val.i_int > 0) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
391
392
    }
    else
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
393
        emit titleChanged( false );
394
395
}

396
void InputManager::UpdateStatus()
397
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
398
399
400
401
402
403
404
405
    /* Update playing status */
    vlc_value_t val; val.i_int = 0;
    var_Get( p_input, "state", &val );
    if( i_old_playing_status != val.i_int )
    {
        i_old_playing_status = val.i_int;
        emit statusChanged( val.i_int );
    }
406
407
}

408
void InputManager::UpdateRate()
409
{
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
410
411
412
413
414
415
416
417
    /* Update Rate */
    int i_new_rate = var_GetInteger( p_input, "rate");
    if( i_new_rate != i_rate )
    {
        i_rate = i_new_rate;
        /* Update rate */
        emit rateChanged( i_rate );
    }
418
419
}

420
void InputManager::UpdateName()
421
{
422
423
    /* Update text, name and nowplaying */
    QString text;
424

425
    /* Try to get the Title, then the Name */
426
427
428
429
430
431
432
    char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
    if( EMPTY_STR( psz_name ) )
    {
        free( psz_name );
        psz_name = input_item_GetName( input_GetItem( p_input ) );
    }

433
    /* Try to get the nowplaying */
434
435
436
437
438
439
    char *psz_nowplaying =
        input_item_GetNowPlaying( input_GetItem( p_input ) );
    if( !EMPTY_STR( psz_nowplaying ) )
    {
        text.sprintf( "%s - %s", psz_nowplaying, psz_name );
    }
440
    else  /* Do it ourself */
441
442
    {
        char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
443

444
445
        if( !EMPTY_STR( psz_artist ) )
            text.sprintf( "%s - %s", psz_artist, psz_name );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
446
447
        else
            text.sprintf( "%s", psz_name );
448

449
        free( psz_artist );
450
    }
451
    /* Free everything */
452
453
454
    free( psz_name );
    free( psz_nowplaying );

455
456
457
458
459
460
461
462
463
    /* If we have Nothing */
    if( text.isEmpty() )
    {
        psz_name = input_item_GetURI( input_GetItem( p_input ) );
        text.sprintf( "%s", psz_name );
        text = text.remove( 0, text.lastIndexOf( DIR_SEP ) + 1 );
        free( psz_name );
    }

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
464
    if( oldName != text )
465
466
    {
        emit nameChanged( text );
467
        oldName = text;
468
    }
469
}
470

471
bool InputManager::hasAudio()
472
{
473
474
475
476
477
478
479
480
481
    if( hasInput() )
    {
        vlc_value_t val;
        var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
        return val.i_int > 0;
    }
    return false;
}

482
void InputManager::UpdateTeletext()
483
484
{
    if( hasInput() )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
485
        telexActivation( var_GetInteger( p_input, "teletext-es" ) >= 0 );
486
    else
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
487
        telexActivation( false );
488
489
}

490
491
492
493
void InputManager::UpdateVout()
{
    if( hasInput() )
    {
494
495
496
497
498
499
500
501
502
503
504
505
506
        /* Get current vout lists from input */
        int i_vout;
        vout_thread_t **pp_vout;
        if( input_Control( p_input, INPUT_GET_VOUTS, &pp_vout, &i_vout ) )
        {
            i_vout = 0;
            pp_vout = NULL;
        }

        /* */
        emit voutListChanged( pp_vout, i_vout );

        /* */
507
        bool b_old_video = b_video;
508
        b_video = i_vout > 0;
509
510
        if( !!b_old_video != !!b_video )
            emit voutChanged( b_video );
511
512
513
514
515
516
517
518
519
520
521
522

        /* Release the vout list */
        for( int i = 0; i < i_vout; i++ )
            vlc_object_release( (vlc_object_t*)pp_vout[i] );
        free( pp_vout );
    }
}
void InputManager::UpdateAout()
{
    if( hasInput() )
    {
        /* TODO */
523
524
    }
}
525
526
527
528
529
530
531
532
533
534
535
void InputManager::UpdateCaching()
{
    float f_newCache = var_GetFloat( p_input, "cache" );
    if( f_newCache != f_cache )
    {
        f_newCache = f_cache;
        /* Update rate */
        emit cachingChanged( f_cache );
    }
}

536
inline void InputManager::UpdateArt()
537
538
{
    /* Update Art meta */
539
    emit artChanged( input_GetItem( p_input ) );
540
541
}

542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
inline void InputManager::UpdateStats()
{
    emit statisticsUpdated( input_GetItem( p_input ) );
}

inline void InputManager::UpdateMeta()
{
    emit metaChanged( input_GetItem( p_input ) );
}

inline void InputManager::UpdateInfo()
{
    emit infoChanged( input_GetItem( p_input ) );
}

557
/* User update of the slider */
zorglub's avatar
zorglub committed
558
559
void InputManager::sliderUpdate( float new_pos )
{
560
561
    if( hasInput() )
        var_SetFloat( p_input, "position", new_pos );
zorglub's avatar
zorglub committed
562
}
563

564
/* User togglePlayPause */
565
566
567
void InputManager::togglePlayPause()
{
    vlc_value_t state;
568
569
570
571
572
573
574
    if( hasInput() )
    {
        var_Get( p_input, "state", &state );
        state.i_int = ( state.i_int != PLAYING_S ) ? PLAYING_S : PAUSE_S;
        var_Set( p_input, "state", state );
        emit statusChanged( state.i_int );
    }
575
576
}

577
578
579
580
void InputManager::sectionPrev()
{
    if( hasInput() )
    {
581
        int i_type = var_Type( p_input, "next-chapter" );
582
        vlc_value_t val; val.b_bool = true;
583
584
585
586
587
588
589
590
591
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "prev-chapter":"prev-title", val );
    }
}

void InputManager::sectionNext()
{
    if( hasInput() )
    {
592
        int i_type = var_Type( p_input, "next-chapter" );
593
        vlc_value_t val; val.b_bool = true;
594
595
596
597
598
599
600
601
        var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
                            "next-chapter":"next-title", val );
    }
}

void InputManager::sectionMenu()
{
    if( hasInput() )
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
602
    {
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
        vlc_value_t val, text;
        vlc_value_t root;

        if( var_Change( p_input, "title  0", VLC_VAR_GETLIST, &val, &text ) < 0 )
            return;

        /* XXX is it "Root" or "Title" we want here ?" (set 0 by default) */
        root.i_int = 0;
        for( int i = 0; i < val.p_list->i_count; i++ )
        {
            if( !strcmp( text.p_list->p_values[i].psz_string, "Title" ) )
                root.i_int = i;
        }
        var_Change( p_input, "title  0", VLC_VAR_FREELIST, &val, &text );

        var_Set( p_input, "title  0", root );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
619
    }
620
621
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
622
623
624
625
626
627
/*
 *  Teletext Functions
 */

/* Set a new Teletext Page */
void InputManager::telexSetPage( int page )
628
{
629
    if( hasInput() )
630
    {
631
632
633
634
        const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
        const int i_spu_es = var_GetInteger( p_input, "spu-es" );

        if( i_teletext_es >= 0 && i_teletext_es == i_spu_es )
635
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
636
            vlc_object_t *p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
637
638
639
640
641
                        "zvbi", FIND_ANYWHERE );
            if( p_vbi )
            {
                var_SetInteger( p_vbi, "vbi-page", page );
                vlc_object_release( p_vbi );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
642
                emit newTelexPageSet( page );
643
            }
644
645
        }
    }
646
647
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
/* Set the transparency on teletext */
void InputManager::telexSetTransparency( bool b_transparentTelextext )
{
    if( hasInput() )
    {
        vlc_object_t *p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
                    "zvbi", FIND_ANYWHERE );
        if( p_vbi )
        {
            var_SetBool( p_vbi, "vbi-opaque", b_transparentTelextext );
            vlc_object_release( p_vbi );
            emit teletextTransparencyActivated( b_transparentTelextext );
        }
    }
}

void InputManager::telexActivation( bool b_enabled )
665
{
666
667
    if( hasInput() )
    {
668
669
670
        const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
        const int i_spu_es = var_GetInteger( p_input, "spu-es" );

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
671
        /* Teletext is possible. Show the buttons */
672
        b_enabled = (i_teletext_es >= 0);
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
673
674
675
676
677
        emit teletextPossible( b_enabled );
        if( !b_enabled ) return;

        /* If Teletext is selected */
        if( i_teletext_es == i_spu_es )
678
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
679
680
681
682
            /* Activate the buttons */
            teletextActivated( true );

            /* Then, find the current page */
683
            int i_page = 100;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
684
685
            vlc_object_t *p_vbi = (vlc_object_t *)
                vlc_object_find_name( p_input, "zvbi", FIND_ANYWHERE );
686
687
688
689
            if( p_vbi )
            {
                i_page = var_GetInteger( p_vbi, "vbi-page" );
                vlc_object_release( p_vbi );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
690
                emit newTelexPageSet( i_page );
691
            }
692
693
        }
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
694
695
    else
        emit teletextPossible( b_enabled );
lukas.durfina's avatar
lukas.durfina committed
696
697
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
698
void InputManager::activateTeletext( bool b_enable )
lukas.durfina's avatar
lukas.durfina committed
699
{
700
701
702
703
704
    if( hasInput() )
    {
        const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
        if( i_teletext_es >= 0 )
        {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
705
            var_SetInteger( p_input, "spu-es", b_enable ? i_teletext_es : -1 );
706
707
        }
    }
708
709
}

710
711
712
713
714
715
716
717
718
void InputManager::reverse()
{
    if( hasInput() )
    {
        int i_rate = var_GetInteger( p_input, "rate" );
        var_SetInteger( p_input, "rate", -i_rate );
    }
}

zorglub's avatar
zorglub committed
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
void InputManager::slower()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-slower" );
}

void InputManager::faster()
{
    if( hasInput() )
        var_SetVoid( p_input, "rate-faster" );
}

void InputManager::normalRate()
{
    if( hasInput() )
        var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
}

737
738
739
740
741
742
void InputManager::setRate( int new_rate )
{
    if( hasInput() )
        var_SetInteger( p_input, "rate", new_rate );
}

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
void InputManager::setAtoB()
{
    if( !timeA )
    {
        timeA = var_GetTime( THEMIM->getInput(), "time"  );
    }
    else if( !timeB )
    {
        timeB = var_GetTime( THEMIM->getInput(), "time"  );
        var_SetTime( THEMIM->getInput(), "time" , timeA );
    }
    else
    {
        timeA = 0;
        timeB = 0;
    }
    emit AtoBchanged( (timeA != 0 ), (timeB != 0 ) );
}

/* Function called regularly when in an AtoB loop */
void InputManager::AtoBLoop( int i_time )
{
    if( timeB )
    {
        if( ( i_time >= (int)( timeB/1000000 ) )
            || ( i_time < (int)( timeA/1000000 ) ) )
            var_SetTime( THEMIM->getInput(), "time" , timeA );
    }
}

773
774
/**********************************************************************
 * MainInputManager implementation. Wrap an input manager and
775
776
 * take care of updating the main playlist input.
 * Used in the main playlist Dialog
777
778
779
 **********************************************************************/
MainInputManager * MainInputManager::instance = NULL;

780
781
MainInputManager::MainInputManager( intf_thread_t *_p_intf )
                 : QObject(NULL), p_intf( _p_intf )
782
783
784
{
    p_input = NULL;
    im = new InputManager( this, p_intf );
785

786
    var_AddCallback( THEPL, "item-change", ItemChanged, im );
787
788
    var_AddCallback( THEPL, "playlist-current", PLItemChanged, this );
    var_AddCallback( THEPL, "activity", PLItemChanged, this );
789

790
    var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
791

792
    /* Warn our embedded IM about input changes */
zorglub's avatar
zorglub committed
793
    CONNECT( this, inputChanged( input_thread_t * ),
794
             im, setInput( input_thread_t * ) );
795
796
797
798
799
800

    /* emit check if playlist has allready started playing */
    vlc_value_t val;
    var_Change( THEPL, "playlist-current", VLC_VAR_CHOICESCOUNT, &val, NULL );
    IMEvent *event = new IMEvent( ItemChanged_Type, val.i_int);
    QApplication::postEvent( this, static_cast<QEvent*>(event) );
801
802
}

zorglub's avatar
zorglub committed
803
804
MainInputManager::~MainInputManager()
{
805
806
    if( p_input )
    {
807
       emit inputChanged( NULL );
808
809
       var_DelCallback( p_input, "state", PLItemChanged, this );
       vlc_object_release( p_input );
810
    }
811

812
    var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
813
814

    var_DelCallback( THEPL, "activity", PLItemChanged, this );
815
    var_DelCallback( THEPL, "item-change", ItemChanged, im );
816

817
    var_DelCallback( THEPL, "playlist-current", PLItemChanged, this );
zorglub's avatar
zorglub committed
818
819
}

820
void MainInputManager::customEvent( QEvent *event )
821
{
822
    int type = event->type();
823
824
825
    if ( type != ItemChanged_Type && type != VolumeChanged_Type )
        return;

826
    // msg_Dbg( p_intf, "New MainIM Event of type: %i", type );
827
828
829
    if( type == VolumeChanged_Type )
    {
        emit volumeChanged();
830
        return;
831
    }
832

833
    /* Should be PLItemChanged Event */
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
834
    if( !p_intf->p_sys->b_isDialogProvider )
835
    {
836
        vlc_mutex_lock( &p_intf->change_lock );
837
        if( p_input && ( p_input->b_dead || !vlc_object_alive (p_input) ) )
838
        {
839
            emit inputChanged( NULL );
840
841
            var_DelCallback( p_input, "state", PLItemChanged, this );
            vlc_object_release( p_input );
842
            p_input = NULL;
843
844
            vlc_mutex_unlock( &p_intf->change_lock );
            return;
845
        }
846

847
848
        if( !p_input )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
849
850
            p_input = playlist_CurrentInput(THEPL);
            if( p_input )
851
            {
852
                var_AddCallback( p_input, "state", PLItemChanged, this );
853
854
855
856
857
                emit inputChanged( p_input );
            }
        }
        vlc_mutex_unlock( &p_intf->change_lock );
    }
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
858
859
    else
    {
860
        /* we are working as a dialogs provider */
dionoea's avatar
dionoea committed
861
        playlist_t *p_playlist = pl_Hold( p_intf );
862
        p_input = playlist_CurrentInput( p_playlist );
863
864
865
866
867
        if( p_input )
        {
            emit inputChanged( p_input );
            vlc_object_release( p_input );
        }
868
        pl_Release( p_intf );
869
870
    }
}
871

872
/* Playlist Control functions */
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
void MainInputManager::stop()
{
   playlist_Stop( THEPL );
}

void MainInputManager::next()
{
   playlist_Next( THEPL );
}

void MainInputManager::prev()
{
   playlist_Prev( THEPL );
}

888
889
void MainInputManager::togglePlayPause()
{
890
891
    /* No input, play */
    if( !p_input )
892
        playlist_Play( THEPL );
893
894
    else
        getIM()->togglePlayPause();
895
}
896

897
/* Static callbacks for MIM */
898
static int PLItemChanged( vlc_object_t *p_this, const char *psz_var,
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
899
900
                        vlc_value_t oldval, vlc_value_t newval, void *param )
{
901
    MainInputManager *mim = (MainInputManager*)param;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
902
903

    IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
904
    QApplication::postEvent( mim, static_cast<QEvent*>(event) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
905
906
907
908
909
910
    return VLC_SUCCESS;
}

static int VolumeChanged( vlc_object_t *p_this, const char *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *param )
{
911
    MainInputManager *mim = (MainInputManager*)param;
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
912
913

    IMEvent *event = new IMEvent( VolumeChanged_Type, newval.i_int );
914
    QApplication::postEvent( mim, static_cast<QEvent*>(event) );
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
915
916
    return VLC_SUCCESS;
}
Laurent Aimar's avatar
Laurent Aimar committed
917