Add prefs-int-scale and makes balance-scale balance only
[gstreamer-omap:cheese.git] / src / cheese-prefs-int-scale.c
1 /*
2  * Copyright © 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
3  * Copyright © 2011 Collabora Ltda
4  *  @author: Luciana Fujii Pontello <luciana.fujii@collabora.co.uk>
5  *
6  * Licensed under the GNU General Public License Version 2
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 <string.h>
23 #include <glib.h>
24
25 #include <cheese-camera.h>
26 #include "cheese-prefs-widget.h"
27 #include "cheese-prefs-int-scale.h"
28
29 #define MAX_SECONDS 0.3
30
31 enum
32 {
33   PROP_0,
34   PROP_PROPERTY_NAME,
35   PROP_GCONF_KEY,
36   PROP_CAMERA
37 };
38
39 typedef struct CheesePrefsIntScalePrivate
40 {
41   CheeseCamera *camera;
42   gchar *property_name;
43   gchar *gconf_key;
44   gint current_value;
45   gboolean has_been_synchronized;  /* Make sure we don't synchronize if client
46                                     * sets camera on construction. */
47   GTimer *timer;
48 } CheesePrefsIntScalePrivate;
49
50 #define CHEESE_PREFS_INT_SCALE_GET_PRIVATE(o)                     \
51   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_PREFS_INT_SCALE, \
52                                 CheesePrefsIntScalePrivate))
53
54 G_DEFINE_TYPE (CheesePrefsIntScale, cheese_prefs_int_scale,
55                CHEESE_TYPE_PREFS_WIDGET);
56
57 static void
58 cheese_prefs_int_scale_init (CheesePrefsIntScale *self)
59 {
60   CheesePrefsIntScalePrivate *priv = CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
61
62   priv->property_name         = NULL;
63   priv->gconf_key             = NULL;
64   priv->has_been_synchronized = FALSE;
65   priv->current_value = 0;
66   priv->timer = NULL;
67 }
68
69 static void
70 cheese_prefs_int_scale_finalize (GObject *object)
71 {
72   CheesePrefsIntScale        *self = CHEESE_PREFS_INT_SCALE (object);
73   CheesePrefsIntScalePrivate *priv = CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
74
75   g_free (priv->property_name);
76   g_free (priv->gconf_key);
77
78   G_OBJECT_CLASS (cheese_prefs_int_scale_parent_class)->finalize (object);
79 }
80
81 static gboolean
82 changed_cb (gpointer self)
83 {
84   CheesePrefsIntScalePrivate *priv =
85       CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
86   GtkWidget *scale;
87   gint value;
88
89   g_object_get (self, "widget", &scale, NULL);
90   value = gtk_range_get_value (GTK_RANGE (scale));
91
92   if (priv->current_value != value)
93   {
94     cheese_camera_set_int_property (priv->camera, priv->property_name, value);
95     g_object_set (CHEESE_PREFS_WIDGET (self)->gconf,
96                   priv->gconf_key, value, NULL);
97     cheese_prefs_widget_notify_changed (CHEESE_PREFS_WIDGET (self));
98   }
99
100   return FALSE;
101 }
102
103 static void
104 cheese_prefs_int_scale_value_changed (GtkRange *scale,
105                                       CheesePrefsIntScale *self)
106 {
107   CheesePrefsIntScalePrivate *priv =
108       CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
109   static gint tag = 0;
110   gdouble seconds_elapsed;
111
112   if (NULL == priv->timer)
113     priv->timer = g_timer_new ();
114
115   seconds_elapsed = g_timer_elapsed (priv->timer, NULL);
116   if (tag && seconds_elapsed < MAX_SECONDS)
117     g_source_remove (tag);
118   else if (seconds_elapsed >= MAX_SECONDS)
119     g_timer_start (priv->timer);
120   tag = g_timeout_add (50, changed_cb, self);
121 }
122
123 static void
124 cheese_prefs_int_scale_synchronize (CheesePrefsWidget *prefs_widget)
125 {
126   CheesePrefsIntScale        *self = CHEESE_PREFS_INT_SCALE (prefs_widget);
127   CheesePrefsIntScalePrivate *priv = CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
128
129   GtkWidget     *scale;
130   GtkAdjustment *adj;
131   gboolean       can_balance;
132   gint stored_value;
133   gdouble min, max, def;
134   gdouble step;
135
136   g_object_get (prefs_widget, "widget", &scale, NULL);
137
138   /* Disconnect to prevent a whole bunch of changed notifications */
139   g_signal_handlers_disconnect_by_func (scale,
140                                         cheese_prefs_int_scale_value_changed,
141                                         prefs_widget);
142
143   can_balance = cheese_camera_get_property_range (priv->camera,
144                                                   priv->property_name,
145                                                   &min, &max,
146                                                   &def, &step);
147
148   adj = GTK_ADJUSTMENT (gtk_adjustment_new (def, min, max, step, 0.0, 0.0));
149   gtk_range_set_adjustment (GTK_RANGE (scale), adj);
150
151   gtk_scale_add_mark (GTK_SCALE (scale), def, GTK_POS_BOTTOM, NULL);
152
153   gtk_widget_set_sensitive (scale, can_balance);
154
155   if (can_balance)
156   {
157     g_object_get (CHEESE_PREFS_WIDGET (self)->gconf,
158                   priv->gconf_key, &stored_value, NULL);
159     gtk_range_set_value (GTK_RANGE (scale), stored_value);
160   }
161   priv->current_value = stored_value;
162
163   g_signal_connect (G_OBJECT (scale), "value-changed",
164                     G_CALLBACK (cheese_prefs_int_scale_value_changed),
165                     self);
166 }
167
168 static void
169 cheese_prefs_int_scale_set_property (GObject *object, guint prop_id,
170                                          const GValue *value,
171                                          GParamSpec *pspec)
172 {
173   CheesePrefsIntScalePrivate *priv =
174       CHEESE_PREFS_INT_SCALE_GET_PRIVATE (object);
175
176   switch (prop_id)
177   {
178     case PROP_PROPERTY_NAME:
179       priv->property_name = g_value_dup_string (value);
180       break;
181     case PROP_GCONF_KEY:
182       priv->gconf_key = g_value_dup_string (value);
183       break;
184     case PROP_CAMERA:
185       priv->camera = CHEESE_CAMERA (g_value_get_object (value));
186       if (priv->has_been_synchronized)
187         cheese_prefs_int_scale_synchronize (CHEESE_PREFS_WIDGET (object));
188       break;
189     default:
190       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191       break;
192   }
193 }
194
195 static void
196 cheese_prefs_int_scale_get_property (GObject *object, guint prop_id,
197                                          GValue *value, GParamSpec *pspec)
198 {
199   CheesePrefsIntScalePrivate *priv =
200       CHEESE_PREFS_INT_SCALE_GET_PRIVATE (object);
201
202   g_return_if_fail (CHEESE_IS_PREFS_INT_SCALE (object));
203
204   switch (prop_id)
205   {
206     case PROP_PROPERTY_NAME:
207       g_value_set_string (value, priv->property_name);
208       break;
209     case PROP_GCONF_KEY:
210       g_value_set_string (value, priv->gconf_key);
211       break;
212     case PROP_CAMERA:
213       g_value_set_object (value, priv->camera);
214       break;
215     default:
216       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
217       break;
218   }
219 }
220
221 static void
222 cheese_prefs_int_scale_class_init (CheesePrefsIntScaleClass *klass)
223 {
224   GObjectClass           *object_class = G_OBJECT_CLASS (klass);
225   CheesePrefsWidgetClass *parent_class = CHEESE_PREFS_WIDGET_CLASS (klass);
226
227   g_type_class_add_private (klass, sizeof (CheesePrefsIntScalePrivate));
228
229   object_class->finalize     = cheese_prefs_int_scale_finalize;
230   object_class->set_property = cheese_prefs_int_scale_set_property;
231   object_class->get_property = cheese_prefs_int_scale_get_property;
232   parent_class->synchronize  = cheese_prefs_int_scale_synchronize;
233
234   g_object_class_install_property (object_class,
235           PROP_PROPERTY_NAME,
236           g_param_spec_string ("property_name",
237                                "",
238                                "Property this widget will control colorbalance",
239                                "",
240                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
241
242   g_object_class_install_property (object_class,
243           PROP_GCONF_KEY,
244           g_param_spec_string ("gconf_key",
245                                "",
246                                "GConf key for balance",
247                                "",
248                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
249
250   g_object_class_install_property (object_class,
251           PROP_CAMERA,
252           g_param_spec_object ("camera",
253                                "camera",
254                                "Camera object",
255                                CHEESE_TYPE_CAMERA,
256                                G_PARAM_READWRITE));
257 }
258
259 CheesePrefsIntScale *
260 cheese_prefs_int_scale_new (GtkWidget *scale,
261                             CheeseCamera *camera,
262                             const gchar *property,
263                             const gchar *gconf_key)
264 {
265   CheesePrefsIntScale        *self;
266   CheesePrefsIntScalePrivate *priv;
267
268   self = g_object_new (CHEESE_TYPE_PREFS_INT_SCALE,
269                        "widget", scale,
270                        "camera", camera,
271                        "property_name", property,
272                        "gconf_key", gconf_key,
273                        NULL);
274
275   priv = CHEESE_PREFS_INT_SCALE_GET_PRIVATE (self);
276
277   return self;
278 }