6e82d865b39aed445f24db7ddec70fafa68473f6
[framework/location/libslp-location.git] / location / location-hybrid.c
1 /*
2  * libslp-location
3  *
4  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Youngae Kang <youngae.kang@samsung.com>, Yunhan Kim <yhan.kim@samsung.com>,
7  *          Genie Kim <daejins.kim@samsung.com>, Minjune Kim <sena06.kim@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "location/location-setting.h"
27 #include "location/location-log.h"
28
29 #include "location/location-module-internal.h"
30
31 #include "location/location-hybrid.h"
32 #include "location/location-marshal.h"
33 #include "location/location-ielement.h"
34 #include "location/location-signaling-util.h"
35 #include "location/location-common-util.h"
36
37 #include "location/location-gps.h"
38 #include "location/location-wps.h"
39 #include "location/location-sps.h"
40
41 typedef struct _LocationHybridPrivate {
42         gboolean is_started;
43         gboolean gps_enabled;
44         gboolean wps_enabled;
45         gboolean sps_enabled;
46         guint interval;
47         LocationObject *gps;
48         LocationObject *wps;
49         LocationObject *sps;
50         gboolean enabled;
51         LocationMethod current_method;
52         LocationPosition *pos;
53         LocationVelocity *vel;
54         LocationAccuracy *acc;
55         GList* boundary_list;
56         ZoneStatus zone_status;
57
58 } LocationHybridPrivate;
59
60 enum {
61         PROP_0,
62         PROP_METHOD_TYPE,
63         PROP_LAST_POSITION,
64         PROP_UPDATE_INTERVAL,
65         PROP_BOUNDARY,
66         PROP_REMOVAL_BOUNDARY,
67         PROP_MAX
68 };
69
70 static guint32 signals[LAST_SIGNAL] = {0, };
71 static GParamSpec *properties[PROP_MAX] = {NULL, };
72
73 #define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), LOCATION_TYPE_HYBRID, LocationHybridPrivate))
74
75 static void location_ielement_interface_init (LocationIElementInterface *iface);
76
77 G_DEFINE_TYPE_WITH_CODE (LocationHybrid, location_hybrid, G_TYPE_OBJECT,
78                          G_IMPLEMENT_INTERFACE (LOCATION_TYPE_IELEMENT,
79                          location_ielement_interface_init));
80
81
82 static LocationObject*
83 hybrid_get_update_method_obj (LocationHybridPrivate* priv)
84 {
85         if(!priv->sps && !priv->gps && !priv->wps) return NULL;
86
87         LocationObject* obj = NULL;
88         if (priv->sps_enabled) {
89                 LOCATION_LOGW("Current method is SPS");
90                 priv->current_method = LOCATION_METHOD_SPS;
91                 obj = priv->sps;
92         } else if (priv->gps_enabled) {
93                 LOCATION_LOGW("Current method is GPS");
94                 priv->current_method = LOCATION_METHOD_GPS;
95                 obj = priv->gps;
96         } else if (priv->wps_enabled) {
97                 LOCATION_LOGW("Current method is WPS");
98                 priv->current_method = LOCATION_METHOD_WPS;
99                 obj = priv->wps;
100         } else {
101                 LOCATION_LOGW("No current method available");
102                 priv->current_method = LOCATION_METHOD_HYBRID;
103                 obj = NULL;
104         }
105         return obj;
106 }
107
108 static gboolean
109 hyrid_is_equal_g_type_method(GType g_type, LocationMethod method)
110 {
111         if (g_type == LOCATION_TYPE_SPS && method == LOCATION_METHOD_SPS) return TRUE;
112         if (g_type == LOCATION_TYPE_GPS && method == LOCATION_METHOD_GPS) return TRUE;
113         if (g_type == LOCATION_TYPE_WPS && method == LOCATION_METHOD_WPS) return TRUE;
114         return FALSE;
115 }
116
117 static void
118 hybrid_update_sps(LocationHybrid* self,
119         guint type,
120         gpointer data,
121         gpointer accuracy)
122 {
123         LocationHybridPrivate* priv = GET_PRIVATE(self);
124         if (!priv->sps) return;
125         LOCATION_LOGD ("hybrid_update_sps");
126
127         switch (type) {
128                 case POSITION_UPDATED: {
129                         if (data) g_object_set(priv->sps, "position-base", data, NULL);
130                         if (priv->gps) {
131                                 LocationSatellite* sat = NULL;
132                                 g_object_get(priv->gps, "satellite", &sat, NULL);
133                                 if (sat) {
134                                         g_object_set(priv->sps, "satellite-info", sat, NULL);
135                                         location_satellite_free (sat);
136                                 }
137                         }
138                         if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
139                         break;
140                 }
141                 case VELOCITY_UPDATED:
142                         if (data) g_object_set(priv->sps, "velocity-base", data, NULL);
143                         if (accuracy) g_object_set(priv->sps, "accuracy-info", accuracy, NULL);
144                         break;
145         }
146 }
147
148 static void
149 hybrid_service_updated (GObject *obj,
150         guint type,
151         gpointer data,
152         gpointer accuracy,
153         gpointer self)
154 {
155         LOCATION_LOGD ("hybrid_service_updated");
156         LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
157         GType g_type = G_TYPE_FROM_INSTANCE(obj);
158         if (g_type == LOCATION_TYPE_GPS) hybrid_update_sps((LocationHybrid*)self, type, data, accuracy);
159         if (hyrid_is_equal_g_type_method(g_type, priv->current_method)) {
160                 LocationAccuracy *acc = (LocationAccuracy*)accuracy;
161                 if (type == POSITION_UPDATED) {
162                         LocationPosition *pos = (LocationPosition*)data;
163                         position_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->pos), &(priv->acc), priv->boundary_list, &(priv->zone_status), TRUE, pos, acc);
164                 } else if (type == VELOCITY_UPDATED) {
165                         LocationVelocity *vel = (LocationVelocity*) data;
166                         velocity_signaling(self, signals, &(priv->enabled), priv->interval, &(priv->vel), TRUE, vel, acc);
167                 } else LOCATION_LOGW ("Undefined GType updated");
168         }
169
170 }
171
172 static void
173 hybrid_service_enabled (GObject *obj,
174         guint status,
175         gpointer self)
176 {
177         LOCATION_LOGD ("hybrid_service_enabled");
178         LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
179         GType g_type = G_TYPE_FROM_INSTANCE(obj);
180         if (g_type == LOCATION_TYPE_SPS)     priv->sps_enabled = TRUE;
181         else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = TRUE;
182         else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = TRUE;
183         else {
184                 LOCATION_LOGW("Undefined GType enabled");
185                 return;
186         }
187         hybrid_get_update_method_obj(priv);
188         if(priv->sps_enabled || priv->gps_enabled || priv->wps_enabled)
189                 enable_signaling(self, signals, &(priv->enabled), TRUE, status);
190 }
191
192 static void
193 hybrid_service_disabled (GObject *obj,
194         guint status,
195         gpointer self)
196 {
197         LOCATION_LOGD ("hybrid_service_disabled");
198         LocationHybridPrivate* priv = GET_PRIVATE((LocationHybrid*)self);
199         GType g_type = G_TYPE_FROM_INSTANCE(obj);
200         if (g_type == LOCATION_TYPE_SPS)     priv->sps_enabled = FALSE;
201         else if(g_type == LOCATION_TYPE_GPS) priv->gps_enabled = FALSE;
202         else if(g_type == LOCATION_TYPE_WPS) priv->wps_enabled = FALSE;
203         else {
204                 LOCATION_LOGW("Undefined GType disabled");
205                 return;
206         }
207         hybrid_get_update_method_obj(priv);
208         if(!priv->sps_enabled && !priv->gps_enabled && !priv->wps_enabled)
209                 enable_signaling(self, signals, &(priv->enabled), FALSE, status);
210 }
211
212 static int
213 location_hybrid_start (LocationHybrid *self)
214 {
215         LOCATION_LOGD("location_hybrid_start");
216
217         int ret_gps = LOCATION_ERROR_NONE;
218         int ret_wps = LOCATION_ERROR_NONE;
219         int ret_sps = LOCATION_ERROR_NONE;
220
221         LocationHybridPrivate* priv = GET_PRIVATE(self);
222         if (priv->is_started == TRUE)
223                 return LOCATION_ERROR_NONE;
224
225         if(priv->gps) ret_gps = location_start(priv->gps);
226         if(priv->wps) ret_wps = location_start(priv->wps);
227         if(priv->sps) ret_sps = location_start(priv->sps);
228
229         if (ret_gps != LOCATION_ERROR_NONE &&
230                 ret_wps != LOCATION_ERROR_NONE &&
231                 ret_sps != LOCATION_ERROR_NONE) {
232                 if (ret_gps == LOCATION_ERROR_NOT_ALLOWED ||
233                                 ret_wps == LOCATION_ERROR_NOT_ALLOWED ||
234                                 ret_sps == LOCATION_ERROR_NOT_ALLOWED) {
235                         priv->is_started = TRUE;
236                         return LOCATION_ERROR_NOT_ALLOWED;
237                 }
238                 else {
239                         return LOCATION_ERROR_NOT_AVAILABLE;
240                 }
241         }
242
243         priv->is_started = TRUE;
244         return LOCATION_ERROR_NONE;
245 }
246
247 static int
248 location_hybrid_stop (LocationHybrid *self)
249 {
250         LOCATION_LOGD("location_hybrid_stop");
251
252         LocationHybridPrivate* priv = GET_PRIVATE(self);
253         if( priv->is_started == FALSE)
254                 return LOCATION_ERROR_NONE;
255
256         int ret_gps = LOCATION_ERROR_NONE;
257         int ret_wps = LOCATION_ERROR_NONE;
258         int ret_sps = LOCATION_ERROR_NONE;
259
260         if(priv->gps) ret_gps = location_stop(priv->gps);
261         if(priv->wps) ret_wps = location_stop(priv->wps);
262         if(priv->sps) ret_sps = location_stop(priv->sps);
263
264         priv->is_started = FALSE;
265
266         if (ret_gps != LOCATION_ERROR_NONE &&
267                 ret_wps != LOCATION_ERROR_NONE &&
268                 ret_sps != LOCATION_ERROR_NONE)
269                 return LOCATION_ERROR_NOT_AVAILABLE;
270
271         return LOCATION_ERROR_NONE;
272 }
273
274 static void
275 location_hybrid_dispose (GObject *gobject)
276 {
277         LOCATION_LOGD("location_hybrid_dispose");
278         G_OBJECT_CLASS (location_hybrid_parent_class)->dispose (gobject);
279 }
280
281 static void
282 location_hybrid_finalize (GObject *gobject)
283 {
284         LOCATION_LOGD("location_hybrid_finalize");
285         LocationHybridPrivate* priv = GET_PRIVATE(gobject);
286
287         if (priv->gps) {
288                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_enabled), gobject);
289                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_disabled), gobject);
290                 g_signal_handlers_disconnect_by_func(priv->gps, G_CALLBACK (hybrid_service_updated), gobject);
291                 location_free(priv->gps);
292         }
293         if (priv->wps) {
294                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_enabled), gobject);
295                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_disabled), gobject);
296                 g_signal_handlers_disconnect_by_func(priv->wps, G_CALLBACK (hybrid_service_updated), gobject);
297                 location_free(priv->wps);
298         }
299         if (priv->sps) {
300                 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_enabled), gobject);
301                 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_disabled), gobject);
302                 g_signal_handlers_disconnect_by_func(priv->sps, G_CALLBACK (hybrid_service_updated), gobject);
303                 location_free(priv->sps);
304         }
305
306         G_OBJECT_CLASS (location_hybrid_parent_class)->finalize (gobject);
307 }
308
309 static void
310 location_hybrid_set_property (GObject *object,
311         guint property_id,
312         const GValue *value,
313         GParamSpec *pspec)
314 {
315         LocationHybridPrivate* priv = GET_PRIVATE(object);
316         if (!priv->gps && !priv->wps && !priv->sps) {
317                 LOCATION_LOGW("Set property is not available now");
318                 return;
319         }
320
321         int ret = 0;
322         switch (property_id){
323                 case PROP_BOUNDARY:{
324                         GList *boundary_list = (GList *)g_list_copy(g_value_get_pointer(value));
325                         ret = set_prop_boundary(&priv->boundary_list, boundary_list);
326                         if(ret != 0) LOCATION_LOGD("Set boundary. Error[%d]", ret);
327                    break;
328                 }
329                 case PROP_REMOVAL_BOUNDARY: {
330                         LocationBoundary *req_boundary = (LocationBoundary*) g_value_dup_boxed(value);
331                         ret = set_prop_removal_boundary(&priv->boundary_list, req_boundary);
332                         if(ret != 0) LOCATION_LOGD("Removal boundary. Error[%d]", ret);
333                         break;
334                 }
335                 case PROP_UPDATE_INTERVAL: {
336                         guint interval = g_value_get_uint(value);
337                         if(interval > 0) {
338                                 if(interval < LOCATION_UPDATE_INTERVAL_MAX)
339                                         priv->interval = interval;
340                                 else
341                                         priv->interval = (guint) LOCATION_UPDATE_INTERVAL_MAX;
342
343                         }
344                         else
345                                 priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
346                         break;
347                 }
348                 default:
349                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
350                         break;
351         }
352 }
353
354 static void
355 location_hybrid_get_property (GObject *object,
356         guint property_id,
357         GValue *value,
358         GParamSpec *pspec)
359 {
360         LocationHybridPrivate *priv = GET_PRIVATE (object);
361         if(!priv->gps && !priv->wps && !priv->sps){
362                 LOCATION_LOGW("Get property is not available now");
363                 return;
364         }
365
366         LOCATION_LOGW("Get Propery ID[%d]", property_id);
367
368         switch (property_id){
369         case PROP_METHOD_TYPE:
370                 g_value_set_int(value, priv->current_method);
371                 break;
372         case PROP_LAST_POSITION:
373                 g_value_set_boxed(value, priv->pos);
374                 break;
375         case PROP_BOUNDARY:
376                 g_value_set_pointer(value, g_list_first(priv->boundary_list));
377                 break;
378         case PROP_UPDATE_INTERVAL:
379                 g_value_set_uint(value, priv->interval);
380                 break;
381         default:
382                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
383                 break;
384         }
385 }
386
387 static int
388 location_hybrid_get_position (LocationHybrid *self,
389         LocationPosition **position,
390         LocationAccuracy **accuracy)
391 {
392         LOCATION_LOGD("location_hybrid_get_position");
393         setting_retval_if_fail(GPS_ENABLED);
394
395         LocationHybridPrivate *priv = GET_PRIVATE (self);
396         LocationObject *obj = hybrid_get_update_method_obj(priv);
397         if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
398         return location_get_position (obj, position, accuracy);
399 }
400
401 static int
402 location_hybrid_get_velocity (LocationHybrid *self,
403         LocationVelocity **velocity,
404         LocationAccuracy **accuracy)
405 {
406         LOCATION_LOGD("location_hybrid_get_velocity");
407         setting_retval_if_fail(GPS_ENABLED);
408
409         LocationHybridPrivate *priv = GET_PRIVATE (self);
410         LocationObject *obj = hybrid_get_update_method_obj(priv);
411         if(!obj) return LOCATION_ERROR_NOT_AVAILABLE;
412         return location_get_velocity (obj, velocity, accuracy);
413 }
414
415 static void
416 location_ielement_interface_init (LocationIElementInterface *iface)
417 {
418         iface->start = (TYPE_START_FUNC)location_hybrid_start;
419         iface->stop = (TYPE_STOP_FUNC)location_hybrid_stop;
420         iface->get_position = (TYPE_GET_POSITION)location_hybrid_get_position;
421         iface->get_velocity = (TYPE_GET_VELOCITY)location_hybrid_get_velocity;
422 }
423
424 static void
425 location_hybrid_init (LocationHybrid *self)
426 {
427         LOCATION_LOGD("location_hybrid_init");
428         LocationHybridPrivate* priv = GET_PRIVATE(self);
429
430         priv->is_started = FALSE;
431         priv->interval = LOCATION_UPDATE_INTERVAL_DEFAULT;
432         priv->gps_enabled = FALSE;
433         priv->wps_enabled = FALSE;
434         priv->sps_enabled = FALSE;
435         priv->gps = NULL;
436         priv->wps = NULL;
437         priv->sps = NULL;
438
439         if(location_is_supported_method(LOCATION_METHOD_GPS)) priv->gps = location_new (LOCATION_METHOD_GPS);
440         if(location_is_supported_method(LOCATION_METHOD_WPS)) priv->wps = location_new (LOCATION_METHOD_WPS);
441         if(location_is_supported_method(LOCATION_METHOD_SPS)) priv->sps = location_new (LOCATION_METHOD_SPS);
442
443         if(priv->gps){
444                 g_signal_connect (priv->gps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
445                 g_signal_connect (priv->gps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
446                 g_signal_connect (priv->gps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
447         }
448         if(priv->wps){
449                 g_signal_connect (priv->wps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
450                 g_signal_connect (priv->wps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
451                 g_signal_connect (priv->wps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
452         }
453         if(priv->sps){
454                 g_signal_connect (priv->sps, "service-enabled", G_CALLBACK(hybrid_service_enabled), self);
455                 g_signal_connect (priv->sps, "service-disabled", G_CALLBACK(hybrid_service_disabled), self);
456                 g_signal_connect (priv->sps, "service-updated", G_CALLBACK(hybrid_service_updated), self);
457         }
458
459         priv->current_method = LOCATION_METHOD_HYBRID;
460         priv->enabled= FALSE;
461
462         priv->pos = NULL;
463         priv->vel = NULL;
464         priv->acc = NULL;
465         priv->zone_status = ZONE_STATUS_NONE;
466         priv->boundary_list = NULL;
467 }
468
469 static void
470 location_hybrid_class_init (LocationHybridClass *klass)
471 {
472         LOCATION_LOGD("location_hybrid_class_init");
473         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
474
475         gobject_class->set_property = location_hybrid_set_property;
476         gobject_class->get_property = location_hybrid_get_property;
477
478         gobject_class->dispose = location_hybrid_dispose;
479         gobject_class->finalize = location_hybrid_finalize;
480
481         g_type_class_add_private (klass, sizeof (LocationHybridPrivate));
482
483         signals[SERVICE_ENABLED] = g_signal_new ("service-enabled",
484                         G_TYPE_FROM_CLASS (klass),
485                         G_SIGNAL_RUN_FIRST |
486                         G_SIGNAL_NO_RECURSE,
487                         G_STRUCT_OFFSET (LocationHybridClass, enabled),
488                         NULL, NULL,
489                         location_VOID__UINT,
490                         G_TYPE_NONE, 1,
491                         G_TYPE_UINT);
492
493         signals[SERVICE_DISABLED] = g_signal_new ("service-disabled",
494                         G_TYPE_FROM_CLASS (klass),
495                         G_SIGNAL_RUN_FIRST |
496                         G_SIGNAL_NO_RECURSE,
497                         G_STRUCT_OFFSET (LocationHybridClass, disabled),
498                         NULL, NULL,
499                         location_VOID__UINT,
500                         G_TYPE_NONE, 1,
501                         G_TYPE_UINT);
502
503         signals[SERVICE_UPDATED] = g_signal_new ("service-updated",
504                         G_TYPE_FROM_CLASS (klass),
505                         G_SIGNAL_RUN_FIRST |
506                         G_SIGNAL_NO_RECURSE,
507                         G_STRUCT_OFFSET (LocationHybridClass, updated),
508                         NULL, NULL,
509                         location_VOID__UINT_POINTER_POINTER,
510                         G_TYPE_NONE, 3,
511                         G_TYPE_UINT,
512                         G_TYPE_POINTER,
513                         G_TYPE_POINTER);
514
515         signals[ZONE_IN] = g_signal_new ("zone-in",
516                         G_TYPE_FROM_CLASS (klass),
517                         G_SIGNAL_RUN_FIRST |
518                         G_SIGNAL_NO_RECURSE,
519                         G_STRUCT_OFFSET (LocationHybridClass, zone_in),
520                         NULL, NULL,
521                         location_VOID__UINT_POINTER_POINTER,
522                         G_TYPE_NONE, 3,
523                         G_TYPE_UINT,
524                         G_TYPE_POINTER,
525                         G_TYPE_POINTER);
526
527         signals[ZONE_OUT] = g_signal_new ("zone-out",
528                         G_TYPE_FROM_CLASS (klass),
529                         G_SIGNAL_RUN_FIRST |
530                         G_SIGNAL_NO_RECURSE,
531                         G_STRUCT_OFFSET (LocationHybridClass, zone_out),
532                         NULL, NULL,
533                         location_VOID__UINT_POINTER_POINTER,
534                         G_TYPE_NONE, 3,
535                         G_TYPE_UINT,
536                         G_TYPE_POINTER,
537                         G_TYPE_POINTER);
538
539         properties[PROP_METHOD_TYPE] = g_param_spec_int ("method",
540                         "method type",
541                         "location method type name",
542                         LOCATION_METHOD_HYBRID,
543                         LOCATION_METHOD_HYBRID,
544                         LOCATION_METHOD_HYBRID,
545                         G_PARAM_READABLE);
546
547         properties[PROP_LAST_POSITION] = g_param_spec_boxed ("last-position",
548                         "hybrid last position prop",
549                         "hybrid last position data",
550                         LOCATION_TYPE_POSITION,
551                         G_PARAM_READABLE);
552
553         properties[PROP_UPDATE_INTERVAL] = g_param_spec_uint ("update-interval",
554                         "update interval prop",
555                         "update interval data",
556                         LOCATION_UPDATE_INTERVAL_MIN,
557                         LOCATION_UPDATE_INTERVAL_MAX,
558                         LOCATION_UPDATE_INTERVAL_DEFAULT,
559                         G_PARAM_READWRITE);
560
561         properties[PROP_BOUNDARY]  = g_param_spec_pointer ("boundary",
562                         "hybrid boundary prop",
563                         "hybrid boundary data",
564                         G_PARAM_READWRITE);
565
566         properties[PROP_REMOVAL_BOUNDARY] = g_param_spec_boxed("removal-boundary",
567                         "hybrid removal boundary prop",
568                         "hybrid removal boundary data",
569                         LOCATION_TYPE_BOUNDARY,
570                         G_PARAM_READWRITE);
571
572         g_object_class_install_properties (gobject_class,
573                         PROP_MAX,
574                         properties);
575
576 }