2c0d44bd5b480846ec649f9ae35052597e94be4a
[vlc.git] / src / control / mediacontrol_util.c
1 /*****************************************************************************
2  * util.c: Utility functions and exceptions management
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "mediacontrol_internal.h"
25 #include <vlc/mediacontrol.h>
26
27 #include <vlc_interface.h>
28 #include <vlc_aout.h>
29 #include <vlc_input.h>
30 #include <vlc_demux.h>
31
32 #include <vlc_vout.h>
33 #include <vlc_osd.h>
34
35 #include <stdlib.h>                                      /* malloc(), free() */
36 #include <string.h>
37
38 #include <errno.h>                                                 /* ENOMEM */
39 #include <stdio.h>
40 #include <ctype.h>
41
42 #ifdef HAVE_UNISTD_H
43 #    include <unistd.h>
44 #endif
45 #ifdef HAVE_SYS_TIME_H
46 #    include <sys/time.h>
47 #endif
48 #ifdef HAVE_SYS_TYPES_H
49 #    include <sys/types.h>
50 #endif
51
52 #define RAISE( c, m )  exception->code = c; \
53                        exception->message = strdup(m);
54
55 /* FIXME: Need to stop accessing private input structures !! */
56 #include "input/input_internal.h"
57
58 vlc_int64_t mediacontrol_unit_convert( input_thread_t *p_input,
59                                        mediacontrol_PositionKey from,
60                                        mediacontrol_PositionKey to,
61                                        vlc_int64_t value )
62 {
63     if( to == from )
64         return value;
65
66     /* For all conversions, we need data from p_input */
67     if( !p_input )
68         return 0;
69
70     switch( from )
71     {
72     case mediacontrol_MediaTime:
73         if( to == mediacontrol_ByteCount )
74         {
75             /* FIXME */
76             /* vlc < 0.8 API */
77             /* return value * 50 * p_input->stream.i_mux_rate / 1000; */
78             return 0;
79         }
80         if( to == mediacontrol_SampleCount )
81         {
82             double f_fps;
83
84             if( demux2_Control( p_input->p->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
85                 return 0;
86             else
87                 return( value * f_fps / 1000.0 );
88         }
89         /* Cannot happen */
90         /* See http://catb.org/~esr/jargon/html/entry/can't-happen.html */
91         break;
92
93     case mediacontrol_SampleCount:
94     {
95         double f_fps;
96
97         if( demux2_Control( p_input->p->input.p_demux, DEMUX_GET_FPS, &f_fps ) ||
98                                 f_fps < 0.1 )
99             return 0;
100
101         if( to == mediacontrol_ByteCount )
102         {
103             /* FIXME */
104             /* vlc < 0.8 API */
105 /*             return ( vlc_int64_t )( value * 50 * p_input->stream.i_mux_rate / f_fps ); */
106             return 0;
107         }
108
109         if( to == mediacontrol_MediaTime )
110             return( vlc_int64_t )( value * 1000.0 / ( double )f_fps );
111
112         /* Cannot happen */
113         break;
114     }
115     case mediacontrol_ByteCount:
116         /* FIXME */
117         return 0;
118 /* vlc < 0.8 API: */
119
120 //         if( p_input->stream.i_mux_rate == 0 )
121 //             return 0;
122 // 
123 //         /* Convert an offset into milliseconds. Taken from input_ext-intf.c.
124 //            The 50 hardcoded constant comes from the definition of i_mux_rate :
125 //            i_mux_rate : the rate we read the stream (in units of 50 bytes/s) ;
126 //            0 if undef */
127 //         if( to == mediacontrol_MediaTime )
128 //             return ( vlc_int64_t )( 1000 * value / 50 / p_input->stream.i_mux_rate );
129 // 
130 //         if( to == mediacontrol_SampleCount )
131 //         {
132 //             double f_fps;
133 //             if( demux2_Control( p_input->input.p_demux, DEMUX_GET_FPS, &f_fps ) || f_fps < 0.1 )
134 //                 return 0;
135 //             else
136 //                 return ( vlc_int64_t )( value * f_fps / 50 / p_input->stream.i_mux_rate );
137 //         }
138         /* Cannot happen */
139         break;
140     }
141     /* Cannot happen */
142     return 0;
143 }
144
145 /* Converts a mediacontrol_Position into a time in microseconds in
146    movie clock time */
147 vlc_int64_t
148 mediacontrol_position2microsecond( input_thread_t* p_input, const mediacontrol_Position * pos )
149 {
150     switch( pos->origin )
151     {
152     case mediacontrol_AbsolutePosition:
153         return ( 1000 * mediacontrol_unit_convert( p_input,
154                                                    pos->key, /* from */
155                                                    mediacontrol_MediaTime,  /* to */
156                                                    pos->value ) );
157         break;
158     case mediacontrol_RelativePosition:
159     {
160         vlc_int64_t l_pos;
161         vlc_value_t val;
162
163         val.i_time = 0;
164         if( p_input )
165         {
166             var_Get( p_input, "time", &val );
167         }
168
169         l_pos = 1000 * mediacontrol_unit_convert( p_input,
170                                                   pos->key,
171                                                   mediacontrol_MediaTime,
172                                                   pos->value );
173         return val.i_time + l_pos;
174         break;
175     }
176     case mediacontrol_ModuloPosition:
177     {
178         vlc_int64_t l_pos;
179         vlc_value_t val;
180
181         val.i_time = 0;
182         if( p_input )
183         {
184             var_Get( p_input, "length", &val );
185         }
186
187         if( val.i_time > 0)
188         {
189             l_pos = ( 1000 * mediacontrol_unit_convert( p_input,
190                                                         pos->key,
191                                                         mediacontrol_MediaTime,
192                                                         pos->value ) );
193         }
194         else
195             l_pos = 0;
196
197         return l_pos % val.i_time;
198         break;
199     }
200     }
201     return 0;
202 }
203
204 mediacontrol_RGBPicture*
205 mediacontrol_RGBPicture__alloc( int datasize )
206 {
207     mediacontrol_RGBPicture* pic;
208
209     pic = ( mediacontrol_RGBPicture * )malloc( sizeof( mediacontrol_RGBPicture ) );
210     if( ! pic )
211         return NULL;
212
213     pic->size = datasize;
214     pic->data = ( char* )malloc( datasize * sizeof( char ) );
215     return pic;
216 }
217
218 void
219 mediacontrol_RGBPicture__free( mediacontrol_RGBPicture* pic )
220 {
221     if( pic )
222         free( pic->data );
223     free( pic );
224 }
225
226 mediacontrol_PlaylistSeq*
227 mediacontrol_PlaylistSeq__alloc( int size )
228 {
229     mediacontrol_PlaylistSeq* ps;
230
231     ps =( mediacontrol_PlaylistSeq* )malloc( sizeof( mediacontrol_PlaylistSeq ) );
232     if( ! ps )
233         return NULL;
234
235     ps->size = size;
236     ps->data = ( char** )malloc( size * sizeof( char* ) );
237     return ps;
238 }
239
240 void
241 mediacontrol_PlaylistSeq__free( mediacontrol_PlaylistSeq* ps )
242 {
243     if( ps )
244     {
245         int i;
246         for( i = 0 ; i < ps->size ; i++ )
247             free( ps->data[i] );
248     }
249     free( ps->data );
250     free( ps );
251 }
252
253 /**
254  * Initialize a VLC exception.
255  *
256  * If given a NULL pointer, it will instanciate a new exception, which
257  * should be later freed by the caller. If given an existing
258  * exception, it will reset its code and message fields. In both
259  * cases, the exception pointer is returned.
260  *
261  * \param exception a pointer on a mediacontrol_Exception
262  * \return a pointer on a mediacontrol_Exception.
263  */
264 mediacontrol_Exception*
265 mediacontrol_exception_init( mediacontrol_Exception *exception )
266 {
267     if( !exception )
268     {
269         exception = ( mediacontrol_Exception* )malloc( sizeof( mediacontrol_Exception ) );
270         if( !exception )
271         {
272             return NULL;
273         }
274     }
275     exception->code = 0;
276     exception->message = NULL;
277     return exception;
278 }
279
280 void
281 mediacontrol_exception_free( mediacontrol_Exception *exception )
282 {
283     if( ! exception )
284         return;
285
286     free( exception->message );
287     free( exception );
288 }
289
290 mediacontrol_RGBPicture*
291 _mediacontrol_createRGBPicture( int i_width, int i_height, long i_chroma, vlc_int64_t l_date,
292                                 char* p_data, int i_datasize )
293 {
294     mediacontrol_RGBPicture *retval;
295
296     retval = mediacontrol_RGBPicture__alloc( i_datasize );
297     if( retval )
298     {
299         retval->width  = i_width;
300         retval->height = i_height;
301         retval->type   = i_chroma;
302         retval->date   = l_date;
303         retval->size   = i_datasize;
304         memcpy( retval->data, p_data, i_datasize );
305     }
306     return retval;
307 }