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