* modest-tny-send-queue.[ch]:
[modest] / src / modest-tny-send-queue.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 #include <modest-tny-send-queue.h>
32 #include <tny-simple-list.h>
33 #include <tny-iterator.h>
34 #include <tny-folder.h>
35 #include <tny-camel-msg.h>
36 #include <modest-tny-account.h>
37
38 /* 'private'/'protected' functions */
39 static void modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass);
40 static void modest_tny_send_queue_init       (gpointer g, gpointer iface_data);
41 static void modest_tny_send_queue_finalize   (GObject *obj);
42 static void modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class);
43
44 /* list my signals  */
45 enum {
46         /* MY_SIGNAL_1, */
47         /* MY_SIGNAL_2, */
48         LAST_SIGNAL
49 };
50
51 typedef struct _ModestTnySendQueuePrivate ModestTnySendQueuePrivate;
52 struct _ModestTnySendQueuePrivate {
53         TnyTransportAccount *account;
54         GThread *flush_outbox_thread;
55         GMutex  *flush_lock;
56         
57 };
58 #define MODEST_TNY_SEND_QUEUE_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
59                                                    MODEST_TYPE_TNY_SEND_QUEUE, \
60                                                    ModestTnySendQueuePrivate))
61 /* globals */
62 static GObjectClass *parent_class = NULL;
63
64 /* uncomment the following if you have defined any signals */
65 /* static guint signals[LAST_SIGNAL] = {0}; */
66
67
68 /*
69  * this thread actually tries to send all the mails in the outbox
70  */
71 static void
72 flush_outbox_thread (TnySendQueue *self)
73 {
74         TnyFolder *outbox, *sentbox;
75         TnyMsg    *msg;
76         TnyHeader *header;
77
78         TnyList *headers;               
79         TnyIterator *iter;
80
81         ModestTnySendQueuePrivate *priv;
82
83         priv    = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
84
85         outbox  = tny_send_queue_get_outbox (self);
86         sentbox = tny_send_queue_get_sentbox (self);
87         
88         headers = tny_simple_list_new ();
89
90         g_mutex_lock (priv->flush_lock);
91         tny_folder_get_headers (outbox, headers, TRUE, NULL); /* FIXME: err */
92         iter = tny_list_create_iterator (headers);
93
94         while (!tny_iterator_is_done (iter)) {
95                 header = TNY_HEADER(tny_iterator_get_current(iter));
96                 msg = tny_folder_get_msg (outbox, header, NULL);        
97                 tny_transport_account_send (priv->account,
98                                             msg, NULL); /* FIXME: err */
99                 tny_folder_add_msg    (sentbox, msg, NULL); /* FIXME: err */
100                 tny_folder_remove_msg (outbox, header, NULL); /* FIXME: err */
101
102                 g_object_unref (G_OBJECT(header));
103                 g_object_unref (G_OBJECT(msg));
104
105                 tny_iterator_next (iter);
106         }
107         
108         
109         g_object_unref (G_OBJECT(headers));
110         g_object_unref (G_OBJECT(iter));
111
112         priv->flush_outbox_thread = NULL;
113         g_mutex_unlock (priv->flush_lock);
114         
115         g_thread_exit (NULL);
116 }
117
118
119 static void
120 modest_tny_send_queue_cancel (TnySendQueue *self, gboolean remove)
121 {
122         MODEST_TNY_SEND_QUEUE_GET_CLASS(self)->cancel_func (self, remove);
123 }
124
125 static void
126 modest_tny_send_queue_add (TnySendQueue *self, TnyMsg *msg)
127 {
128         MODEST_TNY_SEND_QUEUE_GET_CLASS(self)->add_func (self, msg);
129 }
130
131
132 static TnyFolder*
133 modest_tny_send_queue_get_sentbox (TnySendQueue *self)
134 {
135         return MODEST_TNY_SEND_QUEUE_GET_CLASS(self)->get_sentbox_func (self);
136 }
137
138
139 static TnyFolder*
140 modest_tny_send_queue_get_outbox (TnySendQueue *self)
141 {
142         return MODEST_TNY_SEND_QUEUE_GET_CLASS(self)->get_outbox_func (self);
143 }
144
145
146
147
148 static void
149 modest_tny_send_queue_cancel_default (TnySendQueue *self, gboolean remove)
150 {
151         /* FIXME */
152 }
153
154
155 static void
156 modest_tny_send_queue_add_default (TnySendQueue *self, TnyMsg *msg)
157 {
158         ModestTnySendQueuePrivate *priv; 
159         TnyFolder *outbox;
160         
161         g_return_if_fail (self);
162         g_return_if_fail (TNY_IS_CAMEL_MSG(msg));
163         
164         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
165         
166         outbox = tny_send_queue_get_outbox (self);
167         tny_folder_add_msg (outbox, msg, NULL);
168
169         priv->flush_outbox_thread = g_thread_create (
170                 (GThreadFunc)flush_outbox_thread,
171                 self, FALSE, NULL);
172 }
173
174 static TnyFolder*
175 modest_tny_send_queue_get_sentbox_default (TnySendQueue *self)
176 {
177         ModestTnySendQueuePrivate *priv; 
178
179         g_return_val_if_fail (self, NULL);
180
181         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
182         
183         return  modest_tny_account_get_special_folder (TNY_ACCOUNT(priv->account),
184                                                        TNY_FOLDER_TYPE_SENT);
185 }
186
187
188 static TnyFolder*
189 modest_tny_send_queue_get_outbox_default (TnySendQueue *self)
190 {
191         ModestTnySendQueuePrivate *priv; 
192
193         g_return_val_if_fail (self, NULL);
194         
195         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
196
197         return modest_tny_account_get_special_folder (TNY_ACCOUNT(priv->account),
198                                                       TNY_FOLDER_TYPE_OUTBOX);
199 }
200
201
202
203
204 GType
205 modest_tny_send_queue_get_type (void)
206 {
207         static GType my_type = 0;
208
209         if (G_UNLIKELY (!camel_type_init_done)) {
210                 if (!g_thread_supported ()) 
211                         g_thread_init (NULL);
212                 camel_type_init ();
213                 camel_type_init_done = TRUE;
214         }
215         
216         if (!my_type) {
217                 static const GTypeInfo my_info = {
218                         sizeof(ModestTnySendQueueClass),
219                         NULL,           /* base init */
220                         NULL,           /* base finalize */
221                         (GClassInitFunc) modest_tny_send_queue_class_init,
222                         NULL,           /* class finalize */
223                         NULL,           /* class data */
224                         sizeof(ModestTnySendQueue),
225                         1,              /* n_preallocs */
226                         (GInstanceInitFunc) modest_tny_send_queue_instance_init,
227                         NULL
228                 };
229
230                 static const GInterfaceInfo tny_send_queue_info = {
231                         (GInterfaceInitFunc) modest_tny_send_queue_init,
232                         /* interface_init */
233                         NULL,         /* interface_finalize */
234                         NULL          /* interface_data */
235                 };
236         
237                 my_type = g_type_register_static (G_TYPE_OBJECT,
238                                                   "ModestTnySendQueue",
239                                                   &my_info, 0);
240                 g_type_add_interface_static (my_type, TNY_TYPE_SEND_QUEUE,
241                                              &tny_send_queue_info);
242         }
243         
244         return my_type;
245 }
246
247
248 static void
249 modest_tny_send_queue_init (gpointer g, gpointer iface_data)
250 {
251         TnySendQueueIface *klass = (TnySendQueueIface*)g;
252         
253         klass->add_func         = modest_tny_send_queue_add;
254         klass->get_outbox_func  = modest_tny_send_queue_get_outbox;
255         klass->get_sentbox_func = modest_tny_send_queue_get_sentbox;
256         klass->cancel_func      = modest_tny_send_queue_cancel;
257 }
258
259
260
261 static void
262 modest_tny_send_queue_class_init (ModestTnySendQueueClass *klass)
263 {
264         GObjectClass *gobject_class;
265
266         gobject_class = (GObjectClass*) klass;
267         
268         parent_class            = g_type_class_peek_parent (klass);
269         gobject_class->finalize = modest_tny_send_queue_finalize;
270
271         klass->add_func         = modest_tny_send_queue_add_default;
272         klass->get_outbox_func  = modest_tny_send_queue_get_outbox_default;
273         klass->get_sentbox_func = modest_tny_send_queue_get_sentbox_default;
274         klass->cancel_func      = modest_tny_send_queue_cancel_default;
275
276         g_type_class_add_private (gobject_class, sizeof(ModestTnySendQueuePrivate));
277 }
278
279 static void
280 modest_tny_send_queue_instance_init (GTypeInstance *instance, gpointer g_class)
281 {
282         ModestTnySendQueue *self;  
283         ModestTnySendQueuePrivate *priv; 
284
285         self = (ModestTnySendQueue*)instance;
286         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
287
288         priv->flush_lock          = g_mutex_new ();
289         priv->flush_outbox_thread = NULL;
290         priv->account = NULL;
291 }
292
293 static void
294 modest_tny_send_queue_finalize (GObject *obj)
295 {
296         ModestTnySendQueuePrivate *priv; 
297         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (obj);
298         
299         if (priv->account) {
300                 g_object_unref (priv->account);
301                 priv->account = NULL;
302         }
303
304         if (priv->flush_lock) {
305                 g_mutex_free (priv->flush_lock);
306                 priv->flush_lock = NULL;
307         }
308         
309         G_OBJECT_CLASS(parent_class)->finalize (obj);
310 }
311
312 ModestTnySendQueue*
313 modest_tny_send_queue_new (TnyTransportAccount *account)
314 {
315         ModestTnySendQueue *self;
316         ModestTnySendQueuePrivate *priv;
317
318         g_return_val_if_fail (account, NULL);
319         
320         self = MODEST_TNY_SEND_QUEUE(g_object_new(MODEST_TYPE_TNY_SEND_QUEUE, NULL));
321         priv = MODEST_TNY_SEND_QUEUE_GET_PRIVATE (self);
322
323         priv->account = account;
324         g_object_ref (G_OBJECT(priv->account));
325         
326         return self;
327 }
328