]> git.sesse.net Git - vlc/blob - src/control/mediacontrol_audio_video.c
Merge 0.8.5-api changes
[vlc] / src / control / mediacontrol_audio_video.c
1 /*****************************************************************************
2  * audio_video.c: Audio/Video management : volume, snapshot, OSD
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Olivier Aubert <olivier.aubert@liris.univ-lyon1.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <mediacontrol_internal.h>
25
26 #include <vlc/mediacontrol.h>
27
28 #include <vlc/intf.h>
29 #include <vlc/vout.h>
30 #include <vlc/aout.h>
31 #include <vlc_demux.h>
32
33 #include <vlc_osd.h>
34
35 #define HAS_SNAPSHOT 1
36
37 #ifdef HAS_SNAPSHOT
38 #include <snapshot.h>
39 #endif
40
41 #include <stdlib.h>                                      /* malloc(), free() */
42 #include <string.h>
43
44 #include <errno.h>                                                 /* ENOMEM */
45 #include <stdio.h>
46 #include <ctype.h>
47
48 #ifdef HAVE_UNISTD_H
49 #    include <unistd.h>
50 #endif
51 #ifdef HAVE_SYS_TIME_H
52 #    include <sys/time.h>
53 #endif
54 #ifdef HAVE_SYS_TYPES_H
55 #    include <sys/types.h>
56 #endif
57
58 #define RAISE( c, m )  exception->code = c; \
59                        exception->message = strdup(m);
60
61 mediacontrol_RGBPicture *
62 mediacontrol_snapshot( mediacontrol_Instance *self,
63                        const mediacontrol_Position * a_position,
64                        mediacontrol_Exception *exception )
65 {
66     mediacontrol_RGBPicture *retval = NULL;
67     input_thread_t* p_input = self->p_playlist->p_input;
68     vout_thread_t *p_vout = NULL;
69     int i_datasize;
70     snapshot_t **pointer;
71     vlc_value_t val;
72     int i_index;
73     snapshot_t *p_best_snapshot;
74     long searched_date;
75 #ifdef HAS_SNAPSHOT
76     int i_cachesize;
77 #endif
78
79     exception=mediacontrol_exception_init( exception );
80
81     /*
82        if( var_Get( self->p_vlc, "snapshot-id", &val ) == VLC_SUCCESS )
83        p_vout = vlc_object_get( self->p_vlc, val.i_int );
84     */
85
86     /* FIXME: if in p_libvlc, we cannot have multiple video outputs */
87     /* Once corrected, search for snapshot-id to modify all instances */
88     if( var_Get( p_input, "snapshot-id", &val ) != VLC_SUCCESS )
89     {
90         RAISE( mediacontrol_InternalException, "No snapshot-id in p_input" );
91         return NULL;
92     }
93     p_vout = vlc_object_get( self->p_vlc, val.i_int );
94
95     if( ! p_vout )
96     {
97         RAISE( mediacontrol_InternalException, "No snapshot module" );
98         return NULL;
99     }
100
101 #ifdef HAS_SNAPSHOT
102     /* We test if the vout is a snapshot module. We cannot test
103        pvout_psz_object_name( which is NULL ). But we can check if
104        there are snapshot-specific variables */
105     if( var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS )
106     {
107         RAISE( mediacontrol_InternalException, "No snapshot module" );
108         vlc_object_release( p_vout );
109         return NULL;
110     }
111     i_datasize = val.i_int;
112
113     /* Handle the a_position parameter */
114     if( ! ( a_position->origin == mediacontrol_RelativePosition
115             && a_position->value == 0 ) )
116     {
117         /* The position is not the current one. Go to it. */
118         mediacontrol_set_media_position( self,
119                                          ( mediacontrol_Position* ) a_position,
120                                          exception );
121         if( exception->code )
122         {
123             vlc_object_release( p_vout );
124             return NULL;
125         }
126     }
127
128     /* FIXME: We should not go further until we got past the position
129        ( which means that we had the possibility to capture the right
130        picture ). */
131
132     vlc_mutex_lock( &p_vout->picture_lock );
133
134     searched_date = mediacontrol_position2microsecond( p_input,
135                                                        ( mediacontrol_Position * ) a_position );
136
137     var_Get( p_vout, "snapshot-cache-size", &val );
138     i_cachesize = val.i_int  ;
139
140     var_Get( p_vout, "snapshot-list-pointer", &val );
141     pointer = ( snapshot_t ** )val.p_address;
142
143     if( ! pointer )
144     {
145         RAISE( mediacontrol_InternalException, "No available snapshot" );
146
147         vlc_mutex_unlock( &p_vout->picture_lock );
148         vlc_object_release( p_vout );
149         return NULL;
150     }
151
152     /* Find the more appropriate picture, based on date */
153     p_best_snapshot = pointer[0];
154
155     for( i_index = 1 ; i_index < i_cachesize ; i_index++ )
156     {
157         long l_diff = pointer[i_index]->date - searched_date;
158         if( l_diff > 0 && l_diff < abs( p_best_snapshot->date - searched_date ))
159         {
160             /* This one is closer, and _after_ the requested position */
161             p_best_snapshot = pointer[i_index];
162         }
163     }
164
165     /* FIXME: add a test for the case that no picture matched the test
166        ( we have p_best_snapshot == pointer[0] */
167     retval = _mediacontrol_createRGBPicture( p_best_snapshot->i_width,
168                                              p_best_snapshot->i_height,
169                                              p_vout->output.i_chroma,
170                                              p_best_snapshot->date,
171                                              p_best_snapshot->p_data,
172                                              i_datasize );
173
174     vlc_mutex_unlock( &p_vout->picture_lock );
175     vlc_object_release( p_vout );
176
177 #endif
178
179     return retval;
180 }
181
182 mediacontrol_RGBPicture **
183 mediacontrol_all_snapshots( mediacontrol_Instance *self,
184                             mediacontrol_Exception *exception )
185 {
186     mediacontrol_RGBPicture **retval = NULL;
187     vout_thread_t *p_vout = NULL;
188     int i_datasize;
189     int i_cachesize;
190     vlc_value_t val;
191     int i_index;
192 #ifdef HAS_SNAPSHOT
193     snapshot_t **pointer;
194 #endif
195
196     exception=mediacontrol_exception_init( exception );
197
198     if( var_Get( self->p_playlist->p_input, "snapshot-id", &val ) == VLC_SUCCESS )
199         p_vout = vlc_object_get( self->p_vlc, val.i_int );
200
201     if( ! p_vout )
202     {
203         RAISE( mediacontrol_InternalException, "No snapshot module" );
204         return NULL;
205     }
206 #ifdef HAS_SNAPSHOT
207     /* We test if the vout is a snapshot module. We cannot test
208        pvout_psz_object_name( which is NULL ). But we can check if
209        there are snapshot-specific variables */
210     if( var_Get( p_vout, "snapshot-datasize", &val ) != VLC_SUCCESS )
211     {
212         RAISE( mediacontrol_InternalException, "No snapshot module" );
213         vlc_object_release( p_vout );
214         return NULL;
215     }
216     i_datasize = val.i_int;
217
218     vlc_mutex_lock( &p_vout->picture_lock );
219
220     var_Get( p_vout, "snapshot-cache-size", &val );
221     i_cachesize = val.i_int  ;
222
223     var_Get( p_vout, "snapshot-list-pointer", &val );
224     pointer = ( snapshot_t ** )val.p_address;
225
226     if( ! pointer )
227     {
228         RAISE( mediacontrol_InternalException, "No available picture" );
229
230         vlc_mutex_unlock( &p_vout->picture_lock );
231         vlc_object_release( p_vout );
232         return NULL;
233     }
234
235     retval = ( mediacontrol_RGBPicture** )malloc( (i_cachesize + 1 ) * sizeof( char* ));
236
237     for( i_index = 0 ; i_index < i_cachesize ; i_index++ )
238     {
239         snapshot_t *p_s = pointer[i_index];
240         mediacontrol_RGBPicture *p_rgb;
241
242         p_rgb = _mediacontrol_createRGBPicture( p_s->i_width,
243                                                 p_s->i_height,
244                                                 p_vout->output.i_chroma,
245                                                 p_s->date,
246                                                 p_s->p_data,
247                                                 i_datasize );
248
249         retval[i_index] = p_rgb;
250     }
251
252     retval[i_cachesize] = NULL;
253
254     vlc_mutex_unlock( &p_vout->picture_lock );
255     vlc_object_release( p_vout );
256
257 #endif
258
259     return retval;
260 }
261
262 int mediacontrol_showtext( vout_thread_t *p_vout, int i_channel,
263                            char *psz_string, text_style_t *p_style,
264                            int i_flags, int i_hmargin, int i_vmargin,
265                            mtime_t i_start, mtime_t i_stop )
266 {
267     subpicture_t *p_spu;
268     video_format_t fmt;
269
270     if( !psz_string ) return VLC_EGENERIC;
271
272     p_spu = spu_CreateSubpicture( p_vout->p_spu );
273     if( !p_spu ) return VLC_EGENERIC;
274
275     /* Create a new subpicture region */
276     memset( &fmt, 0, sizeof(video_format_t) );
277     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
278     fmt.i_aspect = 0;
279     fmt.i_width = fmt.i_height = 0;
280     fmt.i_x_offset = fmt.i_y_offset = 0;
281     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_vout), &fmt );
282     if( !p_spu->p_region )
283     {
284         msg_Err( p_vout, "cannot allocate SPU region" );
285         spu_DestroySubpicture( p_vout->p_spu, p_spu );
286         return VLC_EGENERIC;
287     }
288
289     p_spu->p_region->psz_text = strdup( psz_string );
290     p_spu->i_start = i_start;
291     p_spu->i_stop = i_stop;
292     p_spu->b_ephemer = VLC_FALSE;
293     p_spu->b_absolute = VLC_FALSE;
294
295     p_spu->i_x = i_hmargin;
296     p_spu->i_y = i_vmargin;
297     p_spu->i_flags = i_flags;
298     p_spu->i_channel = i_channel;
299
300     spu_DisplaySubpicture( p_vout->p_spu, p_spu );
301
302     return VLC_SUCCESS;
303 }
304
305
306 void
307 mediacontrol_display_text( mediacontrol_Instance *self,
308                            const char * message,
309                            const mediacontrol_Position * begin,
310                            const mediacontrol_Position * end,
311                            mediacontrol_Exception *exception )
312 {
313     input_thread_t *p_input = NULL;
314     vout_thread_t *p_vout = NULL;
315     char* psz_message;
316
317     psz_message = strdup( message );
318     if( !psz_message )
319     {
320         RAISE( mediacontrol_InternalException, "No more memory" );
321         return;
322     }
323
324     p_vout = vlc_object_find( self->p_playlist, VLC_OBJECT_VOUT, FIND_CHILD );
325     if( ! p_vout )
326     {
327         RAISE( mediacontrol_InternalException, "No video output" );
328         return;
329     }
330
331     if( begin->origin == mediacontrol_RelativePosition &&
332         begin->value == 0 &&
333         end->origin == mediacontrol_RelativePosition )
334     {
335         mtime_t i_duration = 0;
336         mtime_t i_now = mdate();
337
338         i_duration = 1000 * mediacontrol_unit_convert( self->p_playlist->p_input,
339                                                        end->key,
340                                                        mediacontrol_MediaTime,
341                                                        end->value );
342
343         mediacontrol_showtext( p_vout, DEFAULT_CHAN, psz_message, NULL,
344                                OSD_ALIGN_BOTTOM | OSD_ALIGN_LEFT, 0, 0,
345                                i_now, i_now + i_duration );
346     }
347     else
348     {
349         mtime_t i_debut, i_fin, i_now;
350
351         p_input = self->p_playlist->p_input;
352         if( ! p_input )
353         {
354             RAISE( mediacontrol_InternalException, "No input" );
355             vlc_object_release( p_vout );
356             return;
357         }
358
359         /* FIXME */
360         /* i_now = input_ClockGetTS( p_input, NULL, 0 ); */
361         i_now = mdate();
362         
363         i_debut = mediacontrol_position2microsecond( p_input,
364                                                      ( mediacontrol_Position* ) begin );
365         i_debut += i_now;
366
367         i_fin = mediacontrol_position2microsecond( p_input,
368                                                    ( mediacontrol_Position * ) end );
369         i_fin += i_now;
370
371         vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, psz_message, NULL,
372                                OSD_ALIGN_BOTTOM | OSD_ALIGN_LEFT, 0, 0,
373                                i_debut, i_fin );
374     }
375
376     vlc_object_release( p_vout );
377 }
378
379 unsigned short
380 mediacontrol_sound_get_volume( mediacontrol_Instance *self,
381                                mediacontrol_Exception *exception )
382 {
383     short retval;
384     audio_volume_t i_volume;
385
386     if( !self->p_intf )
387     {
388         RAISE( mediacontrol_InternalException, "No interface module" );
389         return 0;
390     }
391     aout_VolumeGet( self->p_intf, &i_volume );
392     retval = i_volume;
393     return retval;
394 }
395
396 void
397 mediacontrol_sound_set_volume( mediacontrol_Instance *self,
398                                const unsigned short volume,
399                                mediacontrol_Exception *exception )
400 {
401     if( !self->p_intf )
402     {
403         RAISE( mediacontrol_InternalException, "No interface module" );
404         return;
405     }
406     aout_VolumeSet( self->p_intf,( audio_volume_t )volume );
407 }
408
409 vlc_bool_t mediacontrol_set_visual( mediacontrol_Instance *self,
410                                     WINDOWHANDLE visual_id,
411                                     mediacontrol_Exception *exception )
412 {
413     vlc_value_t value;
414     int ret;
415
416     if( !self->p_vlc )
417     {
418         RAISE( mediacontrol_InternalException, "No vlc reference" );
419         return 0;
420     }
421     value.i_int=visual_id;
422     ret = var_Set(self->p_vlc, "drawable", value);
423     
424     return (ret == VLC_SUCCESS);
425 }