Update changelog
[Ale.git] / ui / ui.h
blob7880326ff633d95cbfcfb22267453edb392ade89
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
21 #ifndef __ui_h__
22 #define __ui_h__
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stdarg.h>
27 #include <assert.h>
28 #include "../ale_pos.h"
29 #include "../config.h"
30 #if HAVE_TIME_H
31 #include <time.h>
32 #endif
33 #if HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
38 * User interface messages.
41 class ui_wo;
43 class ui {
44 private:
45 static ui *singleton;
48 * UI type
50 * 0. stream
51 * 1. tty
54 static int type;
56 static int output_performance_data;
58 protected:
61 * Data
64 FILE *ui_stream;
66 struct status_type {
67 enum {
69 * Special
72 UNDEFINED,
75 * Incremental rendering.
78 LOAD_FILE, EXPOSURE_PASS_1,
79 LODCLUSTER_CREATE, PREMATCH, ALIGN, POSTMATCH,
80 EXPOSURE_PASS_2, RENDERA, RENDERD, RENDERO, WRITED,
81 WRITEO, FRAME_DONE, SET_DONE,
84 * Irani-Peleg rendering.
87 IP_RENDER, IP_STEP_DONE, IP_UPDATE, IP_WRITE,
90 * 3D.
93 D3_CONTROL_POINT_SOLVE, D3_SUBDIVIDING_SPACE,
94 D3_UPDATING_OCCUPANCY, D3_RENDER
96 } code, orender_current;
98 int arender_current;
99 double match_value;
100 int onum;
101 int steps;
102 int steps_completed;
103 double exp_multiplier[3];
104 double perturb_size;
105 double align_lod;
106 double mc;
107 unsigned int frame_num;
108 unsigned int irani_peleg_stage;
109 unsigned int secondary_frame_num;
110 unsigned int view_num;
111 unsigned int x_coordinate, y_coordinate;;
112 unsigned int filtering, focusing;
113 unsigned int space_num;
114 unsigned int total_spaces;
115 double cp_max_perturb;
116 double cp_min_perturb;
117 double cp_cur_perturb;
118 double cp_cur_error;
120 status_type() {
121 code = UNDEFINED;
122 steps_completed = 0;
124 for (int k = 0; k < 3; k++)
125 exp_multiplier[k] = 1;
127 } status;
130 * Performance data
133 #if HAVE_GETTIMEOFDAY
134 typedef struct timeval ale_timer_t;
135 #else
136 typedef time_t ale_timer_t;
137 #endif
139 ale_timer_t d2_align_sample_start_time;
140 ale_timer_t d2_align_sim_start_time;
141 ale_timer_t d2_incremental_start_time;
142 ale_timer_t d2_irani_peleg_start_time;
143 ale_timer_t d2_align_sample_total_time;
144 ale_timer_t d2_align_sim_total_time;
145 ale_timer_t d2_incremental_total_time;
146 ale_timer_t d2_irani_peleg_total_time;
149 * Constructor
152 ui() {
153 ui_stream = stderr;
154 #if HAVE_GETTIMEOFDAY
155 d2_irani_peleg_total_time.tv_usec = 0;
156 d2_irani_peleg_total_time.tv_sec = 0;
157 d2_incremental_total_time.tv_usec = 0;
158 d2_incremental_total_time.tv_sec = 0;
159 d2_align_sample_total_time.tv_usec = 0;
160 d2_align_sample_total_time.tv_sec = 0;
161 d2_align_sim_total_time.tv_usec = 0;
162 d2_align_sim_total_time.tv_sec = 0;
163 #else
164 d2_incremental_total_time = 0;
165 d2_irani_peleg_total_time = 0;
166 d2_align_sample_total_time = 0;
167 d2_align_sim_total_time = 0;
168 #endif
172 * Print function
175 virtual void printf(char *format, ...) = 0;
178 * UI update function
181 virtual void update() = 0;
184 * Match format strings for textual UIs.
187 char *format_string_ok() {
188 return " okay (%f%% match)";
190 char *format_string_no_match() {
191 return " no match (%f%% match)";
193 char *format_string_working() {
194 return " (%f%% match)";
197 void timer_start(void *t) {
198 #if HAVE_GETTIMEOFDAY
199 gettimeofday((timeval *) t, NULL);
200 #else
201 *((time_t *) t) = time(NULL);
202 #endif
205 void timer_stop(void *start_v, void *total_v) {
206 #if HAVE_GETTIMEOFDAY
207 timeval t;
208 timeval *start = (timeval *) start_v;
209 timeval *total = (timeval *) total_v;
211 gettimeofday(&t, NULL);
213 t.tv_sec -= start->tv_sec;
214 t.tv_usec -= start->tv_usec;
216 total->tv_sec += t.tv_sec;
217 total->tv_usec += t.tv_usec;
219 while (total->tv_usec >= 1000000) {
220 total->tv_sec += 1;
221 total->tv_usec -= 1000000;
224 while (total->tv_usec < 0) {
225 total->tv_sec -= 1;
226 total->tv_usec += 1000000;
228 #else
229 time_t t = time(NULL);
230 t -= *((time_t *) start_v);
231 *((time_t *) total_v) += t;
232 #endif
236 public:
239 * Handle options and other user input.
242 static void handle_input(int argc, const char *argv[], const char *package,
243 const char *short_version, const char *version);
245 static ui *get();
247 static void set_stream() {
248 assert(singleton == NULL);
249 type = 0;
252 static void set_tty() {
253 assert(singleton == NULL);
254 type = 1;
257 static void set_profile() {
258 output_performance_data = 1;
262 * Messages from the engine
265 void d2_align_sim_start() {
266 timer_start((void *) &d2_align_sim_start_time);
269 void d2_align_sim_stop() {
270 timer_stop((void *) &d2_align_sim_start_time, (void *) &d2_align_sim_total_time);
273 void d2_align_sample_start() {
274 timer_start((void *) &d2_align_sample_start_time);
277 void d2_align_sample_stop() {
278 timer_stop((void *) &d2_align_sample_start_time, (void *) &d2_align_sample_total_time);
281 void d2_incremental_start() {
282 timer_start((void *) &d2_incremental_start_time);
285 void d2_incremental_stop() {
286 timer_stop((void *) &d2_incremental_start_time, (void *) &d2_incremental_total_time);
289 void d2_irani_peleg_start() {
290 timer_start((void *) &d2_irani_peleg_start_time);
293 void d2_irani_peleg_stop() {
294 timer_stop((void *) &d2_irani_peleg_start_time, (void *) &d2_irani_peleg_total_time);
297 void exp_multiplier(double m0, double m1, double m2) {
298 status.exp_multiplier[0] = m0;
299 status.exp_multiplier[1] = m1;
300 status.exp_multiplier[2] = m2;
303 void exp_multiplier(double mult[3]) {
304 for (int k = 0; k < 3; k++)
305 status.exp_multiplier[k] = mult[k];
308 void set_steps(int count) {
309 status.steps = count;
312 void set_steps_completed(int count) {
313 status.steps_completed = count;
316 void set_match(double match) {
317 status.match_value = (1 - match) * 100;
318 update();
321 void loading_file() {
322 status.code = status.LOAD_FILE;
323 update();
326 void exposure_1() {
327 status.code = status.EXPOSURE_PASS_1;
328 update();
331 void exposure_2() {
332 status.code = status.EXPOSURE_PASS_2;
333 update();
336 void prematching() {
337 status.code = status.PREMATCH;
338 update();
341 void postmatching() {
342 status.code = status.POSTMATCH;
343 update();
346 void constructing_lod_clusters(ale_pos lod) {
347 status.code = status.LODCLUSTER_CREATE;
348 status.align_lod = lod;
349 update();
352 void aligning(ale_pos perturb, ale_pos lod) {
353 status.perturb_size = perturb;
354 status.align_lod = lod;
355 status.code = status.ALIGN;
356 update();
359 void set_orender_current(int num) {
360 status.onum = num;
361 if (num == 0)
362 status.orender_current = status.RENDERD;
363 else
364 status.orender_current = status.RENDERO;
367 void set_arender_current() {
368 status.arender_current = 1;
371 void clear_arender_current() {
372 status.arender_current = 0;
375 void rendering() {
377 * Current alignment rendering tasks must complete
378 * before any current output rendering tasks can
379 * start.
381 if (status.arender_current) {
382 status.code = status.RENDERA;
383 status.arender_current = 0;
384 } else {
385 status.code = status.orender_current;
387 update();
390 void writing_output(int num) {
391 status.onum = num;
392 if (num == 0)
393 status.code = status.WRITED;
394 else
395 status.code = status.WRITEO;
396 update();
399 void d3_control_point_data(double max_perturbation, double min_perturbation, double cur_perturbation,
400 double current_error) {
401 status.cp_max_perturb = max_perturbation;
402 status.cp_min_perturb = min_perturbation;
403 status.cp_cur_perturb = cur_perturbation;
404 status.cp_cur_error = current_error;
405 update();
408 void d3_control_point_step() {
409 printf(".");
410 update();
413 void d3_subdivision_status(unsigned int primary_frame, unsigned int secondary_frame,
414 unsigned int i, unsigned int j) {
415 status.code = status.D3_SUBDIVIDING_SPACE;
416 status.frame_num = primary_frame;
417 status.secondary_frame_num = secondary_frame;
418 status.y_coordinate = i;
419 status.x_coordinate = j;
421 update();
424 void d3_total_spaces(int total_spaces) {
425 status.total_spaces = total_spaces;
428 void d3_increment_spaces() {
429 status.total_spaces++;
432 void d3_occupancy_status(int frame) {
433 status.code = status.D3_UPDATING_OCCUPANCY;
434 status.frame_num = frame;
435 status.space_num = 0;
436 update();
439 void d3_increment_space_num() {
440 status.space_num++;
441 update();
444 void d3_render_status(int filter, int focus, int frame, int view, int i, int j, int space) {
445 status.code = status.D3_RENDER;
447 status.filtering = filter;
448 status.focusing = focus;
450 status.frame_num = frame;
451 status.view_num = view;
452 status.y_coordinate = i;
453 status.x_coordinate = j;
455 status.space_num = space;
457 update();
462 * Informational output
465 void ip_start() {
466 printf("Iterating Irani-Peleg");
469 void ip_frame_start(unsigned int num) {
470 status.code = status.IP_RENDER;
471 status.frame_num = num;
472 status.irani_peleg_stage = 0;
475 void ip_frame_simulate_start() {
476 status.irani_peleg_stage = 1;
477 update();
480 void ip_frame_correct_start() {
481 status.irani_peleg_stage = 2;
482 update();
485 void ip_update() {
486 status.code = status.IP_UPDATE;
487 update();
490 void ip_write() {
491 status.code = status.IP_WRITE;
492 update();
495 void ip_step_done() {
496 status.code = status.IP_STEP_DONE;
497 printf(".");
500 void ip_done() {
501 printf("\n");
504 void original_frame_start(const char *name) {
505 status.code = status.UNDEFINED;
506 printf("Original Frame:\n");
507 printf(" '%s'", name);
510 void original_frame_done() {
511 status.code = status.FRAME_DONE;
512 update();
515 void supplemental_frame_start(const char *name) {
516 static int section_announced = 0;
518 if (!section_announced) {
519 printf("Supplemental Frames:\n");
520 section_announced = 1;
523 status.code = status.UNDEFINED;
524 status.steps_completed = 0;
525 printf(" '%s'", name);
528 void supplemental_frame_done() {
529 status.code = status.FRAME_DONE;
530 update();
533 void alignment_monte_carlo_parameter(ale_pos mc) {
534 status.mc = (mc > 1) ? 1 : mc;
537 void alignment_perturbation_level(ale_pos perturb, ale_pos lod) {
538 status.perturb_size = perturb;
539 status.align_lod = lod;
540 status.steps_completed++;
541 printf(".");
544 void alignment_match_ok() {
545 status.code = status.UNDEFINED;
546 printf(format_string_ok(), status.match_value);
549 void alignment_no_match() {
550 status.code = status.UNDEFINED;
551 printf(format_string_no_match(), status.match_value);
554 void ale_2d_done(double value) {
555 status.code = status.UNDEFINED;
556 printf("Average match: %f%%", value);
557 status.code = status.SET_DONE;
558 update();
559 if (output_performance_data) {
560 printf("\n");
561 printf("Real time measurements\n");
562 printf("======================\n");
563 printf("\n");
564 #if HAVE_GETTIMEOFDAY
565 printf("Alignment (sampling) : %f s\n", (double) d2_align_sample_total_time.tv_sec
566 + (double) d2_align_sample_total_time.tv_usec / (double) 1000000);
567 printf("Alignment (checking) : %f s\n", (double) d2_align_sim_total_time.tv_sec
568 + (double) d2_align_sim_total_time.tv_usec / (double) 1000000);
569 printf("Incremental rendering : %f s\n", (double) d2_incremental_total_time.tv_sec
570 + (double) d2_incremental_total_time.tv_usec / (double) 1000000);
571 printf("Irani-Peleg rendering : %f s\n", (double) d2_irani_peleg_total_time.tv_sec
572 + (double) d2_irani_peleg_total_time.tv_usec / (double) 1000000);
573 #else
574 printf("Alignment (sampling) : %f s\n", (double) d2_align_sample_total_time);
575 printf("Alignment (checking) : %f s\n", (double) d2_align_sim_total_time);
576 printf("Incremental rendering : %f s\n", (double) d2_incremental_total_time);
577 printf("Irani-Peleg rendering : %f s\n", (double) d2_irani_peleg_total_time);
578 #endif
579 printf("\n");
583 void d3_start() {
584 status.code = status.UNDEFINED;
585 printf("Rendering 3D");
586 update();
589 void d3_control_point_solve() {
590 status.code = status.D3_CONTROL_POINT_SOLVE;
591 update();
594 void d3_init_view_angle(double angle) {
595 status.code = status.UNDEFINED;
596 update();
599 void d3_final_view_angle(double angle) {
600 status.code = status.UNDEFINED;
601 update();
604 void d3_control_point_solve_done() {
605 status.code = status.UNDEFINED;
606 update();
609 void d3_subdividing_space() {
610 status.code = status.D3_SUBDIVIDING_SPACE;
611 update();
614 void d3_subdividing_space_done() {
615 status.code = status.UNDEFINED;
616 update();
619 void d3_updating_occupancy() {
620 status.code = status.D3_UPDATING_OCCUPANCY;
621 update();
624 void d3_updating_occupancy_done() {
625 status.code = status.UNDEFINED;
626 update();
629 void d3_writing_output(const char *name) {
630 static int section_announced = 0;
632 if (!section_announced) {
633 printf(":\n");
634 section_announced = 1;
637 printf(" '%s'", name);
639 update();
642 void d3_writing_output_done() {
643 status.code = status.UNDEFINED;
644 printf(".\n");
645 update();
649 * Warnings
652 void warn(const char *string) {
653 printf("\n\n*** Warning: %s. ***\n\n\n");
657 * Errors
660 void exec_failure(const char *exec, const char *arg1, const char *arg2) {
661 printf("\n\n*** An error occurred while running `%s %s %s`. ***\n\n\n", exec, arg1, arg2);
662 exit(1);
665 void fork_failure(const char *location) {
666 printf("\n\n*** Could not fork in %s. ***\n\n\n", location);
667 exit(1);
670 void memory_error(const char *purpose) {
671 printf("Unable to allocate memory for %s.\n", purpose);
672 exit(1);
675 void memory_error_location(const char *location) {
676 printf("Unable to allocate memory in %s.\n", location);
677 exit(1);
680 void cli_not_enough(const char *option) {
681 printf("\n\n*** Not enough arguments for `%s' ***\n\n", option);
682 exit(1);
685 void cli_bad_arg(const char *option) {
686 printf("\n\n*** Bad argument to `%s' ***\n\n", option);
687 exit(1);
690 void error(const char *string) {
691 printf("\n\n*** Error: %s. ***\n\n\n", string);
692 exit(1);
695 void illegal_option(const char *string) {
696 printf("\n\n*** Error: illegal option %s ***\n\n", string);
697 exit(1);
700 void unknown_device(const char *string) {
701 printf("\n\n*** Error: unknown device %s ***\n\n", string);
702 exit(1);
705 void error_hint(const char *error, const char *hint) {
706 printf("\n\n*** Error: %s", error);
707 printf( "\n*** Hint: %s\n\n\n", hint);
708 exit(1);
711 virtual ~ui() {
715 #include "ui_wo.h"
717 #endif