ale/ui/ui.h
2022-07-30 14:46:04 -03:00

799 lines
16 KiB
C++

// Copyright 2004 David Hilvert <dhilvert@auricle.dyndns.org>,
// <dhilvert@ugcs.caltech.edu>
/* This file is part of the Anti-Lamenessing Engine.
The Anti-Lamenessing Engine is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
The Anti-Lamenessing Engine is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Anti-Lamenessing Engine; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ui_h__
#define __ui_h__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <assert.h>
#include "../ale_pos.h"
#include "../config.h"
#if HAVE_TIME_H
#include <time.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <map>
/*
* Time structures.
*/
namespace d2 {
struct trans_multi;
typedef trans_multi transformation;
struct trans_abstract;
struct trans_single;
}
class ale_timer_t {
#if HAVE_GETTIMEOFDAY
struct timeval tv;
#else
time_t tt;
#endif
double total;
public:
ale_timer_t() {
total = 0;
}
void start() {
#if HAVE_GETTIMEOFDAY
gettimeofday(&tv, NULL);
#else
tt = time(NULL);
#endif
}
void stop() {
#if HAVE_GETTIMEOFDAY
timeval t;
gettimeofday(&t, NULL);
t.tv_sec -= tv.tv_sec;
t.tv_usec -= tv.tv_usec;
total += t.tv_sec + ((double) 1 / (double) 1000000) * t.tv_usec;
#else
time_t t = time(NULL);
t -= tt;
total += t;
#endif
}
double get_total() {
return total;
}
};
/*
* User interface messages.
*/
class ui_wo;
class ui {
private:
static ui *singleton;
/*
* UI type
*
* 0. stream
* 1. tty
* 2. log
* 3. quiet
*/
static int type;
static int output_performance_data;
protected:
/*
* Data
*/
FILE *ui_stream;
struct status_type {
enum {
/*
* Special
*/
UNDEFINED,
/*
* Incremental rendering.
*/
LOAD_FILE, EXPOSURE_PASS_1,
LODCLUSTER_CREATE, PREMATCH, ALIGN, GLOBAL_ALIGN, POSTMATCH,
EXPOSURE_PASS_2, RENDERA, RENDERD, RENDERO, WRITED,
WRITEO, FRAME_DONE, SET_DONE, MULTI,
/*
* Irani-Peleg rendering.
*/
IP_RENDER, IP_STEP_DONE, IP_UPDATE, IP_WRITE,
/*
* 3D.
*/
D3_CONTROL_POINT_SOLVE, D3_SUBDIVIDING_SPACE,
D3_UPDATING_OCCUPANCY, D3_RENDER
} code, orender_current;
int arender_current;
double match_value;
int onum;
int steps;
int steps_completed;
int step_type;
double exp_multiplier[3];
double perturb_size;
double align_lod;
unsigned int frame_num;
unsigned int irani_peleg_stage;
unsigned int secondary_frame_num;
unsigned int view_num;
unsigned int x_coordinate, y_coordinate;;
unsigned int filtering, focusing;
unsigned int space_num;
unsigned int total_spaces;
double cp_max_perturb;
double cp_min_perturb;
double cp_cur_perturb;
double cp_cur_error;
int cache;
status_type() {
code = UNDEFINED;
steps_completed = 0;
cache = 1;
for (int k = 0; k < 3; k++)
exp_multiplier[k] = 1;
}
} status;
/*
* Performance data
*/
ale_timer_t d2_align_sample;
ale_timer_t d2_align_sim;
ale_timer_t d2_incremental;
ale_timer_t d2_irani_peleg;
std::map<double,ale_timer_t> perturb_timers;
/*
* Constructor
*/
ui() {
ui_stream = stderr;
}
/*
* Print function
*/
virtual void printf(const char *format, ...) = 0;
/*
* UI update function
*/
virtual void update() = 0;
/*
* Match format strings for textual UIs.
*/
const char *format_string_ok() {
return " okay (%9.6f%% match)";
}
const char *format_string_no_match() {
return " no match (%9.6f%% match)";
}
const char *format_string_working() {
return " (%9.6f%% match)";
}
public:
/*
* Handle options and other user input.
*/
static void handle_input(int argc, const char *argv[], const char *package,
const char *short_version, const char *version);
static ui *get();
static void set_stream() {
assert(singleton == NULL);
type = 0;
}
static void set_tty() {
assert(singleton == NULL);
type = 1;
}
static void set_log() {
assert (singleton == NULL);
type = 2;
}
static void set_quiet() {
assert(singleton == NULL);
type = 3;
}
static void set_profile() {
output_performance_data = 1;
}
/*
* Messages from the engine
*/
virtual void identify_output(const char *name) {
printf("Output file will be '%s'.\n", name);
}
virtual void d2_align_sim_start() {
d2_align_sim.start();
}
virtual void d2_align_sim_stop() {
d2_align_sim.stop();
}
virtual void d2_align_sample_start() {
d2_align_sample.start();
}
virtual void d2_align_sample_stop() {
d2_align_sample.stop();
}
virtual void d2_incremental_start() {
d2_incremental.start();
}
virtual void d2_incremental_stop() {
d2_incremental.stop();
}
virtual void d2_irani_peleg_start() {
d2_irani_peleg.start();
}
virtual void d2_irani_peleg_stop() {
d2_irani_peleg.stop();
}
virtual void exp_multiplier(double m0, double m1, double m2) {
status.exp_multiplier[0] = m0;
status.exp_multiplier[1] = m1;
status.exp_multiplier[2] = m2;
}
void exp_multiplier(double mult[3]) {
exp_multiplier(mult[0], mult[1], mult[2]);
}
virtual void set_steps(int count, int type = 0) {
status.steps = count;
status.step_type = type;
}
virtual void set_steps_completed(int count) {
status.steps_completed = count;
}
virtual void set_match(double match) {
status.match_value = (1 - match) * 100;
update();
}
virtual void set_offset(d2::trans_single offset);
virtual void set_offset(d2::trans_multi offset);
virtual void gs_mo(ale_pos gs_mo) {
}
virtual void cache_status(unsigned int c) {
status.cache = c;
}
virtual void loading_file() {
status.code = status.LOAD_FILE;
update();
}
virtual void exposure_1() {
status.code = status.EXPOSURE_PASS_1;
update();
}
virtual void exposure_2() {
status.code = status.EXPOSURE_PASS_2;
update();
}
virtual void prematching() {
status.code = status.PREMATCH;
update();
}
virtual void postmatching() {
status.code = status.POSTMATCH;
update();
}
virtual void constructing_lod_clusters(ale_pos lod) {
status.code = status.LODCLUSTER_CREATE;
status.align_lod = lod;
update();
}
virtual void global_alignment(ale_pos perturb, ale_pos lod) {
status.perturb_size = perturb;
status.align_lod = lod;
status.code = status.GLOBAL_ALIGN;
update();
}
virtual void aligning(ale_pos perturb, ale_pos lod) {
perturb_timers[perturb].start();
status.perturb_size = perturb;
status.align_lod = lod;
status.code = status.ALIGN;
update();
}
virtual void multi() {
status.code = status.MULTI;
update();
}
virtual void following() {
}
virtual void set_orender_current(int num) {
status.onum = num;
if (num == 0)
status.orender_current = status.RENDERD;
else
status.orender_current = status.RENDERO;
}
virtual void set_arender_current() {
status.arender_current = 1;
}
virtual void clear_arender_current() {
status.arender_current = 0;
}
virtual void rendering() {
/*
* Current alignment rendering tasks must complete
* before any current output rendering tasks can
* start.
*/
if (status.arender_current) {
status.code = status.RENDERA;
status.arender_current = 0;
} else {
status.code = status.orender_current;
}
update();
}
virtual void writing_output(int num) {
status.onum = num;
if (num == 0)
status.code = status.WRITED;
else
status.code = status.WRITEO;
update();
}
virtual void d3_control_point_data(double max_perturbation, double min_perturbation, double cur_perturbation,
double current_error) {
status.cp_max_perturb = max_perturbation;
status.cp_min_perturb = min_perturbation;
status.cp_cur_perturb = cur_perturbation;
status.cp_cur_error = current_error;
update();
}
virtual void d3_control_point_step() {
printf(".");
update();
}
virtual void d3_subdivision_status(unsigned int primary_frame, unsigned int secondary_frame,
unsigned int i, unsigned int j) {
status.code = status.D3_SUBDIVIDING_SPACE;
status.frame_num = primary_frame;
status.secondary_frame_num = secondary_frame;
status.y_coordinate = i;
status.x_coordinate = j;
update();
}
virtual void d3_total_spaces(int total_spaces) {
status.total_spaces = total_spaces;
}
virtual void d3_increment_spaces() {
status.total_spaces++;
}
virtual void d3_occupancy_status(int frame) {
status.code = status.D3_UPDATING_OCCUPANCY;
status.frame_num = frame;
status.space_num = 0;
update();
}
virtual void d3_increment_space_num() {
status.space_num++;
update();
}
virtual void d3_render_status(int filter, int focus, int frame, int view, int i, int j, int space) {
status.code = status.D3_RENDER;
status.filtering = filter;
status.focusing = focus;
status.frame_num = frame;
status.view_num = view;
status.y_coordinate = i;
status.x_coordinate = j;
status.space_num = space;
update();
}
/*
* Informational output
*/
virtual void ip_start() {
printf("Iterating Irani-Peleg");
}
virtual void refilter_start() {
printf("Re-filtering incremental results");
}
virtual void ip_frame_start(unsigned int num) {
status.code = status.IP_RENDER;
status.frame_num = num;
status.irani_peleg_stage = 0;
update();
}
virtual void ip_frame_simulate_start() {
status.code = status.IP_RENDER;
status.irani_peleg_stage = 1;
update();
}
virtual void ip_frame_correct_start() {
status.code = status.IP_RENDER;
status.irani_peleg_stage = 2;
update();
}
virtual void ip_update() {
status.code = status.IP_UPDATE;
update();
}
virtual void ip_write() {
status.code = status.IP_WRITE;
update();
}
virtual void ip_step_done() {
status.code = status.IP_STEP_DONE;
printf(".");
}
virtual void ip_done() {
printf("\n");
}
virtual void refilter_done() {
printf(".\n");
}
virtual void original_frame_start(const char *name) {
status.code = status.UNDEFINED;
printf("Original Frame:\n");
printf(" '%s'", name);
}
virtual void original_frame_done() {
status.code = status.FRAME_DONE;
update();
}
virtual void supplemental_frame_start(const char *name) {
static int section_announced = 0;
if (!section_announced) {
printf("Supplemental Frames:\n");
section_announced = 1;
}
status.code = status.UNDEFINED;
status.steps_completed = 0;
printf(" '%s'", name);
}
virtual void supplemental_frame_done() {
status.code = status.FRAME_DONE;
update();
}
virtual void alignment_degree_complete(int degree) {
if (status.step_type == 1) {
status.steps_completed++;
printf("*");
}
}
virtual void alignment_perturbation_level(ale_pos perturb, ale_pos lod) {
perturb_timers[status.perturb_size].stop();
perturb_timers[perturb].start();
status.perturb_size = perturb;
status.align_lod = lod;
if (status.step_type == 0) {
status.steps_completed++;
printf(".");
}
}
virtual void alignment_dims(unsigned int hr, unsigned int wr, unsigned int hi, unsigned int wi) {
}
virtual void start_multi_alignment_element(d2::trans_multi &tm) {
}
virtual void alignment_match_ok() {
status.code = status.UNDEFINED;
printf(format_string_ok(), status.match_value);
}
virtual void alignment_no_match() {
status.code = status.UNDEFINED;
printf(format_string_no_match(), status.match_value);
}
virtual void ale_2d_done(double value) {
status.code = status.UNDEFINED;
printf("Average match: %f%%", value);
status.code = status.SET_DONE;
update();
if (output_performance_data) {
printf("\n");
printf("Real time measurements\n");
printf("======================\n");
printf("\n");
printf("Alignment (sampling) : %f s\n", d2_align_sample.get_total());
printf("Alignment (checking) : %f s\n", d2_align_sim.get_total());
printf("Incremental rendering : %f s\n", d2_incremental.get_total());
printf("Irani-Peleg rendering : %f s\n", d2_irani_peleg.get_total());
printf("\n");
printf("Details (local alignment)\n");
printf("-------------------------\n");
int have_details = 0;
for (std::map<double,ale_timer_t>::iterator i = perturb_timers.begin();
i != perturb_timers.end(); i++) {
if (i->second.get_total() == 0.0
&& i == perturb_timers.begin())
continue;
printf("Alignment (perturb %f): %f s\n",
i->first, i->second.get_total());
have_details = 1;
}
if (!have_details) {
printf("No local alignment performed.\n");
}
printf("\n");
}
}
virtual void d3_start() {
status.code = status.UNDEFINED;
printf("Rendering 3D");
update();
}
virtual void d3_control_point_solve() {
status.code = status.D3_CONTROL_POINT_SOLVE;
update();
}
virtual void d3_init_view_angle(double angle) {
status.code = status.UNDEFINED;
update();
}
virtual void d3_final_view_angle(double angle) {
status.code = status.UNDEFINED;
update();
}
virtual void d3_control_point_solve_done() {
status.code = status.UNDEFINED;
update();
}
virtual void d3_subdividing_space() {
status.code = status.D3_SUBDIVIDING_SPACE;
update();
}
virtual void d3_subdividing_space_done() {
status.code = status.UNDEFINED;
update();
}
virtual void d3_updating_occupancy() {
status.code = status.D3_UPDATING_OCCUPANCY;
update();
}
virtual void d3_updating_occupancy_done() {
status.code = status.UNDEFINED;
update();
}
virtual void d3_writing_output(const char *name) {
static int section_announced = 0;
if (!section_announced) {
printf(":\n");
section_announced = 1;
}
printf(" '%s'", name);
update();
}
virtual void d3_writing_output_done() {
status.code = status.UNDEFINED;
printf(".\n");
update();
}
/*
* Warnings
*/
virtual void warn(const char *string) {
printf("\n\n*** Warning: %s. ***\n\n\n");
}
/*
* Errors
*/
virtual void exec_failure(const char *exec, const char *arg1, const char *arg2) {
printf("\n\n*** An error occurred while running `%s %s %s`. ***\n\n\n", exec, arg1, arg2);
exit(1);
}
virtual void fork_failure(const char *location) {
printf("\n\n*** Could not fork in %s. ***\n\n\n", location);
exit(1);
}
virtual void memory_error(const char *purpose) {
printf("\n\n*** Unable to allocate memory for %s. ***\n\n\n", purpose);
exit(1);
}
virtual void memory_error_location(const char *location) {
printf("\n\n*** Unable to allocate memory in %s.\n\n\n", location);
exit(1);
}
virtual void cli_not_enough(const char *option) {
printf("\n\n*** Not enough arguments for `%s' ***\n\n\n", option);
exit(1);
}
virtual void cli_bad_arg(const char *option) {
printf("\n\n*** Bad argument to `%s' ***\n\n", option);
exit(1);
}
virtual void error(const char *string) {
printf("\n\n*** Error: %s. ***\n\n\n", string);
exit(1);
}
virtual void illegal_option(const char *string) {
printf("\n\n*** Error: illegal option %s ***\n\n", string);
exit(1);
}
virtual void unknown_device(const char *string) {
printf("\n\n*** Error: unknown device %s ***\n\n", string);
exit(1);
}
virtual void error_hint(const char *error, const char *hint) {
printf("\n\n*** Error: %s", error);
printf( "\n*** Hint: %s\n\n\n", hint);
exit(1);
}
virtual void cache(double usage, double max) {
}
virtual void log_message(const char *message) {
}
virtual ~ui() {
}
};
#include "ui_wo.h"
#endif