Fix a segfault in Skins2 interface.
[vlc.git] / 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     /* emit UpdateStatus so that main_interface updates controls 
145      * if there is new videotracks (mpeg-ts)*/
146     var_AddCallback( p_input, "video-es", ItemStateChanged, this );
147     /* src/input/es-out.c: */
148     var_AddCallback( p_input, "teletext-es", ChangeTeletext, this );
149     /* src/input/input.c:1765 */
150     var_AddCallback( p_input, "rate-change", ItemRateChanged, this );
151     /* src/input/input.c:2003 */
152     var_AddCallback( p_input, "title", ItemTitleChanged, this );
153     /* src/input/input.c:734 for timers update*/
154     var_AddCallback( p_input, "intf-change", InterfaceChanged, this );
155 }
156
157 /* Delete the callbacks on Input. Self explanatory */
158 void InputManager::delCallbacks()
159 {
160     var_DelCallback( p_input, "spu-es", ChangeSPU, this );
161     var_DelCallback( p_input, "video-es", ItemStateChanged, this );
162     var_DelCallback( p_input, "teletext-es", ChangeTeletext, this );
163     var_DelCallback( p_input, "state", ItemStateChanged, this );
164     var_DelCallback( p_input, "rate-change", ItemRateChanged, this );
165     var_DelCallback( p_input, "title", ItemTitleChanged, this );
166     var_DelCallback( p_input, "intf-change", InterfaceChanged, this );
167 }
168
169 /* Convert the event from the callbacks in actions */
170 void InputManager::customEvent( QEvent *event )
171 {
172     int type = event->type();
173     IMEvent *ple = static_cast<IMEvent *>(event);
174
175     if ( type != PositionUpdate_Type &&
176          type != ItemChanged_Type &&
177          type != ItemRateChanged_Type &&
178          type != ItemTitleChanged_Type &&
179          type != ItemSpuChanged_Type &&
180          type != ItemTeletextChanged_Type &&
181          type != ItemStateChanged_Type )
182         return;
183
184     if( !hasInput() ) return;
185
186     if( ( type != PositionUpdate_Type  &&
187           type != ItemRateChanged_Type &&
188           type != ItemSpuChanged_Type &&
189           type != ItemTeletextChanged_Type &&
190           type != ItemStateChanged_Type
191         )
192         && ( i_input_id != ple->i_id ) )
193         return;
194
195     if( type != PositionUpdate_Type )
196         msg_Dbg( p_intf, "New Event: type %i", type );
197
198     /* Actions */
199     switch( type )
200     {
201     case PositionUpdate_Type:
202         UpdatePosition();
203         break;
204     case ItemChanged_Type:
205         UpdateMeta();
206         UpdateStatus();
207         UpdateArt();
208         break;
209     case ItemStateChanged_Type:
210         UpdateStatus();
211         UpdateNavigation();
212         UpdateMeta();
213         break;
214     case ItemTitleChanged_Type:
215         UpdateNavigation();
216         UpdateMeta();
217         break;
218     case ItemRateChanged_Type:
219         UpdateRate();
220         break;
221     case ItemSpuChanged_Type:
222         UpdateSPU();
223         break;
224     case ItemTeletextChanged_Type:
225         UpdateTeletext();
226         break;
227     }
228 }
229
230 void InputManager::UpdatePosition()
231 {
232     /* Update position */
233     int i_length, i_time; /* Int is enough, since we store seconds */
234     float f_pos;
235     i_length = var_GetTime(  p_input , "length" ) / 1000000;
236     i_time = var_GetTime(  p_input , "time") / 1000000;
237     f_pos = var_GetFloat(  p_input , "position" );
238     emit positionUpdated( f_pos, i_time, i_length );
239 }
240
241 void InputManager::UpdateNavigation()
242 {
243     /* Update navigation status */
244     vlc_value_t val; val.i_int = 0;
245     var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
246     if( val.i_int > 0 )
247     {
248         val.i_int = 0;
249         var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
250         emit navigationChanged( (val.i_int > 0) ? 1 : 2 );
251     }
252     else
253     {
254         emit navigationChanged( 0 );
255     }
256 }
257
258 void InputManager::UpdateStatus()
259 {
260     /* Update playing status */
261     vlc_value_t val; val.i_int = 0;
262     var_Get( p_input, "state", &val );
263     if( i_old_playing_status != val.i_int )
264     {
265         i_old_playing_status = val.i_int;
266         emit statusChanged( val.i_int );
267     }
268 }
269
270 void InputManager::UpdateRate()
271 {
272     /* Update Rate */
273     int i_new_rate = var_GetInteger( p_input, "rate");
274     if( i_new_rate != i_rate )
275     {
276         i_rate = i_new_rate;
277         /* Update rate */
278         emit rateChanged( i_rate );
279     }
280 }
281
282 void InputManager::UpdateMeta()
283 {
284     /* Update text, name and nowplaying */
285     QString text;
286
287     char *psz_name = input_item_GetTitle( input_GetItem( p_input ) );
288     if( EMPTY_STR( psz_name ) )
289     {
290         free( psz_name );
291         psz_name = input_item_GetName( input_GetItem( p_input ) );
292     }
293
294     char *psz_nowplaying =
295         input_item_GetNowPlaying( input_GetItem( p_input ) );
296     if( !EMPTY_STR( psz_nowplaying ) )
297     {
298         text.sprintf( "%s - %s", psz_nowplaying, psz_name );
299     }
300     else
301     {
302         char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) );
303         if( !EMPTY_STR( psz_artist ) )
304         {
305             text.sprintf( "%s - %s", psz_artist, psz_name );
306         }
307         else
308         {
309             text.sprintf( "%s", psz_name );
310         }
311         free( psz_artist );
312     }
313     free( psz_name );
314     free( psz_nowplaying );
315
316     if( old_name != text )
317     {
318         emit nameChanged( text );
319         old_name=text;
320     }
321 }
322
323 bool InputManager::hasAudio()
324 {
325     if( hasInput() )
326     {
327         vlc_value_t val;
328         var_Change( p_input, "audio-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
329         return val.i_int > 0;
330     }
331     return false;
332 }
333
334 bool InputManager::hasVideo()
335 {
336     if( hasInput() )
337     {
338         vlc_value_t val;
339         var_Change( p_input, "video-es", VLC_VAR_CHOICESCOUNT, &val, NULL );
340         return val.i_int > 0;
341     }
342     return false;
343
344 }
345
346 void InputManager::UpdateSPU()
347 {
348     UpdateTeletext();
349 }
350
351 void InputManager::UpdateTeletext()
352 {
353     if( hasInput() )
354         telexToggle( var_GetInteger( p_input, "teletext-es" ) >= 0 );
355     else
356         telexToggle( false );
357 }
358
359
360
361 void InputManager::UpdateArt()
362 {
363     /* Update Art meta */
364     QString url;
365     char *psz_art = input_item_GetArtURL( input_GetItem( p_input ) );
366     url.sprintf("%s", psz_art );
367     free( psz_art );
368     if( artUrl != url )
369     {
370         artUrl = url.replace( "file://",QString("" ) );
371         /* Taglib seems to define a attachment://, It won't work yet */
372         artUrl = url.replace( "attachment://",QString("" ) );
373         emit artChanged( artUrl );
374         msg_Dbg( p_intf, "Art:  %s", qtu( artUrl ) );
375     }
376 }
377
378 /* User update of the slider */
379 void InputManager::sliderUpdate( float new_pos )
380 {
381     if( hasInput() )
382         var_SetFloat( p_input, "position", new_pos );
383 }
384
385 /* User togglePlayPause */
386 void InputManager::togglePlayPause()
387 {
388     vlc_value_t state;
389     var_Get( p_input, "state", &state );
390     state.i_int = ( state.i_int != PLAYING_S ) ? PLAYING_S : PAUSE_S;
391     var_Set( p_input, "state", state );
392     emit statusChanged( state.i_int );
393 }
394
395 void InputManager::sectionPrev()
396 {
397     if( hasInput() )
398     {
399         int i_type = var_Type( p_input, "next-chapter" );
400         vlc_value_t val; val.b_bool = true;
401         var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
402                             "prev-chapter":"prev-title", val );
403     }
404 }
405
406 void InputManager::sectionNext()
407 {
408     if( hasInput() )
409     {
410         int i_type = var_Type( p_input, "next-chapter" );
411         vlc_value_t val; val.b_bool = true;
412         var_Set( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
413                             "next-chapter":"next-title", val );
414     }
415 }
416
417 void InputManager::sectionMenu()
418 {
419     if( hasInput() )
420     {
421         vlc_value_t val, text;
422         vlc_value_t root;
423
424         if( var_Change( p_input, "title  0", VLC_VAR_GETLIST, &val, &text ) < 0 )
425             return;
426
427         /* XXX is it "Root" or "Title" we want here ?" (set 0 by default) */
428         root.i_int = 0;
429         for( int i = 0; i < val.p_list->i_count; i++ )
430         {
431             if( !strcmp( text.p_list->p_values[i].psz_string, "Title" ) )
432                 root.i_int = i;
433         }
434         var_Change( p_input, "title  0", VLC_VAR_FREELIST, &val, &text );
435
436         var_Set( p_input, "title  0", root );
437     }
438 }
439
440 void InputManager::telexGotoPage( int page )
441 {
442     if( hasInput() )
443     {
444         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
445         const int i_spu_es = var_GetInteger( p_input, "spu-es" );
446
447         if( i_teletext_es >= 0 && i_teletext_es == i_spu_es )
448         {
449             vlc_object_t *p_vbi;
450             p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
451                         "zvbi", FIND_ANYWHERE );
452             if( p_vbi )
453             {
454                 var_SetInteger( p_vbi, "vbi-page", page );
455                 vlc_object_release( p_vbi );
456             }
457         }
458     }
459     emit setNewTelexPage( page );
460 }
461
462 void InputManager::telexToggle( bool b_enabled )
463 {
464     if( hasInput() )
465     {
466         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
467         const int i_spu_es = var_GetInteger( p_input, "spu-es" );
468
469         b_enabled = (i_teletext_es >= 0);
470         emit teletextEnabled( b_enabled );
471         if( b_enabled && (i_teletext_es == i_spu_es) )
472         {
473             vlc_object_t *p_vbi;
474             int i_page = 100;
475             p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
476                         "zvbi", FIND_ANYWHERE );
477             if( p_vbi )
478             {
479                 i_page = var_GetInteger( p_vbi, "vbi-page" );
480                 vlc_object_release( p_vbi );
481                 i_page = b_enabled ? i_page : 0;
482                 telexGotoPage( i_page );
483             }
484         }
485     }
486     else emit teletextEnabled( b_enabled );
487 }
488
489 void InputManager::telexToggleButtons()
490 {
491     if( hasInput() )
492     {
493         const int i_teletext_es = var_GetInteger( p_input, "teletext-es" );
494         if( i_teletext_es >= 0 )
495         {
496             const int i_spu_es = var_GetInteger( p_input, "spu-es" );
497
498             if( i_teletext_es == i_spu_es )
499                 var_SetInteger( p_input, "spu-es", -1 );
500             else
501                 var_SetInteger( p_input, "spu-es", i_teletext_es );
502
503             emit toggleTelexButtons();
504         }
505     }
506 }
507
508 void InputManager::telexSetTransparency()
509 {
510     if( hasInput() )
511     {
512         vlc_object_t *p_vbi;
513         p_vbi = (vlc_object_t *) vlc_object_find_name( p_input,
514                     "zvbi", FIND_ANYWHERE );
515         if( p_vbi )
516         {
517             var_SetBool( p_vbi, "vbi-opaque", b_transparentTelextext );
518             b_transparentTelextext = !b_transparentTelextext;
519             vlc_object_release( p_vbi );
520         }
521     }
522     emit toggleTelexTransparency();
523 }
524
525 void InputManager::slower()
526 {
527     if( hasInput() )
528         var_SetVoid( p_input, "rate-slower" );
529 }
530
531 void InputManager::faster()
532 {
533     if( hasInput() )
534         var_SetVoid( p_input, "rate-faster" );
535 }
536
537 void InputManager::normalRate()
538 {
539     if( hasInput() )
540         var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
541 }
542
543 void InputManager::setRate( int new_rate )
544 {
545     if( hasInput() )
546         var_SetInteger( p_input, "rate", new_rate );
547 }
548
549 /**********************************************************************
550  * MainInputManager implementation. Wrap an input manager and
551  * take care of updating the main playlist input.
552  * Used in the main playlist Dialog
553  **********************************************************************/
554 MainInputManager * MainInputManager::instance = NULL;
555
556 MainInputManager::MainInputManager( intf_thread_t *_p_intf )
557                  : QObject(NULL), p_intf( _p_intf )
558 {
559     p_input = NULL;
560     im = new InputManager( this, p_intf );
561
562 //    var_AddCallback( THEPL, "item-change", PLItemChanged, this );
563     var_AddCallback( THEPL, "item-change", ItemChanged, im );
564     var_AddCallback( THEPL, "playlist-current", PLItemChanged, this );
565     var_AddCallback( THEPL, "activity", PLItemChanged, this );
566
567     var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
568
569     // No necessary, I think TODO REMOVE ME at the end
570     //var_AddCallback( THEPL, "intf-change", ItemChanged, im );
571
572     /* Warn our embedded IM about input changes */
573     CONNECT( this, inputChanged( input_thread_t * ),
574              im, setInput( input_thread_t * ) );
575
576     /* emit check if playlist has allready started playing */
577     vlc_value_t val;
578     var_Change( THEPL, "playlist-current", VLC_VAR_CHOICESCOUNT, &val, NULL );
579     IMEvent *event = new IMEvent( ItemChanged_Type, val.i_int);
580     QApplication::postEvent( this, static_cast<QEvent*>(event) );
581
582 }
583
584 MainInputManager::~MainInputManager()
585 {
586     if( p_input )
587     {
588        var_DelCallback( p_input, "state", PLItemChanged, this );
589        vlc_object_release( p_input );
590        emit inputChanged( NULL );
591     }
592
593     var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
594
595     var_DelCallback( THEPL, "activity", PLItemChanged, this );
596     var_DelCallback( THEPL, "item-change", ItemChanged, im );
597 //    var_DelCallback( THEPL, "item-change", PLItemChanged, this );
598
599     var_DelCallback( THEPL, "playlist-current", PLItemChanged, this );
600 }
601
602 void MainInputManager::customEvent( QEvent *event )
603 {
604     int type = event->type();
605     if ( type != ItemChanged_Type && type != VolumeChanged_Type )
606         return;
607
608     // msg_Dbg( p_intf, "New MainIM Event of type: %i", type );
609     if( type == VolumeChanged_Type )
610     {
611         emit volumeChanged();
612         return;
613     }
614
615     /* Should be PLItemChanged Event */
616     if( VLC_OBJECT_INTF == p_intf->i_object_type ) /* FIXME: don't use object type */
617     {
618         vlc_mutex_lock( &p_intf->change_lock );
619         if( p_input && ( p_input->b_dead || !vlc_object_alive (p_input) ) )
620         {
621             var_DelCallback( p_input, "state", PLItemChanged, this );
622             vlc_object_release( p_input );
623             emit inputChanged( NULL );
624             p_input = NULL;
625             vlc_mutex_unlock( &p_intf->change_lock );
626             return;
627         }
628
629         if( !p_input )
630         {
631             QPL_LOCK;
632             p_input = THEPL->p_input;
633             if( p_input && !( !vlc_object_alive (p_input) || p_input->b_dead) )
634             {
635                 vlc_object_yield( p_input );
636                 var_AddCallback( p_input, "state", PLItemChanged, this );
637                 emit inputChanged( p_input );
638             }
639             else
640                 p_input = NULL;
641             QPL_UNLOCK;
642         }
643         vlc_mutex_unlock( &p_intf->change_lock );
644     }
645     else
646     {
647         /* we are working as a dialogs provider */
648         playlist_t *p_playlist = pl_Yield( p_intf );
649         p_input = playlist_CurrentInput( p_playlist );
650         if( p_input )
651         {
652             emit inputChanged( p_input );
653             vlc_object_release( p_input );
654         }
655         pl_Release( p_intf );
656     }
657 }
658
659 /* Playlist Control functions */
660 void MainInputManager::stop()
661 {
662    playlist_Stop( THEPL );
663 }
664
665 void MainInputManager::next()
666 {
667    playlist_Next( THEPL );
668 }
669
670 void MainInputManager::prev()
671 {
672    playlist_Prev( THEPL );
673 }
674
675 void MainInputManager::togglePlayPause()
676 {
677     if( p_input == NULL )
678     {
679         playlist_Play( THEPL );
680         return;
681     }
682     getIM()->togglePlayPause();
683 }
684
685 bool MainInputManager::teletextState()
686 {
687     im = getIM();
688     if( im->hasInput() )
689     {
690         const int i_teletext_es = var_GetInteger( getInput(), "teletext-es" );
691         const int i_spu_es = var_GetInteger( getInput(), "spu-es" );
692
693         return i_teletext_es >= 0 && i_teletext_es == i_spu_es;
694     }
695     return false;
696 }
697
698 /* Static callbacks */
699
700 /* IM */
701 static int InterfaceChanged( vlc_object_t *p_this, const char *psz_var,
702                            vlc_value_t oldval, vlc_value_t newval, void *param )
703 {
704     static int counter = 0;
705     InputManager *im = (InputManager*)param;
706
707     counter = ++counter % 4;
708     if(!counter)
709         return VLC_SUCCESS;
710     IMEvent *event = new IMEvent( PositionUpdate_Type, 0 );
711     QApplication::postEvent( im, static_cast<QEvent*>(event) );
712     return VLC_SUCCESS;
713 }
714
715 static int ItemStateChanged( vlc_object_t *p_this, const char *psz_var,
716                            vlc_value_t oldval, vlc_value_t newval, void *param )
717 {
718     InputManager *im = (InputManager*)param;
719
720     IMEvent *event = new IMEvent( ItemStateChanged_Type, 0 );
721     QApplication::postEvent( im, static_cast<QEvent*>(event) );
722     return VLC_SUCCESS;
723 }
724
725 static int ItemRateChanged( vlc_object_t *p_this, const char *psz_var,
726                            vlc_value_t oldval, vlc_value_t newval, void *param )
727 {
728     InputManager *im = (InputManager*)param;
729
730     IMEvent *event = new IMEvent( ItemRateChanged_Type, 0 );
731     QApplication::postEvent( im, static_cast<QEvent*>(event) );
732     return VLC_SUCCESS;
733 }
734
735 static int ItemTitleChanged( vlc_object_t *p_this, const char *psz_var,
736                            vlc_value_t oldval, vlc_value_t newval, void *param )
737 {
738     InputManager *im = (InputManager*)param;
739
740     IMEvent *event = new IMEvent( ItemTitleChanged_Type, 0 );
741     QApplication::postEvent( im, static_cast<QEvent*>(event) );
742     return VLC_SUCCESS;
743 }
744
745 static int ItemChanged( vlc_object_t *p_this, const char *psz_var,
746                         vlc_value_t oldval, vlc_value_t newval, void *param )
747 {
748     InputManager *im = (InputManager*)param;
749
750     IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
751     QApplication::postEvent( im, static_cast<QEvent*>(event) );
752     return VLC_SUCCESS;
753 }
754
755 static int ChangeSPU( vlc_object_t *p_this, const char *var, vlc_value_t o,
756                         vlc_value_t n, void *param )
757 {
758     InputManager *im = (InputManager*)param;
759     IMEvent *event = new IMEvent( ItemSpuChanged_Type, 0 );
760     QApplication::postEvent( im, static_cast<QEvent*>(event) );
761     return VLC_SUCCESS;
762 }
763
764 static int ChangeTeletext( vlc_object_t *p_this, const char *var, vlc_value_t o,
765                            vlc_value_t n, void *param )
766 {
767
768     InputManager *im = (InputManager*)param;
769     IMEvent *event = new IMEvent( ItemTeletextChanged_Type, 0 );
770     QApplication::postEvent( im, static_cast<QEvent*>(event) );
771     return VLC_SUCCESS;
772 }
773
774 /* MIM */
775 static int PLItemChanged( vlc_object_t *p_this, const char *psz_var,
776                         vlc_value_t oldval, vlc_value_t newval, void *param )
777 {
778     MainInputManager *mim = (MainInputManager*)param;
779
780     IMEvent *event = new IMEvent( ItemChanged_Type, newval.i_int );
781     QApplication::postEvent( mim, static_cast<QEvent*>(event) );
782     return VLC_SUCCESS;
783 }
784
785 static int VolumeChanged( vlc_object_t *p_this, const char *psz_var,
786                         vlc_value_t oldval, vlc_value_t newval, void *param )
787 {
788     MainInputManager *mim = (MainInputManager*)param;
789
790     IMEvent *event = new IMEvent( VolumeChanged_Type, newval.i_int );
791     QApplication::postEvent( mim, static_cast<QEvent*>(event) );
792     return VLC_SUCCESS;
793 }
794