1 /* -*- Mode: C; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
2 
3 /*
4  * GImageView
5  * Copyright (C) 2001-2003 Takuro Ashie
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  *
21  * $Id: gimv_image_saver.c,v 1.4 2004/03/07 11:53:30 makeinu Exp $
22  */
23 
24 #include "gimv_image_saver.h"
25 #include "gtk2-compat.h"
26 
27 
28 typedef enum {
29    SAVE_START_SIGNAL,
30    PROGRESS_UPDATE_SIGNAL,
31    SAVE_END_SIGNAL,
32    LAST_SIGNAL
33 } GimvImageLoaderSignalType;
34 
35 
36 typedef enum
37 {
38    GIMV_IMAGE_SAVER_SAVING_FLAG    = 1 << 0,
39    GIMV_IMAGE_SAVER_CANCEL_FLAG    = 1 << 1,
40    GIMV_IMAGE_SAVER_SHOW_TIME_FLAG = 1 << 2,
41    GIMV_IMAGE_SAVER_DEBUG_FLAG     = 1 << 3
42 } GimvImageSaverFlags;
43 
44 
45 struct GimvImageSaverPriv_Tag
46 {
47    GimvImageSaverFlags flags;
48 };
49 
50 
51 static void gimv_image_saver_class_init (GimvImageSaverClass *klass);
52 static void gimv_image_saver_init       (GimvImageSaver      *saver);
53 static void gimv_image_saver_destroy    (GtkObject           *object);
54 
55 
56 static GtkObjectClass *parent_class = NULL;
57 static gint gimv_image_saver_signals[LAST_SIGNAL] = {0};
58 
59 
60 /*******************************************************************************
61  *
62  *  Plugin Management
63  *
64  ******************************************************************************/
65 GHashTable *image_savers = NULL;
66 
67 gboolean
gimv_image_saver_plugin_regist(const gchar * plugin_name,const gchar * module_name,gpointer impl,gint size)68 gimv_image_saver_plugin_regist (const gchar *plugin_name,
69                                 const gchar *module_name,
70                                 gpointer impl,
71                                 gint     size)
72 {
73    GimvImageSaverPlugin *saver_funcs = impl;
74 
75    g_return_val_if_fail (module_name, FALSE);
76    g_return_val_if_fail (saver_funcs, FALSE);
77    g_return_val_if_fail (size > 0, FALSE);
78    g_return_val_if_fail (saver_funcs->if_version == GIMV_IMAGE_SAVER_IF_VERSION, FALSE);
79    g_return_val_if_fail (saver_funcs->format && saver_funcs->save, FALSE);
80 
81    if (!image_savers)
82       image_savers = g_hash_table_new (g_str_hash, g_str_equal);
83 
84    g_hash_table_insert (image_savers, saver_funcs->format, saver_funcs);
85 
86    return TRUE;
87 }
88 
89 
90 
91 /*******************************************************************************
92  *
93  *
94  *
95  ******************************************************************************/
96 GtkType
gimv_image_saver_get_type(void)97 gimv_image_saver_get_type (void)
98 {
99    static GtkType gimv_image_saver_type = 0;
100 
101    if (!gimv_image_saver_type) {
102       static const GtkTypeInfo gimv_image_saver_info = {
103          "GimvImageSaver",
104          sizeof (GimvImageSaver),
105          sizeof (GimvImageSaverClass),
106          (GtkClassInitFunc) gimv_image_saver_class_init,
107          (GtkObjectInitFunc) gimv_image_saver_init,
108          NULL,
109          NULL,
110          (GtkClassInitFunc) NULL,
111       };
112 
113       gimv_image_saver_type = gtk_type_unique (gtk_object_get_type (),
114                                                &gimv_image_saver_info);
115    }
116 
117    return gimv_image_saver_type;
118 }
119 
120 
121 static void
gimv_image_saver_class_init(GimvImageSaverClass * klass)122 gimv_image_saver_class_init (GimvImageSaverClass *klass)
123 {
124    GtkObjectClass *object_class;
125 
126    object_class = (GtkObjectClass *) klass;
127    parent_class = gtk_type_class (gtk_object_get_type ());
128 
129    gimv_image_saver_signals[SAVE_START_SIGNAL]
130       = gtk_signal_new ("save_start",
131                         GTK_RUN_FIRST,
132                         GTK_CLASS_TYPE (object_class),
133                         GTK_SIGNAL_OFFSET (GimvImageSaverClass, save_start),
134                         gtk_signal_default_marshaller,
135                         GTK_TYPE_NONE, 0);
136 
137    gimv_image_saver_signals[PROGRESS_UPDATE_SIGNAL]
138       = gtk_signal_new ("progress_update",
139                         GTK_RUN_FIRST,
140                         GTK_CLASS_TYPE (object_class),
141                         GTK_SIGNAL_OFFSET (GimvImageSaverClass, save_end),
142                         gtk_signal_default_marshaller,
143                         GTK_TYPE_NONE, 0);
144 
145    gimv_image_saver_signals[SAVE_END_SIGNAL]
146       = gtk_signal_new ("save_end",
147                         GTK_RUN_FIRST,
148                         GTK_CLASS_TYPE (object_class),
149                         GTK_SIGNAL_OFFSET (GimvImageSaverClass, save_end),
150                         gtk_signal_default_marshaller,
151                         GTK_TYPE_NONE, 0);
152 
153    gtk_object_class_add_signals (object_class,
154                                  gimv_image_saver_signals, LAST_SIGNAL);
155 
156    object_class->destroy  = gimv_image_saver_destroy;
157 
158    klass->save_start      = NULL;
159    klass->progress_update = NULL;
160    klass->save_end        = NULL;
161 }
162 
163 
164 static void
gimv_image_saver_init(GimvImageSaver * saver)165 gimv_image_saver_init (GimvImageSaver *saver)
166 {
167    saver->info        = NULL;
168    saver->image       = NULL;
169    saver->format      = NULL;
170    saver->filename    = NULL;
171    saver->comments    = NULL;
172    saver->n_comments  = 0;
173    saver->param       = NULL;
174 
175    saver->timer       = g_timer_new ();
176 
177    saver->priv        = g_new0 (GimvImageSaverPriv, 1);
178    saver->priv->flags = 0;
179 
180 #ifdef USE_GTK2
181    gtk_object_ref (GTK_OBJECT (saver));
182    gtk_object_sink (GTK_OBJECT (saver));
183 #endif
184 }
185 
186 
187 static void
gimv_image_saver_destroy(GtkObject * object)188 gimv_image_saver_destroy (GtkObject *object)
189 {
190    GimvImageSaver *saver = GIMV_IMAGE_SAVER (object);
191 
192    gimv_image_saver_reset (saver);
193 
194    if (saver->timer) {
195       g_timer_destroy (saver->timer);
196       saver->timer = NULL;
197    }
198 
199    if (saver->priv) {
200       g_free (saver->priv);
201       saver->priv = NULL;
202    }
203 
204    if (GTK_OBJECT_CLASS (parent_class)->destroy)
205       (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
206 }
207 
208 
209 GimvImageSaver *
gimv_image_saver_new(void)210 gimv_image_saver_new (void)
211 {
212    GimvImageSaver *saver
213       = GIMV_IMAGE_SAVER (gtk_type_new (gimv_image_saver_get_type ()));
214 
215    return saver;
216 }
217 
218 
219 GimvImageSaver *
gimv_image_saver_new_with_attr(GimvImage * image,const gchar * path,const gchar * format)220 gimv_image_saver_new_with_attr (GimvImage *image,
221                                 const gchar *path,
222                                 const gchar *format)
223 {
224    GimvImageSaver *saver
225       = GIMV_IMAGE_SAVER (gtk_type_new (gimv_image_saver_get_type ()));
226 
227    gimv_image_saver_set_image (saver, image);
228    gimv_image_saver_set_path (saver, path);
229    gimv_image_saver_set_format (saver, format);
230 
231    return saver;
232 }
233 
234 
235 GimvImageSaver *
gimv_image_saver_ref(GimvImageSaver * saver)236 gimv_image_saver_ref (GimvImageSaver *saver)
237 {
238    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), NULL);
239 
240    gtk_object_ref (GTK_OBJECT (saver));
241 
242    return saver;
243 }
244 
245 
246 void
gimv_image_saver_unref(GimvImageSaver * saver)247 gimv_image_saver_unref (GimvImageSaver *saver)
248 {
249    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
250 
251    gtk_object_unref (GTK_OBJECT (saver));
252 }
253 
254 
255 void
gimv_image_saver_reset(GimvImageSaver * saver)256 gimv_image_saver_reset (GimvImageSaver *saver)
257 {
258    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
259    g_return_if_fail (!gimv_image_saver_is_saving (saver));
260 
261    if (saver->info) {
262       gimv_image_info_unref (saver->info);
263       saver->info = NULL;
264    }
265 
266    if (saver->image) {
267       gimv_image_unref (saver->image);
268       saver->image = NULL;
269    }
270 
271    if (saver->format) {
272       g_free (saver->format);
273       saver->format = NULL;
274    }
275 
276    if (saver->filename) {
277       g_free (saver->filename);
278       saver->filename = NULL;
279    }
280 
281    if (saver->comments) {
282       gint i;
283 
284       for (i = 0; i < saver->n_comments; i++) {
285          g_free (saver->comments[i].key);
286          g_free (saver->comments[i].text);
287       }
288       g_free (saver->comments);
289       saver->comments = NULL;
290    }
291    saver->n_comments = 0;
292 
293    if (saver->param) {
294       /* FIXME */
295       saver->param = NULL;
296    }
297 
298    if (saver->timer) {
299       g_timer_stop (saver->timer);
300       g_timer_reset (saver->timer);
301    }
302 
303    if (saver->priv) {
304       saver->priv->flags = 0;
305    }
306 }
307 
308 
309 void
gimv_image_saver_set_image(GimvImageSaver * saver,GimvImage * image)310 gimv_image_saver_set_image (GimvImageSaver *saver, GimvImage *image)
311 {
312    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
313    g_return_if_fail (!gimv_image_saver_is_saving (saver));
314 
315    saver->image = gimv_image_ref (image);
316 }
317 
318 
319 void
gimv_image_saver_set_path(GimvImageSaver * saver,const gchar * path)320 gimv_image_saver_set_path (GimvImageSaver *saver,
321                            const gchar    *path)
322 {
323    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
324    g_return_if_fail (!gimv_image_saver_is_saving (saver));
325    g_return_if_fail (path && *path);
326 
327    saver->filename = g_strdup (path);
328 }
329 
330 
331 void
gimv_image_saver_set_format(GimvImageSaver * saver,const gchar * format)332 gimv_image_saver_set_format (GimvImageSaver *saver,
333                              const gchar    *format)
334 {
335    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
336    g_return_if_fail (!gimv_image_saver_is_saving (saver));
337    g_return_if_fail (format && *format);
338 
339    saver->format = g_strdup (format);
340 }
341 
342 
343 void
gimv_image_saver_set_image_info(GimvImageSaver * saver,GimvImageInfo * info)344 gimv_image_saver_set_image_info (GimvImageSaver *saver, GimvImageInfo *info)
345 {
346    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
347    g_return_if_fail (!gimv_image_saver_is_saving (saver));
348 
349    saver->info = gimv_image_info_ref (info);
350 }
351 
352 
353 void
gimv_image_saver_set_comment(GimvImageSaver * saver,const gchar * key,const gchar * value)354 gimv_image_saver_set_comment (GimvImageSaver *saver,
355                               const gchar    *key,
356                               const gchar    *value)
357 {
358    gint pos;
359 
360    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
361    g_return_if_fail (!gimv_image_saver_is_saving (saver));
362    g_return_if_fail (key && *key);
363    g_return_if_fail (value);
364 
365    if (!saver->comments) {
366       saver->comments = g_new (GimvImageSaverText, 1);
367       saver->n_comments = 1;
368    } else {
369       saver->n_comments++;
370       saver->comments
371          = g_realloc (saver->comments,
372                       sizeof (GimvImageSaverText) * saver->n_comments);
373    }
374 
375    pos = saver->n_comments - 1;
376 
377    saver->comments[pos].key  = g_strdup(key);
378    saver->comments[pos].text = g_strdup(value);
379 }
380 
381 
382 gboolean
gimv_image_saver_save(GimvImageSaver * saver)383 gimv_image_saver_save (GimvImageSaver *saver)
384 {
385    GimvImageSaverPlugin *saver_funcs;
386    gboolean retval;
387 
388    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), FALSE);
389    g_return_val_if_fail (saver->priv, FALSE);
390    g_return_val_if_fail (!gimv_image_saver_is_saving (saver), FALSE);
391    g_return_val_if_fail (saver->filename, FALSE);
392    g_return_val_if_fail (saver->format, FALSE);
393    g_return_val_if_fail (saver->image, FALSE);
394 
395    saver->priv->flags |= GIMV_IMAGE_SAVER_SAVING_FLAG;
396 
397    gtk_signal_emit (GTK_OBJECT(saver),
398                     gimv_image_saver_signals[SAVE_START_SIGNAL]);
399 
400    g_timer_reset (saver->timer);
401    g_timer_start (saver->timer);
402 
403    saver_funcs = g_hash_table_lookup (image_savers, saver->format);
404    if (!saver_funcs) {
405       gtk_signal_emit (GTK_OBJECT(saver),
406                        gimv_image_saver_signals[SAVE_END_SIGNAL]);
407       g_timer_stop (saver->timer);
408       g_timer_reset (saver->timer);
409       return FALSE;
410    }
411 
412    retval = saver_funcs->save (saver,
413                                saver->image,
414                                saver->filename,
415                                saver->format);
416 
417    saver->priv->flags &= ~GIMV_IMAGE_SAVER_CANCEL_FLAG;
418    saver->priv->flags &= ~GIMV_IMAGE_SAVER_SAVING_FLAG;
419 
420    g_timer_stop (saver->timer);
421 
422    gtk_signal_emit (GTK_OBJECT(saver),
423                     gimv_image_saver_signals[SAVE_END_SIGNAL]);
424 
425    return retval;
426 }
427 
428 
429 void
gimv_image_saver_save_start(GimvImageSaver * saver)430 gimv_image_saver_save_start (GimvImageSaver *saver)
431 {
432    g_return_if_fail (!gimv_image_saver_is_saving (saver));
433 
434    gimv_image_saver_save (saver);
435 }
436 
437 
438 void
gimv_image_saver_save_stop(GimvImageSaver * saver)439 gimv_image_saver_save_stop (GimvImageSaver *saver)
440 {
441    g_return_if_fail (GIMV_IS_IMAGE_SAVER (saver));
442 
443    saver->priv->flags |= GIMV_IMAGE_SAVER_CANCEL_FLAG;
444 }
445 
446 
447 gboolean
gimv_image_saver_is_saving(GimvImageSaver * saver)448 gimv_image_saver_is_saving (GimvImageSaver *saver)
449 {
450    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), FALSE);
451 
452    if (saver->priv && (saver->priv->flags & GIMV_IMAGE_SAVER_SAVING_FLAG))
453       return TRUE;
454    else
455       return FALSE;
456 }
457 
458 
459 
460 
461 GimvImageInfo *
gimv_image_saver_get_image_info(GimvImageSaver * saver)462 gimv_image_saver_get_image_info (GimvImageSaver *saver)
463 {
464    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), NULL);
465 
466    return saver->info;
467 }
468 
469 
470 const gchar *
gimv_image_saver_get_path(GimvImageSaver * saver)471 gimv_image_saver_get_path (GimvImageSaver *saver)
472 {
473    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), NULL);
474 
475    return saver->filename;
476 }
477 
478 
479 const gchar *
gimv_image_saver_get_format(GimvImageSaver * saver)480 gimv_image_saver_get_format (GimvImageSaver *saver)
481 {
482    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), NULL);
483 
484    return saver->format;
485 }
486 
487 
488 GimvImage *
gimv_image_saver_get_image(GimvImageSaver * saver)489 gimv_image_saver_get_image (GimvImageSaver *saver)
490 {
491    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), NULL);
492 
493    return saver->image;
494 }
495 
496 
497 gint
gimv_image_saver_get_n_comments(GimvImageSaver * saver)498 gimv_image_saver_get_n_comments (GimvImageSaver *saver)
499 {
500    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), 0);
501 
502    return saver->n_comments;
503 }
504 
505 
506 gboolean
gimv_image_saver_get_comment(GimvImageSaver * saver,gint idx,const gchar ** key,const gchar ** value)507 gimv_image_saver_get_comment (GimvImageSaver *saver,
508                               gint idx,
509                               const gchar **key,
510                               const gchar **value)
511 {
512    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), FALSE);
513 
514    if (idx < 0 || idx >= saver->n_comments) return FALSE;
515 
516    if (key)
517       *key = saver->comments[idx].key;
518    if (value)
519       *value = saver->comments[idx].text;
520 
521    return TRUE;
522 }
523 
524 
525 gboolean
gimv_image_saver_progress_update(GimvImageSaver * saver)526 gimv_image_saver_progress_update (GimvImageSaver *saver)
527 {
528    g_return_val_if_fail (GIMV_IS_IMAGE_SAVER (saver), FALSE);
529    g_return_val_if_fail (gimv_image_saver_is_saving (saver), FALSE);
530    g_return_val_if_fail (saver->priv, FALSE);
531 
532    gtk_signal_emit (GTK_OBJECT(saver),
533                     gimv_image_saver_signals[PROGRESS_UPDATE_SIGNAL]);
534 
535    if (saver->priv->flags & GIMV_IMAGE_SAVER_CANCEL_FLAG)
536       return FALSE;
537    else
538       return TRUE;
539 }
540