2
* * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>,
3
* * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include <rawstudio.h>
21
#include "rs-output.h"
22
#include "conf_interface.h"
24
G_DEFINE_TYPE (RSOutput, rs_output, G_TYPE_OBJECT)
26
static void integer_changed(GtkAdjustment *adjustment, gpointer user_data);
27
static void boolean_changed(GtkToggleButton *togglebutton, gpointer user_data);
28
static void string_changed(GtkEditable *editable, gpointer user_data);
31
rs_output_class_init(RSOutputClass *klass)
33
/* Some sane defaults */
34
klass->extension = "";
35
klass->display_name = "N/A";
39
rs_output_init(RSOutput *self)
44
* Instantiate a new RSOutput type
45
* @param identifier A string representing a type, for example "RSJpegfile"
46
* @return A new RSOutput or NULL on failure
49
rs_output_new(const gchar *identifier)
51
RSOutput *output = NULL;
53
g_assert(identifier != NULL);
55
GType type = g_type_from_name(identifier);
57
if (g_type_is_a (type, RS_TYPE_OUTPUT))
58
output = g_object_new(type, NULL);
60
g_warning("%s is not a RSOutput",identifier);
62
if (!RS_IS_OUTPUT(output))
63
g_warning("Could not instantiate output of type \"%s\"", identifier);
69
* Get a filename extension as announced by a RSOutput module
70
* @param output A RSOutput
71
* @return A proposed filename extension excluding the ., this should not be freed.
74
rs_output_get_extension(RSOutput *output)
76
g_assert(RS_IS_OUTPUT(output));
78
if (RS_OUTPUT_GET_CLASS(output)->extension)
79
return RS_OUTPUT_GET_CLASS(output)->extension;
85
* Actually execute the saver
86
* @param output A RSOutput
87
* @param filter A RSFilter to get image data from
88
* @return TRUE on success, FALSE on error
91
rs_output_execute(RSOutput *output, RSFilter *filter)
93
g_assert(RS_IS_OUTPUT(output));
94
g_assert(RS_IS_FILTER(filter));
96
if (RS_OUTPUT_GET_CLASS(output)->execute)
97
return RS_OUTPUT_GET_CLASS(output)->execute(output, filter);
103
integer_changed(GtkAdjustment *adjustment, gpointer user_data)
105
RSOutput *output = RS_OUTPUT(user_data);
106
gint value = (gint) gtk_adjustment_get_value(adjustment);
107
gchar *name = g_object_get_data(G_OBJECT(adjustment), "spec-name");
108
gchar *confpath = g_object_get_data(G_OBJECT(adjustment), "conf-path");
111
g_object_set(output, name, value, NULL);
114
rs_conf_set_integer(confpath, value);
118
boolean_changed(GtkToggleButton *togglebutton, gpointer user_data)
120
RSOutput *output = RS_OUTPUT(user_data);
121
gboolean value = gtk_toggle_button_get_active(togglebutton);
122
gchar *name = g_object_get_data(G_OBJECT(togglebutton), "spec-name");
123
gchar *confpath = g_object_get_data(G_OBJECT(togglebutton), "conf-path");
126
g_object_set(output, name, value, NULL);
129
rs_conf_set_boolean(confpath, value);
133
string_changed(GtkEditable *editable, gpointer user_data)
135
RSOutput *output = RS_OUTPUT(user_data);
137
const gchar *value = gtk_entry_get_text(GTK_ENTRY(editable));
138
gchar *name = g_object_get_data(G_OBJECT(editable), "spec-name");
139
gchar *confpath = g_object_get_data(G_OBJECT(editable), "conf-path");
142
g_object_set(output, name, value, NULL);
145
rs_conf_set_string(confpath, value);
149
colorspace_changed(RSColorSpaceSelector *selector, RSColorSpace *color_space, gpointer user_data)
151
RSOutput *output = RS_OUTPUT(user_data);
153
const gchar *name = g_object_get_data(G_OBJECT(selector), "spec-name");
154
const gchar *confpath = g_object_get_data(G_OBJECT(selector), "conf-path");
157
g_object_set(output, name, color_space, NULL);
160
rs_conf_set_string(confpath, G_OBJECT_TYPE_NAME(color_space));
164
* Load parameters from config for a RSOutput
165
* @param output A RSOutput
166
* @param conf_prefix The prefix to prepend on config-keys.
169
rs_output_set_from_conf(RSOutput *output, const gchar *conf_prefix)
171
GObjectClass *klass = G_OBJECT_GET_CLASS(output);
176
g_assert(RS_IS_OUTPUT(output));
177
g_assert(conf_prefix != NULL);
179
specs = g_object_class_list_properties(G_OBJECT_CLASS(klass), &n_specs);
180
for(i=0; i<n_specs; i++)
182
GType type = G_PARAM_SPEC_VALUE_TYPE(specs[i]);
183
gchar *confpath = NULL;
185
confpath = g_strdup_printf("%s:%s:%s", conf_prefix, G_OBJECT_TYPE_NAME(output), specs[i]->name);
187
if (type == RS_TYPE_COLOR_SPACE)
191
if (confpath && (str = rs_conf_get_string(confpath)))
193
RSColorSpace *color_space;
194
color_space = rs_color_space_new_singleton(str);
196
g_object_set(output, specs[i]->name, color_space, NULL);
203
gboolean boolean = FALSE;
204
if (rs_conf_get_boolean(confpath, &boolean))
205
g_object_set(output, specs[i]->name, boolean, NULL);
211
if (rs_conf_get_integer(confpath, &integer))
212
g_object_set(output, specs[i]->name, integer, NULL);
217
gchar *str = rs_conf_get_string(confpath);
220
g_object_set(output, specs[i]->name, str, NULL);
226
g_debug("rs_output_set_from_conf: Unknown configuration type encountered");
233
* Build a GtkWidget that can edit parameters of a RSOutput
234
* @param output A RSOutput
235
* @param conf_prefix If this is non-NULL, the value will be saved in config,
236
* and reloaded next time.
237
* @return A new GtkWidget representing all parameters of output
240
rs_output_get_parameter_widget(RSOutput *output, const gchar *conf_prefix)
242
GtkWidget *box = gtk_vbox_new(FALSE, 0);
243
GObjectClass *klass = G_OBJECT_GET_CLASS(output);
249
/* Maintain a reference to the RSOutput */
250
g_object_ref(output);
251
g_object_set_data_full(G_OBJECT(box), "just-for-refcounting", output, g_object_unref);
253
/* Iterate through all GParamSpec's and build a GtkWidget representing them */
254
specs = g_object_class_list_properties(G_OBJECT_CLASS(klass), &n_specs);
255
for(i=0; i<n_specs; i++)
257
gchar *confpath = NULL;
258
GtkWidget *widget = NULL;
260
/* Ignore "filename" for now */
261
if (g_str_equal(specs[i]->name, "filename"))
264
/* Iw the caller has supplied ud with a conf prefix, sync everything
265
* with config system */
267
confpath = g_strdup_printf("%s:%s:%s", conf_prefix, G_OBJECT_TYPE_NAME(output), specs[i]->name);
269
GType type = G_PARAM_SPEC_VALUE_TYPE(specs[i]);
271
if (type == GTK_TYPE_WIDGET)
273
g_object_get(output, specs[i]->name, &widget, NULL);
275
else if (type == RS_TYPE_COLOR_SPACE)
277
GtkWidget *cs_widget = rs_color_space_selector_new();
278
GtkWidget *label = gtk_label_new(g_param_spec_get_blurb(specs[i]));
279
g_object_set_data(G_OBJECT(cs_widget), "spec-name", specs[i]->name);
280
g_object_set_data_full(G_OBJECT(cs_widget), "conf-path", confpath, g_free);
282
rs_color_space_selector_add_all(RS_COLOR_SPACE_SELECTOR(cs_widget));
283
rs_color_space_selector_set_selected_by_name(RS_COLOR_SPACE_SELECTOR(cs_widget), "RSSrgb");
285
if (confpath && (str = rs_conf_get_string(confpath)))
287
RSColorSpace *color_space;
288
color_space = rs_color_space_selector_set_selected_by_name(RS_COLOR_SPACE_SELECTOR(cs_widget), str);
290
g_object_set(output, specs[i]->name, color_space, NULL);
293
g_signal_connect(cs_widget, "colorspace-selected", G_CALLBACK(colorspace_changed), output);
294
widget = gtk_hbox_new(FALSE, 2);
295
gtk_box_pack_start(GTK_BOX(widget), label, FALSE, TRUE, 0);
296
gtk_box_pack_start(GTK_BOX(widget), cs_widget, TRUE, TRUE, 0);
302
gboolean boolean = FALSE;
304
/* Should this be dropped, and then let the user worry about
305
* calling rs_output_set_from_conf()? */
306
if (confpath && rs_conf_get_boolean(confpath, &boolean))
307
g_object_set(output, specs[i]->name, boolean, NULL);
309
g_object_get(output, specs[i]->name, &boolean, NULL);
311
widget = gtk_check_button_new_with_label(g_param_spec_get_blurb(specs[i]));
312
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), boolean);
313
g_object_set_data(G_OBJECT(widget), "spec-name", specs[i]->name);
314
g_object_set_data_full(G_OBJECT(widget), "conf-path", confpath, g_free);
315
g_signal_connect(widget, "toggled", G_CALLBACK(boolean_changed), output);
326
if (confpath && rs_conf_get_integer(confpath, &integer))
327
g_object_set(output, specs[i]->name, integer, NULL);
329
g_object_get(output, specs[i]->name, &integer, NULL);
331
adj = gtk_adjustment_new((gdouble) integer,
332
(gdouble) (((GParamSpecInt*)specs[i])->minimum),
333
(gdouble) (((GParamSpecInt*)specs[i])->maximum),
335
g_object_set_data(G_OBJECT(adj), "spec-name", specs[i]->name);
336
g_object_set_data_full(G_OBJECT(adj), "conf-path", confpath, g_free);
337
g_signal_connect(adj, "value-changed", G_CALLBACK(integer_changed), output);
339
label = gtk_label_new(g_param_spec_get_blurb(specs[i]));
340
scale = gtk_hscale_new(GTK_ADJUSTMENT(adj));
341
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
342
spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1.0, 0);
344
widget = gtk_hbox_new(FALSE, 2);
345
gtk_box_pack_start(GTK_BOX(widget), label, FALSE, TRUE, 0);
346
gtk_box_pack_start(GTK_BOX(widget), scale, TRUE, TRUE, 0);
347
gtk_box_pack_start(GTK_BOX(widget), spin, FALSE, TRUE, 0);
352
GtkWidget *label = gtk_label_new(g_param_spec_get_blurb(specs[i]));
353
GtkWidget *entry = gtk_entry_new();
355
if (confpath && (str = rs_conf_get_string(confpath)))
357
g_object_set(output, specs[i]->name, str, NULL);
361
g_object_get(output, specs[i]->name, &str, NULL);
364
gtk_entry_set_text(GTK_ENTRY(entry), str);
368
g_object_set_data(G_OBJECT(entry), "spec-name", specs[i]->name);
369
g_object_set_data_full(G_OBJECT(entry), "conf-path", confpath, g_free);
370
g_signal_connect(entry, "changed", G_CALLBACK(string_changed), output);
372
widget = gtk_hbox_new(FALSE, 2);
373
gtk_box_pack_start(GTK_BOX(widget), label, FALSE, TRUE, 0);
374
gtk_box_pack_start(GTK_BOX(widget), entry, TRUE, TRUE, 0);
378
g_assert_not_reached();
381
gtk_box_pack_start(GTK_BOX(box), widget, FALSE, FALSE, 3);