1 /*****************************************************************
2 * gmerlin - a general purpose multimedia framework and applications
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <config.h>
30 #include <gmerlin/translation.h>
31 #include <gmerlin/plugin.h>
32 #include <gmerlin/utils.h>
33
34
35 #include <linux/videodev.h>
36 #include "pwc-ioctl.h"
37 #include "pwc.h"
38
39 typedef struct
40 {
41 struct pwc_leds led;
42 } pwc_priv_t;
43
44 /* Special stuff for Phillips webcams */
45
bg_pwc_probe(int fd)46 int bg_pwc_probe(int fd)
47 {
48 struct pwc_probe p;
49 struct video_capability c;
50
51 memset(&p, 0, sizeof(p));
52 memset(&c, 0, sizeof(c));
53
54 if(ioctl(fd, VIDIOCPWCPROBE, &p) < 0)
55 return 0;
56
57 if(ioctl(fd, VIDIOCGCAP, &c) < 0)
58 return 0;
59
60
61 if(!strcmp(p.name, c.name))
62 return 1;
63 return 0;
64 }
65
66 static const bg_parameter_info_t pwc_parameters[] =
67 {
68 {
69 .name = "pwc_general",
70 .long_name = TRS("PWC General"),
71 .type = BG_PARAMETER_SECTION,
72 },
73 {
74 .name = "pwc_framerate",
75 .long_name = TRS("Framerate"),
76 .type = BG_PARAMETER_INT,
77 .val_min = { .val_i = 4 },
78 .val_max = { .val_i = 30 },
79 .val_default = { .val_i = 10 },
80 },
81 {
82 .name = "pwc_compression",
83 .long_name = TRS("Compression"),
84 .type = BG_PARAMETER_STRINGLIST,
85 .flags = BG_PARAMETER_SYNC,
86 .val_default = { .val_str = "Medium" },
87 .multi_labels = (char const *[]){ TRS("None"),
88 TRS("Low"),
89 TRS("Medium"),
90 TRS("High"),
91 NULL },
92 .multi_names = (char const *[]){ "None",
93 "Low",
94 "Medium",
95 "High",
96 NULL },
97 },
98 {
99 .name = "pwc_gain",
100 .long_name = TRS("Gain control (-1 = Auto)"),
101 .type = BG_PARAMETER_SLIDER_INT,
102 .flags = BG_PARAMETER_SYNC,
103 .val_default = { .val_i = -1 },
104 .val_min = { .val_i = -1 },
105 .val_max = { .val_i = 65535 },
106 },
107 {
108 .name = "pwc_shutterspeed",
109 .long_name = TRS("Shutter speed (-1 = Auto)"),
110 .type = BG_PARAMETER_SLIDER_INT,
111 .flags = BG_PARAMETER_SYNC,
112 .val_default = { .val_i = -1 },
113 .val_min = { .val_i = -1 },
114 .val_max = { .val_i = 65535 },
115 },
116 {
117 .name = "pwc_sharpness",
118 .long_name = TRS("Sharpness (-1 = Auto)"),
119 .type = BG_PARAMETER_SLIDER_INT,
120 .flags = BG_PARAMETER_SYNC,
121 .val_default = { .val_i = -1 },
122 .val_min = { .val_i = -1 },
123 .val_max = { .val_i = 65535 },
124 },
125 {
126 .name = "pwc_backlight",
127 .long_name = TRS("Backlight compensation"),
128 .type = BG_PARAMETER_CHECKBUTTON,
129 .flags = BG_PARAMETER_SYNC,
130 .val_default = { .val_i = 1 },
131 },
132 {
133 .name = "pwc_flicker",
134 .long_name = TRS("Flicker compensation"),
135 .type = BG_PARAMETER_CHECKBUTTON,
136 .flags = BG_PARAMETER_SYNC,
137 .val_default = { .val_i = 0 },
138 },
139 {
140 .name = "pwc_whitebalance_section",
141 .long_name = TRS("PWC Whitebalance"),
142 .type = BG_PARAMETER_SECTION,
143 },
144 {
145 .name = "pwc_whitebalance",
146 .long_name = TRS("White balance"),
147 .type = BG_PARAMETER_STRINGLIST,
148 .flags = BG_PARAMETER_SYNC,
149 .val_default = { .val_str = "Auto" },
150 .multi_names = (char const *[]){ "Indoor",
151 "Outdoor",
152 "Fluorescent lighting",
153 "Manual",
154 "Auto",
155 NULL },
156 .multi_labels = (char const *[]){ TRS("Indoor"),
157 TRS("Outdoor"),
158 TRS("Fluorescent lighting"),
159 TRS("Manual"),
160 TRS("Auto"),
161 NULL },
162 },
163 {
164 .name = "pwc_manual_red",
165 .long_name = TRS("Manual red gain"),
166 .type = BG_PARAMETER_SLIDER_INT,
167 .flags = BG_PARAMETER_SYNC,
168 .val_min = { .val_i = 0 },
169 .val_max = { .val_i = 65535 },
170 .val_default = { .val_i = 32000 },
171 },
172 {
173 .name = "pwc_manual_blue",
174 .long_name = TRS("Manual blue gain"),
175 .type = BG_PARAMETER_SLIDER_INT,
176 .flags = BG_PARAMETER_SYNC,
177 .val_min = { .val_i = 0 },
178 .val_max = { .val_i = 65535 },
179 .val_default = { .val_i = 32000 },
180 },
181 {
182 .name = "pwc_control_speed",
183 .long_name = TRS("Auto speed"),
184 .type = BG_PARAMETER_SLIDER_INT,
185 .flags = BG_PARAMETER_SYNC,
186 .val_min = { .val_i = 0 },
187 .val_max = { .val_i = 65535 },
188 .val_default = { .val_i = 32000 },
189 },
190 {
191 .name = "pwc_control_delay",
192 .long_name = TRS("Auto delay"),
193 .type = BG_PARAMETER_SLIDER_INT,
194 .flags = BG_PARAMETER_SYNC,
195 .val_min = { .val_i = 0 },
196 .val_max = { .val_i = 65535 },
197 .val_default = { .val_i = 32000 },
198 },
199 {
200 .name = "pwc_led_section",
201 .long_name = TRS("PWC LED"),
202 .type = BG_PARAMETER_SECTION,
203 },
204 {
205 .name = "pwc_led_on",
206 .long_name = TRS("LED on time (secs)"),
207 .type = BG_PARAMETER_FLOAT,
208 .val_min = { .val_f = 0.0 },
209 .val_max = { .val_f = 255.0 },
210 .val_default = { .val_f = 1.0 },
211 .num_digits = 1,
212 },
213 {
214 .name = "pwc_led_off",
215 .long_name = TRS("LED off time (secs)"),
216 .type = BG_PARAMETER_FLOAT,
217 .val_min = { .val_f = 0.0 },
218 .val_max = { .val_f = 255.0 },
219 .val_default = { .val_f = 0.0 },
220 .num_digits = 1,
221 },
222 { /* End of parameters */ }
223
224 };
225
226 /* Reallocate parameter array */
227
bg_pwc_get_parameters(int fd,bg_parameter_info_t ** parameters)228 void * bg_pwc_get_parameters(int fd, bg_parameter_info_t ** parameters)
229 {
230 int i;
231 bg_parameter_info_t * p;
232 int num_generic_parameters;
233 int num_pwc_parameters;
234 pwc_priv_t * ret;
235
236
237 p = *parameters;
238
239 num_generic_parameters = 0;
240 while(p[num_generic_parameters].name)
241 {
242 /* Exchange the "whiteness" parameter by Gamma */
243
244 if(!strcmp(p[num_generic_parameters].name, "whiteness"))
245 {
246 p[num_generic_parameters].long_name =
247 bg_strdup(p[num_generic_parameters].long_name,
248 "Gamma");
249 }
250 num_generic_parameters++;
251 }
252
253 num_pwc_parameters = 0;
254 while(pwc_parameters[num_pwc_parameters].name)
255 num_pwc_parameters++;
256
257 p = realloc(p, (num_generic_parameters+num_pwc_parameters+1)*sizeof(*p));
258
259 memset(p + num_generic_parameters, 0, (num_pwc_parameters+1)*sizeof(*p));
260
261 for(i = 0; i < num_pwc_parameters; i++)
262 {
263 bg_parameter_info_copy(p + (num_generic_parameters + i),
264 &pwc_parameters[i]);
265 }
266 *parameters = p;
267
268 ret = calloc(1, sizeof(*ret));
269 return ret;
270 }
271
bg_pwc_destroy(void * p)272 void bg_pwc_destroy(void*p)
273 {
274 free(p);
275 }
276
277
278 /* Handle parameters beginning with "pwc_" */
279
bg_pwc_set_parameter(int fd,void * priv,const char * name,const bg_parameter_value_t * val)280 void bg_pwc_set_parameter(int fd, void * priv,
281 const char * name, const bg_parameter_value_t * val)
282 {
283 pwc_priv_t * p;
284 int compression;
285 struct video_window win;
286 struct pwc_whitebalance whitebalance;
287 struct pwc_wb_speed wb_speed;
288
289 p = priv;
290
291 if(!name)
292 {
293 ioctl(fd, VIDIOCPWCSLED, &p->led);
294 return;
295 }
296 else if(!strcmp(name, "pwc_framerate"))
297 {
298 if(ioctl(fd, VIDIOCGWIN, &win) < 0)
299 return;
300
301 win.flags &= ~PWC_FPS_FRMASK;
302 win.flags |= (val->val_i << PWC_FPS_SHIFT);
303 ioctl(fd, VIDIOCSWIN, &win);
304 }
305 else if(!strcmp(name, "pwc_compression"))
306 {
307 compression = 0;
308 if(!strcmp(val->val_str, "None"))
309 compression = 0;
310 else if(!strcmp(val->val_str, "Low"))
311 compression = 1;
312 else if(!strcmp(val->val_str, "Medium"))
313 compression = 2;
314 else if(!strcmp(val->val_str, "High"))
315 compression = 3;
316 ioctl(fd, VIDIOCPWCSCQUAL, &compression);
317 }
318 else if(!strcmp(name, "pwc_gain"))
319 {
320 ioctl(fd, VIDIOCPWCSAGC, &val->val_i);
321 }
322 else if(!strcmp(name, "pwc_shutterspeed"))
323 {
324 ioctl(fd, VIDIOCPWCSSHUTTER, &val->val_i);
325 }
326 else if(!strcmp(name, "pwc_sharpness"))
327 {
328 ioctl(fd, VIDIOCPWCSCONTOUR, &val->val_i);
329 }
330 else if(!strcmp(name, "pwc_backlight"))
331 {
332 ioctl(fd, VIDIOCPWCSBACKLIGHT, &val->val_i);
333 }
334 else if(!strcmp(name, "pwc_flicker"))
335 {
336 ioctl(fd, VIDIOCPWCSFLICKER, &val->val_i);
337 }
338 else if(!strcmp(name, "pwc_whitebalance"))
339 {
340 if(ioctl(fd, VIDIOCPWCGAWB, &whitebalance) < 0)
341 return;
342 if(!strcmp(val->val_str, "Indoor"))
343 whitebalance.mode = PWC_WB_INDOOR;
344 else if(!strcmp(val->val_str, "Outdoor"))
345 whitebalance.mode = PWC_WB_OUTDOOR;
346 else if(!strcmp(val->val_str, "Fluorescent lighting"))
347 whitebalance.mode = PWC_WB_FL;
348 else if(!strcmp(val->val_str, "Manual"))
349 whitebalance.mode = PWC_WB_MANUAL;
350 else if(!strcmp(val->val_str, "Auto"))
351 whitebalance.mode = PWC_WB_AUTO;
352 ioctl(fd, VIDIOCPWCSAWB, &whitebalance);
353 }
354 else if(!strcmp(name, "pwc_manual_red"))
355 {
356 if(ioctl(fd, VIDIOCPWCGAWB, &whitebalance) < 0)
357 return;
358 whitebalance.manual_red = val->val_i;
359 ioctl(fd, VIDIOCPWCSAWB, &whitebalance);
360 }
361 else if(!strcmp(name, "pwc_manual_blue"))
362 {
363 if(ioctl(fd, VIDIOCPWCGAWB, &whitebalance) < 0)
364 return;
365 whitebalance.manual_blue = val->val_i;
366 ioctl(fd, VIDIOCPWCSAWB, &whitebalance);
367 }
368 else if(!strcmp(name, "pwc_control_speed"))
369 {
370 if(ioctl(fd, VIDIOCPWCGAWBSPEED, &wb_speed) < 0)
371 return;
372 wb_speed.control_speed = val->val_i;
373 ioctl(fd, VIDIOCPWCSAWBSPEED, &wb_speed);
374 }
375 else if(!strcmp(name, "pwc_control_delay"))
376 {
377 if(ioctl(fd, VIDIOCPWCGAWBSPEED, &wb_speed) < 0)
378 return;
379 wb_speed.control_delay = val->val_i;
380 ioctl(fd, VIDIOCPWCSAWBSPEED, &wb_speed);
381 }
382 else if(!strcmp(name, "pwc_led_on"))
383 {
384 p->led.led_on = (int)(val->val_f * 1000.0 + 0.5);
385 }
386 else if(!strcmp(name, "pwc_led_off"))
387 {
388 p->led.led_off = (int)(val->val_f * 1000.0 + 0.5);
389 }
390
391 }
392