root/trunk/libtinymailui-gtk/tny-gtk-pixbuf-stream.c

Revision 3666 (checked in by jdapena, 7 months ago)

* Use GOnce registering all types in tinymail to make

registering thread-safe.

Line 
1 /* libtinymailui-gtk - The Tiny Mail UI library for Gtk+
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
21 /**
22  * TnyGtkPixbufStream:
23  *
24  * A #TnyStream for building a #GdkPixbuf from a stream in Tinymail, like when
25  * streaming a #TnyMimePart that is an image to a #GdkPixbuf that will be used
26  * by a #GtkImage.
27  *
28  * free-function: g_object_unref
29  **/
30
31 #include <config.h>
32
33
34 #include <string.h>
35 #include <glib.h>
36
37 #include <gtk/gtk.h>
38
39 #include <tny-stream.h>
40 #include <tny-gtk-pixbuf-stream.h>
41
42 static GObjectClass *parent_class = NULL;
43
44
45 typedef struct _TnyGtkPixbufStreamPriv TnyGtkPixbufStreamPriv;
46
47 struct _TnyGtkPixbufStreamPriv
48 {
49         GdkPixbufLoader *loader;
50 };
51
52 #define TNY_GTK_PIXBUF_STREAM_GET_PRIVATE(o)    \
53         (G_TYPE_INSTANCE_GET_PRIVATE ((o), TNY_TYPE_GTK_PIXBUF_STREAM, TnyGtkPixbufStreamPriv))
54
55
56 static gssize
57 tny_pixbuf_write_to_stream (TnyStream *self, TnyStream *output)
58 {
59         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->write_to_stream(self, output);
60 }
61
62 static gssize
63 tny_pixbuf_write_to_stream_default (TnyStream *self, TnyStream *output)
64 {
65         char tmp_buf[4096];
66         gssize total = 0;
67         gssize nb_read;
68         gssize nb_written;
69
70         g_assert (TNY_IS_STREAM (output));
71
72         while (G_LIKELY (!tny_stream_is_eos (self)))
73         {
74                 nb_read = tny_stream_read (self, tmp_buf, sizeof (tmp_buf));
75                 if (G_UNLIKELY (nb_read < 0))
76                         return -1;
77                 else if (G_LIKELY (nb_read > 0)) {
78                         const gchar *end;
79                         if (!g_utf8_validate (tmp_buf, nb_read, &end))
80                                 g_warning ("utf8 invalid: %d of %d", (gint)nb_read,
81                                            (gint)(end - tmp_buf));
82                                
83                         nb_written = 0;
84        
85                         while (G_LIKELY (nb_written < nb_read))
86                         {
87                                 gssize len = tny_stream_write (output, tmp_buf + nb_written,
88                                                                   nb_read - nb_written);
89                                 if (G_UNLIKELY (len < 0))
90                                         return -1;
91                                 nb_written += len;
92                         }
93                         total += nb_written;
94                 }
95         }
96         return total;
97 }
98
99 static gssize
100 tny_gtk_pixbuf_stream_read (TnyStream *self, char *buffer, gsize n)
101 {
102         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->read(self, buffer, n);
103 }
104
105 static gssize
106 tny_gtk_pixbuf_stream_read_default (TnyStream *self, char *buffer, gsize n)
107 {
108         return (gssize) n;
109 }
110
111 static gssize
112 tny_gtk_pixbuf_stream_write (TnyStream *self, const char *buffer, gsize n)
113 {
114         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->write(self, buffer, n);
115 }
116
117 static gssize
118 tny_gtk_pixbuf_stream_write_default (TnyStream *self, const char *buffer, gsize n)
119 {
120         TnyGtkPixbufStreamPriv *priv = TNY_GTK_PIXBUF_STREAM_GET_PRIVATE (self);
121         gssize wr = (gssize) n;
122
123         if (!gdk_pixbuf_loader_write (priv->loader, (const guchar *) buffer, n, NULL))
124                 wr = -1;
125
126         return (gssize) wr;
127 }
128
129 static gint
130 tny_gtk_pixbuf_stream_flush (TnyStream *self)
131 {
132         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->flush(self);
133 }
134
135 static gint
136 tny_gtk_pixbuf_stream_flush_default (TnyStream *self)
137 {
138         return 0;
139 }
140
141 static gint
142 tny_gtk_pixbuf_stream_close (TnyStream *self)
143 {
144         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->close(self);
145 }
146
147 static gint
148 tny_gtk_pixbuf_stream_close_default (TnyStream *self)
149 {
150         return 0;
151 }
152
153 static gboolean
154 tny_gtk_pixbuf_stream_is_eos (TnyStream *self)
155 {
156         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->is_eos(self);
157 }
158
159 static gboolean
160 tny_gtk_pixbuf_stream_is_eos_default (TnyStream *self)
161 {
162         return TRUE;
163 }
164
165 static gint
166 tny_gtk_pixbuf_stream_reset (TnyStream *self)
167 {
168         return TNY_GTK_PIXBUF_STREAM_GET_CLASS (self)->reset(self);
169 }
170
171 static gint
172 tny_gtk_pixbuf_stream_reset_default (TnyStream *self)
173 {
174         return 0;
175 }
176
177
178 /**
179  * tny_gtk_pixbuf_stream_new:
180  * @mime_type: the MIME type, for example image/jpeg
181  *
182  * Create an adaptor instance between #TnyStream and #GdkPixbuf
183  *
184  * returns: (caller-owns): a new #TnyStream instance
185  * since: 1.0
186  * audience: application-developer
187  **/
188 TnyStream*
189 tny_gtk_pixbuf_stream_new (const gchar *mime_type)
190 {
191         TnyGtkPixbufStream *self = g_object_new (TNY_TYPE_GTK_PIXBUF_STREAM, NULL);
192         TnyGtkPixbufStreamPriv *priv = TNY_GTK_PIXBUF_STREAM_GET_PRIVATE (self);
193
194         /* TODO: Handle errors */
195         priv->loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, NULL);
196
197         return TNY_STREAM (self);
198 }
199
200 /**
201  * tny_gtk_pixbuf_stream_get_pixbuf:
202  * @self: a #TnyGtkPixbufStream
203  *
204  * Get the #GfkPixbuf that got created when we streamed data to @self.
205  *
206  * returns: (caller-owns): a #GdkPixbuf instance
207  * since: 1.0
208  * audience: application-developer
209  **/
210 GdkPixbuf *
211 tny_gtk_pixbuf_stream_get_pixbuf (TnyGtkPixbufStream *self)
212 {
213         TnyGtkPixbufStreamPriv *priv = TNY_GTK_PIXBUF_STREAM_GET_PRIVATE (self);
214         return gdk_pixbuf_loader_get_pixbuf (priv->loader);
215 }
216
217 static void
218 tny_gtk_pixbuf_stream_instance_init (GTypeInstance *instance, gpointer g_class)
219 {
220         TnyGtkPixbufStream *self = (TnyGtkPixbufStream *)instance;
221         TnyGtkPixbufStreamPriv *priv = TNY_GTK_PIXBUF_STREAM_GET_PRIVATE (self);
222
223         priv->loader = NULL;
224
225         return;
226 }
227
228 static void
229 tny_gtk_pixbuf_stream_finalize (GObject *object)
230 {
231         TnyGtkPixbufStream *self = (TnyGtkPixbufStream *)object;
232         TnyGtkPixbufStreamPriv *priv = TNY_GTK_PIXBUF_STREAM_GET_PRIVATE (self);
233
234         if (priv->loader) {
235                 gdk_pixbuf_loader_close (priv->loader, NULL);
236                 g_object_unref (priv->loader);
237         }
238
239         (*parent_class->finalize) (object);
240
241         return;
242 }
243
244 static void
245 tny_stream_init (gpointer g, gpointer iface_data)
246 {
247         TnyStreamIface *klass = (TnyStreamIface *)g;
248
249         klass->read= tny_gtk_pixbuf_stream_read;
250         klass->write= tny_gtk_pixbuf_stream_write;
251         klass->flush= tny_gtk_pixbuf_stream_flush;
252         klass->close= tny_gtk_pixbuf_stream_close;
253         klass->is_eos= tny_gtk_pixbuf_stream_is_eos;
254         klass->reset= tny_gtk_pixbuf_stream_reset;
255         klass->write_to_stream= tny_pixbuf_write_to_stream;
256
257         return;
258 }
259
260 static void
261 tny_gtk_pixbuf_stream_class_init (TnyGtkPixbufStreamClass *class)
262 {
263         GObjectClass *object_class;
264
265         parent_class = g_type_class_peek_parent (class);
266         object_class = (GObjectClass*) class;
267
268         class->read= tny_gtk_pixbuf_stream_read_default;
269         class->write= tny_gtk_pixbuf_stream_write_default;
270         class->flush= tny_gtk_pixbuf_stream_flush_default;
271         class->close= tny_gtk_pixbuf_stream_close_default;
272         class->is_eos= tny_gtk_pixbuf_stream_is_eos_default;
273         class->reset= tny_gtk_pixbuf_stream_reset_default;
274         class->write_to_stream= tny_pixbuf_write_to_stream_default;
275
276         object_class->finalize = tny_gtk_pixbuf_stream_finalize;
277
278         g_type_class_add_private (object_class, sizeof (TnyGtkPixbufStreamPriv));
279
280         return;
281 }
282
283 static gpointer
284 tny_gtk_pixbuf_stream_register_type (gpointer notused)
285 {
286         GType type = 0;
287
288         static const GTypeInfo info =
289                 {
290                   sizeof (TnyGtkPixbufStreamClass),
291                   NULL,   /* base_init */
292                   NULL,   /* base_finalize */
293                   (GClassInitFunc) tny_gtk_pixbuf_stream_class_init,   /* class_init */
294                   NULL,   /* class_finalize */
295                   NULL,   /* class_data */
296                   sizeof (TnyGtkPixbufStream),
297                   0,      /* n_preallocs */
298                   tny_gtk_pixbuf_stream_instance_init    /* instance_init */
299                 };
300
301         static const GInterfaceInfo tny_stream_info =
302                 {
303                   (GInterfaceInitFunc) tny_stream_init, /* interface_init */
304                   NULL,         /* interface_finalize */
305                   NULL          /* interface_data */
306                 };
307
308         type = g_type_register_static (G_TYPE_OBJECT,
309                                        "TnyGtkPixbufStream",
310                                        &info, 0);
311
312         g_type_add_interface_static (type, TNY_TYPE_STREAM,
313                                      &tny_stream_info);
314
315         return GUINT_TO_POINTER (type);
316 }
317
318 GType
319 tny_gtk_pixbuf_stream_get_type (void)
320 {
321         static GOnce once = G_ONCE_INIT;
322         g_once (&once, tny_gtk_pixbuf_stream_register_type, NULL);
323         return GPOINTER_TO_UINT (once.retval);
324 }
Note: See TracBrowser for help on using the browser.