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