Camera tracking: libmv distortion API now also uses camera intrinsics
[blender.git] / source / blender / blenkernel / intern / report.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation (2008).
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/blenkernel/intern/report.c
27  *  \ingroup bke
28  */
29
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_dynstr.h"
39 #include "BLI_utildefines.h"
40
41 #include "BLF_translation.h"
42
43 #include "BKE_report.h"
44 #include "BKE_global.h" /* G.background only */
45
46 static const char *report_type_str(int type)
47 {
48         switch (type) {
49                 case RPT_DEBUG:
50                         return TIP_("Debug");
51                 case RPT_INFO:
52                         return TIP_("Info");
53                 case RPT_OPERATOR:
54                         return TIP_("Operator");
55                 case RPT_PROPERTY:
56                         return TIP_("Property");
57                 case RPT_WARNING:
58                         return TIP_("Warning");
59                 case RPT_ERROR:
60                         return TIP_("Error");
61                 case RPT_ERROR_INVALID_INPUT:
62                         return TIP_("Invalid Input Error");
63                 case RPT_ERROR_INVALID_CONTEXT:
64                         return TIP_("Invalid Context Error");
65                 case RPT_ERROR_OUT_OF_MEMORY:
66                         return TIP_("Out Of Memory Error");
67                 default:
68                         return TIP_("Undefined Type");
69         }
70 }
71
72 void BKE_reports_init(ReportList *reports, int flag)
73 {
74         if (!reports)
75                 return;
76
77         memset(reports, 0, sizeof(ReportList));
78
79         reports->storelevel = RPT_INFO;
80         reports->printlevel = RPT_ERROR;
81         reports->flag = flag;
82 }
83
84 void BKE_reports_clear(ReportList *reports)
85 {
86         Report *report, *report_next;
87
88         if (!reports)
89                 return;
90
91         report = reports->list.first;
92
93         while (report) {
94                 report_next = report->next;
95                 MEM_freeN((void *)report->message);
96                 MEM_freeN(report);
97                 report = report_next;
98         }
99
100         reports->list.first = reports->list.last = NULL;
101 }
102
103 void BKE_report(ReportList *reports, ReportType type, const char *_message)
104 {
105         Report *report;
106         int len;
107         const char *message = TIP_(_message);
108
109         /* in background mode always print otherwise there are cases the errors wont be displayed,
110          * but still add to the report list since this is used for python exception handling */
111         if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
112                 printf("%s: %s\n", report_type_str(type), message);
113                 fflush(stdout); /* this ensures the message is printed before a crash */
114         }
115
116         if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
117                 char *message_alloc;
118                 report = MEM_callocN(sizeof(Report), "Report");
119                 report->type = type;
120                 report->typestr = report_type_str(type);
121
122                 len = strlen(message);
123                 message_alloc = MEM_callocN(sizeof(char) * (len + 1), "ReportMessage");
124                 memcpy(message_alloc, message, sizeof(char) * (len + 1));
125                 report->message = message_alloc;
126                 report->len = len;
127                 BLI_addtail(&reports->list, report);
128         }
129 }
130
131 void BKE_reportf(ReportList *reports, ReportType type, const char *_format, ...)
132 {
133         DynStr *ds;
134         Report *report;
135         va_list args;
136         const char *format = TIP_(_format);
137
138         if (G.background || !reports || ((reports->flag & RPT_PRINT) && (type >= reports->printlevel))) {
139                 printf("%s: ", report_type_str(type));
140                 va_start(args, _format);
141                 vprintf(format, args);
142                 va_end(args);
143                 fprintf(stdout, "\n"); /* otherise each report needs to include a \n */
144                 fflush(stdout); /* this ensures the message is printed before a crash */
145         }
146
147         if (reports && (reports->flag & RPT_STORE) && (type >= reports->storelevel)) {
148                 report = MEM_callocN(sizeof(Report), "Report");
149
150                 ds = BLI_dynstr_new();
151                 va_start(args, _format);
152                 BLI_dynstr_vappendf(ds, format, args);
153                 va_end(args);
154
155                 report->message = BLI_dynstr_get_cstring(ds);
156                 report->len = BLI_dynstr_get_len(ds);
157                 BLI_dynstr_free(ds);
158
159                 report->type = type;
160                 report->typestr = report_type_str(type);
161
162                 BLI_addtail(&reports->list, report);
163         }
164 }
165
166 void BKE_reports_prepend(ReportList *reports, const char *_prepend)
167 {
168         Report *report;
169         DynStr *ds;
170         const char *prepend = TIP_(_prepend);
171
172         if (!reports)
173                 return;
174
175         for (report = reports->list.first; report; report = report->next) {
176                 ds = BLI_dynstr_new();
177
178                 BLI_dynstr_append(ds, prepend);
179                 BLI_dynstr_append(ds, report->message);
180                 MEM_freeN((void *)report->message);
181
182                 report->message = BLI_dynstr_get_cstring(ds);
183                 report->len = BLI_dynstr_get_len(ds);
184
185                 BLI_dynstr_free(ds);
186         }
187 }
188
189 void BKE_reports_prependf(ReportList *reports, const char *_prepend, ...)
190 {
191         Report *report;
192         DynStr *ds;
193         va_list args;
194         const char *prepend = TIP_(_prepend);
195
196         if (!reports)
197                 return;
198
199         for (report = reports->list.first; report; report = report->next) {
200                 ds = BLI_dynstr_new();
201                 va_start(args, _prepend);
202                 BLI_dynstr_vappendf(ds, prepend, args);
203                 va_end(args);
204
205                 BLI_dynstr_append(ds, report->message);
206                 MEM_freeN((void *)report->message);
207
208                 report->message = BLI_dynstr_get_cstring(ds);
209                 report->len = BLI_dynstr_get_len(ds);
210
211                 BLI_dynstr_free(ds);
212         }
213 }
214
215 ReportType BKE_report_print_level(ReportList *reports)
216 {
217         if (!reports)
218                 return RPT_ERROR;
219
220         return reports->printlevel;
221 }
222
223 void BKE_report_print_level_set(ReportList *reports, ReportType level)
224 {
225         if (!reports)
226                 return;
227
228         reports->printlevel = level;
229 }
230
231 ReportType BKE_report_store_level(ReportList *reports)
232 {
233         if (!reports)
234                 return RPT_ERROR;
235
236         return reports->storelevel;
237 }
238
239 void BKE_report_store_level_set(ReportList *reports, ReportType level)
240 {
241         if (!reports)
242                 return;
243
244         reports->storelevel = level;
245 }
246
247 char *BKE_reports_string(ReportList *reports, ReportType level)
248 {
249         Report *report;
250         DynStr *ds;
251         char *cstring;
252
253         if (!reports || !reports->list.first)
254                 return NULL;
255
256         ds = BLI_dynstr_new();
257         for (report = reports->list.first; report; report = report->next)
258                 if (report->type >= level)
259                         BLI_dynstr_appendf(ds, "%s: %s\n", report->typestr, report->message);
260
261         if (BLI_dynstr_get_len(ds))
262                 cstring = BLI_dynstr_get_cstring(ds);
263         else
264                 cstring = NULL;
265
266         BLI_dynstr_free(ds);
267         return cstring;
268 }
269
270 void BKE_reports_print(ReportList *reports, ReportType level)
271 {
272         char *cstring = BKE_reports_string(reports, level);
273         
274         if (cstring == NULL)
275                 return;
276         
277         puts(cstring);
278         fflush(stdout);
279         MEM_freeN(cstring);
280 }
281
282 Report *BKE_reports_last_displayable(ReportList *reports)
283 {
284         Report *report;
285         
286         for (report = reports->list.last; report; report = report->prev) {
287                 if (ELEM3(report->type, RPT_ERROR, RPT_WARNING, RPT_INFO))
288                         return report;
289         }
290         
291         return NULL;
292 }
293
294 int BKE_reports_contain(ReportList *reports, ReportType level)
295 {
296         Report *report;
297         if (reports != NULL) {
298                 for (report = reports->list.first; report; report = report->next)
299                         if (report->type >= level)
300                                 return TRUE;
301         }
302         return FALSE;
303 }
304
305 bool BKE_report_write_file_fp(FILE *fp, ReportList *reports, const char *header)
306 {
307         Report *report;
308
309         if (header) {
310                 fputs(header, fp);
311         }
312
313         for (report = reports->list.first; report; report = report->next) {
314                 fprintf((FILE *)fp, "%s  # %s\n", report->message, report->typestr);
315         }
316
317         return true;
318 }
319
320 bool BKE_report_write_file(const char *filepath, ReportList *reports, const char *header)
321 {
322         FILE *fp;
323
324         errno = 0;
325         fp = BLI_fopen(filepath, "wb");
326         if (fp == NULL) {
327                 fprintf(stderr, "Unable to save '%s': %s\n",
328                         filepath, errno ? strerror(errno) : "Unknown error opening file");
329                 return false;
330         }
331
332         BKE_report_write_file_fp(fp, reports, header);
333
334         fclose(fp);
335
336         return true;
337 }