Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
example.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2011 Henrik Andersson.
4 Copyright (C) 2010-2012, 2014 johannes hanika.
5 Copyright (C) 2010 Stuart Henderson.
6 Copyright (C) 2010-2018, 2020 Tobias Ellinghaus.
7 Copyright (C) 2011 Robert Bieber.
8 Copyright (C) 2012 Christian Tellefsen.
9 Copyright (C) 2012-2014 Jérémy Rosen.
10 Copyright (C) 2012 Richard Wonka.
11 Copyright (C) 2012 Simon Spannagel.
12 Copyright (C) 2013-2014, 2018, 2020 Pascal Obry.
13 Copyright (C) 2014 Pascal de Bruijn.
14 Copyright (C) 2014-2016 Roman Lebedev.
15 Copyright (C) 2019 Denis Dyakov.
16 Copyright (C) 2019 Heiko Bauke.
17 Copyright (C) 2019 jakubfi.
18 Copyright (C) 2019 Philippe Weyland.
19 Copyright (C) 2022 Martin Bařinka.
20 Copyright (C) 2023, 2025 Aurélien PIERRE.
21 Copyright (C) 2023 Maurizio Paglia.
22 Copyright (C) 2023 Ricky Moon.
23
24 darktable is free software: you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation, either version 3 of the License, or
27 (at your option) any later version.
28
29 darktable is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with darktable. If not, see <http://www.gnu.org/licenses/>.
36*/
37
38#include "system/macros.h"
39#include "system/mem_alloc.h"
41#include "common/paths.h"
43#include "common/image.h"
44#include "caches/image_cache.h"
49#include <stdio.h>
50#include <stdlib.h>
51
52DT_MODULE(2)
53
54typedef struct _email_attachment_t
55{
56 int32_t imgid; // The image id of exported image
57 gchar *file; // Full filename of exported image
59
60// saved params
66
67
68const char *name(const struct dt_imageio_module_storage_t *self)
69{
70 return _("send as email");
71}
72
73void *legacy_params(dt_imageio_module_storage_t *self, const void *const old_params,
74 const size_t old_params_size, const int old_version, const int new_version,
75 size_t *new_size)
76{
77 if(old_version == 1 && new_version == 2)
78 {
79 typedef struct dt_imageio_email_v1_t
80 {
81 char filename[1024];
82 GList *images;
83 } dt_imageio_email_v1_t;
84
86 dt_imageio_email_v1_t *o = (dt_imageio_email_v1_t *)old_params;
87
88 g_strlcpy(n->filename, o->filename, sizeof(n->filename));
89
90 *new_size = self->params_size(self);
91 return n;
92 }
93 return NULL;
94}
95
97{
98 *width = 1536;
99 *height = 1536;
100 return 1;
101}
102
103
107
109{
110 dt_free(self->gui_data);
111}
112
116
117int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int32_t imgid,
118 dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total,
119 const gboolean high_quality, const gboolean upscale, const gboolean export_masks,
120 dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent,
121 dt_export_metadata_t *metadata)
122{
124
125 _email_attachment_t *attachment = (_email_attachment_t *)g_malloc(sizeof(_email_attachment_t));
126 attachment->imgid = imgid;
127
128 /* construct a temporary file name */
129 char tmpdir[DT_PATH_MAX] = { 0 };
130 dt_loc_get_tmp_dir(tmpdir, sizeof(tmpdir));
131
132 char dirname[DT_PATH_MAX] = { 0 };
133 gboolean from_cache = FALSE;
134 dt_image_full_path(imgid, dirname, sizeof(dirname), &from_cache, __FUNCTION__);
135 gchar *filename = g_path_get_basename(dirname);
136
137 g_strlcpy(dirname, filename, sizeof(dirname));
138
139 dt_image_path_append_version(imgid, dirname, sizeof(dirname));
140
141 gchar *end = g_strrstr(dirname, ".") + 1;
142
143 if(end) *end = '\0';
144
145 g_strlcat(dirname, format->extension(fdata), sizeof(dirname));
146
147 // set exported filename
148
149 attachment->file = g_build_filename(tmpdir, dirname, (char *)NULL);
150
151 if(dt_imageio_export(imgid, attachment->file, format, fdata, high_quality, upscale, TRUE, export_masks, icc_type,
152 icc_filename, icc_intent, self, sdata, num, total, metadata) != 0)
153 {
154 fprintf(stderr, "[imageio_storage_email] could not export to file: `%s'!\n", attachment->file);
155 dt_control_log(_("could not export to file `%s'!"), attachment->file);
156 dt_free(attachment->file);
157 dt_free(attachment);
158 dt_free(filename);
159 return 1;
160 }
161
162 dt_control_log(ngettext("%d/%d exported to `%s'", "%d/%d exported to `%s'", num),
163 num, total, attachment->file);
164
165#ifdef _OPENMP // store can be called in parallel, so synch access to shared memory
166#pragma omp critical
167#endif
168 d->images = g_list_append(d->images, attachment);
169
170 dt_free(filename);
171
172 return 0;
173}
174
176{
177 return sizeof(dt_imageio_email_t) - sizeof(GList *);
178}
179
181{
182}
183
185{
187 return d;
188}
189
190int set_params(dt_imageio_module_storage_t *self, const void *params, const int size)
191{
192 if(size != self->params_size(self)) return 1;
193 return 0;
194}
195
197{
198 if(IS_NULL_PTR(params)) return;
199 dt_free(params);
200}
201
203{
205
206 const gchar *imageBodyFormat = " - %s (%s)\\n"; // filename, exif oneliner
207 const gint nb_images = g_list_length(d->images);
208 const gint argc = 5 + (2 * nb_images);
209
210 char **argv = g_malloc0(sizeof(char *) * (argc + 1));
211
212 gchar *body = NULL;
213
214 argv[0] = "xdg-email";
215 argv[1] = "--subject";
216 argv[2] = _("images exported from Ansel");
217 argv[3] = "--body";
218 int n = 5;
219
220 for(GList *iter = d->images; iter; iter = g_list_next(iter))
221 {
222 gchar exif[256] = { 0 };
223 _email_attachment_t *attachment = (_email_attachment_t *)iter->data;
224 gchar *filename = g_path_get_basename(attachment->file);
225 const dt_image_t *img = dt_image_cache_get(attachment->imgid, 'r');
226 dt_image_print_exif(img, exif, sizeof(exif));
228
229 gchar *imgbody = g_strdup_printf(imageBodyFormat, filename, exif);
230 if (!IS_NULL_PTR(body)) {
231 gchar *body_bak = body;
232 body = g_strconcat(body_bak, imgbody, NULL);
233 dt_free(body_bak);
234 }
235 else
236 {
237 body = g_strdup(imgbody);
238 }
239 dt_free(imgbody);
240 dt_free(filename);
241
242 argv[n] = g_strdup("--attach");
243 // use attachment->file directly as we need to freed it, and this way it will be
244 // freed as part of the argument release after the spawn below.
245 argv[n+1] = attachment->file;
246 n += 2;
247 }
248 g_list_free_full(d->images, dt_free_gpointer);
249 d->images = NULL;
250
251 argv[4] = body;
252
253 argv[argc] = NULL;
254
255 fprintf(stderr, "[email] launching '");
256 for (int k=0; k<argc; k++) fprintf(stderr, " %s", argv[k]);
257 fprintf(stderr, "'\n");
258
259 gint exit_status = 0;
260
261 g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
262 NULL, NULL, NULL, NULL, &exit_status, NULL);
263
264 for (int k=4; k<argc; k++) dt_free(argv[k]);
265 dt_free(argv);
266
267 if(exit_status)
268 {
269 dt_control_log(_("could not launch email client!"));
270 }
271}
272
274{
275 const char *mime = format->mime(NULL);
276 if(mime[0] == '\0') // this seems to be the copy format
277 return 0;
278
279 return 1;
280}
281
282// clang-format off
283// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
284// vim: shiftwidth=2 expandtab tabstop=2 cindent
285// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
286// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
const char * mime(dt_imageio_module_data_t *data)
Definition avif.c:646
void dt_image_path_append_version(const int32_t imgid, char *pathname, size_t pathname_len)
void dt_image_print_exif(const dt_image_t *img, char *line, size_t line_len)
void dt_image_full_path(const int32_t imgid, char *pathname, size_t pathname_len, gboolean *from_cache, const char *calling_func)
Get the full path of an image out of the database.
void dt_control_log(const char *msg,...)
Definition control.c:824
GtkTreeStore * store
its model, owned by the view
void * get_params(dt_imageio_module_storage_t *self)
Definition example.c:184
void finalize_store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *params)
Definition example.c:202
int recommended_dimension(struct dt_imageio_module_storage_t *self, dt_imageio_module_data_t *data, uint32_t *width, uint32_t *height)
Definition example.c:96
void gui_cleanup(dt_imageio_module_storage_t *self)
Definition example.c:108
void free_params(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *params)
Definition example.c:196
size_t params_size(dt_imageio_module_storage_t *self)
Definition example.c:175
void gui_init(dt_imageio_module_storage_t *self)
Definition example.c:104
int supported(struct dt_imageio_module_storage_t *storage, struct dt_imageio_module_format_t *format)
Definition example.c:273
void init(dt_imageio_module_storage_t *self)
Definition example.c:180
void gui_reset(dt_imageio_module_storage_t *self)
Definition example.c:113
void * legacy_params(dt_imageio_module_storage_t *self, const void *const old_params, const size_t old_params_size, const int old_version, const int new_version, size_t *new_size)
Definition example.c:73
int set_params(dt_imageio_module_storage_t *self, const void *params, const int size)
Definition example.c:190
void dt_loc_get_tmp_dir(char *tmpdir, size_t bufsize)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
int dt_imageio_export(const int32_t imgid, const char *filename, dt_imageio_module_format_t *format, dt_imageio_module_data_t *format_params, const gboolean high_quality, const gboolean copy_metadata, const gboolean export_masks, dt_colorspaces_color_profile_type_t icc_type, const gchar *icc_filename, dt_iop_color_intent_t icc_intent, dt_imageio_module_storage_t *storage, dt_imageio_module_data_t *storage_params, int num, int total, dt_export_metadata_t *metadata)
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
Definition mem_alloc.h:184
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
size_t size
Definition mipmap_cache.c:3
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
#define DT_PATH_MAX
Buffer size for a filesystem path anywhere in Ansel.
Definition paths.h:57
#define DT_MAX_PATH_FOR_PARAMS
Definition paths.h:65
const char * name
Definition pdf.h:90
dt_iop_color_intent_t
ICC rendering intent, as stored in iop params and in conf.
dt_colorspaces_color_profile_type_t
char filename[DT_MAX_PATH_FOR_PARAMS]
Definition example.c:63
Telling the user something happened.