1 /*****************************************************************************
2 * input_manager.cpp : Manage an input and interact with its GUI elements
3 ****************************************************************************
4 * Copyright (C) 2006-2008 the VideoLAN team
7 * Authors: Clément Stenac <zorglub@videolan.org>
8 * Ilkka Ollakka <ileoo@videolan.org>
9 * Jean-Baptiste <jb@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
30 #include "input_manager.hpp"
31 #include "dialogs_provider.hpp"
33 static int ChangeSPU( vlc_object_t *p_this, const char *var, vlc_value_t o,
34 vlc_value_t n, void *param );
35 static int ItemChanged( vlc_object_t *, const char *,
36 vlc_value_t, vlc_value_t, void * );
37 static int PLItemChanged( vlc_object_t *, const char *,
38 vlc_value_t, vlc_value_t, void * );
39 static int InterfaceChanged( vlc_object_t *, const char *,
40 vlc_value_t, vlc_value_t, void * );
41 static int ItemStateChanged( vlc_object_t *, const char *,
42 vlc_value_t, vlc_value_t, void * );
43 static int ItemRateChanged( vlc_object_t *, const char *,
44 vlc_value_t, vlc_value_t, void * );
45 static int ItemTitleChanged( vlc_object_t *, const char *,
46 vlc_value_t, vlc_value_t, void * );
47 static int VolumeChanged( vlc_object_t *, const char *,
48 vlc_value_t, vlc_value_t, void * );
50 /**********************************************************************
51 * InputManager implementation
52 **********************************************************************
53 * The Input Manager can be the main one around the playlist
54 * But can also be used for VLM dialog or similar
55 **********************************************************************/
57 InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) :
58 QObject( parent ), p_intf( _p_intf )
60 i_old_playing_status = END_S;
68 InputManager::~InputManager()
73 /* Define the Input used.
74 Add the callbacks on input
75 p_input is yield once here */
76 void InputManager::setInput( input_thread_t *_p_input )
80 if( p_input && !( p_input->b_dead || p_input->b_die ) )
82 vlc_object_yield( p_input );
83 emit statusChanged( PLAYING_S );
89 i_input_id = input_GetItem( p_input )->i_id;
95 emit rateChanged( INPUT_RATE_DEFAULT );
100 /* delete Input if it ever existed.
101 Delete the callbacls on input
102 p_input is released once here */
103 void InputManager::delInput()
108 i_old_playing_status = END_S;
112 emit positionUpdated( 0.0, 0 ,0 );
113 emit statusChanged( END_S );
114 emit nameChanged( "" );
115 emit artChanged( "" );
116 emit rateChanged( INPUT_RATE_DEFAULT );
117 vlc_object_release( p_input );
123 /* Add the callbacks on Input. Self explanatory */
124 void InputManager::addCallbacks()
126 /* We don't care about:
132 - position, time, length, because they are included in intf-change
134 /* src/input/input.c:1629 */
135 var_AddCallback( p_input, "state", ItemStateChanged, this );
136 /* src/input/es-out.c:552 */
137 var_AddCallback( p_input, "spu-es", ChangeSPU, this );
138 /* src/input/input.c:1765 */
139 var_AddCallback( p_input, "rate-change", ItemRateChanged, this );
140 /* src/input/input.c:2003 */
141 var_AddCallback( p_input, "title", ItemTitleChanged, this );
142 /* src/input/input.c:734 for timers update*/
143 var_AddCallback( p_input, "intf-change", InterfaceChanged, this );
146 /* Delete the callbacks on Input. Self explanatory */
147 void InputManager::delCallbacks()
149 var_DelCallback( p_input, "spu-es", ChangeSPU, this );
150 var_DelCallback( p_input, "state", ItemStateChanged, this );
151 var_DelCallback( p_input, "rate-change", ItemRateChanged, this );
152 var_DelCallback( p_input, "title", ItemTitleChanged, this );
153 var_DelCallback( p_input, "intf-change", InterfaceChanged, this );
156 /* Convert the event from the callbacks in actions */
157 void InputManager::customEvent( QEvent *event )
159 int type = event->type();
160 IMEvent *ple = static_cast<IMEvent *>(event);
162 if ( type != PositionUpdate_Type &&
163 type != ItemChanged_Type &&
164 type != ItemRateChanged_Type &&
165 type != ItemTitleChanged_Type &&
166 type != ItemSpuChanged_Type &&
167 type != ItemStateChanged_Type )
170 if( !hasInput() ) return;
172 if( ( type != PositionUpdate_Type &&
173 type != ItemRateChanged_Type &&
174 type != ItemSpuChanged_Type &&
175 type != ItemStateChanged_Type
177 && ( i_input_id != ple->i_id ) )
180 if( type != PositionUpdate_Type )
181 msg_Dbg( p_intf, "New Event: type %i", type );
186 case PositionUpdate_Type:
189 case ItemChanged_Type:
195 case ItemRateChanged_Type:
198 case ItemTitleChanged_Type:
202 case ItemStateChanged_Type:
204 case ItemSpuChanged_Type:
210 void InputManager::UpdatePosition()
212 /* Update position */
213 int i_length, i_time; /* Int is enough, since we store seconds */
215 i_length = var_GetTime( p_input , "length" ) / 1000000;
216 i_time = var_GetTime( p_input , "time") / 1000000;
217 f_pos = var_GetFloat( p_input , "position" );
218 emit positionUpdated( f_pos, i_time, i_length );
221 void InputManager::UpdateNavigation()
223 /* Update navigation status */
224 vlc_value_t val; val.i_int = 0;
225 var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
229 var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
230 emit navigationChanged( (val.i_int > 0) ? 1 : 2 );
234 emit navigationChanged( 0 );
238 void InputManager::UpdateStatus()
240 /* Update playing status */
241 vlc_value_t val; val.i_int = 0;
242 var_Get( p_input, "state", &val );
243 if( i_old_playing_status != val.i_int )
245 i_old_playing_status = val.i_int;
246 emit statusChanged( val.i_int );
250 void InputManager::UpdateRate()
253 int i_new_rate = var_GetInteger( p_input, "rate");
254 if( i_new_rate != i_rate )
258 emit rateChanged( i_rate );
262 void InputManager::UpdateMeta()
264 /* Update text, name and nowplaying */
267 char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
268 if( EMPTY_STR( psz_name ) )
271 psz_name = input_item_GetName( input_GetItem( p_input ) );
274 char *psz_nowplaying =
275 input_item_GetNowPlaying( input_GetItem( p_input ) );
276 if( !EMPTY_STR( psz_nowplaying ) )
278 text.sprintf( "%s - %s", psz_nowplaying, psz_name );
282 char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
283 if( !EMPTY_STR( psz_artist ) )
285 text.sprintf( "%s - %s", psz_artist, psz_name );
289 text.sprintf( "%s", psz_name );
294 free( psz_nowplaying );
296 if( old_name != text )
298 emit nameChanged( text );
303 bool InputManager::hasAudio()
308 var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
309 return val.i_int > 0;
314 bool InputManager::hasVideo()
319 var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
320 return val.i_int > 0;
326 void InputManager::UpdateSPU()
332 var_Change( p_input, "spu-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
334 /* Update teletext status*/
335 emit teletextEnabled( val.i_int > 0 );/* FIXME */
340 emit teletextEnabled( false );
341 telexToggle( false );
346 void InputManager::UpdateArt()
348 /* Update Art meta */
350 char *psz_art = input_item_GetArtURL( input_GetItem( p_input ) );
351 url.sprintf("%s", psz_art );
355 artUrl = url.replace( "file://",QString("" ) );
356 /* Taglib seems to define a attachment://, It won't work yet */
357 artUrl = url.replace( "attachment://",QString("" ) );
358 emit artChanged( artUrl );
359 msg_Dbg( p_intf, "Art: %s", qtu( artUrl ) );
363 /* User update of the slider */
364 void InputManager::sliderUpdate( float new_pos )
367 var_SetFloat( p_input, "position", new_pos );
370 /* User togglePlayPause */
371 void InputManager::togglePlayPause()
374 var_Get( p_input, "state", &state );
375 state.i_int = ( state.i_int != PLAYING_S ) ? PLAYING_S : PAUSE_S;
376 var_Set( p_input, "state", state );
377 emit statusChanged( state.i_int );
380 void InputManager::sectionPrev()
384 int i_type = var_Type( p_input, "next-chapter" );
385 vlc_value_t val; val.b_bool = true;
386 var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
387 "prev-chapter":"prev-title", val );
391 void InputManager::sectionNext()
395 int i_type = var_Type( p_input, "next-chapter" );
396 vlc_value_t val; val.b_bool = true;
397 var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
398 "next-chapter":"next-title", val );
402 void InputManager::sectionMenu()
406 vlc_value_t val; val.i_int = 2;
407 var_Set( p_input, "title 0", val );
412 void InputManager::telexGotoPage( int page )
417 p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
418 "zvbi", FIND_ANYWHERE );
421 var_SetInteger( p_vbi, "vbi-page", page );
422 vlc_object_release( p_vbi );
427 void InputManager::telexToggle( bool b_enabled )
434 p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
435 "zvbi", FIND_ANYWHERE );
438 i_page = var_GetInteger( p_vbi, "vbi-page" );
439 vlc_object_release( p_vbi );
442 i_page = b_enabled ? i_page : 0;
443 telexGotoPage( i_page );
446 void InputManager::telexSetTransparency( bool b_transp )
451 p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
452 "zvbi", FIND_ANYWHERE );
455 var_SetBool( p_input->p_libvlc, "vbi-opaque", b_transp );
456 vlc_object_release( p_vbi );
462 void InputManager::slower()
465 var_SetVoid( p_input, "rate-slower" );
468 void InputManager::faster()
471 var_SetVoid( p_input, "rate-faster" );
474 void InputManager::normalRate()
477 var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
480 void InputManager::setRate( int new_rate )
483 var_SetInteger( p_input, "rate", new_rate );
486 /**********************************************************************
487 * MainInputManager implementation. Wrap an input manager and
488 * take care of updating the main playlist input.
489 * Used in the main playlist Dialog
490 **********************************************************************/
491 MainInputManager * MainInputManager::instance = NULL;
493 MainInputManager::MainInputManager( intf_thread_t *_p_intf )
494 : QObject(NULL), p_intf( _p_intf )
497 im = new InputManager( this, p_intf );
499 // var_AddCallback( THEPL, "item-change", PLItemChanged, this );
500 var_AddCallback( THEPL, "item-change", ItemChanged, im );
501 var_AddCallback( THEPL, "playlist-current", PLItemChanged, this );
502 var_AddCallback( THEPL, "activity", PLItemChanged, this );
504 var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
506 // No necessary, I think TODO REMOVE ME at the end
507 //var_AddCallback( THEPL, "intf-change", ItemChanged, im );
509 /* Warn our embedded IM about input changes */
510 CONNECT( this, inputChanged( input_thread_t * ),
511 im, setInput( input_thread_t * ) );
514 MainInputManager::~MainInputManager()
518 var_DelCallback( p_input, "state", PLItemChanged, this );
519 vlc_object_release( p_input );
520 emit inputChanged( NULL );
523 var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
525 var_DelCallback( THEPL, "activity", PLItemChanged, this );
526 var_DelCallback( THEPL, "item-change", ItemChanged, im );
527 // var_DelCallback( THEPL, "item-change", PLItemChanged, this );
529 var_DelCallback( THEPL, "playlist-current", PLItemChanged, this );
532 void MainInputManager::customEvent( QEvent *event )
534 int type = event->type();
535 if ( type != ItemChanged_Type && type != VolumeChanged_Type )
538 // msg_Dbg( p_intf, "New MainIM Event of type: %i", type );
539 if( type == VolumeChanged_Type )
541 emit volumeChanged();
545 /* Should be PLItemChanged Event */
546 if( VLC_OBJECT_INTF == p_intf->i_object_type ) /* FIXME: don't use object type */
548 vlc_mutex_lock( &p_intf->change_lock );
549 if( p_input && ( p_input->b_dead || p_input->b_die ) )
551 var_DelCallback( p_input, "state", PLItemChanged, this );
552 vlc_object_release( p_input );
553 emit inputChanged( NULL );
555 vlc_mutex_unlock( &p_intf->change_lock );
562 p_input = THEPL->p_input;
563 if( p_input && !( p_input->b_die || p_input->b_dead) )
565 vlc_object_yield( p_input );
566 var_AddCallback( p_input, "state", PLItemChanged, this );
567 emit inputChanged( p_input );
573 vlc_mutex_unlock( &p_intf->change_lock );
577 /* we are working as a dialogs provider */
578 playlist_t *p_playlist = pl_Yield( p_intf );
579 p_input = p_playlist->p_input;
580 emit inputChanged( p_input );
584 /* Playlist Control functions */
585 void MainInputManager::stop()
587 playlist_Stop( THEPL );
590 void MainInputManager::next()
592 playlist_Next( THEPL );
595 void MainInputManager::prev()
597 playlist_Prev( THEPL );
600 void MainInputManager::togglePlayPause()
602 if( p_input == NULL )
604 playlist_Play( THEPL );
607 getIM()->togglePlayPause();
610 /* Static callbacks */
613 static int InterfaceChanged( vlc_object_t *p_this, const char *psz_var,
614 vlc_value_t oldval, vlc_value_t newval, void *param )
616 static int counter = 0;
617 InputManager *im = (InputManager*)param;
619 counter = ++counter % 4;
622 IMEvent *event = new IMEvent( PositionUpdate_Type, 0 );
623 QApplication::postEvent( im, static_cast<QEvent*>(event) );
627 static int ItemStateChanged( vlc_object_t *p_this, const char *psz_var,
628 vlc_value_t oldval, vlc_value_t newval, void *param )
630 InputManager *im = (InputManager*)param;
632 IMEvent *event = new IMEvent( ItemStateChanged_Type, 0 );
633 QApplication::postEvent( im, static_cast<QEvent*>(event) );
637 static int ItemRateChanged( vlc_object_t *p_this, const char *psz_var,
638 vlc_value_t oldval, vlc_value_t newval, void *param )
640 InputManager *im = (InputManager*)param;
642 IMEvent *event = new IMEvent( ItemRateChanged_Type, 0 );
643 QApplication::postEvent( im, static_cast<QEvent*>(event) );
647 static int ItemTitleChanged( vlc_object_t *p_this, const char *psz_var,
648 vlc_value_t oldval, vlc_value_t newval, void *param )
650 InputManager *im = (InputManager*)param;
652 IMEvent *event = new IMEvent( ItemTitleChanged_Type, 0 );
653 QApplication::postEvent( im, static_cast<QEvent*>(event) );
657 static int ItemChanged( vlc_object_t *p_this, const char *psz_var,
658 vlc_value_t oldval, vlc_value_t newval, void *param )
660 InputManager *im = (InputManager*)param;
662 IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
663 QApplication::postEvent( im, static_cast<QEvent*>(event) );
667 static int ChangeSPU( vlc_object_t *p_this, const char *var, vlc_value_t o,
668 vlc_value_t n, void *param )
670 InputManager *im = (InputManager*)param;
671 IMEvent *event = new IMEvent( ItemSpuChanged_Type, 0 );
672 QApplication::postEvent( im, static_cast<QEvent*>(event) );
678 static int PLItemChanged( vlc_object_t *p_this, const char *psz_var,
679 vlc_value_t oldval, vlc_value_t newval, void *param )
681 MainInputManager *mim = (MainInputManager*)param;
683 IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
684 QApplication::postEvent( mim, static_cast<QEvent*>(event) );
688 static int VolumeChanged( vlc_object_t *p_this, const char *psz_var,
689 vlc_value_t oldval, vlc_value_t newval, void *param )
691 MainInputManager *mim = (MainInputManager*)param;
693 IMEvent *event = new IMEvent( VolumeChanged_Type, newval.i_int );
694 QApplication::postEvent( mim, static_cast<QEvent*>(event) );