]> git.sesse.net Git - vlc/blob - modules/gui/qt4/input_manager.cpp
Delete the "QPainter::begin: A paint device can only be painted by one painter at...
[vlc] / modules / gui / qt4 / input_manager.cpp
1 /*****************************************************************************
2  * input_manager.cpp : Manage an input and interact with its GUI elements
3  ****************************************************************************
4  * Copyright (C) 2006-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: ClĂ©ment Stenac <zorglub@videolan.org>
8  *          Ilkka Ollakka  <ileoo@videolan.org>
9  *          Jean-Baptiste <jb@videolan.org>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include "qt4.hpp"
30 #include "input_manager.hpp"
31 #include "dialogs_provider.hpp"
32
33 static int ChangeSPU( vlc_object_t *p_this, const char *var, vlc_value_t o,
34                       vlc_value_t n, void *param );
35
36 static int ChangeTeletext( vlc_object_t *p_this, const char *var, vlc_value_t o,
37                            vlc_value_t n, void *param );
38
39 static int ItemChanged( vlc_object_t *, const char *,
40                         vlc_value_t, vlc_value_t, void * );
41 static int PLItemChanged( vlc_object_t *, const char *,
42                         vlc_value_t, vlc_value_t, void * );
43 static int InterfaceChanged( vlc_object_t *, const char *,
44                             vlc_value_t, vlc_value_t, void * );
45 static int ItemStateChanged( vlc_object_t *, const char *,
46                         vlc_value_t, vlc_value_t, void * );
47 static int ItemRateChanged( vlc_object_t *, const char *,
48                         vlc_value_t, vlc_value_t, void * );
49 static int ItemTitleChanged( vlc_object_t *, const char *,
50                         vlc_value_t, vlc_value_t, void * );
51 static int VolumeChanged( vlc_object_t *, const char *,
52                         vlc_value_t, vlc_value_t, void * );
53
54 /**********************************************************************
55  * InputManager implementation
56  **********************************************************************
57  * The Input Manager can be the main one around the playlist
58  * But can also be used for VLM dialog or similar
59  **********************************************************************/
60
61 InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) :
62                            QObject( parent ), p_intf( _p_intf )
63 {
64     i_old_playing_status = END_S;
65     old_name     = "";
66     artUrl       = "";
67     p_input      = NULL;
68     i_rate       = 0;
69     i_input_id   = 0;
70     b_transparentTelextext = false;
71 }
72
73 InputManager::~InputManager()
74 {
75     delInput();
76 }
77
78 /* Define the Input used.
79    Add the callbacks on input
80    p_input is yield once here */
81 void InputManager::setInput( input_thread_t *_p_input )
82 {
83     delInput();
84     p_input = _p_input;
85     if( p_input && !( p_input->b_dead || !vlc_object_alive (p_input) ) )
86     {
87         vlc_object_yield( p_input );
88         emit statusChanged( PLAYING_S );
89         UpdateMeta();
90         UpdateArt();
91         UpdateSPU();
92         UpdateTeletext();
93         UpdateNavigation();
94         addCallbacks();
95         i_input_id = input_GetItem( p_input )->i_id;
96     }
97     else
98     {
99         p_input = NULL;
100         i_input_id = 0;
101         emit rateChanged( INPUT_RATE_DEFAULT );
102     }
103 }
104
105 /* delete Input if it ever existed.
106    Delete the callbacls on input
107    p_input is released once here */
108 void InputManager::delInput()
109 {
110     if( p_input )
111     {
112         delCallbacks();
113         i_old_playing_status = END_S;
114         i_input_id = 0;
115         old_name   = "";
116         artUrl     = "";
117         emit positionUpdated( 0.0, 0 ,0 );
118         emit statusChanged( END_S );
119         emit nameChanged( "" );
120         emit artChanged( "" );
121         emit rateChanged( INPUT_RATE_DEFAULT );
122         vlc_object_release( p_input );
123         p_input = NULL;
124         UpdateSPU();
125         UpdateTeletext();
126     }
127 }
128
129 /* Add the callbacks on Input. Self explanatory */
130 void InputManager::addCallbacks()
131 {
132     /* We don't care about:
133        - chapter
134        - programs
135        - audio-delay
136        - spu-delay
137        - bookmark
138        - position, time, length, because they are included in intf-change
139      */
140     /* src/input/input.c:1629 */
141     var_AddCallback( p_input, "state", ItemStateChanged, this );
142     /* src/input/es-out.c:552 */
143     var_AddCallback( p_input, "spu-es", ChangeSPU, this );
144     /* src/input/es-out.c: */
145     var_AddCallback( p_input, "teletext-es", ChangeTeletext, this );
146     /* src/input/input.c:1765 */
147     var_AddCallback( p_input, "rate-change", ItemRateChanged, this );
148     /* src/input/input.c:2003 */
149     var_AddCallback( p_input, "title", ItemTitleChanged, this );
150     /* src/input/input.c:734 for timers update*/
151     var_AddCallback( p_input, "intf-change", InterfaceChanged, this );
152 }
153
154 /* Delete the callbacks on Input. Self explanatory */
155 void InputManager::delCallbacks()
156 {
157     var_DelCallback( p_input, "spu-es", ChangeSPU, this );
158     var_DelCallback( p_input, "teletext-es", ChangeTeletext, this );
159     var_DelCallback( p_input, "state", ItemStateChanged, this );
160     var_DelCallback( p_input, "rate-change", ItemRateChanged, this );
161     var_DelCallback( p_input, "title", ItemTitleChanged, this );
162     var_DelCallback( p_input, "intf-change", InterfaceChanged, this );
163 }
164
165 /* Convert the event from the callbacks in actions */
166 void InputManager::customEvent( QEvent *event )
167 {
168     int type = event->type();
169     IMEvent *ple = static_cast<IMEvent *>(event);
170
171     if ( type != PositionUpdate_Type &&
172          type != ItemChanged_Type &&
173          type != ItemRateChanged_Type &&
174          type != ItemTitleChanged_Type &&
175          type != ItemSpuChanged_Type &&
176          type != ItemTeletextChanged_Type &&
177          type != ItemStateChanged_Type )
178         return;
179
180     if( !hasInput() ) return;
181
182     if( ( type != PositionUpdate_Type  &&
183           type != ItemRateChanged_Type &&
184           type != ItemSpuChanged_Type &&
185           type != ItemTeletextChanged_Type &&
186           type != ItemStateChanged_Type
187         )
188         && ( i_input_id != ple->i_id ) )
189         return;
190
191     if( type != PositionUpdate_Type )
192         msg_Dbg( p_intf, "New Event: type %i", type );
193
194     /* Actions */
195     switch( type )
196     {
197     case PositionUpdate_Type:
198         UpdatePosition();
199         break;
200     case ItemChanged_Type:
201         UpdateMeta();
202         UpdateStatus();
203         UpdateArt();
204         break;
205     case ItemStateChanged_Type:
206         UpdateStatus();
207         UpdateNavigation();
208         UpdateMeta();
209         break;
210     case ItemTitleChanged_Type:
211         UpdateNavigation();
212         UpdateMeta();
213         break;
214     case ItemRateChanged_Type:
215         UpdateRate();
216         break;
217     case ItemSpuChanged_Type:
218         UpdateSPU();
219         break;
220     case ItemTeletextChanged_Type:
221         UpdateTeletext();
222         break;
223     }
224 }
225
226 void InputManager::UpdatePosition()
227 {
228     /* Update position */
229     int i_length, i_time; /* Int is enough, since we store seconds */
230     float f_pos;
231     i_length = var_GetTime(  p_input , "length" ) / 1000000;
232     i_time = var_GetTime(  p_input , "time") / 1000000;
233     f_pos = var_GetFloat(  p_input , "position" );
234     emit positionUpdated( f_pos, i_time, i_length );
235 }
236
237 void InputManager::UpdateNavigation()
238 {
239     /* Update navigation status */
240     vlc_value_t val; val.i_int = 0;
241     var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
242     if( val.i_int > 0 )
243     {
244         val.i_int = 0;
245         var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
246         emit navigationChanged( (val.i_int > 0) ? 1 : 2 );
247     }
248     else
249     {
250         emit navigationChanged( 0 );
251     }
252 }
253
254 void InputManager::UpdateStatus()
255 {
256     /* Update playing status */
257     vlc_value_t val; val.i_int = 0;
258     var_Get( p_input, "state", &val );
259     if( i_old_playing_status != val.i_int )
260     {
261         i_old_playing_status = val.i_int;
262         emit statusChanged( val.i_int );
263     }
264 }
265
266 void InputManager::UpdateRate()
267 {
268     /* Update Rate */
269     int i_new_rate = var_GetInteger( p_input, "rate");
270     if( i_new_rate != i_rate )
271     {
272         i_rate = i_new_rate;
273         /* Update rate */
274         emit rateChanged( i_rate );
275     }
276 }
277
278 void InputManager::UpdateMeta()
279 {
280     /* Update text, name and nowplaying */
281     QString text;
282
283     char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
284     if( EMPTY_STR( psz_name ) )
285     {
286         free( psz_name );
287         psz_name = input_item_GetName( input_GetItem( p_input ) );
288     }
289
290     char *psz_nowplaying =
291         input_item_GetNowPlaying( input_GetItem( p_input ) );
292     if( !EMPTY_STR( psz_nowplaying ) )
293     {
294         text.sprintf( "%s - %s", psz_nowplaying, psz_name );
295     }
296     else
297     {
298         char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
299         if( !EMPTY_STR( psz_artist ) )
300         {
301             text.sprintf( "%s - %s", psz_artist, psz_name );
302         }
303         else
304         {
305             text.sprintf( "%s", psz_name );
306         }
307         free( psz_artist );
308     }
309     free( psz_name );
310     free( psz_nowplaying );
311
312     if( old_name != text )
313     {
314         emit nameChanged( text );
315         old_name=text;
316     }
317 }
318
319 bool InputManager::hasAudio()
320 {
321     if( hasInput() )
322     {
323         vlc_value_t val;
324         var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
325         return val.i_int > 0;
326     }
327     return false;
328 }
329
330 bool InputManager::hasVideo()
331 {
332     if( hasInput() )
333     {
334         vlc_value_t val;
335         var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
336         return val.i_int > 0;
337     }
338     return false;
339
340 }
341
342 void InputManager::UpdateSPU()
343 {
344     UpdateTeletext();
345 }
346
347 void InputManager::UpdateTeletext()
348 {
349     if( hasInput() )
350         telexToggle( var_GetInteger( p_input, "teletext-es" ) >= 0 );
351     else
352         telexToggle( false );
353 }
354
355
356
357 void InputManager::UpdateArt()
358 {
359     /* Update Art meta */
360     QString url;
361     char *psz_art = input_item_GetArtURL( input_GetItem( p_input ) );
362     url.sprintf("%s", psz_art );
363     free( psz_art );
364     if( artUrl != url )
365     {
366         artUrl = url.replace( "file://",QString("" ) );
367         /* Taglib seems to define a attachment://, It won't work yet */
368         artUrl = url.replace( "attachment://",QString("" ) );
369         emit artChanged( artUrl );
370         msg_Dbg( p_intf, "Art:  %s", qtu( artUrl ) );
371     }
372 }
373
374 /* User update of the slider */
375 void InputManager::sliderUpdate( float new_pos )
376 {
377     if( hasInput() )
378         var_SetFloat( p_input, "position", new_pos );
379 }
380
381 /* User togglePlayPause */
382 void InputManager::togglePlayPause()
383 {
384     vlc_value_t state;
385     var_Get( p_input, "state", &state );
386     state.i_int = ( state.i_int != PLAYING_S ) ? PLAYING_S : PAUSE_S;
387     var_Set( p_input, "state", state );
388     emit statusChanged( state.i_int );
389 }
390
391 void InputManager::sectionPrev()
392 {
393     if( hasInput() )
394     {
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                             "prev-chapter":"prev-title", val );
399     }
400 }
401
402 void InputManager::sectionNext()
403 {
404     if( hasInput() )
405     {
406         int i_type = var_Type( p_input, "next-chapter" );
407         vlc_value_t val; val.b_bool = true;
408         var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
409                             "next-chapter":"next-title", val );
410     }
411 }
412
413 void InputManager::sectionMenu()
414 {
415     if( hasInput() )
416     {
417         vlc_value_t val; val.i_int = 2;
418         var_Set( p_input, "title  0", val );
419     }
420 }
421
422 void InputManager::telexGotoPage( int page )
423 {
424     if( hasInput() )
425     {
426         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
427         const int i_spu_es = var_GetInteger( p_input, "spu-es" );
428
429         if( i_teletext_es >= 0 && i_teletext_es == i_spu_es )
430         {
431             vlc_object_t *p_vbi;
432             p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
433                         "zvbi", FIND_ANYWHERE );
434             if( p_vbi )
435             {
436                 var_SetInteger( p_vbi, "vbi-page", page );
437                 vlc_object_release( p_vbi );
438             }
439         }
440     }
441     emit setNewTelexPage( page );
442 }
443
444 void InputManager::telexToggle( bool b_enabled )
445 {
446     if( hasInput() )
447     {
448         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
449         const int i_spu_es = var_GetInteger( p_input, "spu-es" );
450
451         b_enabled = (i_teletext_es >= 0);
452         emit teletextEnabled( b_enabled );
453         if( b_enabled && (i_teletext_es == i_spu_es) )
454         {
455             vlc_object_t *p_vbi;
456             int i_page = 100;
457             p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
458                         "zvbi", FIND_ANYWHERE );
459             if( p_vbi )
460             {
461                 i_page = var_GetInteger( p_vbi, "vbi-page" );
462                 vlc_object_release( p_vbi );
463                 i_page = b_enabled ? i_page : 0;
464                 telexGotoPage( i_page );
465             }
466         }
467     }
468     else emit teletextEnabled( b_enabled );
469 }
470
471 void InputManager::telexToggleButtons()
472 {
473     if( hasInput() )
474     {
475         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
476         if( i_teletext_es >= 0 )
477         {
478             const int i_spu_es = var_GetInteger( p_input, "spu-es" );
479
480             if( i_teletext_es == i_spu_es )
481                 var_SetInteger( p_input, "spu-es", -1 );
482             else
483                 var_SetInteger( p_input, "spu-es", i_teletext_es );
484
485             emit toggleTelexButtons();
486         }
487     }
488 }
489
490 void InputManager::telexSetTransparency()
491 {
492     if( hasInput() )
493     {
494         vlc_object_t *p_vbi;
495         p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
496                     "zvbi", FIND_ANYWHERE );
497         if( p_vbi )
498         {
499             var_SetBool( p_vbi, "vbi-opaque", b_transparentTelextext );
500             b_transparentTelextext = !b_transparentTelextext;
501             vlc_object_release( p_vbi );
502         }
503     }
504     emit toggleTelexTransparency();
505 }
506
507 void InputManager::slower()
508 {
509     if( hasInput() )
510         var_SetVoid( p_input, "rate-slower" );
511 }
512
513 void InputManager::faster()
514 {
515     if( hasInput() )
516         var_SetVoid( p_input, "rate-faster" );
517 }
518
519 void InputManager::normalRate()
520 {
521     if( hasInput() )
522         var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
523 }
524
525 void InputManager::setRate( int new_rate )
526 {
527     if( hasInput() )
528         var_SetInteger( p_input, "rate", new_rate );
529 }
530
531 /**********************************************************************
532  * MainInputManager implementation. Wrap an input manager and
533  * take care of updating the main playlist input.
534  * Used in the main playlist Dialog
535  **********************************************************************/
536 MainInputManager * MainInputManager::instance = NULL;
537
538 MainInputManager::MainInputManager( intf_thread_t *_p_intf )
539                  : QObject(NULL), p_intf( _p_intf )
540 {
541     p_input = NULL;
542     im = new InputManager( this, p_intf );
543
544 //    var_AddCallback( THEPL, "item-change", PLItemChanged, this );
545     var_AddCallback( THEPL, "item-change", ItemChanged, im );
546     var_AddCallback( THEPL, "playlist-current", PLItemChanged, this );
547     var_AddCallback( THEPL, "activity", PLItemChanged, this );
548
549     var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
550
551     // No necessary, I think TODO REMOVE ME at the end
552     //var_AddCallback( THEPL, "intf-change", ItemChanged, im );
553
554     /* Warn our embedded IM about input changes */
555     CONNECT( this, inputChanged( input_thread_t * ),
556              im, setInput( input_thread_t * ) );
557
558     /* emit check if playlist has allready started playing */
559     vlc_value_t val;
560     var_Change( THEPL, "playlist-current", VLC_VAR_CHOICESCOUNT, &val, NULL );
561     IMEvent *event = new IMEvent( ItemChanged_Type, val.i_int);
562     QApplication::postEvent( this, static_cast<QEvent*>(event) );
563
564 }
565
566 MainInputManager::~MainInputManager()
567 {
568     if( p_input )
569     {
570        var_DelCallback( p_input, "state", PLItemChanged, this );
571        vlc_object_release( p_input );
572        emit inputChanged( NULL );
573     }
574
575     var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
576
577     var_DelCallback( THEPL, "activity", PLItemChanged, this );
578     var_DelCallback( THEPL, "item-change", ItemChanged, im );
579 //    var_DelCallback( THEPL, "item-change", PLItemChanged, this );
580
581     var_DelCallback( THEPL, "playlist-current", PLItemChanged, this );
582 }
583
584 void MainInputManager::customEvent( QEvent *event )
585 {
586     int type = event->type();
587     if ( type != ItemChanged_Type && type != VolumeChanged_Type )
588         return;
589
590     // msg_Dbg( p_intf, "New MainIM Event of type: %i", type );
591     if( type == VolumeChanged_Type )
592     {
593         emit volumeChanged();
594         return;
595     }
596
597     /* Should be PLItemChanged Event */
598     if( VLC_OBJECT_INTF == p_intf->i_object_type ) /* FIXME: don't use object type */
599     {
600         vlc_mutex_lock( &p_intf->change_lock );
601         if( p_input && ( p_input->b_dead || !vlc_object_alive (p_input) ) )
602         {
603             var_DelCallback( p_input, "state", PLItemChanged, this );
604             vlc_object_release( p_input );
605             emit inputChanged( NULL );
606             p_input = NULL;
607             vlc_mutex_unlock( &p_intf->change_lock );
608             return;
609         }
610
611         if( !p_input )
612         {
613             QPL_LOCK;
614             p_input = THEPL->p_input;
615             if( p_input && !( !vlc_object_alive (p_input) || p_input->b_dead) )
616             {
617                 vlc_object_yield( p_input );
618                 var_AddCallback( p_input, "state", PLItemChanged, this );
619                 emit inputChanged( p_input );
620             }
621             else
622                 p_input = NULL;
623             QPL_UNLOCK;
624         }
625         vlc_mutex_unlock( &p_intf->change_lock );
626     }
627     else
628     {
629         /* we are working as a dialogs provider */
630         playlist_t *p_playlist = pl_Yield( p_intf );
631         p_input = playlist_CurrentInput( p_playlist );
632         emit inputChanged( p_input );
633         vlc_object_release( p_input );
634         pl_Release( p_intf );
635     }
636 }
637
638 /* Playlist Control functions */
639 void MainInputManager::stop()
640 {
641    playlist_Stop( THEPL );
642 }
643
644 void MainInputManager::next()
645 {
646    playlist_Next( THEPL );
647 }
648
649 void MainInputManager::prev()
650 {
651    playlist_Prev( THEPL );
652 }
653
654 void MainInputManager::togglePlayPause()
655 {
656     if( p_input == NULL )
657     {
658         playlist_Play( THEPL );
659         return;
660     }
661     getIM()->togglePlayPause();
662 }
663
664 bool MainInputManager::teletextState()
665 {
666     im = getIM();
667     if( im->hasInput() )
668     {
669         const int i_teletext_es = var_GetInteger( getInput(), "teletext-es" );
670         const int i_spu_es = var_GetInteger( getInput(), "spu-es" );
671
672         return i_teletext_es >= 0 && i_teletext_es == i_spu_es;
673     }
674     return false;
675 }
676
677 /* Static callbacks */
678
679 /* IM */
680 static int InterfaceChanged( vlc_object_t *p_this, const char *psz_var,
681                            vlc_value_t oldval, vlc_value_t newval, void *param )
682 {
683     static int counter = 0;
684     InputManager *im = (InputManager*)param;
685
686     counter = ++counter % 4;
687     if(!counter)
688         return VLC_SUCCESS;
689     IMEvent *event = new IMEvent( PositionUpdate_Type, 0 );
690     QApplication::postEvent( im, static_cast<QEvent*>(event) );
691     return VLC_SUCCESS;
692 }
693
694 static int ItemStateChanged( vlc_object_t *p_this, const char *psz_var,
695                            vlc_value_t oldval, vlc_value_t newval, void *param )
696 {
697     InputManager *im = (InputManager*)param;
698
699     IMEvent *event = new IMEvent( ItemStateChanged_Type, 0 );
700     QApplication::postEvent( im, static_cast<QEvent*>(event) );
701     return VLC_SUCCESS;
702 }
703
704 static int ItemRateChanged( vlc_object_t *p_this, const char *psz_var,
705                            vlc_value_t oldval, vlc_value_t newval, void *param )
706 {
707     InputManager *im = (InputManager*)param;
708
709     IMEvent *event = new IMEvent( ItemRateChanged_Type, 0 );
710     QApplication::postEvent( im, static_cast<QEvent*>(event) );
711     return VLC_SUCCESS;
712 }
713
714 static int ItemTitleChanged( vlc_object_t *p_this, const char *psz_var,
715                            vlc_value_t oldval, vlc_value_t newval, void *param )
716 {
717     InputManager *im = (InputManager*)param;
718
719     IMEvent *event = new IMEvent( ItemTitleChanged_Type, 0 );
720     QApplication::postEvent( im, static_cast<QEvent*>(event) );
721     return VLC_SUCCESS;
722 }
723
724 static int ItemChanged( vlc_object_t *p_this, const char *psz_var,
725                         vlc_value_t oldval, vlc_value_t newval, void *param )
726 {
727     InputManager *im = (InputManager*)param;
728
729     IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
730     QApplication::postEvent( im, static_cast<QEvent*>(event) );
731     return VLC_SUCCESS;
732 }
733
734 static int ChangeSPU( vlc_object_t *p_this, const char *var, vlc_value_t o,
735                         vlc_value_t n, void *param )
736 {
737     InputManager *im = (InputManager*)param;
738     IMEvent *event = new IMEvent( ItemSpuChanged_Type, 0 );
739     QApplication::postEvent( im, static_cast<QEvent*>(event) );
740     return VLC_SUCCESS;
741 }
742
743 static int ChangeTeletext( vlc_object_t *p_this, const char *var, vlc_value_t o,
744                            vlc_value_t n, void *param )
745 {
746
747     InputManager *im = (InputManager*)param;
748     IMEvent *event = new IMEvent( ItemTeletextChanged_Type, 0 );
749     QApplication::postEvent( im, static_cast<QEvent*>(event) );
750     return VLC_SUCCESS;
751 }
752
753 /* MIM */
754 static int PLItemChanged( vlc_object_t *p_this, const char *psz_var,
755                         vlc_value_t oldval, vlc_value_t newval, void *param )
756 {
757     MainInputManager *mim = (MainInputManager*)param;
758
759     IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
760     QApplication::postEvent( mim, static_cast<QEvent*>(event) );
761     return VLC_SUCCESS;
762 }
763
764 static int VolumeChanged( vlc_object_t *p_this, const char *psz_var,
765                         vlc_value_t oldval, vlc_value_t newval, void *param )
766 {
767     MainInputManager *mim = (MainInputManager*)param;
768
769     IMEvent *event = new IMEvent( VolumeChanged_Type, newval.i_int );
770     QApplication::postEvent( mim, static_cast<QEvent*>(event) );
771     return VLC_SUCCESS;
772 }
773