1 /*
2  * Copyright (C) 2000-2020 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * convenience/abstraction layer, functions to implement
21  * libxine's public interface
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <sys/types.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <pthread.h>
32 #include <stdarg.h>
33 #if defined (__linux__) || defined (__GLIBC__)
34 #include <endian.h>
35 #elif defined (__FreeBSD__)
36 #include <machine/endian.h>
37 #endif
38 
39 #include <xine/xine_internal.h>
40 #include <xine/audio_out.h>
41 #include <xine/video_out.h>
42 #include <xine/demux.h>
43 #include <xine/post.h>
44 
45 #include "xine_private.h"
46 
47 /*
48  * version information / checking
49  */
50 
xine_get_version_string(void)51 const char *xine_get_version_string(void) {
52   return VERSION
53 #ifndef NDEBUG
54     "[DEBUG]"
55 #endif
56     ;
57 }
58 
xine_get_version(int * major,int * minor,int * sub)59 void xine_get_version (int *major, int *minor, int *sub) {
60   *major = XINE_MAJOR;
61   *minor = XINE_MINOR;
62   *sub   = XINE_SUB;
63 }
64 
xine_check_version(int major,int minor,int sub)65 int xine_check_version(int major, int minor, int sub) {
66 
67   if((XINE_MAJOR > major) ||
68      ((XINE_MAJOR == major) && (XINE_MINOR > minor)) ||
69      ((XINE_MAJOR == major) && (XINE_MINOR == minor) && (XINE_SUB >= sub)))
70     return 1;
71 
72   return 0;
73 }
74 
75 /*
76  * public config object access functions
77  */
78 
xine_config_register_string(xine_t * self,const char * key,const char * def_value,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)79 const char* xine_config_register_string (xine_t *self,
80 					 const char *key,
81 					 const char *def_value,
82 					 const char *description,
83 					 const char *help,
84 					 int   exp_level,
85 					 xine_config_cb_t changed_cb,
86 					 void *cb_data) {
87 
88   return self->config->register_string (self->config,
89 					key,
90 					def_value,
91 					description,
92 					help,
93 					exp_level,
94 					changed_cb,
95 					cb_data);
96 
97 }
98 
xine_config_register_filename(xine_t * self,const char * key,const char * def_value,int req_type,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)99 const char* xine_config_register_filename (xine_t *self,
100 					   const char *key,
101 					   const char *def_value,
102 					   int req_type,
103 					   const char *description,
104 					   const char *help,
105 					   int   exp_level,
106 					   xine_config_cb_t changed_cb,
107 					   void *cb_data) {
108 
109   return self->config->register_filename (self->config,
110 					  key, def_value, req_type,
111 					  description, help, exp_level,
112 					  changed_cb, cb_data);
113 }
114 
xine_config_register_range(xine_t * self,const char * key,int def_value,int min,int max,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)115 int xine_config_register_range (xine_t *self,
116 				const char *key,
117 				int def_value,
118 				int min, int max,
119 				const char *description,
120 				const char *help,
121 				int   exp_level,
122 				xine_config_cb_t changed_cb,
123 				void *cb_data) {
124   return self->config->register_range (self->config,
125 				       key, def_value, min, max,
126 				       description, help, exp_level,
127 				       changed_cb, cb_data);
128 }
129 
130 
xine_config_register_enum(xine_t * self,const char * key,int def_value,char ** values,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)131 int xine_config_register_enum (xine_t *self,
132 			       const char *key,
133 			       int def_value,
134 			       char **values,
135 			       const char *description,
136 			       const char *help,
137 			       int   exp_level,
138 			       xine_config_cb_t changed_cb,
139 			       void *cb_data) {
140   return self->config->register_enum (self->config,
141 				      key, def_value, values,
142 				      description, help, exp_level,
143 				      changed_cb, cb_data);
144 }
145 
146 
xine_config_register_num(xine_t * self,const char * key,int def_value,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)147 int xine_config_register_num (xine_t *self,
148 			      const char *key,
149 			      int def_value,
150 			      const char *description,
151 			      const char *help,
152 			      int   exp_level,
153 			      xine_config_cb_t changed_cb,
154 			      void *cb_data) {
155   return self->config->register_num (self->config,
156 				     key, def_value,
157 				     description, help, exp_level,
158 				     changed_cb, cb_data);
159 }
160 
161 
xine_config_register_bool(xine_t * self,const char * key,int def_value,const char * description,const char * help,int exp_level,xine_config_cb_t changed_cb,void * cb_data)162 int xine_config_register_bool (xine_t *self,
163 			       const char *key,
164 			       int def_value,
165 			       const char *description,
166 			       const char *help,
167 			       int   exp_level,
168 			       xine_config_cb_t changed_cb,
169 			       void *cb_data) {
170   return self->config->register_bool (self->config,
171 				      key, def_value,
172 				      description, help, exp_level,
173 				      changed_cb, cb_data);
174 }
175 
xine_config_unregister_callbacks(xine_t * self,const char * key,xine_config_cb_t changed_cb,void * cb_data,size_t cb_data_size)176 int xine_config_unregister_callbacks (xine_t *self,
177   const char *key, xine_config_cb_t changed_cb, void *cb_data, size_t cb_data_size) {
178   /* avoid misuse */
179   if (!key && !changed_cb && !cb_data)
180     return 0;
181   if (!self)
182     return 0;
183   if (!self->config)
184     return 0;
185   return self->config->unregister_callbacks (self->config, key, changed_cb, cb_data, cb_data_size);
186 }
187 
xine_config_lookup_num(xine_t * this,const char * key,int def_value)188 int xine_config_lookup_num(xine_t *this, const char *key, int def_value) {
189   return this->config->lookup_num(this->config, key, def_value);
190 }
191 
xine_config_lookup_string(xine_t * this,const char * key)192 char *xine_config_lookup_string(xine_t *this, const char *key) {
193   return this->config->lookup_string(this->config, key);
194 }
195 
xine_config_free_string(xine_t * this,char ** value)196 void xine_config_free_string(xine_t *this, char **value) {
197   this->config->free_string(this->config, value);
198 }
199 
200 /*
201  * helper function:
202  *
203  * copy current config entry data to user-provided memory
204  * and return status
205  */
206 
config_get_current_entry(xine_t * this,xine_cfg_entry_t * entry)207 static int config_get_current_entry (xine_t *this, xine_cfg_entry_t *entry) {
208 
209   config_values_t *config = this->config;
210 
211   if (!config->cur)
212     return 0;
213 
214   entry->key            = config->cur->key;
215   entry->type           = config->cur->type;
216   entry->str_value      = config->cur->str_value;
217   entry->str_default    = config->cur->str_default;
218   entry->num_value      = config->cur->num_value;
219   entry->num_default    = config->cur->num_default;
220   entry->range_min      = config->cur->range_min;
221   entry->range_max      = config->cur->range_max;
222   entry->enum_values    = config->cur->enum_values;
223 
224   entry->description    = config->cur->description;
225   entry->help           = config->cur->help;
226   entry->callback       = config->cur->callback;
227   entry->callback_data  = config->cur->callback_data;
228   entry->exp_level      = config->cur->exp_level;
229 
230   return 1;
231 }
232 
233 /*
234  * get first config item
235  */
xine_config_get_first_entry(xine_t * this,xine_cfg_entry_t * entry)236 int  xine_config_get_first_entry (xine_t *this, xine_cfg_entry_t *entry) {
237   int result;
238   config_values_t *config = this->config;
239 
240   pthread_mutex_lock(&config->config_lock);
241   config->cur = config->first;
242 
243   /* do not hand out unclaimed entries */
244   while (config->cur && config->cur->type == XINE_CONFIG_TYPE_UNKNOWN)
245     config->cur = config->cur->next;
246   result = config_get_current_entry (this, entry);
247   pthread_mutex_unlock(&config->config_lock);
248 
249   return result;
250 }
251 
252 
253 /*
254  * get next config item (iterate through the items)
255  * this will return NULL when called after returning the last item
256  */
xine_config_get_next_entry(xine_t * this,xine_cfg_entry_t * entry)257 int xine_config_get_next_entry (xine_t *this, xine_cfg_entry_t *entry) {
258   int result;
259   config_values_t *config = this->config;
260 
261   pthread_mutex_lock(&config->config_lock);
262 
263   if (!config->cur) {
264     pthread_mutex_unlock(&config->config_lock);
265     return (xine_config_get_first_entry(this, entry));
266   }
267 
268   /* do not hand out unclaimed entries */
269   do {
270     config->cur = config->cur->next;
271   } while (config->cur && config->cur->type == XINE_CONFIG_TYPE_UNKNOWN);
272   result = config_get_current_entry (this, entry);
273   pthread_mutex_unlock(&config->config_lock);
274 
275   return result;
276 }
277 
278 
279 /*
280  * search for a config entry by key
281  */
282 
xine_config_lookup_entry(xine_t * this,const char * key,xine_cfg_entry_t * entry)283 int xine_config_lookup_entry (xine_t *this, const char *key,
284 			      xine_cfg_entry_t *entry) {
285   int result;
286   config_values_t *config = this->config;
287 
288   pthread_mutex_lock(&config->config_lock);
289   /* safe because of the mutex is recursive */
290   config->cur = config->lookup_entry (config, key);
291 
292   /* do not hand out unclaimed entries */
293   if (config->cur && config->cur->type == XINE_CONFIG_TYPE_UNKNOWN)
294     config->cur = NULL;
295   result = config_get_current_entry (this, entry);
296   pthread_mutex_unlock(&config->config_lock);
297 
298   return result;
299 }
300 
301 
302 /*
303  * update a config entry (which was returned from lookup_entry() )
304  */
xine_config_update_entry(xine_t * this,const xine_cfg_entry_t * entry)305 void xine_config_update_entry (xine_t *this, const xine_cfg_entry_t *entry) {
306 
307   switch (entry->type) {
308   case XINE_CONFIG_TYPE_RANGE:
309   case XINE_CONFIG_TYPE_ENUM:
310   case XINE_CONFIG_TYPE_NUM:
311   case XINE_CONFIG_TYPE_BOOL:
312     this->config->update_num (this->config, entry->key, entry->num_value);
313     break;
314 
315   case XINE_CONFIG_TYPE_STRING:
316     this->config->update_string (this->config, entry->key, entry->str_value);
317     break;
318 
319   default:
320     xprintf (this, XINE_VERBOSITY_DEBUG,
321 	     "xine_interface: error, unknown config entry type %d\n", entry->type);
322     break;
323   }
324 }
325 
326 
xine_config_reset(xine_t * this)327 void xine_config_reset (xine_t *this) {
328 
329   config_values_t *config = this->config;
330   cfg_entry_t *entry;
331 
332   pthread_mutex_lock(&config->config_lock);
333   config->cur = NULL;
334 
335   entry = config->first;
336   while (entry) {
337     cfg_entry_t *next;
338     next = entry->next;
339     free (entry);
340     entry = next;
341   }
342 
343   config->first = NULL;
344   config->last = NULL;
345   pthread_mutex_unlock(&config->config_lock);
346 }
347 
xine_port_send_gui_data(xine_video_port_t * vo,int type,void * data)348 int xine_port_send_gui_data (xine_video_port_t *vo,
349 			   int type, void *data) {
350 
351   return vo->driver->gui_data_exchange (vo->driver,
352 						  type, data);
353 }
354 
send_audio_amp_event_internal(xine_stream_private_t * stream)355 static void send_audio_amp_event_internal (xine_stream_private_t *stream) {
356   xine_event_t            event;
357   xine_audio_level_data_t data;
358 
359   data.left
360     = data.right
361     = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP);
362   data.mute
363     = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP_MUTE);
364 
365   event.type        = XINE_EVENT_AUDIO_AMP_LEVEL;
366   event.data        = &data;
367   event.data_length = sizeof (data);
368 
369   xine_event_send (&stream->s, &event);
370 }
371 
xine_set_param(xine_stream_t * s,int param,int value)372 void xine_set_param (xine_stream_t *s, int param, int value) {
373   xine_stream_private_t *stream = (xine_stream_private_t *)s;
374   xine_private_t *xine;
375   /* Avoid crashing */
376   if ( ! stream ) {
377     lprintf ("xine_interface: xine_set_param called with NULL stream.\n");
378     return;
379   }
380   xine = (xine_private_t *)stream->s.xine;
381 
382   switch (param) {
383   case XINE_PARAM_SPEED:
384     pthread_mutex_lock (&stream->frontend_lock);
385     _x_set_speed (&stream->s, value);
386     pthread_mutex_unlock (&stream->frontend_lock);
387     break;
388 
389   case XINE_PARAM_FINE_SPEED:
390     pthread_mutex_lock (&stream->frontend_lock);
391     _x_set_fine_speed (&stream->s, value);
392     pthread_mutex_unlock (&stream->frontend_lock);
393     break;
394 
395   case XINE_PARAM_AV_OFFSET:
396     stream->s.metronom->set_option (stream->s.metronom, METRONOM_AV_OFFSET, value);
397     break;
398 
399   case XINE_PARAM_SPU_OFFSET:
400     stream->s.metronom->set_option (stream->s.metronom, METRONOM_SPU_OFFSET, value);
401     break;
402 
403   case XINE_PARAM_AUDIO_CHANNEL_LOGICAL:
404     pthread_mutex_lock (&stream->frontend_lock);
405     if (value < -2)
406       value = -2;
407     stream->audio_channel_user = value;
408     pthread_mutex_unlock (&stream->frontend_lock);
409     break;
410 
411   case XINE_PARAM_SPU_CHANNEL:
412     _x_select_spu_channel (&stream->s, value);
413     break;
414 
415   case XINE_PARAM_VIDEO_CHANNEL:
416     pthread_mutex_lock (&stream->frontend_lock);
417     if (value<0)
418       value = 0;
419     stream->video_channel = value;
420     pthread_mutex_unlock (&stream->frontend_lock);
421     break;
422 
423   case XINE_PARAM_AUDIO_VOLUME:
424     xine->port_ticket->acquire (xine->port_ticket, 1);
425     if (stream->s.audio_out)
426       stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_MIXER_VOL, value);
427     xine->port_ticket->release (xine->port_ticket, 1);
428     break;
429 
430   case XINE_PARAM_AUDIO_MUTE:
431     xine->port_ticket->acquire (xine->port_ticket, 1);
432     if (stream->s.audio_out)
433       stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_MUTE_VOL, value);
434     xine->port_ticket->release (xine->port_ticket, 1);
435     break;
436 
437   case XINE_PARAM_AUDIO_COMPR_LEVEL:
438     xine->port_ticket->acquire (xine->port_ticket, 1);
439     if (stream->s.audio_out)
440       stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_COMPRESSOR, value);
441     xine->port_ticket->release (xine->port_ticket, 1);
442     break;
443 
444   case XINE_PARAM_AUDIO_AMP_LEVEL:
445     xine->port_ticket->acquire (xine->port_ticket, 1);
446     if (stream->s.audio_out) {
447       int old_value = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP);
448       if (old_value != stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_AMP, value))
449         send_audio_amp_event_internal (stream);
450     }
451     xine->port_ticket->release(xine->port_ticket, 1);
452     break;
453 
454   case XINE_PARAM_AUDIO_AMP_MUTE:
455     xine->port_ticket->acquire (xine->port_ticket, 1);
456     if (stream->s.audio_out) {
457       int old_value = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP_MUTE);
458       if (old_value != stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_AMP_MUTE, value))
459         send_audio_amp_event_internal(stream);
460     }
461     xine->port_ticket->release (xine->port_ticket, 1);
462     break;
463 
464   case XINE_PARAM_AUDIO_CLOSE_DEVICE:
465     xine->port_ticket->acquire (xine->port_ticket, 1);
466     if (stream->s.audio_out)
467       stream->s.audio_out->set_property (stream->s.audio_out, AO_PROP_CLOSE_DEVICE, value);
468     xine->port_ticket->release (xine->port_ticket, 1);
469     break;
470 
471   case XINE_PARAM_EQ_30HZ:
472   case XINE_PARAM_EQ_60HZ:
473   case XINE_PARAM_EQ_125HZ:
474   case XINE_PARAM_EQ_250HZ:
475   case XINE_PARAM_EQ_500HZ:
476   case XINE_PARAM_EQ_1000HZ:
477   case XINE_PARAM_EQ_2000HZ:
478   case XINE_PARAM_EQ_4000HZ:
479   case XINE_PARAM_EQ_8000HZ:
480   case XINE_PARAM_EQ_16000HZ:
481     xine->port_ticket->acquire (xine->port_ticket, 1);
482     if (stream->s.audio_out)
483       stream->s.audio_out->set_property (stream->s.audio_out,
484 				       param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ,
485 				       value);
486     xine->port_ticket->release (xine->port_ticket, 1);
487     break;
488 
489   case XINE_PARAM_VERBOSITY:
490     stream->s.xine->verbosity = value;
491     break;
492 
493   case XINE_PARAM_VO_SHARPNESS:
494   case XINE_PARAM_VO_NOISE_REDUCTION:
495   case XINE_PARAM_VO_HUE:
496   case XINE_PARAM_VO_SATURATION:
497   case XINE_PARAM_VO_CONTRAST:
498   case XINE_PARAM_VO_BRIGHTNESS:
499   case XINE_PARAM_VO_GAMMA:
500   case XINE_PARAM_VO_DEINTERLACE:
501   case XINE_PARAM_VO_ASPECT_RATIO:
502   case XINE_PARAM_VO_ZOOM_X:
503   case XINE_PARAM_VO_ZOOM_Y:
504   case XINE_PARAM_VO_TVMODE:
505   case XINE_PARAM_VO_CROP_LEFT:
506   case XINE_PARAM_VO_CROP_RIGHT:
507   case XINE_PARAM_VO_CROP_TOP:
508   case XINE_PARAM_VO_CROP_BOTTOM:
509     xine->port_ticket->acquire (xine->port_ticket, 1);
510     stream->s.video_out->set_property (stream->s.video_out, param, value);
511     xine->port_ticket->release (xine->port_ticket, 1);
512     break;
513 
514   case XINE_PARAM_VO_SINGLE_STEP:
515     pthread_mutex_lock (&stream->frontend_lock);
516     if (_x_get_fine_speed (&stream->s) != XINE_SPEED_PAUSE) {
517       _x_set_fine_speed (&stream->s, XINE_SPEED_PAUSE);
518     } else {
519       /* HACK: temporarily resume decoders. */
520       _x_set_fine_speed (&stream->s, XINE_LIVE_PAUSE_ON);
521       /* rather miss 1 strobe than wait or freeze. */
522       if (xine->port_ticket->ticket_revoked == 0) {
523         xine->port_ticket->acquire (xine->port_ticket, 1);
524         stream->s.video_out->set_property (stream->s.video_out, param, value);
525         stream->s.audio_out->set_property (stream->s.audio_out, param, value);
526         xine->port_ticket->release (xine->port_ticket, 1);
527       }
528     }
529     pthread_mutex_unlock (&stream->frontend_lock);
530     break;
531 
532   case XINE_PARAM_IGNORE_VIDEO:
533     _x_stream_info_set (&stream->s, XINE_STREAM_INFO_IGNORE_VIDEO, value);
534     break;
535 
536   case XINE_PARAM_IGNORE_AUDIO:
537     _x_stream_info_set (&stream->s, XINE_STREAM_INFO_IGNORE_AUDIO, value);
538     break;
539 
540   case XINE_PARAM_IGNORE_SPU:
541     _x_stream_info_set (&stream->s, XINE_STREAM_INFO_IGNORE_SPU, value);
542     break;
543 
544   case XINE_PARAM_METRONOM_PREBUFFER:
545     stream->s.metronom->set_option (stream->s.metronom, METRONOM_PREBUFFER, value);
546     break;
547 
548   case XINE_PARAM_BROADCASTER_PORT:
549     if( !stream->broadcaster && value ) {
550       stream->broadcaster = _x_init_broadcaster (&stream->s, value);
551     } else if ( stream->broadcaster && !value ) {
552       _x_close_broadcaster(stream->broadcaster);
553       stream->broadcaster = NULL;
554     }
555     break;
556 
557   case XINE_PARAM_EARLY_FINISHED_EVENT:
558     stream->early_finish_event = !!value;
559     break;
560 
561   case XINE_PARAM_DELAY_FINISHED_EVENT:
562     stream->delay_finish_event = value;
563     break;
564 
565   case XINE_PARAM_GAPLESS_SWITCH:
566     stream->gapless_switch = !!value;
567     if( stream->gapless_switch && !stream->early_finish_event ) {
568       xprintf (stream->s.xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n");
569     }
570     break;
571 
572   default:
573     xprintf (stream->s.xine, XINE_VERBOSITY_DEBUG,
574 	     "xine_interface: unknown or deprecated stream param %d set\n", param);
575   }
576 }
577 
xine_get_param(xine_stream_t * s,int param)578 int xine_get_param (xine_stream_t *s, int param) {
579   xine_stream_private_t *stream = (xine_stream_private_t *)s;
580   xine_private_t *xine;
581   int ret;
582   /* Avoid crashing */
583   if ( ! stream ) {
584     lprintf ("xine_interface: xine_set_param called with NULL stream.\n");
585     return 0;
586   }
587   xine = (xine_private_t *)stream->s.xine;
588 
589   switch (param) {
590   case XINE_PARAM_SPEED:
591     ret = _x_get_speed (&stream->s);
592     break;
593 
594   case XINE_PARAM_FINE_SPEED:
595     ret = _x_get_fine_speed (&stream->s);
596     break;
597 
598   case XINE_PARAM_AV_OFFSET:
599     ret = stream->s.metronom->get_option (stream->s.metronom, METRONOM_AV_OFFSET);
600     break;
601 
602   case XINE_PARAM_SPU_OFFSET:
603     ret = stream->s.metronom->get_option (stream->s.metronom, METRONOM_SPU_OFFSET);
604     break;
605 
606   case XINE_PARAM_AUDIO_CHANNEL_LOGICAL:
607     ret = stream->audio_channel_user;
608     break;
609 
610   case XINE_PARAM_SPU_CHANNEL:
611     ret = stream->s.spu_channel_user;
612     break;
613 
614   case XINE_PARAM_VIDEO_CHANNEL:
615     ret = stream->video_channel;
616     break;
617 
618   case XINE_PARAM_AUDIO_VOLUME:
619     xine->port_ticket->acquire (xine->port_ticket, 1);
620     if (!stream->s.audio_out)
621       ret = -1;
622     else
623       ret = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_MIXER_VOL);
624     xine->port_ticket->release (xine->port_ticket, 1);
625     break;
626 
627   case XINE_PARAM_AUDIO_MUTE:
628     xine->port_ticket->acquire (xine->port_ticket, 1);
629     if (!stream->s.audio_out)
630       ret = -1;
631     else
632       ret = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_MUTE_VOL);
633     xine->port_ticket->release (xine->port_ticket, 1);
634     break;
635 
636   case XINE_PARAM_AUDIO_COMPR_LEVEL:
637     xine->port_ticket->acquire (xine->port_ticket, 1);
638     if (!stream->s.audio_out)
639       ret = -1;
640     else
641       ret = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_COMPRESSOR);
642     xine->port_ticket->release (xine->port_ticket, 1);
643     break;
644 
645   case XINE_PARAM_AUDIO_AMP_LEVEL:
646     xine->port_ticket->acquire (xine->port_ticket, 1);
647     if (!stream->s.audio_out)
648       ret = -1;
649     else
650       ret = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP);
651     xine->port_ticket->release (xine->port_ticket, 1);
652     break;
653 
654   case XINE_PARAM_AUDIO_AMP_MUTE:
655     xine->port_ticket->acquire (xine->port_ticket, 1);
656     if (!stream->s.audio_out)
657       ret = -1;
658     else
659       ret = stream->s.audio_out->get_property (stream->s.audio_out, AO_PROP_AMP_MUTE);
660     xine->port_ticket->release (xine->port_ticket, 1);
661     break;
662 
663   case XINE_PARAM_EQ_30HZ:
664   case XINE_PARAM_EQ_60HZ:
665   case XINE_PARAM_EQ_125HZ:
666   case XINE_PARAM_EQ_250HZ:
667   case XINE_PARAM_EQ_500HZ:
668   case XINE_PARAM_EQ_1000HZ:
669   case XINE_PARAM_EQ_2000HZ:
670   case XINE_PARAM_EQ_4000HZ:
671   case XINE_PARAM_EQ_8000HZ:
672   case XINE_PARAM_EQ_16000HZ:
673     xine->port_ticket->acquire (xine->port_ticket, 1);
674     if (!stream->s.audio_out)
675       ret = -1;
676     else
677       ret=  stream->s.audio_out->get_property (stream->s.audio_out,
678 					     param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ);
679     xine->port_ticket->release (xine->port_ticket, 1);
680     break;
681 
682   case XINE_PARAM_VERBOSITY:
683     ret = stream->s.xine->verbosity;
684     break;
685 
686   case XINE_PARAM_VO_SHARPNESS:
687   case XINE_PARAM_VO_NOISE_REDUCTION:
688   case XINE_PARAM_VO_HUE:
689   case XINE_PARAM_VO_SATURATION:
690   case XINE_PARAM_VO_CONTRAST:
691   case XINE_PARAM_VO_BRIGHTNESS:
692   case XINE_PARAM_VO_GAMMA:
693   case XINE_PARAM_VO_DEINTERLACE:
694   case XINE_PARAM_VO_ASPECT_RATIO:
695   case XINE_PARAM_VO_ZOOM_X:
696   case XINE_PARAM_VO_ZOOM_Y:
697   case XINE_PARAM_VO_TVMODE:
698   case XINE_PARAM_VO_WINDOW_WIDTH:
699   case XINE_PARAM_VO_WINDOW_HEIGHT:
700   case XINE_PARAM_VO_CROP_LEFT:
701   case XINE_PARAM_VO_CROP_RIGHT:
702   case XINE_PARAM_VO_CROP_TOP:
703   case XINE_PARAM_VO_CROP_BOTTOM:
704     xine->port_ticket->acquire (xine->port_ticket, 1);
705     ret = stream->s.video_out->get_property(stream->s.video_out, param);
706     xine->port_ticket->release (xine->port_ticket, 1);
707     break;
708 
709   case XINE_PARAM_IGNORE_VIDEO:
710     ret = _x_stream_info_get_public (&stream->s, XINE_STREAM_INFO_IGNORE_VIDEO);
711     break;
712 
713   case XINE_PARAM_IGNORE_AUDIO:
714     ret = _x_stream_info_get_public (&stream->s, XINE_STREAM_INFO_IGNORE_AUDIO);
715     break;
716 
717   case XINE_PARAM_IGNORE_SPU:
718     ret = _x_stream_info_get_public (&stream->s, XINE_STREAM_INFO_IGNORE_SPU);
719     break;
720 
721   case XINE_PARAM_METRONOM_PREBUFFER:
722     ret = stream->s.metronom->get_option (stream->s.metronom, METRONOM_PREBUFFER);
723     break;
724 
725   case XINE_PARAM_BROADCASTER_PORT:
726     if( stream->broadcaster )
727       ret = _x_get_broadcaster_port(stream->broadcaster);
728     else
729       ret = 0;
730     break;
731 
732   case XINE_PARAM_EARLY_FINISHED_EVENT:
733     ret = stream->early_finish_event;
734     break;
735 
736   case XINE_PARAM_DELAY_FINISHED_EVENT:
737     ret = stream->delay_finish_event;
738     break;
739 
740   case XINE_PARAM_GAPLESS_SWITCH:
741     ret = stream->gapless_switch;
742     break;
743 
744   default:
745     xprintf (stream->s.xine, XINE_VERBOSITY_DEBUG,
746 	     "xine_interface: unknown or deprecated stream param %d requested\n", param);
747     ret = 0;
748   }
749 
750   return ret;
751 }
752 
xine_get_stream_info(xine_stream_t * s,int info)753 uint32_t xine_get_stream_info (xine_stream_t *s, int info) {
754   xine_stream_private_t *stream = (xine_stream_private_t *)s;
755 
756   switch (info) {
757 
758   case XINE_STREAM_INFO_SEEKABLE:
759     if (stream->s.input_plugin)
760       return stream->s.input_plugin->get_capabilities (stream->s.input_plugin)
761         & (INPUT_CAP_SEEKABLE | INPUT_CAP_SLOW_SEEKABLE | INPUT_CAP_TIME_SEEKABLE);
762     return 0;
763 
764   case XINE_STREAM_INFO_HAS_CHAPTERS:
765     if (stream->demux.plugin)
766       if (stream->demux.plugin->get_capabilities (stream->demux.plugin) & DEMUX_CAP_CHAPTERS)
767         return 1;
768     if (stream->s.input_plugin)
769       if (stream->s.input_plugin->get_capabilities (stream->s.input_plugin) & INPUT_CAP_CHAPTERS)
770         return 1;
771     return 0;
772 
773   case XINE_STREAM_INFO_BITRATE:
774   case XINE_STREAM_INFO_VIDEO_WIDTH:
775   case XINE_STREAM_INFO_VIDEO_HEIGHT:
776   case XINE_STREAM_INFO_VIDEO_RATIO:
777   case XINE_STREAM_INFO_VIDEO_CHANNELS:
778   case XINE_STREAM_INFO_VIDEO_STREAMS:
779   case XINE_STREAM_INFO_VIDEO_BITRATE:
780   case XINE_STREAM_INFO_VIDEO_FOURCC:
781   case XINE_STREAM_INFO_VIDEO_HANDLED:
782   case XINE_STREAM_INFO_FRAME_DURATION:
783   case XINE_STREAM_INFO_AUDIO_CHANNELS:
784   case XINE_STREAM_INFO_AUDIO_BITS:
785   case XINE_STREAM_INFO_AUDIO_SAMPLERATE:
786   case XINE_STREAM_INFO_AUDIO_BITRATE:
787   case XINE_STREAM_INFO_AUDIO_FOURCC:
788   case XINE_STREAM_INFO_AUDIO_HANDLED:
789   case XINE_STREAM_INFO_HAS_AUDIO:
790   case XINE_STREAM_INFO_HAS_VIDEO:
791   case XINE_STREAM_INFO_IGNORE_VIDEO:
792   case XINE_STREAM_INFO_IGNORE_AUDIO:
793   case XINE_STREAM_INFO_IGNORE_SPU:
794   case XINE_STREAM_INFO_VIDEO_HAS_STILL:
795   case XINE_STREAM_INFO_SKIPPED_FRAMES:
796   case XINE_STREAM_INFO_DISCARDED_FRAMES:
797   case XINE_STREAM_INFO_VIDEO_AFD:
798   case XINE_STREAM_INFO_DVD_TITLE_NUMBER:
799   case XINE_STREAM_INFO_DVD_TITLE_COUNT:
800   case XINE_STREAM_INFO_DVD_CHAPTER_NUMBER:
801   case XINE_STREAM_INFO_DVD_CHAPTER_COUNT:
802   case XINE_STREAM_INFO_DVD_ANGLE_NUMBER:
803   case XINE_STREAM_INFO_DVD_ANGLE_COUNT:
804     return _x_stream_info_get_public (&stream->s, info);
805 
806   case XINE_STREAM_INFO_MAX_AUDIO_CHANNEL:
807     return stream->audio_track_map_entries;
808 
809   case XINE_STREAM_INFO_MAX_SPU_CHANNEL:
810     return stream->spu_track_map_entries;
811 
812   default:
813     xprintf (stream->s.xine, XINE_VERBOSITY_DEBUG,
814 	     "xine_interface: unknown or deprecated stream info %d requested\n", info);
815   }
816   return 0;
817 }
818 
xine_get_meta_info(xine_stream_t * stream,int info)819 const char *xine_get_meta_info (xine_stream_t *stream, int info) {
820   return _x_meta_info_get_public(stream, info);
821 }
822 
xine_osd_new(xine_stream_t * stream,int x,int y,int width,int height)823 xine_osd_t *xine_osd_new(xine_stream_t *stream, int x, int y, int width, int height) {
824   xine_osd_t *this = (xine_osd_t *)stream->osd_renderer->new_object(stream->osd_renderer, width, height);
825   this->osd.renderer->set_position(&this->osd, x, y);
826   this->osd.renderer->set_encoding(&this->osd, "");
827   return this;
828 }
829 
xine_osd_get_capabilities(xine_osd_t * this)830 uint32_t xine_osd_get_capabilities(xine_osd_t *this) {
831   return this->osd.renderer->get_capabilities(&this->osd);
832 }
833 
xine_osd_draw_point(xine_osd_t * this,int x,int y,int color)834 void xine_osd_draw_point(xine_osd_t *this, int x, int y, int color) {
835   this->osd.renderer->point(&this->osd, x, y, color);
836 }
837 
xine_osd_draw_line(xine_osd_t * this,int x1,int y1,int x2,int y2,int color)838 void xine_osd_draw_line(xine_osd_t *this, int x1, int y1, int x2, int y2, int color) {
839   this->osd.renderer->line(&this->osd, x1, y1, x2, y2, color);
840 }
841 
xine_osd_draw_rect(xine_osd_t * this,int x1,int y1,int x2,int y2,int color,int filled)842 void xine_osd_draw_rect(xine_osd_t *this, int x1, int y1, int x2, int y2, int color, int filled) {
843   if (filled) {
844     this->osd.renderer->filled_rect(&this->osd, x1, y1, x2, y2, color);
845   } else {
846     this->osd.renderer->line(&this->osd, x1, y1, x2, y1, color);
847     this->osd.renderer->line(&this->osd, x2, y1, x2, y2, color);
848     this->osd.renderer->line(&this->osd, x2, y2, x1, y2, color);
849     this->osd.renderer->line(&this->osd, x1, y2, x1, y1, color);
850   }
851 }
852 
xine_osd_draw_text(xine_osd_t * this,int x1,int y1,const char * text,int color_base)853 void xine_osd_draw_text(xine_osd_t *this, int x1, int y1, const char *text, int color_base) {
854   this->osd.renderer->render_text(&this->osd, x1, y1, text, color_base);
855 }
856 
xine_osd_get_text_size(xine_osd_t * this,const char * text,int * width,int * height)857 void xine_osd_get_text_size(xine_osd_t *this, const char *text, int *width, int *height) {
858   this->osd.renderer->get_text_size(&this->osd, text, width, height);
859 }
860 
xine_osd_set_font(xine_osd_t * this,const char * fontname,int size)861 int xine_osd_set_font(xine_osd_t *this, const char *fontname, int size) {
862   return this->osd.renderer->set_font(&this->osd, fontname, size);
863 }
864 
xine_osd_set_encoding(xine_osd_t * this,const char * encoding)865 void xine_osd_set_encoding(xine_osd_t *this, const char *encoding) {
866   this->osd.renderer->set_encoding(&this->osd, encoding);
867 }
868 
xine_osd_set_position(xine_osd_t * this,int x,int y)869 void xine_osd_set_position(xine_osd_t *this, int x, int y) {
870   this->osd.renderer->set_position(&this->osd, x, y);
871 }
872 
xine_osd_show(xine_osd_t * this,int64_t vpts)873 void xine_osd_show(xine_osd_t *this, int64_t vpts) {
874   this->osd.renderer->show(&this->osd, vpts);
875 }
876 
xine_osd_show_unscaled(xine_osd_t * this,int64_t vpts)877 void xine_osd_show_unscaled(xine_osd_t *this, int64_t vpts) {
878   this->osd.renderer->show_unscaled(&this->osd, vpts);
879 }
880 
xine_osd_hide(xine_osd_t * this,int64_t vpts)881 void xine_osd_hide(xine_osd_t *this, int64_t vpts) {
882   this->osd.renderer->hide(&this->osd, vpts);
883 }
884 
xine_osd_clear(xine_osd_t * this)885 void xine_osd_clear(xine_osd_t *this) {
886   this->osd.renderer->clear(&this->osd);
887 }
888 
xine_osd_free(xine_osd_t * this)889 void xine_osd_free(xine_osd_t *this) {
890   this->osd.renderer->free_object(&this->osd);
891 }
892 
xine_osd_set_palette(xine_osd_t * this,const uint32_t * const color,const uint8_t * const trans)893 void xine_osd_set_palette(xine_osd_t *this, const uint32_t *const color, const uint8_t *const trans) {
894   this->osd.renderer->set_palette(&this->osd, color, trans);
895 }
896 
xine_osd_set_text_palette(xine_osd_t * this,int palette_number,int color_base)897 void xine_osd_set_text_palette(xine_osd_t *this, int palette_number, int color_base) {
898   this->osd.renderer->set_text_palette(&this->osd, palette_number, color_base);
899 }
900 
xine_osd_get_palette(xine_osd_t * this,uint32_t * color,uint8_t * trans)901 void xine_osd_get_palette(xine_osd_t *this, uint32_t *color, uint8_t *trans) {
902   this->osd.renderer->get_palette(&this->osd, color, trans);
903 }
904 
xine_osd_draw_bitmap(xine_osd_t * this,uint8_t * bitmap,int x1,int y1,int width,int height,uint8_t * palette_map)905 void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap,
906 			    int x1, int y1, int width, int height,
907 			    uint8_t *palette_map) {
908   this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map);
909 }
910 
xine_osd_set_argb_buffer(xine_osd_t * this,uint32_t * argb_buffer,int dirty_x,int dirty_y,int dirty_width,int dirty_height)911 void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer,
912     int dirty_x, int dirty_y, int dirty_width, int dirty_height) {
913   this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, dirty_x, dirty_y, dirty_width, dirty_height);
914 }
915 
xine_osd_set_extent(xine_osd_t * this,int extent_width,int extent_height)916 void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) {
917   this->osd.renderer->set_extent(&this->osd, extent_width, extent_height);
918 }
919 
xine_osd_set_video_window(xine_osd_t * this,int window_x,int window_y,int window_width,int window_height)920 void xine_osd_set_video_window(xine_osd_t *this, int window_x, int window_y, int window_width, int window_height) {
921   this->osd.renderer->set_video_window(&this->osd, window_x, window_y, window_width, window_height);
922 }
923 
924 
xine_post_list_inputs(xine_post_t * this_gen)925 const char *const *xine_post_list_inputs(xine_post_t *this_gen) {
926   post_plugin_t *this = (post_plugin_t *)this_gen;
927   return this->input_ids;
928 }
929 
xine_post_list_outputs(xine_post_t * this_gen)930 const char *const *xine_post_list_outputs(xine_post_t *this_gen) {
931   post_plugin_t *this = (post_plugin_t *)this_gen;
932   return this->output_ids;
933 }
934 
xine_post_input(xine_post_t * this_gen,const char * name)935 xine_post_in_t *xine_post_input(xine_post_t *this_gen, const char *name) {
936   post_plugin_t  *this = (post_plugin_t *)this_gen;
937   xine_list_iterator_t ite = NULL;
938   xine_post_in_t *input;
939 
940   while ((input = xine_list_next_value (this->input, &ite))) {
941     if (strcmp(input->name, name) == 0)
942       return input;
943   }
944   return NULL;
945 }
946 
xine_post_output(xine_post_t * this_gen,const char * name)947 xine_post_out_t *xine_post_output(xine_post_t *this_gen, const char *name) {
948   post_plugin_t   *this = (post_plugin_t *)this_gen;
949   xine_list_iterator_t ite = NULL;
950   xine_post_out_t *output;
951 
952   while ((output = xine_list_next_value (this->output, &ite))) {
953     if (strcmp(output->name, name) == 0)
954       return output;
955   }
956   return NULL;
957 }
958 
xine_post_wire(xine_post_out_t * source,xine_post_in_t * target)959 int xine_post_wire(xine_post_out_t *source, xine_post_in_t *target) {
960   if (source && source->rewire) {
961     if (target) {
962       if (source->type == target->type)
963         return source->rewire(source, target->data);
964       else
965         return 0;
966     } else
967       return source->rewire(source, NULL);
968   }
969   return 0;
970 }
971 
xine_post_wire_video_port(xine_post_out_t * source,xine_video_port_t * vo)972 int xine_post_wire_video_port(xine_post_out_t *source, xine_video_port_t *vo) {
973   if (source && source->rewire) {
974     if (vo) {
975       if (source->type == XINE_POST_DATA_VIDEO)
976         return source->rewire(source, vo);
977       else
978         return 0;
979     } else
980       return source->rewire(source, NULL);
981   }
982   return 0;
983 }
984 
xine_post_wire_audio_port(xine_post_out_t * source,xine_audio_port_t * ao)985 int xine_post_wire_audio_port(xine_post_out_t *source, xine_audio_port_t *ao) {
986   if (source && source->rewire) {
987     if (ao) {
988       if (source->type == XINE_POST_DATA_AUDIO)
989         return source->rewire(source, ao);
990       else
991         return 0;
992     } else
993       return source->rewire(source, NULL);
994   }
995   return 0;
996 }
997 
xine_get_video_source(xine_stream_t * s)998 xine_post_out_t * xine_get_video_source (xine_stream_t *s) {
999   xine_stream_private_t *stream = (xine_stream_private_t *)s;
1000   return &stream->video_source;
1001 }
1002 
xine_get_audio_source(xine_stream_t * s)1003 xine_post_out_t * xine_get_audio_source (xine_stream_t *s) {
1004   xine_stream_private_t *stream = (xine_stream_private_t *)s;
1005   return &stream->audio_source;
1006 }
1007 
1008 /* report error/message to UI. may be provided with several
1009  * string parameters. last parameter must be NULL.
1010  */
_x_message(xine_stream_t * stream,int type,...)1011 int _x_message(xine_stream_t *stream, int type, ...) {
1012   xine_ui_message_data_t *data;
1013   xine_event_t            event;
1014   const char              *explanation;
1015   size_t                  size;
1016   int                     n;
1017   va_list                 ap;
1018   char                   *s, *params;
1019   char                   *args[1025];
1020   static const char *const std_explanation[] = {
1021     "",
1022     N_("Warning:"),
1023     N_("Unknown host:"),
1024     N_("Unknown device:"),
1025     N_("Network unreachable"),
1026     N_("Connection refused:"),
1027     N_("File not found:"),
1028     N_("Read error from:"),
1029     N_("Error loading library:"),
1030     N_("Encrypted media stream detected"),
1031     N_("Security message:"),
1032     N_("Audio device unavailable"),
1033     N_("Permission error"),
1034     N_("File is empty:"),
1035   };
1036 
1037   if (!stream) return 0;
1038 
1039   if( type >= 0 && (size_t)type < sizeof(std_explanation)/
1040                            sizeof(std_explanation[0]) ) {
1041     explanation = _(std_explanation[type]);
1042     size = strlen(explanation)+1;
1043   } else {
1044     explanation = NULL;
1045     size = 0;
1046   }
1047 
1048   n = 0;
1049   va_start(ap, type);
1050   while(((s = va_arg(ap, char *)) != NULL) && (n < 1024)) {
1051     size += strlen(s) + 1;
1052     args[n] = s;
1053     n++;
1054   }
1055   va_end(ap);
1056 
1057   args[n] = NULL;
1058 
1059   size += sizeof(xine_ui_message_data_t) + 1;
1060   data = calloc(1, size );
1061 
1062   strcpy(data->compatibility.str, "Upgrade your frontend to see the error messages");
1063   data->type           = type;
1064   data->num_parameters = n;
1065 
1066   if( explanation ) {
1067     strcpy(data->messages, explanation);
1068     data->explanation = data->messages - (char *)data;
1069     params = data->messages + strlen(explanation) + 1;
1070   } else {
1071     data->explanation = 0;
1072     params            = data->messages;
1073   }
1074 
1075   data->parameters = params - (char *)data;
1076 
1077   n       = 0;
1078   *params = '\0';
1079 
1080   while(args[n]) {
1081     strcpy(params, args[n]);
1082     params += strlen(args[n]) + 1;
1083     n++;
1084   }
1085 
1086   *params = '\0';
1087 
1088   event.type        = XINE_EVENT_UI_MESSAGE;
1089   event.stream      = stream;
1090   event.data_length = size;
1091   event.data        = data;
1092   xine_event_send(stream, &event);
1093 
1094   free(data);
1095 
1096   return 1;
1097 }
1098 
xine_get_current_vpts(xine_stream_t * s)1099 int64_t xine_get_current_vpts (xine_stream_t *s) {
1100   xine_stream_private_t *stream = (xine_stream_private_t *)s;
1101   return stream->s.xine->clock->get_current_time (stream->s.xine->clock);
1102 }
1103