1 // Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
2 // <dhilvert@ugcs.caltech.edu>
4 /* This file is part of the Anti-Lamenessing Engine.
6 The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with the Anti-Lamenessing Engine; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 class ui_tty
: public ui
{
52 fputc('\r', ui_stream
);
53 fputs(buffer
, ui_stream
);
54 status_index
= buffer_index
;
58 while (status_index
< terminal_width
) {
60 fprintf(ui_stream
, " ");
65 fputc('\r', ui_stream
);
66 for (int i
= 0; i
< terminal_width
; i
++) {
67 fprintf(ui_stream
, " ");
72 void status_printf(int count
, ...) {
79 char *local_buffer
= (char *) calloc(terminal_width
- status_index
, sizeof(char));
86 for (int i
= 0; i
< count
; i
++) {
92 for (int arg
= 0; arg
< i
+ 1; arg
++)
93 format
= va_arg(ap
, char *);
94 for (int arg
= i
+ 1; arg
< count
; arg
++)
99 n
= vsnprintf(local_buffer
, terminal_width
- status_index
, format
, ap
);
102 if (n
< 0 || n
> terminal_width
- status_index
- 1)
105 fputs(local_buffer
, ui_stream
);
115 * If we reach this point, then there was no valid string produced.
123 void pad_align_status() {
124 for (int i
= 0; i
< status
.steps
- status
.steps_completed
; i
++) {
125 status_printf(1, " ");
128 void pad_match_status() {
129 status_printf(1, " ");
132 void write_match_status() {
133 status_printf(1, format_string_working(), status
.match_value
);
136 void write_status() {
138 if (status
.code
== status
.UNDEFINED
139 || status
.code
== status
.FRAME_DONE
140 || status
.code
== status
.SET_DONE
141 || status
.code
== status
.IP_STEP_DONE
) {
146 if (status
.code
== status
.ALIGN
147 || status
.code
== status
.POSTMATCH
148 || status
.code
== status
.EXPOSURE_PASS_2
) {
150 write_match_status();
153 status_printf(1, " | ");
155 switch (status
.code
) {
156 case status_type::LOAD_FILE
:
157 status_printf(3, "Loading Image", "Loading", "load");
159 case status_type::EXPOSURE_PASS_1
:
160 status_printf(3, "Registering exposure (first pass)", "Registering exposure", "regexp1");
162 case status_type::LODCLUSTER_CREATE
:
163 status_printf(3, "Creating LOD cluster, scale %f", "Creating LOD clusters", "lodcluster",
164 pow(2, -status
.align_lod
));
166 case status_type::PREMATCH
:
167 status_printf(3, "Calculating pre-alignment match", "Calculating match", "prematch");
169 case status_type::ALIGN
:
170 status_printf(5, "Aligning [perturb=%f] [lod=%f] [mc=%f] [exp_mult=%f %f %f]",
171 "Aligning [perturb=%f] [lod=%f] [mc=%f]",
172 "Aligning [perturb=%f] [lod=%f]",
176 pow(2, -status
.align_lod
),
178 status
.exp_multiplier
[0],
179 status
.exp_multiplier
[1],
180 status
.exp_multiplier
[2]);
182 case status_type::POSTMATCH
:
183 status_printf(3, "Calculating post-alignment match", "Calculating match", "postmatch");
185 case status_type::EXPOSURE_PASS_2
:
186 status_printf(3, "Registering exposure (second pass)", "Registering exposure", "regexp2");
188 case status_type::RENDERA
:
189 status_printf(3, "Rendering alignment reference image", "Rendering", "render-a");
191 case status_type::RENDERD
:
192 status_printf(3, "Rendering default chain", "Rendering", "render-d");
194 case status_type::RENDERO
:
195 status_printf(3, "Rendering chain %d", "Rendering", "render-o%d", status
.onum
);
197 case status_type::WRITED
:
198 status_printf(4, "Writing default chain to '%s'",
199 "Writing '%s'", "Writing", "write-d", d2::image_rw::output_name());
201 case status_type::WRITEO
:
202 status_printf(3, "Writing image for chain %d", "Writing", "write-o%d", status
.onum
);
204 case status_type::IP_RENDER
:
205 status_printf(2, /* "Processing frame '%s'%s", */ "Processing frame '%s'", "Processing",
206 d2::image_rw::name(status
.frame_num
), status
.irani_peleg_stage
207 ? ((status
.irani_peleg_stage
== 1) ? " [simulate]" : " [backproject]")
210 case status_type::IP_UPDATE
:
211 status_printf(3, "Updating approximation", "Updating", "update");
213 case status_type::IP_WRITE
:
214 status_printf(3, "Writing '%s'", "Writing", "write", d2::image_rw::output_name());
216 case status_type::D3_CONTROL_POINT_SOLVE
:
217 status_printf(1, "Aligning control points, %f%% done, error=%f",
218 log(status
.cp_cur_perturb
/ status
.cp_max_perturb
)
219 / log(status
.cp_min_perturb
/ status
.cp_max_perturb
),
220 status
.cp_cur_error
);
222 case status_type::D3_SUBDIVIDING_SPACE
:
223 status_printf(2, "Subdividing space, frame pair (%u, %u), y=%u, x=%u, spaces=%u",
224 "Subdividing space", status
.frame_num
,
225 status
.secondary_frame_num
, status
.y_coordinate
, status
.x_coordinate
,
226 status
.total_spaces
);
228 case status_type::D3_UPDATING_OCCUPANCY
:
229 status_printf(2, "Updating occupancy, step %u/%u, frame %u, space %u/%u",
230 "Updating occupancy", status
.steps_completed
,
231 status
.steps
, status
.frame_num
,
232 status
.space_num
, status
.total_spaces
);
234 case status_type::D3_RENDER
:
235 if (status
.filtering
== 0 && status
.focusing
== 0) {
236 status_printf(1, "space %u/%u",
237 status
.space_num
, status
.total_spaces
);
238 } else if (status
.filtering
== 1 && status
.focusing
== 0) {
239 status_printf(1, "frame %u, y=%u, x=%u",
240 status
.frame_num
, status
.y_coordinate
, status
.x_coordinate
);
241 } else if (status
.filtering
== 0 && status
.focusing
== 1) {
242 status_printf(1, "y=%u, x=%u, view=%u", status
.y_coordinate
, status
.x_coordinate
,
244 } else if (status
.filtering
== 1 && status
.focusing
== 1) {
245 status_printf(1, "view=%u, y=%u, x=%u, frame=%u",
246 status
.view_num
, status
.y_coordinate
, status
.x_coordinate
,
264 void printf(char *format
, ...) {
268 if (buffer_index
>= 0 && buffer_index
< terminal_width
/* && format[strlen(format) - 1] != '\n' */) {
269 va_start(ap
, format
);
270 n
= vsnprintf(buffer
+ buffer_index
, terminal_width
- buffer_index
, format
, ap
);
274 if (n
>= 0 && n
< terminal_width
- buffer_index
) {
276 * The message fits in the buffer, so update the index
277 * and write buffer and status information.
282 if (format
[strlen(format
) - 1] == '\n') {
290 * The message does not fit in the buffer, so write any
291 * existing buffer and append the new text to the stream.
293 if (buffer_index
>= 0) {
294 assert(buffer_index
< terminal_width
);
295 buffer
[buffer_index
] = '\0';
299 va_start(ap
, format
);
300 vfprintf(ui_stream
, format
, ap
);
305 * This is not the only case that produces a newline,
306 * but ignoring other cases should be safe.
308 if (format
[strlen(format
) - 1] == '\n') {
315 static time_t last_update
= 0;
316 time_t now
= time(NULL
);
319 * Handle DONE status.
322 if (status
.code
== status_type::FRAME_DONE
) {
324 fputc('\n', ui_stream
);
330 if (status
.code
== status_type::SET_DONE
) {
331 fputc('\n', ui_stream
);
338 * Handle optional output.
341 if (now
== last_update
)
351 * Constructor may throw an exception to signal that using ui_wo would
352 * be more appropriate.
355 int exception_value
= 1;
357 if (!isatty(fileno(ui_stream
)))
358 throw exception_value
;
361 * Don't use the last column, as this may cause
362 * wrapping in some environments (BSD, Hurd).
365 terminal_width
= get_terminal_width(ui_stream
) - 1;
367 if (terminal_width
< 0)
368 throw exception_value
;
370 buffer
= (char *) calloc(terminal_width
+ 1, sizeof(char));
375 throw exception_value
;