root/trunk/libtinymail-maemo/tny-maemo-conic-device.c

Revision 3699 (checked in by svillar, 6 months ago)

Added error domain

Line 
1 /* libtinymail-camel - The Tiny Mail base library for Maemo
2  * Copyright (C) 2006-2007 Philip Van Hoof <pvanhoof@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with self library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21 #include <glib.h>
22 #include <glib-object.h>
23 #include <tny-maemo-conic-device.h>
24 #include <conicevent.h>
25 #include <coniciap.h>
26 #include <conicconnection.h>
27 #include <conicconnectionevent.h>
28 #include <string.h>
29 #include <tny-error.h>
30 #include <gdk/gdk.h> /* For GDK_THREAD_ENTER/LEAVE */
31
32 static void stop_loop (TnyMaemoConicDevice *self);
33
34 static gboolean tny_maemo_conic_device_is_online (TnyDevice *self);
35
36 static GObjectClass *parent_class = NULL;
37
38 typedef struct {
39         TnyMaemoConicDevice *self;
40         gchar* iap_id;
41         gpointer user_data;
42         TnyMaemoConicDeviceConnectCallback callback;
43 } ConnectInfo;
44
45 typedef struct {
46         ConIcConnection *cnx;
47         gboolean is_online;
48         gchar *iap;
49         gboolean forced; /* Whether the is_online value is forced rather than real. */
50         ConnectInfo *connect_slot;
51         /* When non-NULL, we are waiting for the success or failure signal. */
52         GMainLoop *loop;
53         gint signal1;
54 } TnyMaemoConicDevicePriv;
55
56
57 #define TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE(o)   \
58         (G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_MAEMO_CONIC_DEVICE, TnyMaemoConicDevicePriv))
59
60 typedef struct {
61         GObject *self;
62         gboolean status;
63 } EmitStatusInfo;
64
65 static gboolean
66 dnsmasq_has_resolv (void)
67 {
68         /* This is because silly Conic does not have a blocking API that tells
69          * us immediately when the device is online. */
70
71         if (!g_file_test ("/var/run/resolv.conf", G_FILE_TEST_EXISTS))
72                 if (!g_file_test ("/tmp/resolv.conf.wlan0", G_FILE_TEST_EXISTS))
73                         if (!g_file_test ("/tmp/resolv.conf.ppp0", G_FILE_TEST_EXISTS))
74                                 return FALSE;
75
76         return TRUE;
77 }
78
79 static gboolean
80 conic_emit_status_idle (gpointer user_data)
81 {
82         EmitStatusInfo *info;
83
84         g_return_val_if_fail (user_data, FALSE);
85        
86         info  = (EmitStatusInfo *) user_data;
87
88         g_debug ("%s: destroying %p (idle)", __FUNCTION__, user_data);
89
90         /* We lock the gdk thread because tinymail wants implementations to do
91          * this before emitting signals from within a g_idle_add_full callback.
92          * See http://www.tinymail.org/trac/tinymail/wiki/HowTnyLockable */
93         gdk_threads_enter ();
94         g_signal_emit (info->self, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED],
95                 0, info->status);
96         gdk_threads_leave ();
97
98         g_debug ("%s: emitted tny-device-connection-changed signal", __FUNCTION__);
99
100         return FALSE;
101 }
102
103 static void
104 conic_emit_status_destroy (gpointer user_data)
105 {
106         EmitStatusInfo *info;
107
108         g_return_if_fail (user_data);
109
110         info = (EmitStatusInfo *) user_data;
111        
112         g_debug ("%s: destroying status info (%p)", __FUNCTION__, user_data);
113
114         if (G_IS_OBJECT(info->self)) {
115                 g_object_unref (info->self);
116                 g_slice_free (EmitStatusInfo, info);
117                 g_debug ("%s: destroyed %p", __FUNCTION__, user_data);
118         } else
119                 g_warning ("%s: BUG: not a valid info", __FUNCTION__);
120 }
121
122 static void
123 conic_emit_status (TnyDevice *self, gboolean status)
124 {
125         EmitStatusInfo *info;
126         guint time = 1000;
127
128         g_return_if_fail (TNY_IS_DEVICE(self));
129        
130         /* Emit it in an idle handler: */
131         info = g_slice_new (EmitStatusInfo);
132        
133         info->self = g_object_ref (self);
134         info->status = status;
135
136         if (!dnsmasq_has_resolv())
137                 time = 5000;
138
139         g_debug ("%s: emitting status (%p, %s) in %d ms",
140                    __FUNCTION__, info, status ? "true" : "false", time);
141
142         g_timeout_add_full (G_PRIORITY_DEFAULT, time, conic_emit_status_idle,
143                 info, conic_emit_status_destroy);
144 }
145
146 static void
147 tny_maemo_conic_device_reset (TnyDevice *device)
148 {
149         TnyMaemoConicDevice *self;
150         TnyMaemoConicDevicePriv *priv;
151         gboolean status_before = FALSE;
152
153         g_return_if_fail (TNY_IS_DEVICE(device));
154        
155         self = TNY_MAEMO_CONIC_DEVICE (device);
156         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
157
158         status_before = tny_maemo_conic_device_is_online (device);
159         priv->forced = FALSE;
160
161         if (status_before != tny_maemo_conic_device_is_online (device))
162                 conic_emit_status (device, !status_before);
163 }
164
165 static void
166 handle_connect (TnyMaemoConicDevice *self, int con_err, int con_state)
167 {
168         TnyMaemoConicDevicePriv *priv;
169
170         g_return_if_fail (TNY_IS_MAEMO_CONIC_DEVICE (self));
171        
172         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
173
174         if (priv->connect_slot) {
175                 GError *err = NULL;
176                 gboolean canceled = FALSE;
177                 ConnectInfo *info = priv->connect_slot;
178
179                 /* Mark it as handled (TODO, this needs a small lock) */
180                 priv->connect_slot = NULL;
181
182                 switch (con_err) {
183                         case CON_IC_CONNECTION_ERROR_NONE:
184                                 break;
185                         case CON_IC_CONNECTION_ERROR_INVALID_IAP:
186                                 g_set_error (&err, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
187                                         "IAP is invalid");
188                                 break;
189                         case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
190                                 g_set_error (&err, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
191                                         "Connection failed");
192                                 break;
193                         case CON_IC_CONNECTION_ERROR_USER_CANCELED:
194                         default:
195                                 canceled = TRUE;
196                                 break;
197                 }
198
199                 if (info->callback) {
200                         /* We lock the gdk thread because tinymail wants implementations to do
201                          * this before invoking callbacks from within a g_idle_add_full callback.
202                          * See http://www.tinymail.org/trac/tinymail/wiki/HowTnyLockable */
203
204                         gdk_threads_enter ();
205                         info->callback (info->self, info->iap_id, canceled, err, info->user_data);
206                         gdk_threads_leave ();
207                 }
208
209                 if (err)
210                         g_error_free (err);
211
212                 if (G_IS_OBJECT(info->self)) {
213                         g_object_unref (info->self);
214                         g_free (info->iap_id);
215                         info->iap_id = NULL;
216                         g_slice_free (ConnectInfo, info);
217                 } else
218                         g_warning ("%s: BUG: info seems b0rked", __FUNCTION__);
219         }
220 }
221
222 typedef struct {
223         TnyMaemoConicDevice *self;
224         int con_err;
225         int con_state;
226 } HandleConnInfo;
227
228 static gboolean
229 handle_con_idle (gpointer data)
230 {
231         HandleConnInfo *info;
232
233         g_return_val_if_fail (data, FALSE);
234        
235         info = (HandleConnInfo *) data;
236         handle_connect (info->self, info->con_err, info->con_state);
237
238         return FALSE;
239 }
240
241 static void
242 handle_con_idle_destroy (gpointer data)
243 {
244         HandleConnInfo *info;
245        
246         g_return_if_fail (data);
247        
248         info = (HandleConnInfo *) data;
249
250         if (G_IS_OBJECT(info->self)) {
251                 g_object_unref (info->self);
252                 g_slice_free (HandleConnInfo, data);
253         } else
254                 g_warning ("%s: BUG: data seems b0rked", __FUNCTION__);
255 }
256
257
258 static void
259 on_connection_event (ConIcConnection *cnx, ConIcConnectionEvent *event, gpointer user_data)
260 {
261         TnyMaemoConicDevice *device;
262         TnyMaemoConicDevicePriv *priv;
263         gboolean is_online = FALSE;
264         gboolean emit = FALSE;
265         HandleConnInfo *iinfo;
266         int con_err, con_state;
267         const gchar *event_iap_id;
268        
269         /* we don't need cnx in this function */
270         g_return_if_fail (user_data && TNY_IS_MAEMO_CONIC_DEVICE(user_data));
271         g_return_if_fail (event && CON_IC_IS_CONNECTION_EVENT(event));
272        
273         device = TNY_MAEMO_CONIC_DEVICE (user_data);
274         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (device);
275
276         /* Don't emit nor make any changes in case of forced state */
277
278         if (priv->forced)
279                 return;
280
281         con_err = con_ic_connection_event_get_error (event);
282         con_state = con_ic_connection_event_get_status (event);
283         event_iap_id = con_ic_event_get_iap_id ((ConIcEvent *) event);
284
285         switch (con_err) {
286                 case CON_IC_CONNECTION_ERROR_NONE:
287                         break;
288                 case CON_IC_CONNECTION_ERROR_INVALID_IAP:
289                         g_warning ("conic: IAP is invalid");
290                         break;
291                 case CON_IC_CONNECTION_ERROR_CONNECTION_FAILED:
292                         g_warning ("conic: connection failed");
293                         break;
294                 case CON_IC_CONNECTION_ERROR_USER_CANCELED:
295                         g_warning ("conic: user cancelled");
296                         break;
297                 default:
298                         g_return_if_reached ();
299         }
300
301         switch (con_state) {
302                 case CON_IC_STATUS_CONNECTED:
303                         g_free (priv->iap);
304                         priv->iap = g_strdup (event_iap_id);
305                         if (!priv->is_online)
306                                 emit = TRUE;
307                         is_online = TRUE;
308                         /* Stop blocking tny_maemo_conic_device_connect(), if we are: */
309                         stop_loop (device);
310                         break;
311
312                 case CON_IC_STATUS_DISCONNECTED:
313                         g_free (priv->iap);
314                         priv->iap = NULL;
315                         if (priv->is_online)
316                                 emit = TRUE;
317                         /* if iap is "" then connection attempt has been canceled */
318                         if ((con_err == CON_IC_CONNECTION_ERROR_NONE) &&
319                             (!event_iap_id || (strlen (event_iap_id)== 0)))
320                                 con_err = CON_IC_CONNECTION_ERROR_USER_CANCELED;
321                         is_online = FALSE;
322                         /* Stop blocking tny_maemo_conic_device_connect(), if we are: */
323                         stop_loop (device);
324                         break;
325
326                 case CON_IC_STATUS_DISCONNECTING:
327                         break;
328                 default:
329                         g_return_if_reached ();
330         }
331
332         priv->is_online = is_online;
333
334         if (priv->connect_slot) {
335
336                 iinfo = g_slice_new (HandleConnInfo);
337                 iinfo->self = (TnyMaemoConicDevice *) g_object_ref (device);
338                 iinfo->con_err = con_err;
339                 iinfo->con_state = con_state;
340
341                 g_idle_add_full (G_PRIORITY_HIGH, handle_con_idle, iinfo,
342                                  handle_con_idle_destroy);
343         }
344
345         if (emit) {
346                 g_debug ("%s: emiting is_online (%s)",
347                          __FUNCTION__, is_online ? "true" : "false");
348                 conic_emit_status (TNY_DEVICE (device), is_online);
349         }
350 }
351
352
353 /**
354  * tny_maemo_conic_device_connect_async:
355  * @self: a #TnyDevice object
356  * @iap_id: the id of the Internet Access Point (IAP), or NULL for 'any;
357  * @user_requested: whether or not the connection was automatically requested or by an user action
358  * @callback: a #TnyMaemoConicDeviceConnectCallback
359  * @user_data: user data for @callback
360  *
361  * Try to connect to a specific IAP, or to any if @iap_id == NULL
362  * this calls con_ic_connection_connect(_by_id).
363  * This may show a dialog to allow the user to select a connection, or
364  * may otherwise take a significant amount of time.
365  **/
366 void 
367 tny_maemo_conic_device_connect_async (TnyMaemoConicDevice *self,
368                                       const gchar* iap_id,
369                                       gboolean user_requested,
370                                       TnyMaemoConicDeviceConnectCallback callback,
371                                       gpointer user_data)
372 {
373         TnyMaemoConicDevicePriv *priv = NULL;
374         gboolean request_failed = FALSE;
375         ConnectInfo *info;
376         GError *err = NULL;
377         ConIcConnectFlags flags;
378
379         g_return_if_fail (self && TNY_IS_MAEMO_CONIC_DEVICE(self));
380
381         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
382
383         info = g_slice_new (ConnectInfo);
384         info->self = (TnyMaemoConicDevice *) g_object_ref (self);
385         info->callback = callback;
386         info->user_data = user_data;
387         info->iap_id = iap_id ? g_strdup (iap_id) : NULL; /* iap_id can be NULL */
388
389         priv->connect_slot = info;
390
391         /* Set the flags */
392         if (user_requested)
393                 flags = CON_IC_CONNECT_FLAG_NONE;
394         else
395                 flags = CON_IC_CONNECT_FLAG_AUTOMATICALLY_TRIGGERED;
396
397         if (iap_id) {
398                 if (!con_ic_connection_connect_by_id (priv->cnx, iap_id, flags)) {
399                         g_set_error (&err, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
400                                 "Could not send connect_by_id dbus message");
401                         request_failed = TRUE;
402                 }
403         } else {
404                 if (!con_ic_connection_connect (priv->cnx, flags)) {
405                         g_set_error (&err, TNY_ERROR_DOMAIN, TNY_SERVICE_ERROR_UNKNOWN,
406                                 "Could not send connect dbus message");
407                         request_failed = TRUE;
408                 }
409         }
410
411         if (request_failed) {
412                 priv->connect_slot = NULL;
413                 if (G_IS_OBJECT(info->self)) {
414                         if (info->callback)
415                                 info->callback (info->self, iap_id, FALSE, err, info->user_data);
416                         g_free (info->iap_id);
417                         info->iap_id = NULL;
418                         g_object_unref (info->self);
419                         info->self = NULL;
420                         g_slice_free (ConnectInfo, info);
421                 } else
422                         g_warning ("%s: BUG: info seems b0rked", __FUNCTION__);
423         }
424 }
425
426
427 /**
428  * tny_maemo_conic_device_disconnect:
429  * @self: a #TnyDevice object
430  * @iap_id: the id of the Internet Access Point (IAP), or NULL for 'any';
431  *
432  * try to disconnect from a specific IAP, or to any if @iap_id == NULL
433  * this calls con_ic_connection_disconnect(_by_id)
434  *
435  * Returns TRUE if sending the command worked, FALSE otherwise
436  **/
437 gboolean
438 tny_maemo_conic_device_disconnect (TnyMaemoConicDevice *self, const gchar* iap_id)
439 {
440         TnyMaemoConicDevicePriv *priv = NULL;
441
442         g_return_val_if_fail (self && TNY_IS_MAEMO_CONIC_DEVICE(self), FALSE);
443
444         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
445         g_return_val_if_fail (priv->cnx, FALSE);
446
447         if (iap_id) {
448                 if (!con_ic_connection_disconnect_by_id (priv->cnx, iap_id)) {
449                         g_warning ("%s: disconnect_by_id failed (%s)",
450                                    __FUNCTION__, iap_id);
451                         return FALSE;
452                 }
453         } else {
454                 if (!con_ic_connection_disconnect (priv->cnx))
455                         g_warning ("Could not send disconnect dbus message");
456                 return FALSE;
457         }
458
459         return TRUE;
460 }
461
462
463
464 /**
465  * tny_maemo_conic_device_get_current_iap_id:
466  * @self: a #TnyDevice object
467  *
468  * retrieve the iap-id of the connection that is currently active; a precondition is
469  * that we _are_ connected.
470  *
471  * Returns: the iap-id for the current connection, or NULL in case of error
472  **/
473 const gchar*
474 tny_maemo_conic_device_get_current_iap_id (TnyMaemoConicDevice *self)
475 {
476         TnyMaemoConicDevicePriv *priv = NULL;
477
478         g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
479         g_return_val_if_fail (tny_maemo_conic_device_is_online(TNY_DEVICE(self)), NULL);
480
481         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
482
483         return priv->iap;
484 }
485
486
487
488 /**
489  * tny_maemo_conic_device_get_iap:
490  * @self: a #TnyDevice object
491  * @iap_id: the id of the IAP to get
492  *
493  * get the IAP object (#ConIcIap) for the given iap-id. The returned GObject must be
494  * freed with g_object_unref after use. Refer to the ConIc documentation for details about
495  * the #ConICIap.
496  
497  *
498  * Returns: ConIcIap object or NULL in case of error
499  **/
500 ConIcIap*
501 tny_maemo_conic_device_get_iap (TnyMaemoConicDevice *self, const gchar *iap_id)
502 {
503         TnyMaemoConicDevicePriv *priv;
504         g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
505         g_return_val_if_fail (iap_id, NULL);
506
507         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
508         g_return_val_if_fail (priv->cnx, NULL);
509
510         /* Note that it is very unusual to return a reference from a get_()
511          * function, but we must do so because that mistake has already been
512          * made in con_ic_connection_get_iap (). If we just unref immediately
513          * then libconic might destroy the object. */
514
515         return con_ic_connection_get_iap (priv->cnx, iap_id);
516 }
517
518
519 /**
520  * tny_maemo_conic_device_get_iap_list:
521  * @self: a #TnyDevice object
522  *
523  * get a list of all IAP objects (#ConIcIap) that are available; it should be freed
524  * with #tny_maemo_conic_device_free_iap_list. This function uses
525  * con_ic_connection_get_all_iaps
526  * 
527  * Returns: the list or NULL in case of error
528  **/
529 GSList*
530 tny_maemo_conic_device_get_iap_list (TnyMaemoConicDevice *self)
531 {
532         TnyMaemoConicDevicePriv *priv;
533        
534         g_return_val_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(self), NULL);
535
536         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
537         g_return_val_if_fail (priv->cnx, NULL);
538
539         return con_ic_connection_get_all_iaps (priv->cnx);
540 }
541
542 static void
543 unref_gobject (GObject *obj)
544 {
545         if (G_IS_OBJECT(obj))
546                 g_object_unref(obj);
547         else
548                 g_warning ("%s: not a valid GObject (%p)",
549                            __FUNCTION__, obj);
550 }
551
552
553 /**
554  * tny_maemo_conic_device_free_iap_list:
555  * @self: a #TnyDevice object
556  * @cnx_list: a list of IAP objects
557  *
558  * free a  list of IAP objects retrieved from tny_maemo_conic_device_get_iap_list
559  **/
560 void
561 tny_maemo_conic_device_free_iap_list (TnyMaemoConicDevice *self, GSList* cnx_list)
562 {
563         g_slist_foreach (cnx_list, (GFunc)unref_gobject, NULL);
564         g_slist_free (cnx_list);
565 }
566
567
568 static void
569 tny_maemo_conic_device_force_online (TnyDevice *device)
570 {
571         TnyMaemoConicDevice *self;
572         TnyMaemoConicDevicePriv *priv;
573         gboolean already_online = FALSE;
574
575         g_return_if_fail (TNY_IS_DEVICE(device));
576
577         self = TNY_MAEMO_CONIC_DEVICE (device);
578         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
579        
580         already_online = tny_maemo_conic_device_is_online (device);
581
582         priv->forced = TRUE;
583         priv->is_online = TRUE;
584
585         /* Signal if it changed: */
586         if (!already_online) {
587                 g_debug ("%s: emiting connection-changed signal",
588                          __FUNCTION__);
589                 g_signal_emit (device, tny_device_signals [TNY_DEVICE_CONNECTION_CHANGED], 0, TRUE);
590         }
591 }
592
593
594 static void
595 tny_maemo_conic_device_force_offline (TnyDevice *device)
596 {
597         TnyMaemoConicDevice *self;
598         TnyMaemoConicDevicePriv *priv;
599         gboolean already_offline = FALSE;
600
601         g_return_if_fail (TNY_IS_DEVICE(device));
602
603         self = TNY_MAEMO_CONIC_DEVICE (device);
604         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
605
606         already_offline = !tny_maemo_conic_device_is_online (device);
607         priv->forced = TRUE;
608         priv->is_online = FALSE;
609
610         /* Signal if it changed: */
611         if (!already_offline)
612                 conic_emit_status (device, FALSE);
613 }
614
615 static gboolean
616 tny_maemo_conic_device_is_online (TnyDevice *self)
617 {
618         g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
619
620         return TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self)->is_online;
621 }
622
623
624 static void
625 tny_maemo_conic_device_instance_init (GTypeInstance *instance, gpointer g_class)
626 {
627         TnyMaemoConicDevice *self = (TnyMaemoConicDevice *)instance;
628         TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
629
630         /* We should not have a real is_online, based on what libconic has told us: */
631
632         priv->forced       = FALSE;
633         priv->iap          = NULL;
634         priv->is_online    = FALSE;
635         priv->connect_slot = NULL;
636         priv->loop         = NULL;
637
638         priv->cnx = con_ic_connection_new ();
639
640         if (!priv->cnx) {       
641                 g_warning ("%s: con_ic_connection_new failed.", __FUNCTION__);
642                 return;
643         }
644
645         /* This might be necessary to make the connection object actually emit
646          * the signal, though the documentation says that they should be sent
647          * even when this is not set, when we explicitly try to connect. The
648          * signal still does not seem to be emitted. */
649         g_object_set (priv->cnx, "automatic-connection-events", TRUE, NULL);
650
651         priv->signal1 = (gint) g_signal_connect (priv->cnx, "connection-event",
652                           G_CALLBACK(on_connection_event), self);
653
654         /* This will get us in connected state only if there is already a connection.
655          * thus, this will setup our state correctly when we receive the signals. */
656         if (!con_ic_connection_connect (priv->cnx,
657                                         CON_IC_CONNECT_FLAG_AUTOMATICALLY_TRIGGERED))
658                 g_warning ("%s: could not send connect dbus message",
659                         __FUNCTION__); 
660 }
661
662
663 /**
664  * tny_maemo_conic_device_new:
665  *
666  * Return value: A new #TnyDevice instance
667  **/
668 TnyDevice*
669 tny_maemo_conic_device_new (void)
670 {
671         return TNY_DEVICE(g_object_new (TNY_TYPE_MAEMO_CONIC_DEVICE, NULL));
672 }
673
674 static void
675 tny_maemo_conic_device_finalize (GObject *obj)
676 {
677         TnyMaemoConicDevicePriv *priv;
678
679         g_return_if_fail (TNY_IS_MAEMO_CONIC_DEVICE(obj));
680
681         g_debug ("%s: shutting the device down...", __FUNCTION__);
682        
683         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (obj);
684
685         if (g_signal_handler_is_connected (priv->cnx, priv->signal1))
686                 g_signal_handler_disconnect (priv->cnx, priv->signal1);
687
688         if (priv->cnx && CON_IC_IS_CONNECTION(priv->cnx)) {
689                 tny_maemo_conic_device_disconnect (TNY_MAEMO_CONIC_DEVICE(obj),
690                                                    priv->iap);
691                 g_object_unref (priv->cnx);
692                 priv->cnx = NULL;
693         } else
694                 g_warning ("%s: BUG: priv->cnx is not a valid connection",
695                            __FUNCTION__);
696        
697         g_free (priv->iap);
698         priv->iap = NULL;
699
700         (*parent_class->finalize) (obj);
701 }
702
703
704 static void
705 tny_device_init (gpointer g, gpointer iface_data)
706 {
707         TnyDeviceIface *klass = (TnyDeviceIface *)g;
708
709         klass->is_online     = tny_maemo_conic_device_is_online;
710         klass->reset         = tny_maemo_conic_device_reset;
711         klass->force_offline = tny_maemo_conic_device_force_offline;
712         klass->force_online  = tny_maemo_conic_device_force_online;
713 }
714
715
716 static void
717 tny_maemo_conic_device_class_init (TnyMaemoConicDeviceClass *class)
718 {
719         GObjectClass *object_class;
720
721         parent_class = g_type_class_peek_parent (class);
722         object_class = (GObjectClass*) class;
723
724         object_class->finalize = tny_maemo_conic_device_finalize;
725
726         g_type_class_add_private (object_class, sizeof (TnyMaemoConicDevicePriv));
727 }
728
729 static gpointer
730 tny_maemo_conic_device_register_type (gpointer notused)
731 {
732         GType type = 0;
733
734         static const GTypeInfo info =
735                 {
736                         sizeof (TnyMaemoConicDeviceClass),
737                         NULL,   /* base_init */
738                         NULL,   /* base_finalize */
739                         (GClassInitFunc) tny_maemo_conic_device_class_init,   /* class_init */
740                         NULL,   /* class_finalize */
741                         NULL,   /* class_data */
742                         sizeof (TnyMaemoConicDevice),
743                         0,      /* n_preallocs */
744                         tny_maemo_conic_device_instance_init    /* instance_init */
745                 };
746
747         static const GInterfaceInfo tny_device_info =
748                 {
749                         (GInterfaceInitFunc) tny_device_init, /* interface_init */
750                         NULL,         /* interface_finalize */
751                         NULL          /* interface_data */
752                 };
753        
754         type = g_type_register_static (G_TYPE_OBJECT,
755                                        "TnyMaemoConicDevice",
756                                        &info, 0);
757        
758         g_type_add_interface_static (type, TNY_TYPE_DEVICE,
759                                      &tny_device_info);
760
761         return GUINT_TO_POINTER (type);
762 }
763
764 GType
765 tny_maemo_conic_device_get_type (void)
766 {
767         static GOnce once = G_ONCE_INIT;
768         g_once (&once, tny_maemo_conic_device_register_type, NULL);
769         return GPOINTER_TO_UINT (once.retval);
770 }
771 static void
772 stop_loop (TnyMaemoConicDevice *self)
773 {
774         TnyMaemoConicDevicePriv *priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
775         if (priv->loop)
776                 g_main_loop_quit (priv->loop);
777         return;
778 }
779
780
781 /**
782  * tny_maemo_conic_device_connect:
783  * @self: a #TnyDevice object
784  * @iap_id: the id of the Internet Access Point (IAP), or NULL for 'any;
785  *
786  * Try to connect to a specific IAP, or to any if @iap_id == NULL
787  * this calls con_ic_connection_connect(_by_id).
788  * This may show a dialog to allow the user to select a connection, or
789  * may otherwise take a significant amount of time. This function blocks until
790  * the connection has either succeeded or failed.
791  *
792  * Returns TRUE if a connection was made, FALSE otherwise.
793  **/
794 gboolean
795 tny_maemo_conic_device_connect (TnyMaemoConicDevice *self,
796                                 const gchar* iap_id,
797                                 gboolean user_requested)
798 {
799         TnyMaemoConicDevicePriv *priv = NULL;
800         gboolean request_failed = FALSE;
801         ConIcConnectFlags flags;
802
803         g_warning ("%s: you should tny_maemo_conic_device_connect_async",
804                    __FUNCTION__);
805
806         g_return_val_if_fail (TNY_IS_DEVICE(self), FALSE);
807         priv = TNY_MAEMO_CONIC_DEVICE_GET_PRIVATE (self);
808
809         g_return_val_if_fail (priv->cnx, FALSE);
810         priv->loop = g_main_loop_new(NULL, FALSE /* not running immediately. */);
811
812         /* Set the flags */
813         if (user_requested)
814                 flags = CON_IC_CONNECT_FLAG_NONE;
815         else
816                 flags = CON_IC_CONNECT_FLAG_AUTOMATICALLY_TRIGGERED;
817
818         if (iap_id) {
819                 if (!con_ic_connection_connect_by_id (priv->cnx, iap_id, flags)) {
820                         g_warning ("could not send connect_by_id dbus message");
821                         request_failed = TRUE;
822                 }
823         } else {
824                 if (!con_ic_connection_connect (priv->cnx, flags)) {
825                         g_warning ("could not send connect dbus message");
826                         request_failed = TRUE;
827                 }
828         }
829
830         if (request_failed) {
831                 g_main_loop_unref (priv->loop);
832                 priv->loop = NULL;
833         }
834        
835         /* Wait for the CON_IC_STATUS_CONNECTED (succeeded) or
836          * CON_IC_STATUS_DISCONNECTED event: */
837          
838         /* This is based on code found in gtk_dialog_run(): */
839         GDK_THREADS_LEAVE();
840         /* Run until g_main_loop_quit() is called by our signal handler. */
841         if (priv->loop)
842                 g_main_loop_run (priv->loop);
843         GDK_THREADS_ENTER();
844
845         if (priv->loop) {
846                 g_main_loop_unref (priv->loop);
847                 priv->loop = NULL;
848         }
849
850         return priv->is_online;
851 }
Note: See TracBrowser for help on using the browser.