]> git.sesse.net Git - vlc/blob - modules/gui/beos/VlcWrapper.cpp
* beos/* : fixed a bug in the progress bar with big files
[vlc] / modules / gui / beos / VlcWrapper.cpp
1 /*****************************************************************************
2  * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port)
3  *****************************************************************************
4  * Copyright (C) 2001 VideoLAN
5  * $Id: VlcWrapper.cpp,v 1.17 2003/01/12 02:08:39 titer Exp $
6  *
7  * Authors: Florian G. Pflug <fgp@phlo.org>
8  *          Jon Lech Johansen <jon-vl@nanocrew.net>
9  *          Tony Casltey <tony@castley.net>
10  *          Stephan Aßmus <stippi@yellowbites.com>
11  *          Eric Petit <titer@videolan.org>
12  *
13  * This program is free software{} you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation{} either version 2 of the License, or
16  * (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY{} without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program{} if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27 #include <AppKit.h>
28 #include <InterfaceKit.h>
29 #include <SupportKit.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33 extern "C" {
34 #include <audio_output.h>
35 #include <aout_internal.h>
36 }
37
38 #include "VlcWrapper.h"
39 #include "MsgVals.h"
40
41 /* constructor */
42 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
43 {
44     p_intf = p_interface;
45     p_input = NULL;
46     p_aout = NULL;
47     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
48                                                 FIND_ANYWHERE );
49 }
50
51 /* destructor */
52 VlcWrapper::~VlcWrapper()
53 {
54     if( p_input )
55     {
56         vlc_object_release( p_input );
57     }
58     if( p_playlist )
59     {
60         vlc_object_release( p_playlist );
61     }
62     if( p_aout )
63     {
64         vlc_object_release( p_aout );
65     }
66 }
67
68 /* UpdateInputAndAOut: updates p_input and p_aout, returns true if the
69    interface needs to be updated */
70 bool VlcWrapper::UpdateInputAndAOut()
71 {
72     if( p_input == NULL )
73     {
74         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
75                                                      FIND_ANYWHERE );
76     }
77     if( p_aout == NULL )
78     {
79         p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
80                                                     FIND_ANYWHERE );
81     }
82         
83     if( p_input != NULL )
84     {
85         if( p_input->b_dead )
86         {
87             vlc_object_release( p_input );
88             p_input = NULL;
89             
90             if( p_aout )
91             {
92                 vlc_object_release( p_aout );
93                 p_aout = NULL;
94             }
95         }
96         return true;
97     }
98     return false;
99 }
100
101
102 /***************************
103  * input infos and control *
104  ***************************/
105
106 bool VlcWrapper::HasInput()
107 {
108     return ( p_input != NULL );
109 //    return ( PlaylistSize() > 0 );
110 }
111
112 /* status (UNDEF_S, PLAYING_S, PAUSE_S, FORWARD_S, BACKWARD_S,
113    REWIND_S, NOT_STARTED_S, START_S) */
114 int VlcWrapper::InputStatus()
115 {
116     if( !p_input )
117     {
118         return UNDEF_S;
119     }
120     return p_input->stream.control.i_status;
121 }
122
123 int VlcWrapper::InputRate()
124 {
125     if( !p_input )
126     {
127         return DEFAULT_RATE;
128     }
129     return p_input->stream.control.i_rate;
130 }
131
132 void VlcWrapper::InputSlower()
133 {
134     if( p_input != NULL )
135     {
136         input_SetStatus( p_input, INPUT_STATUS_SLOWER );
137     }
138 }
139
140 void VlcWrapper::InputFaster()
141 {
142     if( p_input != NULL )
143     {
144         input_SetStatus( p_input, INPUT_STATUS_FASTER );
145     }
146 }
147
148 BList * VlcWrapper::InputGetChannels( int i_cat )
149 {
150     if( p_input )
151     {
152         unsigned int i;
153         uint32 what;
154         const char* fieldName;
155
156         switch( i_cat )
157         {
158             case AUDIO_ES:
159             {
160                 what = SELECT_CHANNEL;
161                 fieldName = "channel";
162                 break;
163             }
164             case SPU_ES:
165             {
166                 what = SELECT_SUBTITLE;
167                 fieldName = "subtitle";
168                 break;
169             }
170             default:
171             return NULL;
172        }
173
174         vlc_mutex_lock( &p_input->stream.stream_lock );
175       
176         /* find which track is currently playing */
177         es_descriptor_t *p_es = NULL;
178         for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
179         {
180             if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
181                 p_es = p_input->stream.pp_selected_es[i];
182         }
183         
184         /* build a list of all tracks */
185         BList *list = new BList( p_input->stream.i_es_number );
186         BMenuItem *menuItem;
187         BMessage *message;
188         char *trackName;
189         
190         /* "None" */
191         message = new BMessage( what );
192         message->AddInt32( fieldName, -1 );
193         menuItem = new BMenuItem( "None", message );
194         if( !p_es )
195             menuItem->SetMarked( true );
196         list->AddItem( menuItem );
197         
198         for( i = 0; i < p_input->stream.i_es_number; i++ )
199         {
200             if( p_input->stream.pp_es[i]->i_cat == i_cat )
201             {
202                 message = new BMessage( what );
203                 message->AddInt32( fieldName, i );
204                 if( strlen( p_input->stream.pp_es[i]->psz_desc ) )
205                     trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
206                 else
207                     trackName = "<unknown>";
208                 menuItem = new BMenuItem( trackName, message );
209                 if( p_input->stream.pp_es[i] == p_es )
210                     menuItem->SetMarked( true );
211                 list->AddItem( menuItem );
212             }
213         }
214         
215         vlc_mutex_unlock( &p_input->stream.stream_lock );
216
217         return list;
218     }
219     return NULL;
220 }
221
222 void VlcWrapper::openFiles( BList* o_files, bool replace )
223 {
224     BString *o_file;
225
226     while( ( o_file = (BString *)o_files->LastItem() ) )
227     {
228         o_files->RemoveItem(o_files->CountItems() - 1);
229         playlist_Add( p_playlist, o_file->String(),
230                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
231         delete o_file;
232     }
233 }
234
235 void VlcWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
236 {
237     BString o_source("");
238     o_source << o_type << ":" << o_device ;
239
240     playlist_Add( p_playlist, o_source.String(),
241                   PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
242 }
243
244
245
246 void VlcWrapper::ToggleLanguage( int i_language )
247 {
248     es_descriptor_t * p_es = NULL;
249     es_descriptor_t * p_es_old = NULL;
250
251     vlc_mutex_lock( &p_input->stream.stream_lock );
252     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
253     {
254         if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
255         {
256             p_es_old = p_input->stream.pp_selected_es[i];
257             break;
258         }
259     }
260     vlc_mutex_unlock( &p_input->stream.stream_lock );
261     
262     if( i_language != -1 )
263     {
264         p_es = p_input->stream.pp_es[i_language];
265     }
266     if( p_es == p_es_old )
267     {
268         return;
269     }
270     if( p_es_old )
271     {
272         input_ToggleES( p_input, p_es_old, VLC_FALSE );
273     }
274     if( p_es )
275     {
276         input_ToggleES( p_input, p_es, VLC_TRUE );
277     }
278 }
279
280 void VlcWrapper::ToggleSubtitle( int i_subtitle )
281 {
282     es_descriptor_t * p_es = NULL;
283     es_descriptor_t * p_es_old = NULL;
284
285     vlc_mutex_lock( &p_input->stream.stream_lock );
286     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
287     {
288         if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
289         {
290             p_es_old = p_input->stream.pp_selected_es[i];
291             break;
292         }
293     }
294     vlc_mutex_unlock( &p_input->stream.stream_lock );
295     
296     if( i_subtitle != -1 )
297     {
298         p_es = p_input->stream.pp_es[i_subtitle];
299     }
300     if( p_es == p_es_old )
301     {
302         return;
303     }
304     if( p_es_old )
305     {
306         input_ToggleES( p_input, p_es_old, VLC_FALSE );
307     }
308     if( p_es )
309     {
310         input_ToggleES( p_input, p_es, VLC_TRUE );
311     }
312 }
313
314 const char*  VlcWrapper::getTimeAsString()
315 {
316     static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
317         
318     if( p_input == NULL )
319     {
320         return ("-:--:--");
321     }     
322    
323     input_OffsetToTime( p_input, 
324                         psz_currenttime, 
325                         p_input->stream.p_selected_area->i_tell );        
326
327     return(psz_currenttime);
328 }
329
330 float  VlcWrapper::getTimeAsFloat()
331 {
332     float f_time = 0.0;
333
334     if( p_input != NULL )
335     {
336         f_time = (float)p_input->stream.p_selected_area->i_tell / 
337                  (float)p_input->stream.p_selected_area->i_size;
338     }    
339     else
340     {
341         f_time = 0.0;
342     }
343     return( f_time );
344 }
345
346 void VlcWrapper::setTimeAsFloat(float f_position)
347 {
348     if( p_input != NULL )
349     {
350         input_Seek( p_input, 
351                    (long long int)(p_input->stream.p_selected_area->i_size
352                        * f_position / SEEKSLIDER_RANGE ), 
353                    INPUT_SEEK_SET);
354     }
355 }
356
357 bool VlcWrapper::IsPlaying()
358 {
359
360         bool playing = false;
361         if ( p_input )
362         {
363                 switch ( p_input->stream.control.i_status )
364                 {
365                         case PLAYING_S:
366                         case FORWARD_S:
367                         case BACKWARD_S:
368                         case START_S:
369                                 playing = true;
370                     break;
371                         case PAUSE_S:
372                         case UNDEF_S:
373                         case NOT_STARTED_S:
374                         default:
375                                 break;
376                 }
377         }
378         return playing;
379
380 }
381
382 /******************************
383  * playlist infos and control *
384  ******************************/
385 int VlcWrapper::PlaylistSize()
386 {
387     vlc_mutex_lock( &p_playlist->object_lock );
388     int i_size = p_playlist->i_size;
389     vlc_mutex_unlock( &p_playlist->object_lock );
390     return i_size;
391 }
392
393 char *VlcWrapper::PlaylistItemName( int i )
394 {
395    return p_playlist->pp_items[i]->psz_name;
396 }
397
398 int VlcWrapper::PlaylistCurrent()
399 {
400     return p_playlist->i_index;
401 }
402
403 int  VlcWrapper::PlaylistStatus()
404 {
405     return p_playlist->i_status;
406 }
407
408 bool VlcWrapper::PlaylistPlay()
409 {
410     if( PlaylistSize() )
411     {
412         playlist_Play( p_playlist );
413     }
414     return( true );
415 }
416
417 void VlcWrapper::PlaylistPause()
418 {
419     if( p_input )
420     {
421         input_SetStatus( p_input, INPUT_STATUS_PAUSE );
422     }
423 }
424
425 void VlcWrapper::PlaylistStop()
426 {
427     playlist_Stop( p_playlist );
428 }
429
430 void VlcWrapper::PlaylistNext()
431 {
432     playlist_Next( p_playlist );
433 }
434
435 void VlcWrapper::PlaylistPrev()
436 {
437     playlist_Prev( p_playlist );
438 }
439
440 void VlcWrapper::PlaylistSkip( int i )
441 {
442     playlist_Skip( p_playlist, i );
443 }
444
445 void VlcWrapper::PlaylistGoto( int i )
446 {
447     playlist_Goto( p_playlist, i );
448 }
449
450 void VlcWrapper::PlaylistLoop()
451 {
452     if ( p_intf->p_sys->b_loop )
453     {
454         playlist_Delete( p_playlist, p_playlist->i_size - 1 );
455     }
456     else
457     {
458         playlist_Add( p_playlist, "vlc:loop",
459                       PLAYLIST_APPEND | PLAYLIST_GO,
460                       PLAYLIST_END );
461     }
462     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
463 }
464
465 BList * VlcWrapper::PlaylistAsArray()
466
467     int i;
468     BList* p_list = new BList(p_playlist->i_size);
469     
470     vlc_mutex_lock( &p_playlist->object_lock );
471
472     for( i = 0; i < p_playlist->i_size; i++ )
473     {
474         p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
475     }
476
477     vlc_mutex_unlock( &p_playlist->object_lock );
478     return( p_list );
479 }
480
481 void VlcWrapper::getPlaylistInfo( int32& currentIndex, int32& maxIndex )
482 {
483         currentIndex = -1;
484         maxIndex = -1;
485         if ( p_playlist )
486         {
487                 maxIndex = p_playlist->i_size;
488                 if ( maxIndex > 0 )
489                         currentIndex = p_playlist->i_index + 1;
490                 else
491                         maxIndex = -1;
492         }
493 }
494
495
496 void VlcWrapper::PlaylistJumpTo( int pos )
497 {
498 #if 0
499         // sanity checks
500         if ( pos < 0 )
501                 pos = 0;
502         int size = playlistSize();
503         if (pos >= size)
504                 pos = size - 1;
505         // weird hack
506     if( p_input_bank->pp_input[0] != NULL )
507                 pos--;
508         // stop current stream
509         playlistStop();
510         // modify current position in playlist
511         playlistLock();
512         p_main->p_playlist->i_index = pos;
513         playlistUnlock();
514         // start playing
515         playlistPlay();
516 #endif
517 }
518
519 void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
520 {
521         if ( canSkipPrev && canSkipNext )
522         {
523                 // init the parameters
524                 *canSkipPrev = false;
525                 *canSkipNext = false;
526                 // get playlist info
527                 int pos = PlaylistCurrent();
528                 int size = PlaylistSize();
529
530                 // see if we have got a stream going            
531                 if ( p_input )
532                 {
533                         vlc_mutex_lock( &p_input->stream.stream_lock );
534
535                         bool hasTitles = p_input->stream.i_area_nb > 1;
536                         int numChapters = p_input->stream.p_selected_area->i_part_nb;
537                         bool hasChapters = numChapters > 1;
538                         // first, look for chapters
539                         if ( hasChapters )
540                         {
541                                 *canSkipPrev = p_input->stream.p_selected_area->i_part > 0;
542                                 *canSkipNext = p_input->stream.p_selected_area->i_part <
543                                                                          p_input->stream.p_selected_area->i_part_nb - 1;
544                         }
545                         // if one of the skip capabilities is false,
546                         // make it depend on titles instead
547                         if ( !*canSkipPrev && hasTitles )
548                                 *canSkipPrev = p_input->stream.p_selected_area->i_id > 1;
549                         if ( !*canSkipNext && hasTitles )
550                                 *canSkipNext = p_input->stream.p_selected_area->i_id <
551                                                    p_input->stream.i_area_nb - 1;
552
553                         vlc_mutex_unlock( &p_input->stream.stream_lock );
554                 }
555                 // last but not least, make capabilities depend on playlist
556                 if ( !*canSkipPrev )
557                         *canSkipPrev = pos > 0;
558                 if ( !*canSkipNext )
559                         *canSkipNext = pos < size - 1;
560         }
561 }
562
563 void VlcWrapper::navigatePrev()
564 {
565         bool hasSkiped = false;
566
567         // see if we have got a stream going            
568         if ( p_input )
569         {
570                 // get information from stream (lock it while looking at it)
571                 vlc_mutex_lock( &p_input->stream.stream_lock );
572
573                 int currentTitle = p_input->stream.p_selected_area->i_id;
574                 int currentChapter = p_input->stream.p_selected_area->i_part;
575                 int numTitles = p_input->stream.i_area_nb;
576                 bool hasTitles = numTitles > 1;
577                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
578                 bool hasChapters = numChapters > 1;
579
580                 vlc_mutex_unlock( &p_input->stream.stream_lock );
581
582                 // first, look for chapters
583                 if ( hasChapters )
584                 {
585                         // skip to the previous chapter
586                         currentChapter--;
587
588                         if ( currentChapter >= 0 )
589                         {
590                                 toggleChapter( currentChapter );
591                                 hasSkiped = true;
592                         }
593                 }
594                 // if we couldn't skip chapters, try titles instead
595                 if ( !hasSkiped && hasTitles )
596                 {
597                         // skip to the previous title
598                         currentTitle--;
599                         // disallow area 0 since it is used for video_ts.vob
600                         if( currentTitle > 0 )
601                         {
602                                 toggleTitle(currentTitle);
603                                 hasSkiped = true;
604                         }
605                 }
606
607         }
608         // last but not least, skip to previous file
609         if ( !hasSkiped )
610                 PlaylistPrev();
611 }
612
613 void VlcWrapper::navigateNext()
614 {
615         bool hasSkiped = false;
616
617         // see if we have got a stream going            
618         if ( p_input )
619         {
620                 // get information from stream (lock it while looking at it)
621                 vlc_mutex_lock( &p_input->stream.stream_lock );
622
623                 int currentTitle = p_input->stream.p_selected_area->i_id;
624                 int currentChapter = p_input->stream.p_selected_area->i_part;
625                 int numTitles = p_input->stream.i_area_nb;
626                 bool hasTitles = numTitles > 1;
627                 int numChapters = p_input->stream.p_selected_area->i_part_nb;
628                 bool hasChapters = numChapters > 1;
629
630                 vlc_mutex_unlock( &p_input->stream.stream_lock );
631
632                 // first, look for chapters
633                 if ( hasChapters )
634                 {
635                         // skip to the next chapter
636                         currentChapter++;
637                         if ( currentChapter < numChapters )
638                         {
639                                 toggleChapter( currentChapter );
640                                 hasSkiped = true;
641                         }
642                 }
643                 // if we couldn't skip chapters, try titles instead
644                 if ( !hasSkiped && hasTitles )
645                 {
646                         // skip to the next title
647                         currentTitle++;
648                         // disallow area 0 since it is used for video_ts.vob
649                         if ( currentTitle < numTitles - 1 )
650                         {
651                                 toggleTitle(currentTitle);
652                                 hasSkiped = true;
653                         }
654                 }
655
656         }
657         // last but not least, skip to next file
658         if ( !hasSkiped )
659                 PlaylistNext();
660 }
661
662
663 /***************************
664  * audio infos and control *
665  ***************************/
666
667 unsigned short VlcWrapper::GetVolume()
668 {
669     if( p_aout != NULL )
670     {
671         unsigned short i_volume;
672         aout_VolumeGet( p_aout, (audio_volume_t*)&i_volume );
673         return i_volume;
674     }
675     return 0;
676 }
677
678 void VlcWrapper::SetVolume(int value)
679 {
680     if( p_aout != NULL )
681     {
682                 if ( p_intf->p_sys->b_mute )
683                 {
684                         p_intf->p_sys->b_mute = 0;
685                 }
686         aout_VolumeSet( p_aout, value );
687     }
688 }
689
690 void VlcWrapper::VolumeMute()
691 {
692     if( p_aout != NULL )
693         {
694             aout_VolumeGet( p_aout, &p_intf->p_sys->i_saved_volume );
695             aout_VolumeMute( p_aout, NULL );
696             p_intf->p_sys->b_mute = 1;
697         }
698 }
699
700 void VlcWrapper::VolumeRestore()
701 {
702     if( p_aout != NULL )
703         {
704         aout_VolumeSet( p_aout, p_intf->p_sys->i_saved_volume );
705         p_intf->p_sys->b_mute = 0;
706         }
707 }
708
709 bool VlcWrapper::IsMuted()
710 {
711     return p_intf->p_sys->b_mute;
712 }
713
714 bool VlcWrapper::HasAudio()
715 {
716     return( p_aout != NULL );
717 }
718
719 /*******
720  * DVD *
721  *******/
722 bool VlcWrapper::HasTitles()
723 {
724     if( !p_input )
725     {
726         return false;
727     }
728     return ( p_input->stream.i_area_nb > 1 );
729 }
730
731 void VlcWrapper::PrevTitle()
732 {
733     int i_id;
734     i_id = p_input->stream.p_selected_area->i_id - 1;
735     if( i_id > 0 )
736     {
737         toggleTitle(i_id);
738     }
739 }
740
741 void VlcWrapper::NextTitle()
742 {
743     unsigned int i_id;
744     i_id = p_input->stream.p_selected_area->i_id + 1;
745     if( i_id < p_input->stream.i_area_nb )
746     {
747         toggleTitle(i_id);
748     }
749 }
750
751 bool VlcWrapper::HasChapters()
752 {
753     if( !p_input )
754     {
755         return false;
756     }
757     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
758 }
759
760 void VlcWrapper::PrevChapter()
761 {
762     int i_id;
763     i_id = p_input->stream.p_selected_area->i_part - 1;
764     if( i_id >= 0 )
765     {
766         toggleChapter(i_id);
767     }
768 }
769
770 void VlcWrapper::NextChapter()
771 {
772     int i_id;
773     i_id = p_input->stream.p_selected_area->i_part + 1;
774     if( i_id >= 0 )
775     {
776         toggleChapter(i_id);
777     }
778 }
779
780 void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
781 {
782         currentIndex = -1;
783         maxIndex = -1;
784         if ( p_input )
785         {
786                 vlc_mutex_lock( &p_input->stream.stream_lock );
787
788                 maxIndex = p_input->stream.i_area_nb - 1;
789                 if ( maxIndex > 0)
790                         currentIndex = p_input->stream.p_selected_area->i_id;
791                 else
792                         maxIndex = -1;
793
794                 vlc_mutex_unlock( &p_input->stream.stream_lock );
795         }
796 }
797
798 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
799 {
800         currentIndex = -1;
801         maxIndex = -1;
802         if ( p_input )
803         {
804                 vlc_mutex_lock( &p_input->stream.stream_lock );
805
806                 maxIndex = p_input->stream.p_selected_area->i_part_nb - 1;
807                 if ( maxIndex > 0)
808                         currentIndex = p_input->stream.p_selected_area->i_part;
809                 else
810                         maxIndex = -1;
811
812                 vlc_mutex_unlock( &p_input->stream.stream_lock );
813         }
814 }
815
816 void VlcWrapper::toggleTitle(int i_title)
817 {
818     if( p_input != NULL )
819     {
820         input_ChangeArea( p_input,
821                           p_input->stream.pp_areas[i_title] );
822
823         vlc_mutex_lock( &p_input->stream.stream_lock );
824
825         vlc_mutex_unlock( &p_input->stream.stream_lock );
826     }
827 }
828
829 void VlcWrapper::toggleChapter(int i_chapter)
830 {
831     if( p_input != NULL )
832     {
833         p_input->stream.p_selected_area->i_part = i_chapter;
834         input_ChangeArea( p_input,
835                           p_input->stream.p_selected_area );
836
837         vlc_mutex_lock( &p_input->stream.stream_lock );
838         vlc_mutex_unlock( &p_input->stream.stream_lock );
839     }
840 }