1 /*
2  * Copyright (C) 2000-2018 the xine project
3  * Copyright (C) 2018      Petri Hintukainen <phintuka@users.sourceforge.net>
4  *
5  * This file is part of xine, a free video player.
6  *
7  * xine is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * xine is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20  *
21  * input plugin helper functions
22  */
23 
24 #ifndef XINE_INPUT_HELPER_H
25 #define XINE_INPUT_HELPER_H
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <errno.h>
32 #include <sys/types.h>
33 
34 #include <xine/attributes.h>
35 #include <xine/xine_internal.h>
36 #include <xine/xineutils.h>
37 
38 /*
39  * mrl array alloc / free helpers
40  */
41 
42 void _x_input_free_mrls(xine_mrl_t ***p);
43 xine_mrl_t **_x_input_alloc_mrls(size_t n);
44 xine_mrl_t **_x_input_realloc_mrls(xine_mrl_t ***p, size_t n);
45 
46 void _x_input_sort_mrls(xine_mrl_t **mrls, ssize_t cnt /* optional, may be -1 */);
47 
48 /*
49  * config helpers
50  */
51 
52 void _x_input_register_show_hidden_files(config_values_t *config);
53 int _x_input_get_show_hidden_files(config_values_t *config);
54 
55 void _x_input_register_default_servers(config_values_t *config);
56 xine_mrl_t **_x_input_get_default_server_mrls(config_values_t *config, const char *type, int *nFiles);
57 
58 /*
59  * default read_block function.
60  * uses read() to fill the block.
61  */
62 buf_element_t *_x_input_default_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo);
63 
_x_input_get_capabilities_preview(input_plugin_t * this_gen)64 static inline uint32_t _x_input_get_capabilities_preview (input_plugin_t *this_gen)
65 {
66   (void)this_gen;
67   return INPUT_CAP_PREVIEW;
68 }
69 
_x_input_get_capabilities_seekable(input_plugin_t * this_gen)70 static inline uint32_t _x_input_get_capabilities_seekable (input_plugin_t *this_gen)
71 {
72   (void)this_gen;
73   return INPUT_CAP_SEEKABLE;
74 }
75 
_x_input_get_capabilities_none(input_plugin_t * this_gen)76 static inline uint32_t _x_input_get_capabilities_none (input_plugin_t *this_gen)
77 {
78   (void)this_gen;
79   return INPUT_CAP_NOCAP;
80 }
81 
_x_input_default_get_blocksize(input_plugin_t * this_gen)82 static inline uint32_t _x_input_default_get_blocksize (input_plugin_t *this_gen)
83 {
84   (void)this_gen;
85   return 0;
86 }
87 
_x_input_default_get_length(input_plugin_t * this_gen)88 static inline off_t _x_input_default_get_length (input_plugin_t *this_gen)
89 {
90   (void)this_gen;
91   return 0;
92 }
93 
_x_input_default_get_optional_data(input_plugin_t * this_gen,void * data,int data_type)94 static inline int _x_input_default_get_optional_data (input_plugin_t *this_gen, void *data, int data_type)
95 {
96   (void)this_gen;
97   (void)data;
98   (void)data_type;
99   return INPUT_OPTIONAL_UNSUPPORTED;
100 }
101 
102 /*
103  * translate (offset, origin) to absolute position
104  */
_x_input_translate_seek(off_t offset,int origin,off_t curpos,off_t length)105 static inline off_t _x_input_translate_seek(off_t offset, int origin, off_t curpos, off_t length)
106 {
107   switch (origin) {
108     case SEEK_SET: break;
109     case SEEK_CUR: offset += curpos; break;
110     case SEEK_END: offset = (length <= 0) ? (-1) : (offset + length); break;
111     default:       offset = -1;  break;
112   }
113 
114   if (offset < 0 || (length > 0 && offset > length)) {
115     errno = EINVAL;
116     return (off_t)-1;
117   }
118 
119   return offset;
120 }
121 
122 /*
123  * seek forward by skipping data
124  */
125 #define MAX_SKIP_BYTES (10*1024*1024)  // 10 MB
_x_input_read_skip(input_plugin_t * input,off_t bytes)126 static inline int _x_input_read_skip(input_plugin_t *input, off_t bytes)
127 {
128   char buf[1024];
129   const off_t max = sizeof(buf);
130 
131   _x_assert(bytes >= 0);
132 
133   if (bytes > MAX_SKIP_BYTES) {
134     /* seeking forward gigabytes would take long time ... */
135     return -1;
136   }
137 
138   while (bytes > 0) {
139     off_t got = input->read(input, buf, (bytes > max) ? max : bytes);
140     if (got <= 0)
141       return -1;
142     bytes -= got;
143   }
144 
145   _x_assert(bytes == 0);
146   return 0;
147 }
148 
149 /*
150  * generic seek function for non-seekable input plugins
151  */
_x_input_seek_preview(input_plugin_t * input,off_t offset,int origin,off_t * curpos,off_t length,off_t preview_size)152 static inline off_t _x_input_seek_preview(input_plugin_t *input, off_t offset, int origin,
153                                           off_t *curpos, off_t length, off_t preview_size)
154 {
155   offset = _x_input_translate_seek(offset, origin, *curpos, length);
156   if (offset < 0)
157     goto fail;
158 
159   /* seek inside preview */
160   if (offset <= preview_size && *curpos <= preview_size) {
161     *curpos = offset;
162     return offset;
163   }
164 
165   /* can't seek back */
166   if (offset < *curpos)
167     goto fail;
168 
169   if (_x_input_read_skip(input, offset - *curpos) < 0)
170     return -1;
171 
172   _x_assert(offset == *curpos);
173   return offset;
174 
175  fail:
176   errno = EINVAL;
177   return (off_t)-1;
178 }
179 
180 #ifdef __cplusplus
181 }
182 #endif
183 
184 #endif /* XINE_INPUT_HELPER_H */
185