1 /*****************************************************************************
2 * controls.c : Video4Linux2 device controls for vlc
3 *****************************************************************************
4 * Copyright (C) 2002-2011 VLC authors and VideoLAN
6 * Authors: Benjamin Pracht <bigben at videolan dot org>
7 * Richard Hosking <richard at hovis dot net>
8 * Antoine Cellerier <dionoea at videolan d.t org>
9 * Dennis Lou <dlou99 at yahoo dot com>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
33 #include <sys/ioctl.h>
35 #include <vlc_common.h>
39 typedef struct vlc_v4l2_ctrl_name
43 } vlc_v4l2_ctrl_name_t;
45 /* NOTE: must be sorted by ID */
46 static const vlc_v4l2_ctrl_name_t controls[] =
48 { "brightness", V4L2_CID_BRIGHTNESS },
49 { "contrast", V4L2_CID_CONTRAST },
50 { "saturation", V4L2_CID_SATURATION },
51 { "hue", V4L2_CID_HUE },
52 { "audio-volume", V4L2_CID_AUDIO_VOLUME },
53 { "audio-balance", V4L2_CID_AUDIO_BALANCE },
54 { "audio-bass", V4L2_CID_AUDIO_BASS },
55 { "audio-treble", V4L2_CID_AUDIO_TREBLE },
56 { "audio-mute", V4L2_CID_AUDIO_MUTE },
57 { "audio-loudness", V4L2_CID_AUDIO_LOUDNESS },
58 { "auto-white-balance", V4L2_CID_AUTO_WHITE_BALANCE },
59 { "do-white-balance", V4L2_CID_DO_WHITE_BALANCE },
60 { "red-balance", V4L2_CID_RED_BALANCE },
61 { "blue-balance", V4L2_CID_BLUE_BALANCE },
62 { "gamma", V4L2_CID_GAMMA },
63 { "autogain", V4L2_CID_AUTOGAIN },
64 { "gain", V4L2_CID_GAIN },
65 { "hflip", V4L2_CID_HFLIP },
66 { "vflip", V4L2_CID_VFLIP },
67 { "power-line-frequency", V4L2_CID_POWER_LINE_FREQUENCY },
68 { "hue-auto", V4L2_CID_HUE_AUTO },
69 { "white-balance-temperature", V4L2_CID_WHITE_BALANCE_TEMPERATURE },
70 { "sharpness", V4L2_CID_SHARPNESS },
71 { "backlight-compensation", V4L2_CID_BACKLIGHT_COMPENSATION },
72 { "chroma-gain-auto", V4L2_CID_CHROMA_AGC },
73 { "color-killer", V4L2_CID_COLOR_KILLER },
74 { "color-effect", V4L2_CID_COLORFX },
75 { "rotate", V4L2_CID_ROTATE },
76 { "bg-color", V4L2_CID_BG_COLOR }, // NOTE: output only
77 { "chroma-gain", V4L2_CID_CHROMA_GAIN },
78 { "brightness-auto", V4L2_CID_AUTOBRIGHTNESS },
79 { "band-stop-filter", V4L2_CID_BAND_STOP_FILTER },
81 { "illuminators-1", V4L2_CID_ILLUMINATORS_1 }, // NOTE: don't care?
82 { "illuminators-2", V4L2_CID_ILLUMINATORS_2 },
83 #define CTRL_CID_KNOWN(cid) \
84 ((((uint32_t)cid) - V4L2_CID_BRIGHTNESS) \
85 <= (V4L2_CID_BAND_STOP_FILTER - V4L2_CID_BRIGHTNESS))
94 int32_t default_value;
95 struct vlc_v4l2_ctrl *next;
98 static int ControlSet (const vlc_v4l2_ctrl_t *c, int_fast32_t value)
100 struct v4l2_control ctrl = {
104 if (v4l2_ioctl (c->fd, VIDIOC_S_CTRL, &ctrl) < 0)
109 static int ControlSet64 (const vlc_v4l2_ctrl_t *c, int64_t value)
111 struct v4l2_ext_control ext_ctrl = {
115 ext_ctrl.value64 = value;
116 struct v4l2_ext_controls ext_ctrls = {
117 .ctrl_class = V4L2_CTRL_ID2CLASS(c->id),
120 .controls = &ext_ctrl,
123 if (v4l2_ioctl (c->fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls) < 0)
128 static int ControlSetStr (const vlc_v4l2_ctrl_t *c, const char *restrict value)
130 struct v4l2_ext_control ext_ctrl = {
132 .size = strlen (value) + 1,
134 ext_ctrl.string = (char *)value;
135 struct v4l2_ext_controls ext_ctrls = {
136 .ctrl_class = V4L2_CTRL_ID2CLASS(c->id),
139 .controls = &ext_ctrl,
142 if (v4l2_ioctl (c->fd, VIDIOC_S_EXT_CTRLS, &ext_ctrls) < 0)
147 static int ControlSetCallback (vlc_object_t *obj, const char *var,
148 vlc_value_t old, vlc_value_t cur, void *data)
150 const vlc_v4l2_ctrl_t *ctrl = data;
155 case V4L2_CTRL_TYPE_INTEGER:
156 case V4L2_CTRL_TYPE_MENU:
157 case V4L2_CTRL_TYPE_BITMASK:
158 case V4L2_CTRL_TYPE_INTEGER_MENU:
159 ret = ControlSet (ctrl, cur.i_int);
161 case V4L2_CTRL_TYPE_BOOLEAN:
162 ret = ControlSet (ctrl, cur.b_bool);
164 case V4L2_CTRL_TYPE_BUTTON:
165 ret = ControlSet (ctrl, 0);
167 case V4L2_CTRL_TYPE_INTEGER64:
168 ret = ControlSet64 (ctrl, cur.i_int);
170 case V4L2_CTRL_TYPE_STRING:
171 ret = ControlSetStr (ctrl, cur.psz_string);
179 msg_Err (obj, "cannot set control %s: %m", var);
186 static void ControlsReset (vlc_object_t *obj, vlc_v4l2_ctrl_t *list)
192 case V4L2_CTRL_TYPE_INTEGER:
193 case V4L2_CTRL_TYPE_MENU:
194 case V4L2_CTRL_TYPE_INTEGER_MENU:
195 var_SetInteger (obj, list->name, list->default_value);
197 case V4L2_CTRL_TYPE_BOOLEAN:
198 var_SetBool (obj, list->name, list->default_value);
206 static int ControlsResetCallback (vlc_object_t *obj, const char *var,
207 vlc_value_t old, vlc_value_t cur, void *data)
209 ControlsReset (obj, data);
210 (void) var; (void) old; (void) cur;
214 static void ControlsSetFromString (vlc_object_t *obj,
215 const vlc_v4l2_ctrl_t *list)
217 char *buf = var_InheritString (obj, CFG_PREFIX"set-ctrls");
225 char *end = strchr (p, '}');
229 while (p != NULL && *p)
231 const char *name, *value;
233 p += strspn (p, ", ");
235 end = strchr (p, ',');
238 p = end; /* next name/value pair */
240 end = strchr (name, '=');
243 /* TODO? support button controls that way? */
244 msg_Err (obj, "syntax error in \"%s\": missing '='", name);
250 for (const vlc_v4l2_ctrl_t *c = list; c != NULL; c = c->next)
251 if (!strcasecmp (name, c->name))
254 case V4L2_CTRL_TYPE_INTEGER:
255 case V4L2_CTRL_TYPE_BOOLEAN:
256 case V4L2_CTRL_TYPE_MENU:
257 case V4L2_CTRL_TYPE_INTEGER_MENU:
259 long val = strtol (value, &end, 0);
262 msg_Err (obj, "syntax error in \"%s\": "
263 " not an integer", value);
270 case V4L2_CTRL_TYPE_INTEGER64:
272 long long val = strtoll (value, &end, 0);
275 msg_Err (obj, "syntax error in \"%s\": "
276 " not an integer", value);
279 ControlSet64 (c, val);
283 case V4L2_CTRL_TYPE_STRING:
284 ControlSetStr (c, value);
287 case V4L2_CTRL_TYPE_BITMASK:
289 unsigned long val = strtoul (value, &end, 0);
292 msg_Err (obj, "syntax error in \"%s\": "
293 " not an integer", value);
301 msg_Err (obj, "setting \"%s\" not supported", name);
305 msg_Err (obj, "control \"%s\" not available", name);
310 static int cidcmp (const void *a, const void *b)
312 const uint32_t *id = a;
313 const vlc_v4l2_ctrl_name_t *name = b;
315 return (int32_t)(*id - name->cid);
319 * Creates a VLC-V4L2 control structure:
320 * In particular, determines a name suitable for a VLC object variable.
321 * \param query V4L2 control query structure [IN]
322 * \return NULL on error
324 static vlc_v4l2_ctrl_t *ControlCreate (int fd,
325 const struct v4l2_queryctrl *query)
327 vlc_v4l2_ctrl_t *ctrl = malloc (sizeof (*ctrl));
328 if (unlikely(ctrl == NULL))
332 ctrl->id = query->id;
333 ctrl->type = query->type;
335 /* Search for a well-known control */
336 const vlc_v4l2_ctrl_name_t *known;
337 known = bsearch (&query->id, controls, sizeof (controls) / sizeof (*known),
338 sizeof (*known), cidcmp);
340 strcpy (ctrl->name, known->name);
342 /* Fallback to automatically-generated control name */
345 for (i = 0; query->name[i]; i++)
347 unsigned char c = query->name[i];
348 if (c == ' ' || c == ',')
354 ctrl->name[i] = '\0';
357 ctrl->default_value = query->default_value;
362 #define CTRL_FLAGS_IGNORE \
363 (V4L2_CTRL_FLAG_DISABLED /* not implemented at all */ \
364 |V4L2_CTRL_FLAG_READ_ONLY /* value is constant */ \
365 |V4L2_CTRL_FLAG_VOLATILE /* value is (variable but) read-only */)
367 static vlc_v4l2_ctrl_t *ControlAddInteger (vlc_object_t *obj, int fd,
368 const struct v4l2_queryctrl *query)
370 msg_Dbg (obj, " integer %s (%08"PRIX32")", query->name, query->id);
371 if (query->flags & CTRL_FLAGS_IGNORE)
374 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
375 if (unlikely(c == NULL))
378 if (var_Create (obj, c->name, VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND))
385 struct v4l2_control ctrl = { .id = query->id };
387 if (v4l2_ioctl (fd, VIDIOC_G_CTRL, &ctrl) >= 0)
389 msg_Dbg (obj, " current: %3"PRId32", default: %3"PRId32,
390 ctrl.value, query->default_value);
391 val.i_int = ctrl.value;
392 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
394 val.i_int = query->minimum;
395 var_Change (obj, c->name, VLC_VAR_SETMIN, &val, NULL);
396 val.i_int = query->maximum;
397 var_Change (obj, c->name, VLC_VAR_SETMAX, &val, NULL);
398 if (query->step != 1)
400 val.i_int = query->step;
401 var_Change (obj, c->name, VLC_VAR_SETSTEP, &val, NULL);
403 val.i_int = query->default_value;
404 var_Change (obj, c->name, VLC_VAR_SETDEFAULT, &val, NULL);
408 static vlc_v4l2_ctrl_t *ControlAddBoolean (vlc_object_t *obj, int fd,
409 const struct v4l2_queryctrl *query)
411 msg_Dbg (obj, " boolean %s (%08"PRIX32")", query->name, query->id);
412 if (query->flags & CTRL_FLAGS_IGNORE)
415 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
416 if (unlikely(c == NULL))
419 if (var_Create (obj, c->name, VLC_VAR_BOOL | VLC_VAR_ISCOMMAND))
426 struct v4l2_control ctrl = { .id = query->id };
428 if (v4l2_ioctl (fd, VIDIOC_G_CTRL, &ctrl) >= 0)
430 msg_Dbg (obj, " current: %s, default: %s",
431 ctrl.value ? " true" : "false",
432 query->default_value ? " true" : "false");
433 val.b_bool = ctrl.value;
434 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
436 val.b_bool = query->default_value;
437 var_Change (obj, c->name, VLC_VAR_SETDEFAULT, &val, NULL);
441 static vlc_v4l2_ctrl_t *ControlAddMenu (vlc_object_t *obj, int fd,
442 const struct v4l2_queryctrl *query)
444 msg_Dbg (obj, " menu %s (%08"PRIX32")", query->name, query->id);
445 if (query->flags & CTRL_FLAGS_IGNORE)
448 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
449 if (unlikely(c == NULL))
452 if (var_Create (obj, c->name, VLC_VAR_INTEGER | VLC_VAR_HASCHOICE
453 | VLC_VAR_ISCOMMAND))
460 struct v4l2_control ctrl = { .id = query->id };
462 if (v4l2_ioctl (fd, VIDIOC_G_CTRL, &ctrl) >= 0)
464 msg_Dbg (obj, " current: %"PRId32", default: %"PRId32,
465 ctrl.value, query->default_value);
466 val.i_int = ctrl.value;
467 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
469 val.i_int = query->minimum;
470 var_Change (obj, c->name, VLC_VAR_SETMIN, &val, NULL);
471 val.i_int = query->maximum;
472 var_Change (obj, c->name, VLC_VAR_SETMAX, &val, NULL);
473 val.i_int = query->default_value;
474 var_Change (obj, c->name, VLC_VAR_SETDEFAULT, &val, NULL);
476 /* Import menu choices */
477 for (uint_fast32_t idx = query->minimum;
478 idx <= (uint_fast32_t)query->maximum;
481 struct v4l2_querymenu menu = { .id = query->id, .index = idx };
483 if (v4l2_ioctl (fd, VIDIOC_QUERYMENU, &menu) < 0)
485 msg_Dbg (obj, " choice %"PRIu32") %s", menu.index, menu.name);
488 val.i_int = menu.index;
489 text.psz_string = (char *)menu.name;
490 var_Change (obj, c->name, VLC_VAR_ADDCHOICE, &val, &text);
495 static vlc_v4l2_ctrl_t *ControlAddButton (vlc_object_t *obj, int fd,
496 const struct v4l2_queryctrl *query)
498 msg_Dbg (obj, " button %s (%08"PRIX32")", query->name, query->id);
499 if (query->flags & CTRL_FLAGS_IGNORE)
502 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
503 if (unlikely(c == NULL))
506 if (var_Create (obj, c->name, VLC_VAR_VOID | VLC_VAR_ISCOMMAND))
514 static vlc_v4l2_ctrl_t *ControlAddInteger64 (vlc_object_t *obj, int fd,
515 const struct v4l2_queryctrl *query)
517 msg_Dbg (obj, " 64-bits %s (%08"PRIX32")", query->name, query->id);
518 if (query->flags & CTRL_FLAGS_IGNORE)
521 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
522 if (unlikely(c == NULL))
525 if (var_Create (obj, c->name, VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND))
531 struct v4l2_ext_control ext_ctrl = { .id = c->id, .size = 0, };
532 struct v4l2_ext_controls ext_ctrls = {
533 .ctrl_class = V4L2_CTRL_ID2CLASS(c->id),
536 .controls = &ext_ctrl,
539 if (v4l2_ioctl (c->fd, VIDIOC_G_EXT_CTRLS, &ext_ctrls) >= 0)
541 vlc_value_t val = { .i_int = ext_ctrl.value64 };
543 msg_Dbg (obj, " current: %"PRId64, val.i_int);
544 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
550 static vlc_v4l2_ctrl_t *ControlAddClass (vlc_object_t *obj, int fd,
551 const struct v4l2_queryctrl *query)
553 msg_Dbg (obj, "control class %s:", query->name);
558 static vlc_v4l2_ctrl_t *ControlAddString (vlc_object_t *obj, int fd,
559 const struct v4l2_queryctrl *query)
561 msg_Dbg (obj, " string %s (%08"PRIX32")", query->name, query->id);
562 if ((query->flags & CTRL_FLAGS_IGNORE) || query->maximum > 65535)
565 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
566 if (unlikely(c == NULL))
569 if (var_Create (obj, c->name, VLC_VAR_STRING | VLC_VAR_ISCOMMAND))
575 /* Get current value */
576 char *buf = malloc (query->maximum + 1);
577 if (likely(buf != NULL))
579 struct v4l2_ext_control ext_ctrl = {
581 .size = query->maximum + 1,
583 ext_ctrl.string = buf;
584 struct v4l2_ext_controls ext_ctrls = {
585 .ctrl_class = V4L2_CTRL_ID2CLASS(c->id),
588 .controls = &ext_ctrl,
591 if (v4l2_ioctl (c->fd, VIDIOC_G_EXT_CTRLS, &ext_ctrls) >= 0)
593 vlc_value_t val = { .psz_string = buf };
595 msg_Dbg (obj, " current: \"%s\"", buf);
596 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
604 static vlc_v4l2_ctrl_t *ControlAddBitMask (vlc_object_t *obj, int fd,
605 const struct v4l2_queryctrl *query)
607 msg_Dbg (obj, " bit mask %s (%08"PRIX32")", query->name, query->id);
608 if (query->flags & CTRL_FLAGS_IGNORE)
611 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
612 if (unlikely(c == NULL))
615 if (var_Create (obj, c->name, VLC_VAR_INTEGER | VLC_VAR_ISCOMMAND))
622 struct v4l2_control ctrl = { .id = query->id };
624 if (v4l2_ioctl (fd, VIDIOC_G_CTRL, &ctrl) >= 0)
626 msg_Dbg (obj, " current: 0x%08"PRIX32", default: 0x%08"PRIX32,
627 ctrl.value, query->default_value);
628 val.i_int = ctrl.value;
629 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
632 var_Change (obj, c->name, VLC_VAR_SETMIN, &val, NULL);
633 val.i_int = (uint32_t)query->maximum;
634 var_Change (obj, c->name, VLC_VAR_SETMAX, &val, NULL);
635 val.i_int = query->default_value;
636 var_Change (obj, c->name, VLC_VAR_SETDEFAULT, &val, NULL);
640 static vlc_v4l2_ctrl_t *ControlAddIntMenu (vlc_object_t *obj, int fd,
641 const struct v4l2_queryctrl *query)
643 msg_Dbg (obj, " int menu %s (%08"PRIX32")", query->name, query->id);
644 if (query->flags & CTRL_FLAGS_IGNORE)
647 vlc_v4l2_ctrl_t *c = ControlCreate (fd, query);
648 if (unlikely(c == NULL))
651 if (var_Create (obj, c->name, VLC_VAR_INTEGER | VLC_VAR_HASCHOICE
652 | VLC_VAR_ISCOMMAND))
659 struct v4l2_control ctrl = { .id = query->id };
661 if (v4l2_ioctl (fd, VIDIOC_G_CTRL, &ctrl) >= 0)
663 msg_Dbg (obj, " current: %"PRId32", default: %"PRId32,
664 ctrl.value, query->default_value);
665 val.i_int = ctrl.value;
666 var_Change (obj, c->name, VLC_VAR_SETVALUE, &val, NULL);
668 val.i_int = query->minimum;
669 var_Change (obj, c->name, VLC_VAR_SETMIN, &val, NULL);
670 val.i_int = query->maximum;
671 var_Change (obj, c->name, VLC_VAR_SETMAX, &val, NULL);
672 val.i_int = query->default_value;
673 var_Change (obj, c->name, VLC_VAR_SETDEFAULT, &val, NULL);
675 /* Import menu choices */
676 for (uint_fast32_t idx = query->minimum;
677 idx <= (uint_fast32_t)query->maximum;
680 struct v4l2_querymenu menu = { .id = query->id, .index = idx };
681 char name[sizeof ("-9223372036854775808")];
683 if (v4l2_ioctl (fd, VIDIOC_QUERYMENU, &menu) < 0)
685 msg_Dbg (obj, " choice %"PRIu32") %"PRId64, menu.index, menu.value);
688 val.i_int = menu.index;
689 sprintf (name, "%"PRId64, menu.value);
690 text.psz_string = name;
691 var_Change (obj, c->name, VLC_VAR_ADDCHOICE, &val, &text);
696 static vlc_v4l2_ctrl_t *ControlAddUnknown (vlc_object_t *obj, int fd,
697 const struct v4l2_queryctrl *query)
699 msg_Dbg (obj, " unknown %s (%08"PRIX32")", query->name, query->id);
700 msg_Warn (obj, " unknown control type %u", (unsigned)query->type);
705 typedef vlc_v4l2_ctrl_t *(*ctrl_type_cb) (vlc_object_t *, int,
706 const struct v4l2_queryctrl *);
709 * Lists all user-class v4l2 controls, sets them to the user specified
710 * value and create the relevant variables to enable run-time changes.
712 vlc_v4l2_ctrl_t *ControlsInit (vlc_object_t *obj, int fd)
714 /* A list of controls that can be modified at run-time is stored in the
715 * "controls" variable. The V4L2 controls dialog can be built from this. */
716 var_Create (obj, "controls", VLC_VAR_INTEGER | VLC_VAR_HASCHOICE);
718 static const ctrl_type_cb handlers[] =
720 [V4L2_CTRL_TYPE_INTEGER] = ControlAddInteger,
721 [V4L2_CTRL_TYPE_BOOLEAN] = ControlAddBoolean,
722 [V4L2_CTRL_TYPE_MENU] = ControlAddMenu,
723 [V4L2_CTRL_TYPE_BUTTON] = ControlAddButton,
724 [V4L2_CTRL_TYPE_INTEGER64] = ControlAddInteger64,
725 [V4L2_CTRL_TYPE_CTRL_CLASS] = ControlAddClass,
726 [V4L2_CTRL_TYPE_STRING] = ControlAddString,
727 [V4L2_CTRL_TYPE_BITMASK] = ControlAddBitMask,
728 [V4L2_CTRL_TYPE_INTEGER_MENU] = ControlAddIntMenu,
731 vlc_v4l2_ctrl_t *list = NULL;
732 struct v4l2_queryctrl query;
734 query.id = V4L2_CTRL_FLAG_NEXT_CTRL;
735 while (v4l2_ioctl (fd, VIDIOC_QUERYCTRL, &query) >= 0)
737 ctrl_type_cb handler = NULL;
738 if (query.type < (sizeof (handlers) / sizeof (handlers[0])))
739 handler = handlers[query.type];
741 handler = ControlAddUnknown;
743 vlc_v4l2_ctrl_t *c = handler (obj, fd, &query);
746 vlc_value_t val, text;
748 var_AddCallback (obj, c->name, ControlSetCallback, c);
749 text.psz_string = (char *)query.name;
750 var_Change (obj, c->name, VLC_VAR_SETTEXT, &text, NULL);
751 val.i_int = query.id;
752 text.psz_string = (char *)c->name;
753 var_Change (obj, "controls", VLC_VAR_ADDCHOICE, &val, &text);
758 query.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
761 /* Set well-known controls from VLC configuration */
762 for (vlc_v4l2_ctrl_t *ctrl = list; ctrl != NULL; ctrl = ctrl->next)
764 if (!CTRL_CID_KNOWN (ctrl->id))
767 char varname[sizeof (CFG_PREFIX) + sizeof (ctrl->name) - 1];
768 sprintf (varname, CFG_PREFIX"%s", ctrl->name);
770 int64_t val = var_InheritInteger (obj, varname);
772 continue; /* the VLC default value: "do not modify" */
773 ControlSet (ctrl, val); /* NOTE: all known are integers or booleans */
776 /* Set any control from the VLC configuration control string */
777 ControlsSetFromString (obj, list);
779 /* Add a control to reset all controls to their default values */
781 vlc_value_t val, text;
783 var_Create (obj, "reset", VLC_VAR_VOID | VLC_VAR_ISCOMMAND);
784 val.psz_string = _("Reset defaults");
785 var_Change (obj, "reset", VLC_VAR_SETTEXT, &val, NULL);
788 text.psz_string = (char *)"reset";
789 var_Change (obj, "controls", VLC_VAR_ADDCHOICE, &val, &text);
790 var_AddCallback (obj, "reset", ControlsResetCallback, list);
792 if (var_InheritBool (obj, CFG_PREFIX"controls-reset"))
793 ControlsReset (obj, list);
798 void ControlsDeinit (vlc_object_t *obj, vlc_v4l2_ctrl_t *list)
800 var_DelCallback (obj, "reset", ControlsResetCallback, list);
801 var_Destroy (obj, "reset");
805 vlc_v4l2_ctrl_t *next = list->next;
807 var_DelCallback (obj, list->name, ControlSetCallback, list);
808 var_Destroy (obj, list->name);
813 var_Destroy (obj, "controls");