Add prefs-int-scale and makes balance-scale balance only
[gstreamer-omap:cheese.git] / src / cheese-prefs-balance-scale.c
1 /*
2  * Copyright © 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
3  *
4  * Licensed under the GNU General Public License Version 2
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <string.h>
21 #include <glib.h>
22
23 #include <cheese-camera.h>
24 #include "cheese-prefs-widget.h"
25 #include "cheese-prefs-balance-scale.h"
26
27 #define MAX_SECONDS 0.3
28
29 enum
30 {
31   PROP_0,
32   PROP_PROPERTY_NAME,
33   PROP_GCONF_KEY,
34   PROP_CAMERA
35 };
36
37 typedef struct CheesePrefsBalanceScalePrivate
38 {
39   CheeseCamera *camera;
40   gchar *property_name;
41   gchar *gconf_key;
42   gint current_value;
43   gboolean has_been_synchronized;  /* Make sure we don't synchronize if client
44                                     * sets camera on construction. */
45   GTimer *timer;
46 } CheesePrefsBalanceScalePrivate;
47
48 #define CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE(o)                     \
49   (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_PREFS_BALANCE_SCALE, \
50                                 CheesePrefsBalanceScalePrivate))
51
52 G_DEFINE_TYPE (CheesePrefsBalanceScale, cheese_prefs_balance_scale, CHEESE_TYPE_PREFS_WIDGET);
53
54 static void
55 cheese_prefs_balance_scale_init (CheesePrefsBalanceScale *self)
56 {
57   CheesePrefsBalanceScalePrivate *priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
58
59   priv->property_name         = NULL;
60   priv->gconf_key             = NULL;
61   priv->has_been_synchronized = FALSE;
62   priv->current_value = 0;
63   priv->timer = NULL;
64 }
65
66 static void
67 cheese_prefs_balance_scale_finalize (GObject *object)
68 {
69   CheesePrefsBalanceScale        *self = CHEESE_PREFS_BALANCE_SCALE (object);
70   CheesePrefsBalanceScalePrivate *priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
71
72   g_free (priv->property_name);
73   g_free (priv->gconf_key);
74
75   G_OBJECT_CLASS (cheese_prefs_balance_scale_parent_class)->finalize (object);
76 }
77
78 static gboolean
79 changed_cb (gpointer self)
80 {
81   CheesePrefsBalanceScalePrivate *priv =
82       CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
83   GtkWidget *scale;
84   gint value;
85
86   g_object_get (self, "widget", &scale, NULL);
87   value = gtk_range_get_value (GTK_RANGE (scale));
88
89   if (priv->current_value != value)
90   {
91     cheese_camera_set_balance_property (priv->camera,
92                                         priv->property_name, value);
93     g_object_set (CHEESE_PREFS_WIDGET (self)->gconf,
94                   priv->gconf_key, value, NULL);
95     cheese_prefs_widget_notify_changed (CHEESE_PREFS_WIDGET (self));
96   }
97
98   return FALSE;
99 }
100
101 static void
102 cheese_prefs_balance_scale_value_changed (GtkRange *scale, CheesePrefsBalanceScale *self)
103 {
104   CheesePrefsBalanceScalePrivate *priv =
105       CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
106   static gint tag = 0;
107   gdouble seconds_elapsed;
108
109   if (NULL == priv->timer)
110     priv->timer = g_timer_new ();
111
112   seconds_elapsed = g_timer_elapsed (priv->timer, NULL);
113   if (tag && seconds_elapsed < MAX_SECONDS)
114     g_source_remove (tag);
115   else if (seconds_elapsed >= MAX_SECONDS)
116     g_timer_start (priv->timer);
117   tag = g_timeout_add (50, changed_cb, self);
118 }
119
120 static void
121 cheese_prefs_balance_scale_synchronize (CheesePrefsWidget *prefs_widget)
122 {
123   CheesePrefsBalanceScale        *self = CHEESE_PREFS_BALANCE_SCALE (prefs_widget);
124   CheesePrefsBalanceScalePrivate *priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
125
126   GtkWidget     *scale;
127   GtkAdjustment *adj;
128   gboolean       can_balance;
129   gint stored_value;
130   gint min, max, def;
131
132   g_object_get (prefs_widget, "widget", &scale, NULL);
133
134   /* Disconnect to prevent a whole bunch of changed notifications */
135   g_signal_handlers_disconnect_by_func (scale, cheese_prefs_balance_scale_value_changed, prefs_widget);
136
137   can_balance = cheese_camera_get_balance_property_range (priv->camera,
138                                                           priv->property_name,
139                                                           &min, &max,
140                                                           &def);
141
142   adj = GTK_ADJUSTMENT (gtk_adjustment_new (def, min, max, 1, 0.0, 0.0));
143   gtk_range_set_adjustment (GTK_RANGE (scale), adj);
144
145   gtk_scale_add_mark (GTK_SCALE (scale), def, GTK_POS_BOTTOM, NULL);
146
147   gtk_widget_set_sensitive (scale, can_balance);
148
149   if (can_balance)
150   {
151     g_object_get (CHEESE_PREFS_WIDGET (self)->gconf, priv->gconf_key, &stored_value, NULL);
152     gtk_range_set_value (GTK_RANGE (scale), stored_value);
153   }
154   priv->current_value = stored_value;
155
156   g_signal_connect (G_OBJECT (scale), "value-changed",
157                     G_CALLBACK (cheese_prefs_balance_scale_value_changed),
158                     self);
159 }
160
161 static void
162 cheese_prefs_balance_scale_set_property (GObject *object, guint prop_id,
163                                          const GValue *value,
164                                          GParamSpec *pspec)
165 {
166   CheesePrefsBalanceScalePrivate *priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (object);
167
168   switch (prop_id)
169   {
170     case PROP_PROPERTY_NAME:
171       priv->property_name = g_value_dup_string (value);
172       break;
173     case PROP_GCONF_KEY:
174       priv->gconf_key = g_value_dup_string (value);
175       break;
176     case PROP_CAMERA:
177       priv->camera = CHEESE_CAMERA (g_value_get_object (value));
178       if (priv->has_been_synchronized)
179         cheese_prefs_balance_scale_synchronize (CHEESE_PREFS_WIDGET (object));
180       break;
181     default:
182       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
183       break;
184   }
185 }
186
187 static void
188 cheese_prefs_balance_scale_get_property (GObject *object, guint prop_id,
189                                          GValue *value, GParamSpec *pspec)
190 {
191   CheesePrefsBalanceScalePrivate *priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (object);
192
193   g_return_if_fail (CHEESE_IS_PREFS_BALANCE_SCALE (object));
194
195   switch (prop_id)
196   {
197     case PROP_PROPERTY_NAME:
198       g_value_set_string (value, priv->property_name);
199       break;
200     case PROP_GCONF_KEY:
201       g_value_set_string (value, priv->gconf_key);
202       break;
203     case PROP_CAMERA:
204       g_value_set_object (value, priv->camera);
205       break;
206     default:
207       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
208       break;
209   }
210 }
211
212 static void
213 cheese_prefs_balance_scale_class_init (CheesePrefsBalanceScaleClass *klass)
214 {
215   GObjectClass           *object_class = G_OBJECT_CLASS (klass);
216   CheesePrefsWidgetClass *parent_class = CHEESE_PREFS_WIDGET_CLASS (klass);
217
218   g_type_class_add_private (klass, sizeof (CheesePrefsBalanceScalePrivate));
219
220   object_class->finalize     = cheese_prefs_balance_scale_finalize;
221   object_class->set_property = cheese_prefs_balance_scale_set_property;
222   object_class->get_property = cheese_prefs_balance_scale_get_property;
223   parent_class->synchronize  = cheese_prefs_balance_scale_synchronize;
224
225   g_object_class_install_property (object_class,
226                                    PROP_PROPERTY_NAME,
227                                    g_param_spec_string ("property_name",
228                                                         "",
229                                                         "Property this widget will control in the videobalance element",
230                                                         "",
231                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
232
233   g_object_class_install_property (object_class,
234                                    PROP_GCONF_KEY,
235                                    g_param_spec_string ("gconf_key",
236                                                         "",
237                                                         "GConf key for balance",
238                                                         "",
239                                                         G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
240
241   g_object_class_install_property (object_class,
242                                    PROP_CAMERA,
243                                    g_param_spec_object ("camera",
244                                                         "camera",
245                                                         "Camera object",
246                                                         CHEESE_TYPE_CAMERA,
247                                                         G_PARAM_READWRITE));
248 }
249
250 CheesePrefsBalanceScale *
251 cheese_prefs_balance_scale_new (GtkWidget    *scale,
252                                 CheeseCamera *camera,
253                                 const gchar  *property,
254                                 const gchar  *gconf_key)
255 {
256   CheesePrefsBalanceScale        *self;
257   CheesePrefsBalanceScalePrivate *priv;
258
259   self = g_object_new (CHEESE_TYPE_PREFS_BALANCE_SCALE,
260                        "widget", scale,
261                        "camera", camera,
262                        "property_name", property,
263                        "gconf_key", gconf_key,
264                        NULL);
265
266   priv = CHEESE_PREFS_BALANCE_SCALE_GET_PRIVATE (self);
267
268   return self;
269 }